machine-bridge-mcp 2.0.0 → 3.0.0-beta.102
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/CHANGELOG.md +1142 -0
- package/CONTRIBUTING.md +23 -25
- package/GOVERNANCE.md +2 -2
- package/README.md +58 -20
- package/SECURITY.md +161 -120
- package/SUPPORT.md +1 -1
- package/browser-extension/broker-auth.js +83 -0
- package/browser-extension/broker-liveness.js +35 -0
- package/browser-extension/browser-error-boundary.js +96 -0
- package/browser-extension/browser-operations.js +1456 -101
- package/browser-extension/devtools-input.js +195 -34
- package/browser-extension/devtools-observation.js +429 -0
- package/browser-extension/devtools-session.js +48 -0
- package/browser-extension/manifest.json +4 -3
- package/browser-extension/page-automation.js +578 -118
- package/browser-extension/pairing-bootstrap.js +42 -0
- package/browser-extension/pairing.js +28 -12
- package/browser-extension/service-worker.js +126 -106
- package/docs/AGENT_CONTEXT.md +13 -10
- package/docs/ARCHITECTURE.md +159 -67
- package/docs/AUDIT.md +1302 -4
- package/docs/CLIENTS.md +19 -6
- package/docs/COMPUTER_USE.md +297 -0
- package/docs/ENGINEERING.md +72 -13
- package/docs/GETTING_STARTED.md +18 -20
- package/docs/LOCAL_AUTHORIZATION.md +115 -72
- package/docs/LOCAL_AUTOMATION.md +27 -21
- package/docs/LOGGING.md +40 -19
- package/docs/MANAGED_JOBS.md +37 -34
- package/docs/MULTI_ACCOUNT.md +98 -37
- package/docs/OPERATIONS.md +145 -51
- package/docs/OVERVIEW.md +14 -11
- package/docs/POLICY_REFERENCE.md +71 -3
- package/docs/PRIVACY.md +41 -2
- package/docs/PROJECT_STANDARDS.md +29 -6
- package/docs/RELEASING.md +238 -64
- package/docs/TESTING.md +150 -39
- package/docs/THREAT_MODEL.md +164 -67
- package/docs/TOOL_REFERENCE.md +653 -60
- package/docs/UPGRADING.md +78 -18
- package/native/macos/MachineBridgeBackgroundInput.swift +1051 -0
- package/native/macos/MachineBridgeBackgroundInputSmokeFixture.swift +295 -0
- package/native/macos/MachineBridgeTrustBroker.swift +233 -0
- package/package.json +94 -16
- package/scripts/accepted-candidate-tarball.mjs +77 -0
- package/scripts/candidate-runtime-store.mjs +93 -0
- package/scripts/check-plan.mjs +73 -3
- package/scripts/check-runner.mjs +129 -17
- package/scripts/commit-message-check.mjs +5 -2
- package/scripts/consumer-package-security.mjs +293 -0
- package/scripts/coverage-check.mjs +251 -15
- package/scripts/coverage-generation.mjs +41 -0
- package/scripts/coverage-range-merge.mjs +41 -0
- package/scripts/foreground-daemon-recovery.mjs +88 -0
- package/scripts/generate-policy-reference.mjs +28 -5
- package/scripts/generate-tool-reference.mjs +1 -1
- package/scripts/generate-worker-types.mjs +21 -11
- package/scripts/github-backlog.mjs +11 -10
- package/scripts/github-push.mjs +62 -16
- package/scripts/github-release-asset.mjs +58 -0
- package/scripts/github-release.mjs +241 -132
- package/scripts/global-package-installation.mjs +68 -0
- package/scripts/hardened-npm-session.mjs +42 -0
- package/scripts/install-published-prerelease.mjs +198 -0
- package/scripts/local-release-acceptance.mjs +103 -45
- package/scripts/macos-background-input-smoke.mjs +515 -0
- package/scripts/network-retry.mjs +8 -1
- package/scripts/npm-global-prefix.mjs +27 -0
- package/scripts/npm-publication-policy.mjs +17 -0
- package/scripts/official-mcp-conformance.mjs +267 -0
- package/scripts/persistent-activation-process.mjs +101 -0
- package/scripts/prepare-pinned-npm.mjs +12 -69
- package/scripts/prerelease-activation.mjs +160 -0
- package/scripts/privacy-check.mjs +14 -6
- package/scripts/promotion-digest.mjs +128 -0
- package/scripts/publish-npm.mjs +260 -0
- package/scripts/published-release.mjs +132 -0
- package/scripts/release-acceptance.mjs +62 -54
- package/scripts/release-browser-extension-store.mjs +172 -0
- package/scripts/release-candidate-manifest.mjs +52 -0
- package/scripts/release-channel.mjs +106 -0
- package/scripts/release-diagnostic.mjs +41 -0
- package/scripts/release-impact-check.mjs +12 -22
- package/scripts/release-oauth-canary-core.mjs +325 -0
- package/scripts/release-oauth-canary-evidence.mjs +100 -0
- package/scripts/release-oauth-canary.mjs +127 -0
- package/scripts/release-publication-guard.mjs +67 -0
- package/scripts/release-soak.mjs +284 -0
- package/scripts/release-state.mjs +1 -1
- package/scripts/run-checks.mjs +44 -7
- package/scripts/run-worker-dry-run.mjs +21 -0
- package/scripts/sarif-security-gate.mjs +2 -1
- package/scripts/sbom-check.mjs +106 -0
- package/scripts/start-release-candidate.mjs +267 -44
- package/scripts/syntax-check.mjs +36 -14
- package/scripts/verification-generation-guard.mjs +15 -0
- package/scripts/verification-idle-sleep-guard.mjs +37 -0
- package/scripts/verification-state.mjs +108 -0
- package/scripts/wrangler-command-lifecycle.mjs +115 -0
- package/src/local/account-access.mjs +13 -1
- package/src/local/account-admin-response.mjs +92 -0
- package/src/local/account-admin.mjs +52 -19
- package/src/local/agent-context-projection.mjs +26 -7
- package/src/local/agent-context.mjs +88 -49
- package/src/local/agent-skill-discovery.mjs +16 -5
- package/src/local/app-automation-macos-jxa.mjs +350 -0
- package/src/local/app-automation.mjs +873 -163
- package/src/local/application-capability-projection.mjs +24 -0
- package/src/local/authority-context.mjs +106 -0
- package/src/local/autostart-log-maintenance.mjs +36 -0
- package/src/local/browser-bridge-http.mjs +5 -3
- package/src/local/browser-bridge.mjs +109 -31
- package/src/local/browser-broker-auth-http.mjs +67 -0
- package/src/local/browser-broker-auth.mjs +98 -0
- package/src/local/browser-broker-routes.mjs +63 -20
- package/src/local/browser-broker-server.mjs +17 -7
- package/src/local/browser-command.mjs +79 -30
- package/src/local/browser-computer-observation-service.mjs +266 -0
- package/src/local/browser-extension-identity.mjs +50 -0
- package/src/local/browser-extension-path.mjs +22 -0
- package/src/local/browser-extension-protocol.mjs +50 -11
- package/src/local/browser-operation-service.mjs +147 -117
- package/src/local/browser-pairing-grant.mjs +109 -0
- package/src/local/browser-pairing-http.mjs +36 -0
- package/src/local/browser-pairing-launch.mjs +58 -0
- package/src/local/browser-pairing-store.mjs +85 -48
- package/src/local/browser-request-registry.mjs +40 -14
- package/src/local/browser-request-settlement.mjs +78 -0
- package/src/local/browser-resource-input.mjs +74 -0
- package/src/local/browser-trusted-input-health.mjs +63 -0
- package/src/local/call-authority.mjs +21 -0
- package/src/local/call-capacity.mjs +45 -0
- package/src/local/call-registry-drain.mjs +54 -0
- package/src/local/call-registry.mjs +30 -15
- package/src/local/capability-observer.mjs +5 -0
- package/src/local/capability-ranking.mjs +3 -2
- package/src/local/child-process-settlement.mjs +132 -0
- package/src/local/cli-account-admin.mjs +40 -6
- package/src/local/cli-activate.mjs +162 -0
- package/src/local/cli-local-admin.mjs +20 -45
- package/src/local/cli-options.mjs +12 -13
- package/src/local/cli-ready-output.mjs +52 -0
- package/src/local/cli-service.mjs +91 -11
- package/src/local/cli.mjs +232 -150
- package/src/local/computer-use-application-observation.mjs +224 -0
- package/src/local/computer-use-arguments.mjs +270 -0
- package/src/local/computer-use-deadline.mjs +50 -0
- package/src/local/computer-use-dispatch-settlement.mjs +40 -0
- package/src/local/computer-use-expectation.mjs +171 -0
- package/src/local/computer-use-observation.mjs +769 -0
- package/src/local/computer-use-recovery.mjs +82 -0
- package/src/local/computer-use-result-budget.mjs +145 -0
- package/src/local/computer-use-snapshot-store.mjs +67 -0
- package/src/local/computer-use.mjs +2255 -0
- package/src/local/daemon-http-relay-auth.mjs +26 -0
- package/src/local/daemon-http-relay-connection.mjs +298 -0
- package/src/local/daemon-http-relay-request.mjs +64 -0
- package/src/local/daemon-http-relay-sequence.mjs +49 -0
- package/src/local/daemon-process.mjs +40 -7
- package/src/local/delegated-process-sandbox.mjs +148 -0
- package/src/local/device-identity.mjs +156 -49
- package/src/local/device-root-provider.mjs +81 -0
- package/src/local/directory-metadata.mjs +47 -0
- package/src/local/doctor-reporting.mjs +23 -0
- package/src/local/durable-process-spec.mjs +80 -0
- package/src/local/errors.mjs +25 -15
- package/src/local/exclusive-file.mjs +74 -26
- package/src/local/execution-limits.mjs +9 -0
- package/src/local/execution-routing.mjs +276 -0
- package/src/local/execution-surface.mjs +23 -0
- package/src/local/file-mutation-coordinator.mjs +47 -0
- package/src/local/file-snapshot-preservation.mjs +24 -0
- package/src/local/filesystem-identity.mjs +54 -0
- package/src/local/fixed-process-environment.mjs +21 -0
- package/src/local/full-access-test.mjs +31 -13
- package/src/local/git-commit.mjs +69 -0
- package/src/local/git-config-safety.mjs +55 -0
- package/src/local/git-log-parser.mjs +41 -0
- package/src/local/git-metadata-boundary.mjs +77 -0
- package/src/local/git-metadata-tree-safety.mjs +59 -0
- package/src/local/git-operation-state.mjs +19 -0
- package/src/local/git-service.mjs +165 -30
- package/src/local/hardened-npm-download-timeout.mjs +46 -0
- package/src/local/hardened-npm-download.mjs +109 -0
- package/src/local/hardened-npm-extract.mjs +20 -0
- package/src/local/hardened-npm-verification.mjs +104 -0
- package/src/local/hardened-npm.mjs +199 -0
- package/src/local/job-runner.mjs +244 -89
- package/src/local/lifecycle.mjs +6 -0
- package/src/local/log.mjs +19 -45
- package/src/local/macos-background-input.mjs +398 -0
- package/src/local/macos-idle-sleep-assertion.mjs +65 -0
- package/src/local/macos-trust-broker.mjs +404 -0
- package/src/local/managed-job-cancellation.mjs +42 -0
- package/src/local/managed-job-capacity.mjs +16 -0
- package/src/local/managed-job-directory-generation.mjs +60 -0
- package/src/local/managed-job-directory.mjs +75 -0
- package/src/local/managed-job-durable-process.mjs +49 -0
- package/src/local/managed-job-lock.mjs +46 -14
- package/src/local/managed-job-plan.mjs +38 -14
- package/src/local/managed-job-projection.mjs +23 -15
- package/src/local/managed-job-retention.mjs +128 -0
- package/src/local/managed-job-runner-claim.mjs +70 -0
- package/src/local/managed-job-runner.mjs +35 -10
- package/src/local/managed-job-storage.mjs +22 -6
- package/src/local/managed-job-terminal-maintenance.mjs +40 -0
- package/src/local/managed-job-terminal.mjs +150 -0
- package/src/local/managed-jobs.mjs +424 -287
- package/src/local/npm-cli.mjs +42 -0
- package/src/local/npm-environment.mjs +37 -0
- package/src/local/operation-authorization.mjs +68 -324
- package/src/local/operation-risk.mjs +51 -4
- package/src/local/owner-state-lock.mjs +118 -0
- package/src/local/package-identity.mjs +9 -0
- package/src/local/patch.mjs +20 -18
- package/src/local/path-inspection.mjs +23 -0
- package/src/local/policy.mjs +19 -0
- package/src/local/private-toolchain-integrity.mjs +54 -0
- package/src/local/process-execution.mjs +87 -75
- package/src/local/process-foreground-timeout.mjs +50 -0
- package/src/local/process-identity.mjs +41 -7
- package/src/local/process-nonreplayable-settlement.mjs +50 -0
- package/src/local/process-result-projection.mjs +22 -0
- package/src/local/process-session-events.mjs +47 -0
- package/src/local/process-session-remote-activity.mjs +10 -0
- package/src/local/process-session-termination.mjs +73 -0
- package/src/local/process-sessions.mjs +144 -112
- package/src/local/process-tracker.mjs +140 -13
- package/src/local/process-tree-ownership-types.d.ts +37 -0
- package/src/local/process-tree-ownership.mjs +57 -0
- package/src/local/process-tree-signal.mjs +34 -0
- package/src/local/process-tree-snapshot.mjs +77 -0
- package/src/local/process-tree-supervisor.mjs +69 -0
- package/src/local/process-tree.mjs +11 -53
- package/src/local/project-metadata.mjs +19 -6
- package/src/local/relay-call-recovery.mjs +58 -38
- package/src/local/relay-connection-classification.mjs +131 -0
- package/src/local/relay-connection-support.mjs +91 -0
- package/src/local/relay-connection.mjs +179 -272
- package/src/local/relay-diagnostics.mjs +91 -0
- package/src/local/relay-heartbeat.mjs +119 -0
- package/src/local/relay-liveness.mjs +109 -0
- package/src/local/relay-peer-diagnostics.mjs +29 -0
- package/src/local/release-runtime-lock.mjs +18 -0
- package/src/local/remote-activity-idle-sleep-guard.mjs +77 -0
- package/src/local/remote-configuration.mjs +48 -0
- package/src/local/resilient-relay-connection.mjs +178 -0
- package/src/local/resource-admission-diagnostics.mjs +52 -0
- package/src/local/resource-admission-policy.mjs +115 -0
- package/src/local/resource-admission.mjs +339 -0
- package/src/local/resource-build-root.mjs +83 -0
- package/src/local/resource-cargo-concurrency.mjs +38 -0
- package/src/local/resource-cmake-concurrency.mjs +42 -0
- package/src/local/resource-command-concurrency.mjs +37 -0
- package/src/local/resource-command-profile.mjs +176 -0
- package/src/local/resource-coordinator-accounting.mjs +21 -0
- package/src/local/resource-cpu-window.mjs +20 -0
- package/src/local/resource-disk-headroom.mjs +13 -0
- package/src/local/resource-elastic-memory.mjs +19 -0
- package/src/local/resource-elastic-request.mjs +36 -0
- package/src/local/resource-foreground-wait.mjs +29 -0
- package/src/local/resource-go-concurrency.mjs +43 -0
- package/src/local/resource-gradle-concurrency.mjs +57 -0
- package/src/local/resource-host-cache.mjs +39 -0
- package/src/local/resource-host-darwin.mjs +54 -0
- package/src/local/resource-host-linux.mjs +35 -0
- package/src/local/resource-host-sample-file.mjs +23 -0
- package/src/local/resource-host-snapshot.mjs +99 -0
- package/src/local/resource-lease-accounting.mjs +119 -0
- package/src/local/resource-light-command.mjs +6 -0
- package/src/local/resource-make-concurrency.mjs +42 -0
- package/src/local/resource-maven-concurrency.mjs +38 -0
- package/src/local/resource-ninja-command-concurrency.mjs +20 -0
- package/src/local/resource-ninja-concurrency.mjs +28 -0
- package/src/local/resource-operations.mjs +26 -10
- package/src/local/resource-pressure.mjs +67 -0
- package/src/local/resource-probe-command.mjs +35 -0
- package/src/local/resource-process-admission.mjs +59 -0
- package/src/local/resource-process-ancestry-cache.mjs +43 -0
- package/src/local/resource-process-ancestry.mjs +32 -0
- package/src/local/resource-process-priority.mjs +15 -0
- package/src/local/resource-project-key.mjs +53 -0
- package/src/local/resource-pytest-concurrency.mjs +33 -0
- package/src/local/resource-release-control-classification.mjs +14 -0
- package/src/local/resource-release-control-executable.mjs +70 -0
- package/src/local/resource-release-control-workspace.mjs +41 -0
- package/src/local/resource-request-contract.mjs +30 -0
- package/src/local/resource-script-classification.mjs +44 -0
- package/src/local/resource-shell-analysis.mjs +58 -0
- package/src/local/resource-staging-recovery.mjs +97 -0
- package/src/local/resource-swift-concurrency.mjs +31 -0
- package/src/local/resource-transaction-lock.mjs +189 -0
- package/src/local/resource-wait.mjs +48 -0
- package/src/local/resource-waiters.mjs +139 -0
- package/src/local/resource-xcode-command.mjs +7 -0
- package/src/local/resource-xcode-concurrency.mjs +34 -0
- package/src/local/resource-xcode-non-build.mjs +19 -0
- package/src/local/runtime-activation.mjs +700 -0
- package/src/local/runtime-activity-projection.mjs +48 -0
- package/src/local/runtime-capabilities.mjs +48 -15
- package/src/local/runtime-diagnostic-state.mjs +14 -0
- package/src/local/runtime-diagnostics.mjs +40 -13
- package/src/local/runtime-info-projection.mjs +60 -0
- package/src/local/runtime-info-relay-projection.mjs +21 -0
- package/src/local/runtime-paths.mjs +2 -1
- package/src/local/runtime-process-routing.mjs +33 -0
- package/src/local/runtime-relay-connection-options.mjs +44 -0
- package/src/local/runtime-relay-control.mjs +98 -0
- package/src/local/runtime-relay.mjs +26 -50
- package/src/local/runtime-reporting.mjs +37 -21
- package/src/local/runtime-resource-service.mjs +77 -0
- package/src/local/runtime-tool-handlers.mjs +13 -10
- package/src/local/runtime.mjs +244 -208
- package/src/local/secure-file.mjs +73 -20
- package/src/local/security-audit-dispatch.mjs +35 -0
- package/src/local/security-audit-log.mjs +215 -0
- package/src/local/security-audit-state.mjs +139 -0
- package/src/local/security-audit-storage.mjs +135 -0
- package/src/local/security-audit-warning.mjs +31 -0
- package/src/local/security-audit-worker.mjs +87 -0
- package/src/local/service-convergence.mjs +42 -1
- package/src/local/service-definition.mjs +24 -0
- package/src/local/service-environment.mjs +18 -10
- package/src/local/service-owner.mjs +146 -0
- package/src/local/service-ownership.mjs +17 -0
- package/src/local/service-restart-handoff.mjs +64 -0
- package/src/local/service-restart-scheduler.mjs +49 -0
- package/src/local/service-runtime-convergence.mjs +52 -0
- package/src/local/service-runtime.mjs +105 -0
- package/src/local/service-status.mjs +60 -0
- package/src/local/service.mjs +385 -92
- package/src/local/shell.mjs +39 -19
- package/src/local/ssh-key.mjs +158 -42
- package/src/local/state-inventory.mjs +50 -24
- package/src/local/state-owner-lock-inventory.mjs +23 -0
- package/src/local/state-root-owned-namespaces.mjs +83 -0
- package/src/local/state-root-retirement.mjs +89 -0
- package/src/local/state.mjs +386 -96
- package/src/local/stdio.mjs +96 -66
- package/src/local/support-state-projection.mjs +30 -0
- package/src/local/system-network-route.mjs +76 -0
- package/src/local/systemd-removal.mjs +20 -0
- package/src/local/tool-executor.mjs +85 -20
- package/src/local/tool-result-boundary.mjs +51 -0
- package/src/local/toolchain-operation-lock.mjs +41 -0
- package/src/local/tools.mjs +7 -5
- package/src/local/trusted-executable.mjs +53 -0
- package/src/local/trusted-git-executable.mjs +34 -0
- package/src/local/trusted-github-cli.mjs +24 -0
- package/src/local/windows-service-convergence.mjs +49 -0
- package/src/local/windows-service.mjs +52 -45
- package/src/local/worker-deployment-fingerprint.mjs +102 -0
- package/src/local/worker-deployment.mjs +48 -60
- package/src/local/worker-health.mjs +12 -4
- package/src/local/worker-secret-file.mjs +37 -17
- package/src/local/workspace-file-service.mjs +156 -239
- package/src/local/workspace-file-transaction.mjs +189 -0
- package/src/local/workspace-search.mjs +55 -0
- package/src/local/wrangler-toolchain/package-lock.json +1505 -0
- package/src/local/wrangler-toolchain/package.json +23 -0
- package/src/local/wrangler-toolchain-verification.mjs +135 -0
- package/src/local/wrangler-toolchain.mjs +188 -0
- package/src/shared/access-contract.json +7 -1
- package/src/shared/activation-recovery.mjs +49 -0
- package/src/shared/admin-auth.d.mts +2 -1
- package/src/shared/admin-auth.mjs +3 -3
- package/src/shared/authority-revocation.d.mts +9 -0
- package/src/shared/authority-revocation.mjs +28 -0
- package/src/shared/daemon-auth.d.mts +11 -0
- package/src/shared/daemon-auth.mjs +17 -0
- package/src/shared/device-session-auth.d.mts +20 -0
- package/src/shared/device-session-auth.mjs +51 -0
- package/src/shared/foreground-timeout.d.mts +15 -0
- package/src/shared/foreground-timeout.mjs +70 -0
- package/src/shared/log-redaction.d.mts +9 -0
- package/src/shared/log-redaction.mjs +51 -0
- package/src/shared/mcp-protocol.d.mts +27 -0
- package/src/shared/mcp-protocol.mjs +275 -0
- package/src/shared/project-overview-projection.d.mts +4 -0
- package/src/shared/project-overview-projection.mjs +96 -0
- package/src/shared/relay-contract.json +28 -0
- package/src/shared/result-projection.d.mts +2 -1
- package/src/shared/result-projection.mjs +13 -2
- package/src/shared/server-metadata.json +15 -9
- package/src/shared/tool-argument-validation.d.mts +17 -0
- package/src/shared/tool-argument-validation.mjs +325 -0
- package/src/shared/tool-call-capacity.d.mts +41 -0
- package/src/shared/tool-call-capacity.mjs +59 -0
- package/src/shared/tool-catalog.json +626 -57
- package/src/worker/access.ts +12 -0
- package/src/worker/account-admin.ts +55 -33
- package/src/worker/authority-revocations.ts +174 -0
- package/src/worker/authority.ts +52 -6
- package/src/worker/daemon-auth.ts +49 -68
- package/src/worker/daemon-channel.ts +36 -0
- package/src/worker/daemon-http-auth.ts +63 -0
- package/src/worker/daemon-http-channel.ts +120 -0
- package/src/worker/daemon-http-controller.ts +163 -0
- package/src/worker/daemon-http-protocol.ts +62 -0
- package/src/worker/daemon-http-registry.ts +82 -0
- package/src/worker/daemon-last-observation.ts +30 -0
- package/src/worker/daemon-liveness.ts +8 -6
- package/src/worker/daemon-ready-dispatch.ts +17 -0
- package/src/worker/daemon-ready-messages.ts +73 -0
- package/src/worker/daemon-ready-waiters.ts +79 -0
- package/src/worker/daemon-recovery-budget.ts +13 -0
- package/src/worker/daemon-registry.ts +58 -0
- package/src/worker/daemon-relay-diagnostics.ts +127 -0
- package/src/worker/daemon-socket-attachment.ts +55 -0
- package/src/worker/daemon-sockets.ts +72 -62
- package/src/worker/daemon-status.ts +38 -0
- package/src/worker/device-session-verifier.ts +129 -0
- package/src/worker/dpop.ts +157 -0
- package/src/worker/durable-process-timeout.ts +29 -0
- package/src/worker/errors.ts +57 -0
- package/src/worker/http.ts +112 -26
- package/src/worker/index.ts +446 -440
- package/src/worker/mcp-access.ts +57 -0
- package/src/worker/mcp-controller.ts +188 -0
- package/src/worker/mcp-http-accept.ts +11 -0
- package/src/worker/mcp-http-contract.ts +322 -0
- package/src/worker/mcp-initialization-compat.ts +141 -0
- package/src/worker/mcp-jsonrpc.ts +11 -29
- package/src/worker/mcp-removed-protocol.ts +17 -0
- package/src/worker/mcp-response-proxy.ts +135 -0
- package/src/worker/mcp-response-stream.ts +65 -0
- package/src/worker/mcp-stale-schema-compat.ts +57 -0
- package/src/worker/mcp-stream-proxy-contract.ts +48 -0
- package/src/worker/mcp-tool-call-input.ts +23 -0
- package/src/worker/nonce-store.ts +33 -35
- package/src/worker/oauth-authorization-page.ts +21 -1
- package/src/worker/oauth-client-admin.ts +52 -0
- package/src/worker/oauth-client-contract.ts +38 -0
- package/src/worker/oauth-controller.ts +107 -47
- package/src/worker/oauth-field-contract.ts +31 -0
- package/src/worker/oauth-record-contract.ts +7 -0
- package/src/worker/oauth-refresh-authority.ts +27 -0
- package/src/worker/oauth-refresh-exchange.ts +162 -0
- package/src/worker/oauth-refresh-families.ts +130 -27
- package/src/worker/oauth-refresh-persistence.ts +116 -0
- package/src/worker/oauth-state.ts +33 -18
- package/src/worker/oauth-store-validation.ts +131 -0
- package/src/worker/oauth-token-derivation.ts +33 -0
- package/src/worker/oauth-token-issuance.ts +119 -0
- package/src/worker/oauth-tokens.ts +56 -190
- package/src/worker/observability.ts +38 -5
- package/src/worker/pending-admission.ts +15 -0
- package/src/worker/pending-call-capacity.ts +108 -0
- package/src/worker/pending-call-contract.ts +42 -5
- package/src/worker/pending-call-deadlines.ts +75 -0
- package/src/worker/pending-calls.ts +131 -125
- package/src/worker/runtime-alarm-storage.ts +37 -0
- package/src/worker/runtime-alarm.ts +136 -0
- package/src/worker/server-info-activity.ts +36 -0
- package/src/worker/server-info-tool-delivery.ts +15 -0
- package/src/worker/server-info.ts +168 -0
- package/src/worker/tool-catalog.ts +47 -1
- package/src/worker/tool-timeout.ts +75 -14
- package/src/worker/websocket-protocol.ts +26 -2
- package/src/worker/worker-edge-guard.ts +90 -0
- package/src/worker/worker-edge-log.ts +65 -0
- package/src/worker/worker-entry.ts +52 -0
- package/src/worker/worker-mcp-config.ts +23 -0
- package/src/worker/worker-metadata.ts +48 -0
- package/src/worker/worker-rate-limit-key.ts +30 -0
- package/src/worker/worker-runtime-config.ts +20 -0
- package/src/worker/worker-static-routes.ts +54 -0
- package/src/worker/worker-task-lifetime.ts +18 -0
- package/tsconfig.local.json +17 -1
- package/wrangler.jsonc +13 -0
- package/src/local/cli-approval.mjs +0 -117
- package/src/local/operation-state-lock.mjs +0 -92
- package/src/worker/mcp-session.ts +0 -72
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
export const MACOS_UI_JXA = String.raw`
|
|
4
|
+
ObjC.import('Foundation');
|
|
5
|
+
ObjC.import('AppKit');
|
|
6
|
+
ObjC.import('CoreGraphics');
|
|
7
|
+
ObjC.bindFunction('proc_pidinfo', ['int', ['int', 'int', 'uint64', 'pointer', 'int']]);
|
|
8
|
+
const PROC_PIDTBSDINFO = 3;
|
|
9
|
+
const PROC_BSDINFO_SIZE = 136;
|
|
10
|
+
const PROC_BSDINFO_START_BYTES = 16;
|
|
11
|
+
function readPayload() {
|
|
12
|
+
const data = $.NSFileHandle.fileHandleWithStandardInput.readDataToEndOfFile;
|
|
13
|
+
const text = ObjC.unwrap($.NSString.alloc.initWithDataEncoding(data, $.NSUTF8StringEncoding));
|
|
14
|
+
return JSON.parse(text);
|
|
15
|
+
}
|
|
16
|
+
function safe(fn, fallback) { try { const value = fn(); return value === undefined || value === null ? fallback : value; } catch (_) { return fallback; } }
|
|
17
|
+
function processStartSignature(processId) {
|
|
18
|
+
// proc_bsdinfo is a stable macOS ABI: 136 bytes with pbi_start_tvsec/usec
|
|
19
|
+
// occupying the final 16 bytes. Preserve those native bytes as base64 so
|
|
20
|
+
// JXA and the native input helper derive one exact PID-generation token.
|
|
21
|
+
const data = $.NSMutableData.dataWithLength(PROC_BSDINFO_SIZE);
|
|
22
|
+
const copied = $.proc_pidinfo(processId, PROC_PIDTBSDINFO, 0, data.mutableBytes, PROC_BSDINFO_SIZE);
|
|
23
|
+
if (typeof copied !== 'number' || copied !== PROC_BSDINFO_SIZE) throw new Error('application process generation is unavailable');
|
|
24
|
+
const start = data.subdataWithRange($.NSMakeRange(PROC_BSDINFO_SIZE - PROC_BSDINFO_START_BYTES, PROC_BSDINFO_START_BYTES));
|
|
25
|
+
const signature = ObjC.unwrap(start.base64EncodedStringWithOptions(0));
|
|
26
|
+
if (typeof signature !== 'string' || !signature) throw new Error('application process generation is unavailable');
|
|
27
|
+
return signature;
|
|
28
|
+
}
|
|
29
|
+
function expectedProcessGenerationForPayload(payload) {
|
|
30
|
+
const value = payload.expectedProcessGeneration;
|
|
31
|
+
if (value === undefined || value === null) return null;
|
|
32
|
+
if (typeof value !== 'string' || !value || value.length > 2048 || /[\r\n\0]/.test(value)) throw new Error('expected process generation is invalid');
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
function processInstanceForPayload(payload, processId) {
|
|
36
|
+
const expected = expectedProcessGenerationForPayload(payload);
|
|
37
|
+
if (payload.includeProcessGeneration !== true && expected === null) return null;
|
|
38
|
+
const running = safe(() => $.NSRunningApplication.runningApplicationWithProcessIdentifier(processId), null);
|
|
39
|
+
if (!running || Boolean(safe(() => running.terminated, true))) throw new Error('application process generation is unavailable');
|
|
40
|
+
return running;
|
|
41
|
+
}
|
|
42
|
+
function processGenerationToken(processId, running) {
|
|
43
|
+
if (!running) throw new Error('application process generation is unavailable');
|
|
44
|
+
return 'proc:' + processStartSignature(processId);
|
|
45
|
+
}
|
|
46
|
+
function processGenerationForPayload(payload, processId, running) {
|
|
47
|
+
const expected = expectedProcessGenerationForPayload(payload);
|
|
48
|
+
if (!running) return null;
|
|
49
|
+
const actual = processGenerationToken(processId, running);
|
|
50
|
+
if (expected !== null && actual !== expected) throw new Error('application process generation changed before operation');
|
|
51
|
+
return actual;
|
|
52
|
+
}
|
|
53
|
+
function assertProcessInstance(running, processId, expectedGeneration) {
|
|
54
|
+
if (!running) return;
|
|
55
|
+
const current = safe(() => $.NSRunningApplication.runningApplicationWithProcessIdentifier(processId), null);
|
|
56
|
+
if (!current || Boolean(safe(() => current.terminated, true)) || !Boolean(running.isEqual(current))
|
|
57
|
+
|| (expectedGeneration !== null && expectedGeneration !== undefined
|
|
58
|
+
&& processGenerationToken(processId, current) !== expectedGeneration)) {
|
|
59
|
+
throw new Error('application process generation changed before operation');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function scalar(value) {
|
|
63
|
+
if (value === null || value === undefined) return null;
|
|
64
|
+
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') return value;
|
|
65
|
+
return String(value).slice(0, 1000);
|
|
66
|
+
}
|
|
67
|
+
function booleanState(value) {
|
|
68
|
+
if (typeof value === 'boolean') return value;
|
|
69
|
+
if (typeof value === 'number') return value === 0 ? false : value === 1 ? true : null;
|
|
70
|
+
if (typeof value !== 'string') return null;
|
|
71
|
+
const text = value.trim().toLowerCase();
|
|
72
|
+
if (text === 'true' || text === '1') return true;
|
|
73
|
+
if (text === 'false' || text === '0') return false;
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
function screenBox(element) {
|
|
77
|
+
const position = safe(() => element.position(), null);
|
|
78
|
+
const size = safe(() => element.size(), null);
|
|
79
|
+
if (!Array.isArray(position) || position.length < 2 || !Array.isArray(size) || size.length < 2) return null;
|
|
80
|
+
const values = [position[0], position[1], size[0], size[1]];
|
|
81
|
+
if (!values.every((item) => typeof item === 'number' && Number.isFinite(item))) return null;
|
|
82
|
+
const box = { x: values[0], y: values[1], width: values[2], height: values[3] };
|
|
83
|
+
if (box.width < 0 || box.height < 0) return null;
|
|
84
|
+
return box;
|
|
85
|
+
}
|
|
86
|
+
function describe(element, index, includeValues, includeGeometry) {
|
|
87
|
+
const item = {
|
|
88
|
+
index,
|
|
89
|
+
role: safe(() => element.role(), ''),
|
|
90
|
+
subrole: safe(() => element.subrole(), ''),
|
|
91
|
+
name: safe(() => element.name(), ''),
|
|
92
|
+
title: safe(() => element.title(), ''),
|
|
93
|
+
description: safe(() => element.description(), ''),
|
|
94
|
+
identifier: safe(() => element.attributes.byName('AXIdentifier').value(), ''),
|
|
95
|
+
enabled: safe(() => element.enabled(), null),
|
|
96
|
+
focused: safe(() => element.focused(), null),
|
|
97
|
+
selected: booleanState(safe(() => element.selected(), null)),
|
|
98
|
+
expanded: booleanState(safe(() => element.expanded(), null))
|
|
99
|
+
};
|
|
100
|
+
if (item.role === 'AXCheckBox' || item.role === 'AXRadioButton') {
|
|
101
|
+
item.checked = booleanState(safe(() => element.value(), null));
|
|
102
|
+
} else {
|
|
103
|
+
item.checked = null;
|
|
104
|
+
}
|
|
105
|
+
if (includeGeometry) item.screen_box = screenBox(element);
|
|
106
|
+
const identity = [item.role, item.subrole, item.name, item.title, item.description, item.identifier].join(' ').toLowerCase();
|
|
107
|
+
item.sensitive = item.role === 'AXSecureTextField' || /(?:password|passwd|secret|token|api[-_ ]?key|otp|one[-_ ]?time|verification|cvc|cvv|security[-_ ]?code|card[-_ ]?number)/.test(identity);
|
|
108
|
+
if (includeValues && !item.sensitive) item.value = scalar(safe(() => element.value(), null));
|
|
109
|
+
return item;
|
|
110
|
+
}
|
|
111
|
+
function dictValue(dict, key, fallback) { return safe(() => ObjC.unwrap(dict.objectForKey(key)), fallback); }
|
|
112
|
+
function systemEventsRead(operation) {
|
|
113
|
+
try { return operation(); }
|
|
114
|
+
catch (error) {
|
|
115
|
+
if (Number(error && error.errorNumber) === -1743) {
|
|
116
|
+
throw new Error('macOS Automation permission to control System Events is required');
|
|
117
|
+
}
|
|
118
|
+
throw error;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function applicationProcessExists(process) {
|
|
122
|
+
return Boolean(systemEventsRead(() => process.exists()));
|
|
123
|
+
}
|
|
124
|
+
function applicationProcessId(process) {
|
|
125
|
+
const processId = systemEventsRead(() => process.unixId());
|
|
126
|
+
if (typeof processId !== 'number' || !Number.isSafeInteger(processId) || processId < 1) throw new Error('application process pid is unavailable');
|
|
127
|
+
return processId;
|
|
128
|
+
}
|
|
129
|
+
function frontWindowForProcess(process) {
|
|
130
|
+
const windows = safe(() => process.windows(), []);
|
|
131
|
+
const count = Math.min(32, Number(windows.length) || 0);
|
|
132
|
+
for (let index = 0; index < count; index += 1) {
|
|
133
|
+
const window = windows[index];
|
|
134
|
+
const bounds = screenBox(window);
|
|
135
|
+
if (bounds && bounds.width > 0 && bounds.height > 0) {
|
|
136
|
+
return { bounds, title: String(safe(() => window.title(), '') || '') };
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
function cgWindowCandidate(info, pid) {
|
|
142
|
+
const ownerPid = Number(dictValue(info, 'kCGWindowOwnerPID', 0));
|
|
143
|
+
const layer = Number(dictValue(info, 'kCGWindowLayer', -1));
|
|
144
|
+
const alpha = Number(dictValue(info, 'kCGWindowAlpha', 1));
|
|
145
|
+
if (ownerPid !== pid || layer !== 0 || !(alpha > 0)) return null;
|
|
146
|
+
const boundsDict = safe(() => info.objectForKey('kCGWindowBounds'), null);
|
|
147
|
+
if (!boundsDict) return null;
|
|
148
|
+
const bounds = {
|
|
149
|
+
x: Number(dictValue(boundsDict, 'X', 0)),
|
|
150
|
+
y: Number(dictValue(boundsDict, 'Y', 0)),
|
|
151
|
+
width: Number(dictValue(boundsDict, 'Width', 0)),
|
|
152
|
+
height: Number(dictValue(boundsDict, 'Height', 0))
|
|
153
|
+
};
|
|
154
|
+
const windowId = Number(dictValue(info, 'kCGWindowNumber', 0));
|
|
155
|
+
if (!Number.isInteger(windowId) || windowId < 1 || !(bounds.width > 0) || !(bounds.height > 0)) return null;
|
|
156
|
+
return { window_id: windowId, bounds, title: String(dictValue(info, 'kCGWindowName', '') || '') };
|
|
157
|
+
}
|
|
158
|
+
function cgWindowsForProcess(pid) {
|
|
159
|
+
const raw = $.CGWindowListCopyWindowInfo($.kCGWindowListOptionOnScreenOnly, $.kCGNullWindowID);
|
|
160
|
+
const count = Math.min(4096, Number($.CFArrayGetCount(raw)) || 0);
|
|
161
|
+
const candidates = [];
|
|
162
|
+
for (let index = 0; index < count; index += 1) {
|
|
163
|
+
const info = ObjC.castRefToObject($.CFArrayGetValueAtIndex(raw, index));
|
|
164
|
+
const candidate = cgWindowCandidate(info, pid);
|
|
165
|
+
if (candidate) candidates.push(candidate);
|
|
166
|
+
}
|
|
167
|
+
return candidates;
|
|
168
|
+
}
|
|
169
|
+
function nearNumber(a, b, tolerance) {
|
|
170
|
+
return typeof a === 'number' && Number.isFinite(a)
|
|
171
|
+
&& typeof b === 'number' && Number.isFinite(b)
|
|
172
|
+
&& Math.abs(a - b) <= tolerance;
|
|
173
|
+
}
|
|
174
|
+
function sameWindowBounds(left, right) {
|
|
175
|
+
return left && right && nearNumber(left.x, right.x, 1) && nearNumber(left.y, right.y, 1) && nearNumber(left.width, right.width, 1) && nearNumber(left.height, right.height, 1);
|
|
176
|
+
}
|
|
177
|
+
function childrenOf(element) { return safe(() => element.uiElements(), []); }
|
|
178
|
+
function flatten(root, maxDepth, maxElements, includeValues, includeMenus, includeGeometry) {
|
|
179
|
+
const output = [];
|
|
180
|
+
const elements = [];
|
|
181
|
+
const stack = [{ element: root, depth: 0, windowBox: null }];
|
|
182
|
+
while (stack.length && output.length < maxElements) {
|
|
183
|
+
const current = stack.pop();
|
|
184
|
+
const children = childrenOf(current.element);
|
|
185
|
+
for (let i = children.length - 1; i >= 0; i--) {
|
|
186
|
+
const child = children[i];
|
|
187
|
+
const item = describe(child, output.length, includeValues, includeGeometry);
|
|
188
|
+
const ownerWindowBox = item.role === 'AXWindow' ? screenBox(child) : current.windowBox;
|
|
189
|
+
if (includeGeometry) item.window_screen_box = ownerWindowBox;
|
|
190
|
+
elements.push(child);
|
|
191
|
+
output.push(item);
|
|
192
|
+
if (output.length >= maxElements) break;
|
|
193
|
+
const isMenuTree = typeof item.role === 'string' && item.role.startsWith('AXMenu');
|
|
194
|
+
if (current.depth + 1 < maxDepth && (includeMenus || !isMenuTree)) {
|
|
195
|
+
stack.push({ element: child, depth: current.depth + 1, windowBox: ownerWindowBox });
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return { output, elements, truncated: stack.length > 0 || output.length >= maxElements };
|
|
200
|
+
}
|
|
201
|
+
function matches(item, selector) {
|
|
202
|
+
for (const key of ['role','subrole','name','title','description','identifier']) {
|
|
203
|
+
if (selector[key] === undefined) continue;
|
|
204
|
+
if (typeof selector[key] !== 'string' || typeof item[key] !== 'string' || item[key].toLowerCase() !== selector[key].toLowerCase()) return false;
|
|
205
|
+
}
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
let mutationStarted = false;
|
|
209
|
+
function main() {
|
|
210
|
+
const payload = readPayload();
|
|
211
|
+
const se = Application('System Events');
|
|
212
|
+
const process = se.applicationProcesses.byName(payload.application);
|
|
213
|
+
if (!applicationProcessExists(process)) throw new Error('application process not found or Accessibility access denied');
|
|
214
|
+
const processId = applicationProcessId(process);
|
|
215
|
+
const expectedProcessId = payload.expectedProcessId;
|
|
216
|
+
if (expectedProcessId !== null && expectedProcessId !== undefined) {
|
|
217
|
+
if (typeof expectedProcessId !== 'number' || !Number.isInteger(expectedProcessId) || expectedProcessId < 1) throw new Error('expected process id is invalid');
|
|
218
|
+
if (processId !== expectedProcessId) throw new Error('application process changed before operation');
|
|
219
|
+
}
|
|
220
|
+
const processInstance = processInstanceForPayload(payload, processId);
|
|
221
|
+
const processGeneration = processGenerationForPayload(payload, processId, processInstance);
|
|
222
|
+
if (payload.operation === 'window_candidates') {
|
|
223
|
+
const front = frontWindowForProcess(process);
|
|
224
|
+
const result = { process_id: processId, front_bounds: front ? front.bounds : null, front_title: front ? front.title : '', candidates: cgWindowsForProcess(processId).slice(0, 32) };
|
|
225
|
+
assertProcessInstance(processInstance, processId, processGeneration);
|
|
226
|
+
if (processGeneration) result.process_generation = processGeneration;
|
|
227
|
+
return result;
|
|
228
|
+
}
|
|
229
|
+
if (payload.operation === 'inspect') {
|
|
230
|
+
const flattened = flatten(process, payload.maxDepth, payload.maxElements, payload.includeValues === true, payload.includeMenus === true, payload.includeGeometry === true);
|
|
231
|
+
const result = { process_id: processId, frontmost: safe(() => process.frontmost(), false), elements: flattened.output, truncated: flattened.truncated, menus_included: payload.includeMenus === true };
|
|
232
|
+
if (payload.includeWindowState === true) {
|
|
233
|
+
const front = frontWindowForProcess(process);
|
|
234
|
+
result.window_state = {
|
|
235
|
+
process_id: processId,
|
|
236
|
+
front_bounds: front ? front.bounds : null,
|
|
237
|
+
front_title: front ? front.title : '',
|
|
238
|
+
candidates: cgWindowsForProcess(processId).slice(0, 32),
|
|
239
|
+
};
|
|
240
|
+
if (processGeneration) result.window_state.process_generation = processGeneration;
|
|
241
|
+
}
|
|
242
|
+
assertProcessInstance(processInstance, processId, processGeneration);
|
|
243
|
+
if (processGeneration) result.process_generation = processGeneration;
|
|
244
|
+
return result;
|
|
245
|
+
}
|
|
246
|
+
if (payload.operation === 'verify_value') {
|
|
247
|
+
const requireGeometry = Boolean(payload.expectedWindowBounds || payload.expectedElementBounds);
|
|
248
|
+
const flattened = flatten(process, payload.maxDepth, payload.maxElements, false, payload.includeMenus === true, requireGeometry);
|
|
249
|
+
const matchesList = [];
|
|
250
|
+
for (let i = 0; i < flattened.output.length; i++) if (matches(flattened.output[i], payload.selector)) matchesList.push(i);
|
|
251
|
+
const chosen = payload.selector.index !== undefined ? matchesList[payload.selector.index] : matchesList[0];
|
|
252
|
+
if (chosen === undefined || chosen < 0 || chosen >= flattened.elements.length) throw new Error('no UI element matched selector during value verification');
|
|
253
|
+
const chosenItem = flattened.output[chosen];
|
|
254
|
+
if (payload.expectedWindowBounds && !sameWindowBounds(chosenItem.window_screen_box, payload.expectedWindowBounds)) {
|
|
255
|
+
throw new Error('application verification target window changed after post observation');
|
|
256
|
+
}
|
|
257
|
+
if (payload.expectedElementBounds && !sameWindowBounds(chosenItem.screen_box, payload.expectedElementBounds)) {
|
|
258
|
+
throw new Error('application verification target geometry changed after post observation');
|
|
259
|
+
}
|
|
260
|
+
assertProcessInstance(processInstance, processId, processGeneration);
|
|
261
|
+
if (chosenItem.sensitive === true) return { supported: false, matched: false, matched_count: matchesList.length, selected_index: chosen, reason: 'sensitive_target' };
|
|
262
|
+
const actual = safe(() => flattened.elements[chosen].value(), null);
|
|
263
|
+
assertProcessInstance(processInstance, processId, processGeneration);
|
|
264
|
+
if (typeof actual !== 'string') return { supported: false, matched: false, matched_count: matchesList.length, selected_index: chosen, reason: 'value_type_unavailable' };
|
|
265
|
+
if (typeof payload.value !== 'string') throw new Error('application verification value is invalid');
|
|
266
|
+
return { supported: true, matched: actual === payload.value, matched_count: matchesList.length, selected_index: chosen, reason: 'compared' };
|
|
267
|
+
}
|
|
268
|
+
if (payload.action === 'activate') {
|
|
269
|
+
assertProcessInstance(processInstance, processId, processGeneration);
|
|
270
|
+
try { mutationStarted = true; process.frontmost = true; }
|
|
271
|
+
catch (_) { throw new Error('application activation may have been partially dispatched; the action outcome is unknown. Inspect the application before retrying.'); }
|
|
272
|
+
assertProcessInstance(processInstance, processId, processGeneration);
|
|
273
|
+
return { ok: true, matched: 1 };
|
|
274
|
+
}
|
|
275
|
+
const requireGeometry = Boolean(payload.expectedWindowBounds || payload.expectedElementBounds);
|
|
276
|
+
const flattened = flatten(process, payload.maxDepth, payload.maxElements, false, payload.includeMenus === true, requireGeometry);
|
|
277
|
+
const matchesList = [];
|
|
278
|
+
for (let i = 0; i < flattened.output.length; i++) if (matches(flattened.output[i], payload.selector)) matchesList.push(i);
|
|
279
|
+
const chosen = payload.selector.index !== undefined ? matchesList[payload.selector.index] : matchesList[0];
|
|
280
|
+
if (chosen === undefined || chosen < 0 || chosen >= flattened.elements.length) throw new Error('no UI element matched selector');
|
|
281
|
+
const chosenItem = flattened.output[chosen];
|
|
282
|
+
if (payload.expectedWindowBounds && !sameWindowBounds(chosenItem.window_screen_box, payload.expectedWindowBounds)) {
|
|
283
|
+
throw new Error('application target window changed before dispatch');
|
|
284
|
+
}
|
|
285
|
+
if (payload.expectedElementBounds && !sameWindowBounds(chosenItem.screen_box, payload.expectedElementBounds)) {
|
|
286
|
+
throw new Error('application target geometry changed before dispatch');
|
|
287
|
+
}
|
|
288
|
+
const element = flattened.elements[chosen];
|
|
289
|
+
assertProcessInstance(processInstance, processId, processGeneration);
|
|
290
|
+
if (payload.action === 'check' || payload.action === 'uncheck') {
|
|
291
|
+
const desired = payload.action === 'check';
|
|
292
|
+
const role = typeof chosenItem.role === 'string' ? chosenItem.role : '';
|
|
293
|
+
if (role !== 'AXCheckBox' && !(payload.action === 'check' && role === 'AXRadioButton')) {
|
|
294
|
+
throw new Error(payload.action === 'check'
|
|
295
|
+
? 'application check target is not an Accessibility checkbox or radio button'
|
|
296
|
+
: 'application uncheck target is not an Accessibility checkbox');
|
|
297
|
+
}
|
|
298
|
+
if (typeof chosenItem.checked !== 'boolean') throw new Error('application target checked state is unavailable before dispatch');
|
|
299
|
+
const checkedBefore = chosenItem.checked;
|
|
300
|
+
if (checkedBefore === desired) {
|
|
301
|
+
assertProcessInstance(processInstance, processId, processGeneration);
|
|
302
|
+
return { ok: true, matched: matchesList.length, selected_index: chosen, no_input_required: true, checked_before: checkedBefore, checked_after: checkedBefore, element: describe(element, chosen, false, false) };
|
|
303
|
+
}
|
|
304
|
+
const press = safe(() => element.actions.byName('AXPress'), null);
|
|
305
|
+
if (!press || !safe(() => press.exists(), false)) throw new Error('application target does not expose AXPress before checked-state dispatch');
|
|
306
|
+
assertProcessInstance(processInstance, processId, processGeneration);
|
|
307
|
+
try { mutationStarted = true; press.perform(); }
|
|
308
|
+
catch (_) { throw new Error('application checked-state input may have been partially dispatched; the action outcome is unknown. Inspect the application before retrying.'); }
|
|
309
|
+
const after = describe(element, chosen, false, false);
|
|
310
|
+
assertProcessInstance(processInstance, processId, processGeneration);
|
|
311
|
+
return { ok: true, matched: matchesList.length, selected_index: chosen, no_input_required: false, checked_before: checkedBefore, checked_after: after.checked, element: after };
|
|
312
|
+
}
|
|
313
|
+
if (payload.action === 'click' || payload.action === 'press') {
|
|
314
|
+
const action = safe(() => element.actions.byName('AXPress'), null);
|
|
315
|
+
assertProcessInstance(processInstance, processId, processGeneration);
|
|
316
|
+
try {
|
|
317
|
+
mutationStarted = true;
|
|
318
|
+
if (action && safe(() => action.exists(), false)) action.perform();
|
|
319
|
+
else element.click();
|
|
320
|
+
} catch (_) {
|
|
321
|
+
throw new Error('application Accessibility input may have been partially dispatched; the action outcome is unknown. Inspect the application before retrying.');
|
|
322
|
+
}
|
|
323
|
+
} else if (payload.action === 'set_value') {
|
|
324
|
+
if (payload.value === null) throw new Error('set_value requires value or value_resource');
|
|
325
|
+
assertProcessInstance(processInstance, processId, processGeneration);
|
|
326
|
+
try { mutationStarted = true; element.value = payload.value; }
|
|
327
|
+
catch (_) { throw new Error('application value input may have been partially dispatched; the action outcome is unknown. Inspect the application before retrying.'); }
|
|
328
|
+
} else if (payload.action === 'focus') {
|
|
329
|
+
assertProcessInstance(processInstance, processId, processGeneration);
|
|
330
|
+
try { mutationStarted = true; element.focused = true; }
|
|
331
|
+
catch (_) { throw new Error('application Accessibility input may have been partially dispatched; the action outcome is unknown. Inspect the application before retrying.'); }
|
|
332
|
+
} else {
|
|
333
|
+
throw new Error('unsupported action');
|
|
334
|
+
}
|
|
335
|
+
const result = { ok: true, matched: matchesList.length, selected_index: chosen, element: describe(element, chosen, false, false) };
|
|
336
|
+
if (payload.includeProcessGeneration === true) {
|
|
337
|
+
result.process_id = processId;
|
|
338
|
+
if (processGeneration) result.process_generation = processGeneration;
|
|
339
|
+
}
|
|
340
|
+
assertProcessInstance(processInstance, processId, processGeneration);
|
|
341
|
+
return result;
|
|
342
|
+
}
|
|
343
|
+
(() => { try { return JSON.stringify(main()); } catch (error) {
|
|
344
|
+
const message = String(error.message || error);
|
|
345
|
+
const safeMessage = mutationStarted
|
|
346
|
+
? 'application Accessibility mutation may have been partially dispatched; the action outcome is unknown. Inspect the application before retrying.'
|
|
347
|
+
: message;
|
|
348
|
+
return JSON.stringify({ error: safeMessage });
|
|
349
|
+
} })()
|
|
350
|
+
`;
|