@moretea-labs/forge 1.8.0 → 1.8.1
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/AGENTS.md +70 -7
- package/CHANGELOG.md +14 -0
- package/CLAUDE.md +17 -2
- package/CONTRIBUTING.md +3 -2
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/adapters/chatgpt/browser-delivery-host.ts +7 -1
- package/adapters/chatgpt/browser-delivery-runtime.ts +529 -56
- package/adapters/chatgpt/controller-binding-store.ts +101 -22
- package/adapters/chatgpt/controller-round-host.ts +15 -25
- package/adapters/chatgpt/controller-round-settlement-store.ts +58 -4
- package/adapters/chatgpt/provider-delivery.ts +228 -1
- package/adapters/chatgpt/work-conversation-binding-store.ts +79 -53
- package/adapters/computer/chatgpt-extension-target.ts +463 -0
- package/adapters/computer/chatgpt-target-router.ts +103 -0
- package/adapters/computer/chrome-extension/background.js +385 -0
- package/adapters/computer/chrome-extension/content.js +378 -0
- package/adapters/computer/chrome-extension/core.js +24 -0
- package/adapters/computer/chrome-extension/manifest.json +30 -0
- package/adapters/computer/desktop-operator-discovery.ts +11 -31
- package/adapters/computer/interaction-target-authority.ts +142 -18
- package/adapters/mcp/auth.ts +0 -1
- package/adapters/mcp/instructions.ts +5 -4
- package/adapters/mcp/multi-repository.ts +3 -19
- package/adapters/mcp/oauth.ts +73 -0
- package/adapters/mcp/paths.ts +4 -1
- package/adapters/mcp/runtime-gateway/automation-receipt-adapter.ts +87 -0
- package/adapters/mcp/runtime-gateway/bounded-result-runtime.ts +62 -0
- package/adapters/mcp/runtime-gateway/cognition-settlement.ts +201 -0
- package/adapters/mcp/runtime-gateway/context-adapter.ts +411 -73
- package/adapters/mcp/runtime-gateway/context-pack-sidecar.ts +91 -0
- package/adapters/mcp/runtime-gateway/controller-authority-adapter.ts +20 -5
- package/adapters/mcp/runtime-gateway/core-capability-adapter.ts +258 -0
- package/adapters/mcp/runtime-gateway/engineering-preconditions.ts +10 -27
- package/adapters/mcp/runtime-gateway/engineering-tool-contract.ts +15 -0
- package/adapters/mcp/runtime-gateway/execution-tools.ts +8 -42
- package/adapters/mcp/runtime-gateway/gateway-execution-adapter.ts +2 -1
- package/adapters/mcp/runtime-gateway/plugin-adapter.ts +117 -45
- package/adapters/mcp/runtime-gateway/process-tools.ts +190 -22
- package/adapters/mcp/runtime-gateway/protected-computer-adapter.ts +16 -4
- package/adapters/mcp/runtime-gateway/recovery-adapter.ts +69 -52
- package/adapters/mcp/runtime-gateway/repository-compat-adapter.ts +4 -35
- package/adapters/mcp/runtime-gateway/result-adapter.ts +10 -4
- package/adapters/mcp/runtime-gateway/router.ts +18 -504
- package/adapters/mcp/runtime-gateway/routing-policy.ts +499 -0
- package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +14 -65
- package/adapters/mcp/runtime-gateway/runtime-readiness-observation.ts +218 -0
- package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +113 -173
- package/adapters/mcp/runtime-gateway/runtime-tools.ts +15 -5
- package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +1 -0
- package/adapters/mcp/runtime-gateway/shared-adapter.ts +20 -0
- package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +358 -266
- package/adapters/mcp/runtime-gateway/typescript-navigation-sidecar.ts +136 -0
- package/adapters/mcp/runtime-gateway/work-adapter.ts +261 -3122
- package/adapters/mcp/runtime-gateway/work-controller-operations.ts +257 -0
- package/adapters/mcp/runtime-gateway/work-detail-projection.ts +60 -0
- package/adapters/mcp/runtime-gateway/work-input-wire-migration.ts +246 -0
- package/adapters/mcp/runtime-gateway/work-learning-operations.ts +145 -0
- package/adapters/mcp/runtime-gateway/work-list-projection.ts +38 -0
- package/adapters/mcp/runtime-gateway/work-plan-operations.ts +382 -0
- package/adapters/mcp/runtime-gateway/work-repair-adapter.ts +308 -0
- package/adapters/mcp/runtime-gateway/work-requirement-operations.ts +148 -0
- package/adapters/mcp/runtime-gateway/work-semantic-operations.ts +263 -0
- package/adapters/mcp/runtime-gateway/work-workflow-operations.ts +113 -0
- package/adapters/mcp/runtime-gateway/workflow-supervisor-adapter.ts +156 -0
- package/adapters/mcp/server.ts +67 -23
- package/adapters/mcp/setup.ts +1 -3
- package/adapters/mcp/tool-mapping/legacy-tool-service.ts +44 -170
- package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +4 -9
- package/adapters/mcp/tool-mapping/repository-tools.ts +133 -142
- package/adapters/mcp/toolset-names.ts +5 -0
- package/adapters/mcp/toolset.ts +6 -5
- package/adapters/mcp/transports/http-observation.ts +365 -0
- package/adapters/mcp/transports/http.ts +154 -677
- package/adapters/mcp/transports/oauth-http.ts +322 -0
- package/adapters/mcp/transports/session-registry.ts +6 -0
- package/adapters/mcp/tunnels/openai-secure-tunnel.ts +89 -5
- package/assets/plugin-registry.v1.json +6 -4
- package/assets/reference-configs/agentic-development-flow.md +25 -0
- package/assets/reference-configs/global-working-rules.md +19 -0
- package/assets/skill-version.json +2 -2
- package/docs/architecture/CURRENT.md +111 -41
- package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +14 -5
- package/docs/architecture/decisions/20260823-immediate-controller-relay.md +6 -3
- package/docs/architecture/decisions/20260907-assistant-learning-loop.md +2 -0
- package/docs/architecture/decisions/20260907-controller-round-transition-policy.md +19 -4
- package/docs/architecture/decisions/20260916-workflow-supervisor-authority.md +249 -0
- package/docs/architecture/decisions/20260917-cognitive-memory-foundation.md +82 -0
- package/docs/architecture/decisions/20260918-stable-candidate-release-lifecycle.md +221 -0
- package/docs/architecture/decisions/20260919-autonomous-work-liveness.md +62 -0
- package/docs/architecture/decisions/20260924-thin-semantic-working-context.md +72 -0
- package/docs/architecture/decisions/20261001-supervisor-turn-authority.md +237 -0
- package/docs/architecture/decisions/20261005-forge-v3-desktop-client-boundary.md +77 -0
- package/docs/architecture/domains/verification.md +1 -0
- package/docs/architecture/domains/workflow-engine.md +6 -0
- package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +1 -1
- package/docs/forge-plugin-management.md +2 -2
- package/docs/operations/controller-performance-and-502.md +17 -0
- package/docs/operations/controller-reliability-runbook.md +2 -2
- package/docs/operations/features.md +1 -1
- package/docs/operations/features.zh-CN.md +1 -1
- package/docs/operations/homebrew.md +2 -2
- package/docs/operations/mcp-tool-exposure.md +2 -0
- package/docs/operations/releasing.md +2 -0
- package/docs/operations/standalone-disaster-recovery.md +14 -6
- package/docs/wiki/Implementation.md +1 -1
- package/package.json +25 -14
- package/packages/kernel/cognition/api/index.ts +6 -0
- package/packages/kernel/cognition/application/activation-service.ts +451 -0
- package/packages/kernel/cognition/application/consolidation-service.ts +185 -0
- package/packages/kernel/cognition/application/legacy-experience-adapter.ts +38 -0
- package/packages/kernel/cognition/application/memory-service.ts +64 -0
- package/packages/kernel/cognition/domain/learning.ts +106 -0
- package/packages/kernel/cognition/domain/memory.ts +254 -0
- package/packages/kernel/controller/api/index.ts +1 -0
- package/packages/kernel/controller/application/continuation-service.ts +281 -0
- package/packages/kernel/controller/application/controller-round-service.ts +12 -0
- package/packages/kernel/controller/domain/controller-round-transition-policy.ts +242 -21
- package/packages/kernel/controller/domain/controller-round.ts +4 -1
- package/packages/kernel/controller/domain/execution-quality.ts +3 -1
- package/packages/kernel/controller/infrastructure/controller-round-store.ts +689 -103
- package/packages/kernel/controller/infrastructure/controller-session-store.ts +297 -71
- package/packages/kernel/controller/ports/controller-host.ts +2 -0
- package/packages/kernel/identity/api/index.ts +10 -0
- package/packages/kernel/identity/domain/activity-projection.ts +43 -0
- package/packages/kernel/identity/domain/capability-broker.ts +60 -0
- package/packages/kernel/identity/domain/grant.ts +72 -0
- package/packages/kernel/identity/domain/owned-resource.ts +116 -0
- package/packages/kernel/identity/domain/user-request.ts +93 -0
- package/packages/kernel/identity/infrastructure/activity-projection-store.ts +77 -0
- package/packages/kernel/identity/infrastructure/capability-broker.ts +81 -0
- package/packages/kernel/identity/infrastructure/grant-store.ts +284 -0
- package/packages/kernel/identity/infrastructure/owned-resource-store.ts +259 -0
- package/packages/kernel/identity/infrastructure/user-request-store.ts +182 -0
- package/packages/kernel/scheduler/api/index.ts +0 -2
- package/packages/kernel/scheduler/application/schedule-service.ts +3 -0
- package/packages/kernel/scheduler/application/settlement.ts +0 -15
- package/packages/kernel/scheduler/domain/schedule.ts +87 -0
- package/packages/kernel/scheduler/infrastructure/schedule-store.ts +153 -133
- package/packages/kernel/work/api/index.ts +3 -2
- package/packages/kernel/work/application/work-service.ts +17 -42
- package/packages/kernel/work/domain/current-task-lineage.ts +104 -0
- package/packages/kernel/work/domain/engineering-design.ts +10 -5
- package/packages/kernel/work/domain/engineering-profile.ts +8 -12
- package/packages/kernel/work/domain/evaluation-promotion-receipt.ts +186 -0
- package/packages/kernel/work/domain/execution-concurrency.ts +19 -26
- package/packages/kernel/work/domain/execution-snapshot.ts +0 -31
- package/packages/kernel/work/domain/implementation-review.ts +14 -331
- package/packages/kernel/work/domain/objective-graph.ts +119 -0
- package/packages/kernel/work/domain/project-engineering-contract.ts +23 -1
- package/packages/kernel/work/domain/repository-completion-receipt.ts +1 -1
- package/packages/kernel/work/domain/state-machine.ts +25 -63
- package/packages/kernel/work/domain/types.ts +57 -51
- package/packages/kernel/work/infrastructure/work-contract-store.ts +819 -728
- package/packages/kernel/work/ports/work-contract-store.ts +5 -2
- package/packages/plugin-runtime/browser/session-authority.ts +2 -1
- package/packages/plugin-runtime/computer/chatgpt-identity.ts +24 -0
- package/packages/plugin-runtime/computer/conversation-target.ts +143 -0
- package/packages/plugin-runtime/computer/index.ts +2 -0
- package/packages/plugin-runtime/computer/target-authority.ts +26 -1
- package/packages/plugin-runtime/external/unix-jsonl-transport.ts +142 -18
- package/packages/protocols/computer/contract.ts +27 -1
- package/scripts/activate-source-baseline.ts +7 -9
- package/scripts/canary-controller-semantic-wait.ts +12 -24
- package/scripts/check-mcp-compatibility.ts +48 -136
- package/scripts/check-runtime-architecture.mjs +622 -217
- package/scripts/forge-local-recovery-helper.mjs +93 -15
- package/scripts/lib/project-init-lib.sh +3 -0
- package/scripts/open-source-audit-allowlist.txt +1 -2
- package/scripts/run-bounded-command.mjs +5 -0
- package/scripts/run-governed-gate.ts +0 -1
- package/scripts/run-mobile-monitor-bridge.ts +0 -1
- package/scripts/smoke-control-plane-failure-domain.ts +94 -0
- package/scripts/smoke-mcp-http-runtime.ts +5 -0
- package/scripts/smoke-runtime-recovery.ts +12 -43
- package/scripts/smoke-schedule-engine.ts +23 -15
- package/scripts/smoke-unattended-transport-recovery.ts +223 -0
- package/scripts/smoke-user-request-continuation-restart.ts +232 -0
- package/scripts/smoke-workflow-supervisor-chrome-adapter.ts +92 -0
- package/scripts/smoke-workflow-supervisor-process-restart.ts +276 -0
- package/scripts/smoke-workflow-supervisor-restart-recovery.ts +150 -0
- package/scripts/smoke-workflow-supervisor.ts +103 -0
- package/scripts/verify-forge-runtime.sh +2 -1
- package/src/cli/agent-jobs/executor-health.ts +11 -34
- package/src/cli/agent-jobs/integration.ts +18 -49
- package/src/cli/agent-jobs/job-manager.ts +7 -3
- package/src/cli/commands/brain-assistant.ts +27 -13
- package/src/cli/commands/brain.ts +13 -15
- package/src/cli/commands/chatgpt.ts +1 -163
- package/src/cli/commands/recovery.ts +135 -121
- package/src/cli/commands/runtime.ts +3 -3
- package/src/cli/commands/setup-profile.ts +8 -0
- package/src/cli/controller/check-runner.ts +13 -2
- package/src/cli/controller/completion-backlog.ts +3 -3
- package/src/cli/controller/completion-orchestrator.ts +4 -43
- package/src/cli/controller/completion-target.ts +3 -72
- package/src/cli/controller/context/source-materializer.ts +81 -100
- package/src/cli/controller/context-pack.ts +10 -8
- package/src/cli/controller/execution-completion.ts +4 -7
- package/src/cli/controller/execution-policy.ts +36 -153
- package/src/cli/controller/governance.ts +2 -3
- package/src/cli/controller/issue-store.ts +4 -99
- package/src/cli/controller/launch-agents.ts +59 -18
- package/src/cli/controller/operational-plan.ts +24 -51
- package/src/cli/controller/runtime-config.ts +5 -1
- package/src/cli/controller/stuck-state-migration.ts +2 -3
- package/src/cli/controller/systemd-user.ts +39 -1
- package/src/cli/editing/edit-session.ts +1 -7
- package/src/cli/local-bridge/console-automations.ts +18 -13
- package/src/cli/local-bridge/console-view-models.ts +3 -12
- package/src/cli/local-bridge/facade-api.ts +64 -191
- package/src/cli/local-bridge/server.ts +24 -147
- package/src/cli/local-bridge/types.ts +0 -1
- package/src/cli/mcp/oauth-client-retirement.ts +74 -0
- package/src/cli/repositories/command-executor.ts +29 -23
- package/src/cli/repositories/command-scope.ts +35 -16
- package/src/cli/repositories/controller-home.ts +48 -0
- package/src/cli/repositories/ephemeral-workspace.ts +20 -30
- package/src/cli/repositories/git-command-executor.ts +2 -2
- package/src/cli/repositories/registry.ts +77 -11
- package/src/cli/repositories/structured-git.ts +62 -2
- package/src/cli/repository/session-cache.ts +92 -6
- package/src/runtime/context/assistant-context.ts +20 -7
- package/src/runtime/context/assistant-work-context.ts +89 -27
- package/src/runtime/context/automatic-learning.ts +565 -0
- package/src/runtime/context/cognitive-attention.ts +173 -0
- package/src/runtime/context/cognitive-skill-canary.ts +158 -0
- package/src/runtime/context/context-closure.ts +46 -9
- package/src/runtime/context/context-pack-process.ts +103 -0
- package/src/runtime/context/context-plane.ts +1 -9
- package/src/runtime/context/direct-controller-learning.ts +298 -0
- package/src/runtime/context/semantic-navigation-contract.ts +9 -0
- package/src/runtime/context/semantic-navigation.ts +6 -34
- package/src/runtime/context/typescript-navigation-process.ts +145 -0
- package/src/runtime/context/typescript-navigation.ts +89 -3
- package/src/runtime/control-plane/cleanup-artifact-retention.ts +212 -9
- package/src/runtime/control-plane/concurrency/work-execution-concurrency.ts +9 -47
- package/src/runtime/control-plane/execution/controller-authority-recovery.ts +34 -4
- package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +29 -20
- package/src/runtime/control-plane/execution/execution-identity.ts +23 -3
- package/src/runtime/control-plane/execution/repository-work-attribution.ts +7 -30
- package/src/runtime/control-plane/execution/retained-work-resume.ts +206 -199
- package/src/runtime/control-plane/execution/session-store.ts +31 -1
- package/src/runtime/control-plane/execution/validation.ts +6 -8
- package/src/runtime/control-plane/execution/work-authority-reconciler.ts +13 -42
- package/src/runtime/control-plane/execution/work-check-evidence.ts +137 -0
- package/src/runtime/control-plane/execution/work-completion-authority.ts +30 -85
- package/src/runtime/control-plane/execution/work-delivery-service.ts +497 -0
- package/src/runtime/control-plane/execution/work-evidence-policy.ts +12 -50
- package/src/runtime/control-plane/execution/work-execution-support.ts +50 -149
- package/src/runtime/control-plane/execution/work-handle-authority.ts +188 -109
- package/src/runtime/control-plane/execution/work-handle-store.ts +19 -43
- package/src/runtime/control-plane/execution/work-head-settlement.ts +53 -20
- package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +52 -29
- package/src/runtime/control-plane/execution/work-operation-service.ts +43 -27
- package/src/runtime/control-plane/execution/work-preparation-service.ts +126 -266
- package/src/runtime/control-plane/execution/work-remote-delivery.ts +2 -3
- package/src/runtime/control-plane/execution/work-revision-diff.ts +39 -0
- package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +173 -186
- package/src/runtime/control-plane/execution/work-validation-reconciler.ts +28 -84
- package/src/runtime/control-plane/execution/work-verification-service.ts +406 -50
- package/src/runtime/control-plane/execution/work-verification-snapshot.ts +5 -1
- package/src/runtime/control-plane/facade/capability-registry.ts +362 -37
- package/src/runtime/control-plane/facade/check-normalization.ts +3 -9
- package/src/runtime/control-plane/facade/codex-delegation.ts +10 -11
- package/src/runtime/control-plane/facade/controller-connection.ts +135 -0
- package/src/runtime/control-plane/facade/goal-workloop-access.ts +1 -20
- package/src/runtime/control-plane/facade/goal-workloop.ts +281 -1753
- package/src/runtime/control-plane/facade/handoff-inbox-application.ts +12 -25
- package/src/runtime/control-plane/facade/handoff-inbox-store.ts +256 -52
- package/src/runtime/control-plane/facade/index.ts +0 -1
- package/src/runtime/control-plane/facade/operation-digest.ts +12 -15
- package/src/runtime/control-plane/facade/plan-contract-store.ts +451 -991
- package/src/runtime/control-plane/facade/policy-gate.ts +0 -23
- package/src/runtime/control-plane/facade/repository-work-admission.ts +12 -22
- package/src/runtime/control-plane/facade/requirement-authority.ts +102 -199
- package/src/runtime/control-plane/facade/requirement-board.ts +3 -3
- package/src/runtime/control-plane/facade/rh-work-operation-contract.ts +51 -14
- package/src/runtime/control-plane/facade/self-healing-loop.ts +18 -53
- package/src/runtime/control-plane/facade/suggested-actions.ts +15 -18
- package/src/runtime/control-plane/facade/types.ts +49 -108
- package/src/runtime/control-plane/facade/work-continuation.ts +8 -8
- package/src/runtime/control-plane/generated-cache-retention.ts +97 -1
- package/src/runtime/control-plane/global-scheduler/autonomous-continuation.ts +248 -0
- package/src/runtime/control-plane/global-scheduler/durable-admission.ts +1 -1
- package/src/runtime/control-plane/global-scheduler/maintenance.ts +239 -112
- package/src/runtime/control-plane/global-scheduler/reconciliation.ts +2 -1
- package/src/runtime/control-plane/global-scheduler/scheduler.ts +66 -40
- package/src/runtime/control-plane/global-scheduler/wake-signal.ts +42 -2
- package/src/runtime/control-plane/governance/access-policy.ts +19 -2
- package/src/runtime/control-plane/governance/authorization.ts +20 -3
- package/src/runtime/control-plane/launcher/chatgpt-round-continuation.ts +63 -300
- package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +28 -300
- package/src/runtime/control-plane/launcher/local-conversation-controller.ts +238 -0
- package/src/runtime/control-plane/launcher/provider-mcp-bootstrap.ts +5 -2
- package/src/runtime/control-plane/launcher/thin-launcher.ts +96 -240
- package/src/runtime/control-plane/persistence/cognition-store.ts +820 -0
- package/src/runtime/control-plane/persistence/experience-store.ts +162 -29
- package/src/runtime/control-plane/persistence/requirement-store.ts +216 -74
- package/src/runtime/control-plane/persistence/sqlite-store.ts +113 -6
- package/src/runtime/control-plane/release-retention.ts +135 -47
- package/src/runtime/control-plane/repository-namespace-retention.ts +2 -2
- package/src/runtime/control-plane/runtime-cleanup.ts +290 -21
- package/src/runtime/control-plane/workspace/project-onboarding.ts +80 -0
- package/src/runtime/control-plane/workspace/semantic-sync-service.ts +19 -5
- package/src/runtime/control-plane/workspace/workspace-store.ts +169 -0
- package/src/runtime/diagnostics/incident-repair.ts +313 -146
- package/src/runtime/diagnostics/mcp-timing.ts +114 -0
- package/src/runtime/evidence/artifact-store.ts +158 -40
- package/src/runtime/evidence/evidence-store.ts +112 -8
- package/src/runtime/evidence/output-handle-index.ts +225 -0
- package/src/runtime/evidence/result-store.ts +158 -44
- package/src/runtime/execution/jobs/store.ts +3 -4
- package/src/runtime/execution/managed-workspace.ts +57 -0
- package/src/runtime/execution/process-runtime/check-facade.ts +1 -1
- package/src/runtime/execution/process-runtime/check-result-retention.ts +2 -2
- package/src/runtime/execution/process-runtime/check-result.ts +105 -1
- package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +18 -8
- package/src/runtime/execution/process-runtime/command-facade.ts +79 -27
- package/src/runtime/execution/process-runtime/gc.ts +15 -2
- package/src/runtime/execution/process-runtime/handle-index.ts +176 -0
- package/src/runtime/execution/process-runtime/host-command-lane.ts +139 -0
- package/src/runtime/execution/process-runtime/index.ts +3 -0
- package/src/runtime/execution/process-runtime/lightweight-managed.ts +251 -72
- package/src/runtime/execution/process-runtime/persisted-check.ts +3 -3
- package/src/runtime/execution/process-runtime/process-runner-entry.ts +47 -5
- package/src/runtime/execution/process-runtime/process-scope.ts +160 -0
- package/src/runtime/execution/process-runtime/resource-claims.ts +65 -61
- package/src/runtime/execution/process-runtime/runtime.ts +35 -2
- package/src/runtime/execution/process-runtime/store.ts +30 -2
- package/src/runtime/execution/process-runtime/types.ts +6 -1
- package/src/runtime/execution/workers/executor.ts +2 -6
- package/src/runtime/platform/service-inventory.ts +130 -0
- package/src/runtime/platform/service-manager.ts +8 -0
- package/src/runtime/plugins/action-application.ts +85 -28
- package/src/runtime/plugins/app-store-connect-adapter.ts +38 -14
- package/src/runtime/plugins/browser-adapter.ts +757 -34
- package/src/runtime/plugins/browser-automation-service.ts +23 -3
- package/src/runtime/plugins/browser-macos-bridge.ts +321 -29
- package/src/runtime/plugins/browser-manifest-surface.ts +45 -11
- package/src/runtime/plugins/browser-native-session-service.ts +63 -13
- package/src/runtime/plugins/browser-registration.ts +16 -0
- package/src/runtime/plugins/browser-runtime.ts +14 -1
- package/src/runtime/plugins/browser-session-authority.ts +2 -2
- package/src/runtime/plugins/browser-session-store.ts +46 -76
- package/src/runtime/plugins/capability-authorization-grants.ts +258 -62
- package/src/runtime/plugins/computer-chatgpt-browser-adapter-installer.ts +219 -0
- package/src/runtime/plugins/computer-chatgpt-macos-target.ts +891 -0
- package/src/runtime/plugins/computer-registration.ts +222 -11
- package/src/runtime/plugins/desktop-operator-external-policy.ts +36 -4
- package/src/runtime/plugins/desktop-operator-registration.ts +12 -4
- package/src/runtime/plugins/external-adapter.ts +42 -6
- package/src/runtime/plugins/external-registration.ts +21 -1
- package/src/runtime/plugins/gmail-adapter.ts +23 -2
- package/src/runtime/plugins/google-calendar-adapter.ts +2 -2
- package/src/runtime/plugins/google-shared.ts +14 -7
- package/src/runtime/plugins/google-tasks-adapter.ts +2 -2
- package/src/runtime/plugins/ios-adapter.ts +1 -1
- package/src/runtime/plugins/lightweight-action.ts +208 -2
- package/src/runtime/plugins/local-system-adapter.ts +12 -2
- package/src/runtime/plugins/managed-process-adapter.ts +12 -5
- package/src/runtime/plugins/plugin-action-sidecar.ts +17 -13
- package/src/runtime/plugins/plugin-management-adapter.ts +1 -1
- package/src/runtime/plugins/store.ts +602 -428
- package/src/runtime/plugins/types.ts +20 -0
- package/src/runtime/plugins/xiaohongshu-publish.ts +16 -0
- package/src/runtime/projections/invalidation.ts +7 -3
- package/src/runtime/projections/materialized-view.ts +80 -36
- package/src/runtime/recovery/actions.ts +3 -3
- package/src/runtime/recovery/capability-action-application.ts +46 -45
- package/src/runtime/recovery/lifecycle-inventory.ts +29 -29
- package/src/runtime/recovery/maintenance-executor.ts +374 -123
- package/src/runtime/recovery/store.ts +29 -11
- package/src/runtime/release/release-coordinator.ts +296 -0
- package/src/runtime/release/release-session.ts +716 -0
- package/src/runtime/release/release-state-migration.ts +25 -0
- package/src/runtime/resources/leases/store.ts +56 -25
- package/src/runtime/root/computer-composition.ts +191 -6
- package/src/runtime/root/controller-progression-composition.ts +192 -0
- package/src/runtime/root/controller-round-composition.ts +20 -1
- package/src/runtime/root/deployment-topology.ts +106 -0
- package/src/runtime/root/entry.ts +4 -3
- package/src/runtime/root/known-good-recovery.ts +184 -0
- package/src/runtime/root/local-bridge.ts +0 -1
- package/src/runtime/root/mcp-transport.ts +111 -18
- package/src/runtime/root/ownership.ts +261 -9
- package/src/runtime/root/package-connector-service.ts +105 -19
- package/src/runtime/root/package-runtime-release.ts +117 -18
- package/src/runtime/root/package-runtime-service.ts +17 -11
- package/src/runtime/root/release-execution-canary.ts +44 -12
- package/src/runtime/root/release-loader.ts +90 -8
- package/src/runtime/root/release-manifest.ts +80 -6
- package/src/runtime/root/release-materialize.ts +372 -28
- package/src/runtime/root/release-store.ts +395 -36
- package/src/runtime/root/runtime-lane.ts +191 -0
- package/src/runtime/root/runtime.ts +159 -27
- package/src/runtime/root/scheduled-controller-composition.ts +28 -3
- package/src/runtime/root/service-runner.ts +2 -2
- package/src/runtime/root/service.ts +36 -33
- package/src/runtime/root/status.ts +48 -0
- package/src/runtime/root/types.ts +32 -3
- package/src/runtime/root/workflow-supervisor-composition.ts +493 -0
- package/src/runtime/root/workflow-supervisor-runtime.ts +209 -0
- package/src/runtime/root/write-fence.ts +50 -2
- package/src/runtime/safe-tooling/google-credential-store.ts +76 -21
- package/src/runtime/safe-tooling/google-oauth-broker.ts +25 -7
- package/src/runtime/safe-tooling/workspace-auth.ts +1 -1
- package/src/runtime/shared/bounded-child-supervisor.ts +9 -1
- package/src/runtime/shared/process-environment.ts +20 -9
- package/src/runtime/shared/response-budget.ts +1 -3
- package/src/runtime/standalone-recovery/controller-home-migration.ts +16 -24
- package/src/runtime/standalone-recovery/core.ts +3702 -342
- package/src/runtime/standalone-recovery/entry.ts +469 -39
- package/src/runtime/standalone-recovery/installer.ts +262 -148
- package/src/runtime/standalone-recovery/mcp-server.ts +29 -193
- package/src/runtime/standalone-recovery/operation-lock.ts +1 -1
- package/src/runtime/standalone-recovery/performance.ts +54 -16
- package/src/runtime/standalone-recovery/release.ts +53 -5
- package/src/runtime/standalone-recovery/service-labels.ts +5 -2
- package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +5 -2
- package/src/runtime/workflow/schedules/browser-probe.ts +17 -6
- package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +10 -3
- package/src/runtime/workflow/schedules/engine.ts +138 -172
- package/src/runtime/workflow/schedules/work-continuation.ts +44 -5
- package/src/runtime/workflows/runtime.ts +15 -19
- package/src/testing/test-governance.ts +5 -1
- package/supervisor/chatgpt-conversation.ts +23 -0
- package/supervisor/client.ts +201 -0
- package/supervisor/control-plane.ts +868 -0
- package/supervisor/entry.ts +15 -0
- package/supervisor/forge-validators.ts +80 -0
- package/supervisor/index.ts +5 -0
- package/supervisor/native-browser-adapter.ts +786 -0
- package/supervisor/native-messaging/host.ts +39 -0
- package/supervisor/native-messaging/manifest.ts +26 -0
- package/supervisor/native-messaging/protocol.ts +27 -0
- package/supervisor/paths.ts +18 -0
- package/supervisor/protocol.ts +202 -0
- package/supervisor/server.ts +404 -0
- package/supervisor/store.ts +1451 -0
- package/supervisor/tsconfig.json +8 -0
- package/supervisor/types.ts +255 -0
- package/adapters/chatgpt/controller-host.ts +0 -119
- package/adapters/mcp/controller-round-compatibility.ts +0 -184
- package/adapters/mcp/frozen-client-semantic-compatibility.ts +0 -292
- package/adapters/mcp/runtime-gateway/work-compat-adapter.ts +0 -502
- package/packages/kernel/progression/api/index.ts +0 -2
- package/packages/kernel/progression/application/projector.ts +0 -211
- package/packages/kernel/progression/domain/types.ts +0 -116
- package/packages/kernel/progression/index.ts +0 -1
- package/packages/kernel/scheduler/application/continuation-service.ts +0 -212
- package/packages/kernel/scheduler/domain/continuation.ts +0 -38
- package/packages/kernel/scheduler/infrastructure/continuation-dispatch-store.ts +0 -38
- package/packages/kernel/work/domain/admission-policy.ts +0 -34
- package/scripts/benchmark-background-check-overlap.ts +0 -228
- package/scripts/benchmark-computer-hotpath.ts +0 -255
- package/scripts/benchmark-controller-hotpath.ts +0 -212
- package/scripts/benchmark-controller-round2.ts +0 -191
- package/scripts/benchmark-ios-agent-device.ts +0 -511
- package/scripts/benchmark-mcp-host.sh +0 -117
- package/scripts/benchmark-mcp-transport.ts +0 -169
- package/scripts/benchmark-operational-memory-activation.ts +0 -235
- package/scripts/benchmark-operational-shadow.ts +0 -28
- package/scripts/benchmark-quality-harness.ts +0 -146
- package/scripts/benchmark-route-session-concurrency.ts +0 -915
- package/scripts/benchmark-thin-harness-gateway-ab.ts +0 -632
- package/scripts/benchmark-thin-harness-mcp-e2e.ts +0 -498
- package/scripts/benchmark-thin-harness.ts +0 -251
- package/scripts/benchmark-typescript-navigation.ts +0 -186
- package/scripts/benchmark-work-efficiency.ts +0 -334
- package/scripts/build-controller-ui.ts +0 -28
- package/scripts/check-npm-release.sh +0 -32
- package/scripts/check-public-release-surface.sh +0 -19
- package/scripts/check-release-published.sh +0 -57
- package/scripts/check-release-readiness.sh +0 -37
- package/scripts/check-release-version.mjs +0 -74
- package/scripts/check-tarball-install-smoke.sh +0 -150
- package/scripts/package-source-archive.sh +0 -147
- package/scripts/public-release-files.txt +0 -39
- package/scripts/public-release.ts +0 -174
- package/scripts/publish-release-tarball.sh +0 -27
- package/scripts/route-nl-vs-ts-eval.ts +0 -679
- package/scripts/stage-runtime-release.ts +0 -44
- package/src/cli/controller/progress.ts +0 -656
- package/src/cli/controller/work-mode.ts +0 -181
- package/src/cli/local-bridge/console-assets.ts +0 -17
- package/src/cli/local-bridge/dashboard.ts +0 -17
- package/src/cli/local-bridge/frontend/src/App.tsx +0 -10
- package/src/cli/local-bridge/frontend/src/components/Button.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/components/DetailPane.tsx +0 -3
- package/src/cli/local-bridge/frontend/src/components/SearchField.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/components/SectionHeader.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/components/Segmented.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/components/StatusText.tsx +0 -3
- package/src/cli/local-bridge/frontend/src/design/icons.tsx +0 -11
- package/src/cli/local-bridge/frontend/src/design/tokens.css +0 -8
- package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +0 -153
- package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +0 -37
- package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +0 -183
- package/src/cli/local-bridge/frontend/src/features/repositories/RepositoriesView.tsx +0 -2
- package/src/cli/local-bridge/frontend/src/features/system/SystemView.tsx +0 -2
- package/src/cli/local-bridge/frontend/src/features/work/WorkView.tsx +0 -4
- package/src/cli/local-bridge/frontend/src/lib/api.ts +0 -30
- package/src/cli/local-bridge/frontend/src/lib/format.ts +0 -4
- package/src/cli/local-bridge/frontend/src/lib/routes.ts +0 -7
- package/src/cli/local-bridge/frontend/src/main.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/shell/AppShell.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/shell/CommandBar.tsx +0 -2
- package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +0 -4
- package/src/cli/local-bridge/frontend/src/styles.css +0 -28
- package/src/cli/local-bridge/frontend/src/types.ts +0 -15
- package/src/cli/local-bridge/frontend/src/vite-env.d.ts +0 -1
- package/src/cli/local-bridge/frontend/vite.config.ts +0 -27
- package/src/cli/local-bridge/ui-dist/app.css +0 -1
- package/src/cli/local-bridge/ui-dist/app.js +0 -11228
- package/src/runtime/control-plane/execution/content-equivalent-commit-authority.ts +0 -169
- package/src/runtime/control-plane/execution/direct-canonical-work-reconciliation.ts +0 -85
- package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +0 -655
- package/src/runtime/control-plane/execution/work-finalization-service.ts +0 -2850
- package/src/runtime/control-plane/execution/work-path-scope.ts +0 -37
- package/src/runtime/control-plane/execution/work-task-receipt.ts +0 -468
- package/src/runtime/control-plane/facade/controller-round-relay.ts +0 -3
- package/src/runtime/control-plane/facade/work-admission-policy.ts +0 -142
- package/src/runtime/control-plane/facade/work-implementation-review.ts +0 -2
- package/src/runtime/control-plane/facade/work-state-machine.ts +0 -2
- package/src/runtime/control-plane/facade/work-task-projection.ts +0 -66
- package/src/runtime/control-plane/routing/index.ts +0 -1
- package/src/runtime/control-plane/routing/route-policy.ts +0 -401
- package/src/runtime/control-plane/routing/workspace-admission.ts +0 -70
|
@@ -5,20 +5,40 @@ import type {
|
|
|
5
5
|
ComputerCaptureRegion,
|
|
6
6
|
ComputerTrustedInput,
|
|
7
7
|
} from '../../../packages/protocols/computer/index';
|
|
8
|
-
import { executeRuntimeComputerBrowserAutomation } from '../root/computer-composition';
|
|
8
|
+
import { executeRuntimeComputerBrowserAutomation, executeRuntimeComputerBrowserTrustedInput } from '../root/computer-composition';
|
|
9
9
|
import { AssistantPluginError } from './errors';
|
|
10
10
|
|
|
11
11
|
export type BrowserAutomationProduct = ComputerBrowserProduct;
|
|
12
12
|
export type BrowserAutomationTabRef = ComputerBrowserTabRef;
|
|
13
13
|
export type BrowserAutomationRegion = ComputerCaptureRegion;
|
|
14
14
|
export type BrowserAutomationTrustedInput = ComputerTrustedInput;
|
|
15
|
-
export
|
|
15
|
+
export interface BrowserAutomationSemanticTargetProof {
|
|
16
|
+
domRole: string;
|
|
17
|
+
accessibleName: string;
|
|
18
|
+
editable: true;
|
|
19
|
+
focused: true;
|
|
20
|
+
multiline: boolean;
|
|
21
|
+
}
|
|
22
|
+
export type BrowserAutomationTrustedInputRequest = Extract<ComputerBrowserAutomationRequest, { action: 'trusted_input' }> & {
|
|
23
|
+
/** Ephemeral Browser-owned proof; never persisted or forwarded to compatibility providers. */
|
|
24
|
+
semanticTarget?: BrowserAutomationSemanticTargetProof;
|
|
25
|
+
};
|
|
26
|
+
export type BrowserAutomationBrokerAction =
|
|
27
|
+
| Exclude<ComputerBrowserAutomationRequest, { action: 'trusted_input' }>
|
|
28
|
+
| BrowserAutomationTrustedInputRequest;
|
|
16
29
|
|
|
17
30
|
export async function callBrowserAutomationBroker(
|
|
18
31
|
request: BrowserAutomationBrokerAction,
|
|
19
32
|
timeoutMs: number,
|
|
20
33
|
): Promise<Record<string, unknown>> {
|
|
21
|
-
|
|
34
|
+
if (request.action === 'trusted_input'
|
|
35
|
+
&& (request.input.kind === 'key' || (request.input.kind === 'text' && request.semanticTarget))) {
|
|
36
|
+
return await executeRuntimeComputerBrowserTrustedInput(request, timeoutMs);
|
|
37
|
+
}
|
|
38
|
+
// Generic trusted text remains on the explicit Browser compatibility contract.
|
|
39
|
+
// Only Browser-owned semantic proof authorizes the Unified Computer text path.
|
|
40
|
+
const { semanticTarget: _semanticTarget, ...compatibilityRequest } = request as BrowserAutomationTrustedInputRequest;
|
|
41
|
+
return await executeRuntimeComputerBrowserAutomation(compatibilityRequest as ComputerBrowserAutomationRequest, timeoutMs);
|
|
22
42
|
}
|
|
23
43
|
|
|
24
44
|
export async function captureBrowserAutomationRegion(region: BrowserAutomationRegion, timeoutMs: number): Promise<Buffer> {
|
|
@@ -6,7 +6,9 @@ import {
|
|
|
6
6
|
callBrowserAutomationBroker,
|
|
7
7
|
captureBrowserAutomationRegion,
|
|
8
8
|
type BrowserAutomationBrokerAction,
|
|
9
|
+
type BrowserAutomationSemanticTargetProof,
|
|
9
10
|
type BrowserAutomationTrustedInput,
|
|
11
|
+
type BrowserAutomationTrustedInputRequest,
|
|
10
12
|
} from './browser-automation-service';
|
|
11
13
|
import { AssistantPluginError } from './errors';
|
|
12
14
|
import type { BrowserNativeAttachAttempt, BrowserNativeProduct } from '../../../packages/protocols/browser/index';
|
|
@@ -64,6 +66,8 @@ export interface MacOsBrowserTabInventoryEntry {
|
|
|
64
66
|
url: string;
|
|
65
67
|
title: string;
|
|
66
68
|
active: boolean;
|
|
69
|
+
/** True when this tab is active in the frontmost browser window. */
|
|
70
|
+
frontmost?: boolean;
|
|
67
71
|
}
|
|
68
72
|
|
|
69
73
|
export interface MacOsBrowserTabInventory {
|
|
@@ -119,7 +123,7 @@ function execFileText(file: string, args: string[], timeoutMs: number): Promise<
|
|
|
119
123
|
}, (error, stdout, stderr) => {
|
|
120
124
|
if (error) {
|
|
121
125
|
const diagnostic = String(stderr || error.message).trim().slice(-2_000);
|
|
122
|
-
reject(new Error(diagnostic || error.message));
|
|
126
|
+
reject(new Error(diagnostic || error.message, { cause: error }));
|
|
123
127
|
return;
|
|
124
128
|
}
|
|
125
129
|
resolve(String(stdout).trim());
|
|
@@ -134,8 +138,12 @@ const defaultRuntimeHooks: MacOsBrowserRuntimeHooks = {
|
|
|
134
138
|
try {
|
|
135
139
|
await execFileText('/usr/bin/pgrep', ['-x', processName], timeoutMs);
|
|
136
140
|
return true;
|
|
137
|
-
} catch {
|
|
138
|
-
|
|
141
|
+
} catch (error) {
|
|
142
|
+
// pgrep's no-match exit is absence; timeout/permission/transport failure
|
|
143
|
+
// cannot prove that an application's tabs are absent.
|
|
144
|
+
const cause = error instanceof Error ? error.cause : undefined;
|
|
145
|
+
if (cause && typeof cause === 'object' && 'code' in cause && cause.code === 1) return false;
|
|
146
|
+
throw error;
|
|
139
147
|
}
|
|
140
148
|
},
|
|
141
149
|
};
|
|
@@ -227,6 +235,12 @@ async function runBrowserAutomationText(
|
|
|
227
235
|
testArgs: string[],
|
|
228
236
|
timeoutMs: number,
|
|
229
237
|
): Promise<string> {
|
|
238
|
+
// AppleScript `tell application` starts an application that is not already
|
|
239
|
+
// running while it compiles the script. Every browser entry point therefore
|
|
240
|
+
// fails closed unless the exact browser process is already live, so routine
|
|
241
|
+
// inventory/reconcile work can never launch the user's browser or hand Forge
|
|
242
|
+
// an unauthenticated profile.
|
|
243
|
+
if ('product' in request) await assertMacOsBrowserApplicationRunning(request.product, timeoutMs);
|
|
230
244
|
if (runtimeHooks.runAppleScript) return await runtimeHooks.runAppleScript(testScript, testArgs, timeoutMs);
|
|
231
245
|
const result = await callBrowserAutomationBroker(request, timeoutMs);
|
|
232
246
|
if (typeof result.value !== 'string') {
|
|
@@ -239,6 +253,76 @@ async function runBrowserAutomationText(
|
|
|
239
253
|
return result.value;
|
|
240
254
|
}
|
|
241
255
|
|
|
256
|
+
/**
|
|
257
|
+
* Non-launching precondition for every Apple Events browser operation.
|
|
258
|
+
* Path existence is checked without scripting the application, and process
|
|
259
|
+
* liveness comes from the process table, so neither probe can start a browser.
|
|
260
|
+
*/
|
|
261
|
+
export async function assertMacOsBrowserApplicationRunning(
|
|
262
|
+
product: MacOsBrowserProduct,
|
|
263
|
+
timeoutMs = DEFAULT_NATIVE_TIMEOUT_MS,
|
|
264
|
+
): Promise<void> {
|
|
265
|
+
const browser = browserDefinition(product);
|
|
266
|
+
const details = { browserProduct: product, bundleId: browser.bundleId, appName: browser.appName };
|
|
267
|
+
if (runtimeHooks.platform !== 'darwin') {
|
|
268
|
+
throw new AssistantPluginError(
|
|
269
|
+
'PLUGIN_BROWSER_NATIVE_APP_UNSUPPORTED_PLATFORM',
|
|
270
|
+
`Native ${browser.appName} Apple Events are unavailable on ${runtimeHooks.platform}.`,
|
|
271
|
+
{ retryable: false, details },
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
if (!browser.appPaths.some((path) => runtimeHooks.appExists(path))) {
|
|
275
|
+
throw new AssistantPluginError(
|
|
276
|
+
'PLUGIN_BROWSER_NATIVE_APP_NOT_INSTALLED',
|
|
277
|
+
`${browser.appName} is not installed; Forge never installs or substitutes a browser application.`,
|
|
278
|
+
{ retryable: false, details },
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
if (!(await runtimeHooks.processRunning(browser.processName, timeoutMs))) {
|
|
282
|
+
throw new AssistantPluginError(
|
|
283
|
+
'PLUGIN_BROWSER_NATIVE_APP_NOT_RUNNING',
|
|
284
|
+
`${browser.appName} is not running; Forge never launches a browser application implicitly.`,
|
|
285
|
+
{ retryable: true, details },
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Start only the browser family already chosen by the Computer target. This
|
|
292
|
+
* is deliberately narrower than a generic browser launch: it never guesses a
|
|
293
|
+
* product, profile, or authentication identity. The caller must have a
|
|
294
|
+
* durable preferred product and must still verify the resulting ChatGPT page
|
|
295
|
+
* before any provider mutation.
|
|
296
|
+
*/
|
|
297
|
+
export async function ensureMacOsBrowserApplicationRunning(
|
|
298
|
+
product: MacOsBrowserProduct,
|
|
299
|
+
timeoutMs = DEFAULT_NATIVE_TIMEOUT_MS,
|
|
300
|
+
): Promise<void> {
|
|
301
|
+
const browser = browserDefinition(product);
|
|
302
|
+
if (runtimeHooks.platform !== 'darwin') throw new AssistantPluginError(
|
|
303
|
+
'PLUGIN_BROWSER_NATIVE_APP_UNSUPPORTED_PLATFORM',
|
|
304
|
+
`Native ${browser.appName} Apple Events are unavailable on ${runtimeHooks.platform}.`,
|
|
305
|
+
{ retryable: false, details: { browserProduct: product } },
|
|
306
|
+
);
|
|
307
|
+
if (!browser.appPaths.some((path) => runtimeHooks.appExists(path))) throw new AssistantPluginError(
|
|
308
|
+
'PLUGIN_BROWSER_NATIVE_APP_NOT_INSTALLED',
|
|
309
|
+
`${browser.appName} is not installed.`,
|
|
310
|
+
{ retryable: false, details: { browserProduct: product } },
|
|
311
|
+
);
|
|
312
|
+
if (await runtimeHooks.processRunning(browser.processName, timeoutMs)) return;
|
|
313
|
+
await execFileText('/usr/bin/open', ['-a', browser.appName], timeoutMs);
|
|
314
|
+
const deadline = Date.now() + Math.max(1_000, timeoutMs);
|
|
315
|
+
while (Date.now() < deadline) {
|
|
316
|
+
if (await runtimeHooks.processRunning(browser.processName, Math.min(1_000, timeoutMs))) return;
|
|
317
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
318
|
+
}
|
|
319
|
+
throw new AssistantPluginError(
|
|
320
|
+
'PLUGIN_BROWSER_NATIVE_APP_START_TIMEOUT',
|
|
321
|
+
`${browser.appName} did not become available after Forge started the remembered browser family.`,
|
|
322
|
+
{ retryable: true, details: { browserProduct: product } },
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
242
326
|
async function captureBrowserAutomation(
|
|
243
327
|
region: { x: number; y: number; width: number; height: number },
|
|
244
328
|
path: string,
|
|
@@ -251,7 +335,7 @@ async function captureBrowserAutomation(
|
|
|
251
335
|
}
|
|
252
336
|
|
|
253
337
|
async function sendBrowserTrustedInput(
|
|
254
|
-
request:
|
|
338
|
+
request: BrowserAutomationTrustedInputRequest,
|
|
255
339
|
timeoutMs: number,
|
|
256
340
|
): Promise<void> {
|
|
257
341
|
if (runtimeHooks.trustedInput) {
|
|
@@ -405,6 +489,8 @@ set maxTabs to 256
|
|
|
405
489
|
set returnedCount to 0
|
|
406
490
|
set truncatedInventory to false
|
|
407
491
|
set outputText to "false"
|
|
492
|
+
set frontWindowId to ""
|
|
493
|
+
if (count of windows) is greater than 0 then set frontWindowId to ((id of front window) as text)
|
|
408
494
|
repeat with candidateWindow in windows
|
|
409
495
|
set activeTabId to ""
|
|
410
496
|
try
|
|
@@ -417,10 +503,11 @@ repeat with candidateWindow in windows
|
|
|
417
503
|
end if
|
|
418
504
|
set candidateWindowId to ((id of candidateWindow) as text)
|
|
419
505
|
set candidateTabId to ((id of candidateTab) as text)
|
|
506
|
+
set candidateFrontmost to (candidateWindowId is frontWindowId)
|
|
420
507
|
set candidateURL to my cleanField((URL of candidateTab as text), recordSeparator, fieldSeparator)
|
|
421
508
|
set candidateTitle to my cleanField((title of candidateTab as text), recordSeparator, fieldSeparator)
|
|
422
509
|
set candidateActive to (candidateTabId is activeTabId)
|
|
423
|
-
set outputText to outputText & recordSeparator & candidateWindowId & fieldSeparator & candidateTabId & fieldSeparator & (candidateActive as text) & fieldSeparator & candidateURL & fieldSeparator & candidateTitle
|
|
510
|
+
set outputText to outputText & recordSeparator & candidateWindowId & fieldSeparator & candidateTabId & fieldSeparator & (candidateActive as text) & fieldSeparator & (candidateFrontmost as text) & fieldSeparator & candidateURL & fieldSeparator & candidateTitle
|
|
424
511
|
set returnedCount to returnedCount + 1
|
|
425
512
|
end repeat
|
|
426
513
|
if truncatedInventory then exit repeat
|
|
@@ -458,14 +545,23 @@ function parseTabInventory(product: MacOsBrowserProduct, raw: string): MacOsBrow
|
|
|
458
545
|
const windowId = (fields[0] ?? '').trim();
|
|
459
546
|
const tabId = (fields[1] ?? '').trim();
|
|
460
547
|
const activeText = (fields[2] ?? '').trim().toLowerCase();
|
|
461
|
-
|
|
548
|
+
const hasFrontmostField = fields.length >= 6 && ['true', 'false'].includes((fields[3] ?? '').trim().toLowerCase());
|
|
549
|
+
const frontmostText = hasFrontmostField ? (fields[3] ?? '').trim().toLowerCase() : undefined;
|
|
550
|
+
if (!windowId || !tabId || (activeText !== 'true' && activeText !== 'false') || (fields.length >= 6 && !hasFrontmostField)) {
|
|
462
551
|
throw new AssistantPluginError(
|
|
463
552
|
'PLUGIN_MACOS_CAPABILITY_BROKER_PROTOCOL_ERROR',
|
|
464
553
|
'Stable Forge macOS capability broker returned invalid browser tab inventory metadata.',
|
|
465
554
|
{ retryable: true },
|
|
466
555
|
);
|
|
467
556
|
}
|
|
468
|
-
tabs.push({
|
|
557
|
+
tabs.push({
|
|
558
|
+
windowId,
|
|
559
|
+
tabId,
|
|
560
|
+
active: activeText === 'true',
|
|
561
|
+
...(frontmostText ? { frontmost: frontmostText === 'true' } : {}),
|
|
562
|
+
url: fields[hasFrontmostField ? 4 : 3] ?? '',
|
|
563
|
+
title: fields.slice(hasFrontmostField ? 5 : 4).join(fieldSeparator),
|
|
564
|
+
});
|
|
469
565
|
if (tabs.length > 256) {
|
|
470
566
|
throw new AssistantPluginError(
|
|
471
567
|
'PLUGIN_MACOS_CAPABILITY_BROKER_PROTOCOL_ERROR',
|
|
@@ -507,30 +603,76 @@ return (frontmost as text) & separator & (URL of targetTab as text) & separator
|
|
|
507
603
|
function activateTargetTabScript(browser: MacOsBrowserDefinition, ref: MacOsBrowserTabRef): string {
|
|
508
604
|
return browserTellScript(browser, `
|
|
509
605
|
${targetTabPreamble(ref)}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
606
|
+
-- Activating by position is only safe inside the same enumeration that produced
|
|
607
|
+
-- the index. A tab created or closed by the provider between those two steps
|
|
608
|
+
-- makes the positional write fail with -1719 ("Can't get item N of every tab"),
|
|
609
|
+
-- so each attempt re-reads the tab list, bounds the index and verifies the exact
|
|
610
|
+
-- tab became active before it is reported as done.
|
|
611
|
+
set targetTabIdText to ((id of targetTab) as text)
|
|
612
|
+
set activationConfirmed to false
|
|
613
|
+
repeat 3 times
|
|
614
|
+
set targetTabIndex to 0
|
|
615
|
+
set candidateIndex to 0
|
|
616
|
+
repeat with candidateTab in tabs of targetWindow
|
|
617
|
+
set candidateIndex to candidateIndex + 1
|
|
618
|
+
if ((id of candidateTab) as text) is targetTabIdText then set targetTabIndex to candidateIndex
|
|
619
|
+
end repeat
|
|
620
|
+
if targetTabIndex is greater than 0 then
|
|
621
|
+
try
|
|
622
|
+
if targetTabIndex is less than or equal to (count of tabs of targetWindow) then
|
|
623
|
+
set active tab index of targetWindow to targetTabIndex
|
|
624
|
+
if ((id of active tab of targetWindow) as text) is targetTabIdText then set activationConfirmed to true
|
|
625
|
+
end if
|
|
626
|
+
end try
|
|
627
|
+
end if
|
|
628
|
+
if activationConfirmed then exit repeat
|
|
629
|
+
delay 0.05
|
|
514
630
|
end repeat
|
|
515
|
-
set active tab index of targetWindow to targetTabIndex
|
|
516
631
|
set index of targetWindow to 1
|
|
517
632
|
activate
|
|
518
633
|
`);
|
|
519
634
|
}
|
|
520
635
|
|
|
521
|
-
function createOwnedTabScript(browser: MacOsBrowserDefinition): string {
|
|
636
|
+
function createOwnedTabScript(browser: MacOsBrowserDefinition, preferredWindowId?: string): string {
|
|
522
637
|
return `on run argv
|
|
523
638
|
set targetUrl to item 1 of argv
|
|
524
639
|
${browserTellScript(browser, `
|
|
525
|
-
|
|
640
|
+
set preferredWindowId to "${preferredWindowId ?? ''}"
|
|
641
|
+
set targetWindow to missing value
|
|
642
|
+
if preferredWindowId is not "" then
|
|
643
|
+
repeat with candidateWindow in windows
|
|
644
|
+
if ((id of candidateWindow) as text) is preferredWindowId then
|
|
645
|
+
set targetWindow to candidateWindow
|
|
646
|
+
exit repeat
|
|
647
|
+
end if
|
|
648
|
+
end repeat
|
|
649
|
+
end if
|
|
650
|
+
if targetWindow is missing value and (count of windows) is greater than 0 then set targetWindow to front window
|
|
651
|
+
if targetWindow is missing value then
|
|
526
652
|
set targetWindow to make new window
|
|
527
653
|
set targetTab to active tab of targetWindow
|
|
528
654
|
set URL of targetTab to targetUrl
|
|
529
655
|
else
|
|
530
656
|
set targetWindow to front window
|
|
531
|
-
set
|
|
657
|
+
set originalActiveTabId to ((id of active tab of targetWindow) as text)
|
|
532
658
|
set targetTab to make new tab at end of tabs of targetWindow with properties {URL:targetUrl}
|
|
533
|
-
|
|
659
|
+
-- Restore the previously active tab by identity, never by a stale position:
|
|
660
|
+
-- the new tab can shift Chrome's tab order and make a pre-create index invalid.
|
|
661
|
+
repeat 3 times
|
|
662
|
+
if ((id of active tab of targetWindow) as text) is originalActiveTabId then exit repeat
|
|
663
|
+
set restoreIndex to 0
|
|
664
|
+
set candidateIndex to 0
|
|
665
|
+
repeat with candidateTab in tabs of targetWindow
|
|
666
|
+
set candidateIndex to candidateIndex + 1
|
|
667
|
+
if ((id of candidateTab) as text) is originalActiveTabId then set restoreIndex to candidateIndex
|
|
668
|
+
end repeat
|
|
669
|
+
if restoreIndex is 0 then exit repeat
|
|
670
|
+
try
|
|
671
|
+
if restoreIndex is less than or equal to (count of tabs of targetWindow) then set active tab index of targetWindow to restoreIndex
|
|
672
|
+
end try
|
|
673
|
+
if ((id of active tab of targetWindow) as text) is originalActiveTabId then exit repeat
|
|
674
|
+
delay 0.05
|
|
675
|
+
end repeat
|
|
534
676
|
end if
|
|
535
677
|
set targetTabId to id of targetTab
|
|
536
678
|
set separator to ASCII character 30
|
|
@@ -804,7 +946,11 @@ export class MacOsAppleEventsPage {
|
|
|
804
946
|
return await runBrowserAutomationText(effectiveRequest, effectiveScript, args, timeoutMs);
|
|
805
947
|
} catch (error) {
|
|
806
948
|
const message = error instanceof Error ? error.message : String(error);
|
|
807
|
-
|
|
949
|
+
// Keep the broker's bounded timeout/serialization identity visible to
|
|
950
|
+
// the sole Supervisor retry policy. Flattening both to the generic
|
|
951
|
+
// operation error makes a blocked tab hot-loop against the global lane.
|
|
952
|
+
const brokerFailure = /\b(BROWSER_AUTOMATION_TIMEOUT|BROWSER_AUTOMATION_SERIALIZATION_BUSY)\b/.exec(message)?.[1];
|
|
953
|
+
throw new AssistantPluginError(brokerFailure ?? 'PLUGIN_BROWSER_NATIVE_OPERATION_FAILED', `${this.browser.appName} Apple Events operation failed: ${message}`, {
|
|
808
954
|
retryable: true,
|
|
809
955
|
details: { browserProduct: this.browser.product, bundleId: this.browser.bundleId },
|
|
810
956
|
});
|
|
@@ -1123,6 +1269,57 @@ export class MacOsAppleEventsPage {
|
|
|
1123
1269
|
await this.refreshMetadata();
|
|
1124
1270
|
}
|
|
1125
1271
|
|
|
1272
|
+
/**
|
|
1273
|
+
* Supervisor-only semantic text boundary. Browser owns exact tab + DOM focus;
|
|
1274
|
+
* Computer receives only a one-shot semantic target proof and remains the OS
|
|
1275
|
+
* mutation transport. Generic Browser trusted text keeps its compatibility
|
|
1276
|
+
* semantics and does not implicitly become ChatGPT-specific.
|
|
1277
|
+
*/
|
|
1278
|
+
async trustedSemanticTextInput(text: string): Promise<void> {
|
|
1279
|
+
if (!this.targetRef) {
|
|
1280
|
+
throw new AssistantPluginError('PLUGIN_BROWSER_TRUSTED_INPUT_UNAVAILABLE', 'Semantic trusted text requires an exact saved browser tab.', { retryable: false });
|
|
1281
|
+
}
|
|
1282
|
+
this.targetRef = await resolveCurrentMacOsBrowserTabRef(this.browser.product, this.targetRef, this.timeoutMs);
|
|
1283
|
+
const metadata = await readResolvedMacOsBrowserOwnedTabMetadata(this.browser.product, this.targetRef, this.timeoutMs);
|
|
1284
|
+
if (!metadata.frontmost || metadata.active !== true) {
|
|
1285
|
+
throw new AssistantPluginError(
|
|
1286
|
+
'PLUGIN_BROWSER_FOREGROUND_REQUIRED',
|
|
1287
|
+
'Semantic trusted text requires the exact saved browser tab to be frontmost and active.',
|
|
1288
|
+
{ retryable: true, details: { browserProduct: this.browser.product, windowId: this.targetRef.windowId, tabId: this.targetRef.tabId } },
|
|
1289
|
+
);
|
|
1290
|
+
}
|
|
1291
|
+
const semanticTarget = await this.evaluate<BrowserAutomationSemanticTargetProof & { valid?: boolean }>(`(() => {
|
|
1292
|
+
const element = document.activeElement;
|
|
1293
|
+
if (!(element instanceof HTMLElement)) return { valid: false };
|
|
1294
|
+
const tag = element.tagName.toLowerCase();
|
|
1295
|
+
const inputType = element instanceof HTMLInputElement ? String(element.type || 'text').toLowerCase() : '';
|
|
1296
|
+
const textInput = element instanceof HTMLTextAreaElement
|
|
1297
|
+
|| element.isContentEditable
|
|
1298
|
+
|| (element instanceof HTMLInputElement && !['button','checkbox','color','file','hidden','image','radio','range','reset','submit'].includes(inputType));
|
|
1299
|
+
const accessibleName = String(element.getAttribute('aria-label') || element.getAttribute('placeholder') || element.getAttribute('title') || element.getAttribute('name') || '').trim();
|
|
1300
|
+
const domRole = String(element.getAttribute('role') || (textInput ? 'textbox' : '')).trim();
|
|
1301
|
+
const multiline = element instanceof HTMLTextAreaElement || element.isContentEditable || element.getAttribute('aria-multiline') === 'true';
|
|
1302
|
+
return { valid: textInput && document.activeElement === element && Boolean(domRole) && Boolean(accessibleName), domRole, accessibleName, editable: true, focused: true, multiline };
|
|
1303
|
+
})()`);
|
|
1304
|
+
if (semanticTarget.valid !== true || semanticTarget.editable !== true || semanticTarget.focused !== true
|
|
1305
|
+
|| !semanticTarget.domRole || !semanticTarget.accessibleName) {
|
|
1306
|
+
throw new AssistantPluginError(
|
|
1307
|
+
'PLUGIN_BROWSER_TRUSTED_INPUT_SEMANTIC_TARGET_UNPROVEN',
|
|
1308
|
+
'Browser could not prove one focused editable DOM target with an accessible identity before trusted text mutation.',
|
|
1309
|
+
{ retryable: true, details: { browserProduct: this.browser.product, windowId: this.targetRef.windowId, tabId: this.targetRef.tabId } },
|
|
1310
|
+
);
|
|
1311
|
+
}
|
|
1312
|
+
const { valid: _valid, ...proof } = semanticTarget;
|
|
1313
|
+
await sendBrowserTrustedInput({
|
|
1314
|
+
action: 'trusted_input',
|
|
1315
|
+
product: this.browser.product,
|
|
1316
|
+
ref: this.targetRef,
|
|
1317
|
+
input: { kind: 'text', text },
|
|
1318
|
+
semanticTarget: proof,
|
|
1319
|
+
}, this.timeoutMs);
|
|
1320
|
+
await this.refreshMetadata();
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1126
1323
|
async screenshot(options: Record<string, unknown>): Promise<Buffer> {
|
|
1127
1324
|
const path = typeof options.path === 'string' ? options.path : undefined;
|
|
1128
1325
|
if (!path) throw new Error('Native browser screenshot requires an output path.');
|
|
@@ -1191,8 +1388,15 @@ export class MacOsAppleEventsPage {
|
|
|
1191
1388
|
const prototype = element instanceof HTMLTextAreaElement ? HTMLTextAreaElement.prototype : HTMLInputElement.prototype;
|
|
1192
1389
|
const setter = Object.getOwnPropertyDescriptor(prototype, 'value')?.set;
|
|
1193
1390
|
if (setter) setter.call(element, ${JSON.stringify(value)}); else element.value = ${JSON.stringify(value)};
|
|
1194
|
-
} else if (element.isContentEditable)
|
|
1195
|
-
|
|
1391
|
+
} else if (element.isContentEditable) {
|
|
1392
|
+
element.focus();
|
|
1393
|
+
const selection = window.getSelection();
|
|
1394
|
+
if (!selection) throw new Error('Contenteditable selection unavailable.');
|
|
1395
|
+
const range = document.createRange();
|
|
1396
|
+
range.selectNodeContents(element); selection.removeAllRanges(); selection.addRange(range);
|
|
1397
|
+
if (!document.execCommand('insertText', false, ${JSON.stringify(value)})) throw new Error('Contenteditable insertion rejected.');
|
|
1398
|
+
return true;
|
|
1399
|
+
} else throw new Error('Element does not accept text input.');
|
|
1196
1400
|
element.dispatchEvent(new Event('input', { bubbles: true }));
|
|
1197
1401
|
element.dispatchEvent(new Event('change', { bubbles: true }));
|
|
1198
1402
|
return true;
|
|
@@ -1200,8 +1404,26 @@ export class MacOsAppleEventsPage {
|
|
|
1200
1404
|
}
|
|
1201
1405
|
|
|
1202
1406
|
async type(selector: string, text: string): Promise<void> {
|
|
1203
|
-
|
|
1204
|
-
|
|
1407
|
+
await this.evaluate(selectorSource(selector, `
|
|
1408
|
+
if ('value' in element) {
|
|
1409
|
+
element.focus();
|
|
1410
|
+
const value = String(element.value || '');
|
|
1411
|
+
const prototype = element instanceof HTMLTextAreaElement ? HTMLTextAreaElement.prototype : HTMLInputElement.prototype;
|
|
1412
|
+
const setter = Object.getOwnPropertyDescriptor(prototype, 'value')?.set;
|
|
1413
|
+
if (setter) setter.call(element, value + ${JSON.stringify(text)}); else element.value = value + ${JSON.stringify(text)};
|
|
1414
|
+
element.dispatchEvent(new Event('input', { bubbles: true }));
|
|
1415
|
+
return true;
|
|
1416
|
+
}
|
|
1417
|
+
if (!element.isContentEditable) throw new Error('Element does not accept text input.');
|
|
1418
|
+
element.focus();
|
|
1419
|
+
const selection = window.getSelection();
|
|
1420
|
+
if (!selection) throw new Error('Contenteditable selection unavailable.');
|
|
1421
|
+
const range = document.createRange();
|
|
1422
|
+
range.selectNodeContents(element); range.collapse(false);
|
|
1423
|
+
selection.removeAllRanges(); selection.addRange(range);
|
|
1424
|
+
if (!document.execCommand('insertText', false, ${JSON.stringify(text)})) throw new Error('Contenteditable insertion rejected.');
|
|
1425
|
+
return true;
|
|
1426
|
+
`));
|
|
1205
1427
|
}
|
|
1206
1428
|
|
|
1207
1429
|
async press(selector: string, key: string): Promise<void> {
|
|
@@ -1388,18 +1610,58 @@ async function resolveCurrentMacOsBrowserTabRef(
|
|
|
1388
1610
|
return { windowId: match.windowId, tabId: match.tabId };
|
|
1389
1611
|
}
|
|
1390
1612
|
|
|
1613
|
+
export interface MacOsBrowserTabInventoryOptions {
|
|
1614
|
+
/**
|
|
1615
|
+
* Correct stale active/frontmost bits through one extra foreground metadata
|
|
1616
|
+
* read. Exact-target callers that only need stable windowId/tabId/url identity
|
|
1617
|
+
* can disable this optional probe so a blocked foreground Apple Events read
|
|
1618
|
+
* cannot starve the inventory itself.
|
|
1619
|
+
*/
|
|
1620
|
+
correctFrontmost?: boolean;
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1391
1623
|
export async function listMacOsBrowserTabs(
|
|
1392
1624
|
product: MacOsBrowserProduct,
|
|
1393
1625
|
timeoutMs = DEFAULT_NATIVE_TIMEOUT_MS,
|
|
1626
|
+
options: MacOsBrowserTabInventoryOptions = {},
|
|
1394
1627
|
): Promise<MacOsBrowserTabInventory> {
|
|
1395
1628
|
const browser = browserDefinition(product);
|
|
1629
|
+
// Capture the frontmost tab before reading the stable inventory when callers
|
|
1630
|
+
// need corrected UI-current metadata. Exact-target identity does not depend on
|
|
1631
|
+
// this optional foreground probe.
|
|
1632
|
+
const inspected = options.correctFrontmost === false
|
|
1633
|
+
? undefined
|
|
1634
|
+
: await inspectBrowser(product, timeoutMs);
|
|
1396
1635
|
const raw = await runBrowserAutomationText(
|
|
1397
1636
|
{ action: 'list_tabs', product },
|
|
1398
1637
|
listTabsScript(browser),
|
|
1399
1638
|
[],
|
|
1400
1639
|
timeoutMs,
|
|
1401
1640
|
);
|
|
1402
|
-
|
|
1641
|
+
const inventory = parseTabInventory(product, raw);
|
|
1642
|
+
if (!inspected) return inventory;
|
|
1643
|
+
const metadata = inspected.metadata;
|
|
1644
|
+
const current = metadata?.frontmost === true && metadata.active !== false
|
|
1645
|
+
? { windowId: metadata.windowId, tabId: metadata.tabId, url: metadata.url.trim() }
|
|
1646
|
+
: undefined;
|
|
1647
|
+
if (!current) return inventory;
|
|
1648
|
+
const hasIdentity = Boolean(current.windowId && current.tabId);
|
|
1649
|
+
const currentMatches = inventory.tabs.filter(tab => (
|
|
1650
|
+
hasIdentity
|
|
1651
|
+
? tab.windowId === current.windowId && tab.tabId === current.tabId
|
|
1652
|
+
: Boolean(current.url) && tab.url.trim() === current.url
|
|
1653
|
+
));
|
|
1654
|
+
const currentMatch = currentMatches.length === 1 ? currentMatches[0] : undefined;
|
|
1655
|
+
if (!currentMatch) return inventory;
|
|
1656
|
+
return {
|
|
1657
|
+
...inventory,
|
|
1658
|
+
tabs: inventory.tabs.map(tab => ({
|
|
1659
|
+
...tab,
|
|
1660
|
+
...(currentMatch.windowId === tab.windowId && currentMatch.tabId === tab.tabId
|
|
1661
|
+
? { active: true, frontmost: true }
|
|
1662
|
+
: { frontmost: false }),
|
|
1663
|
+
})),
|
|
1664
|
+
};
|
|
1403
1665
|
}
|
|
1404
1666
|
|
|
1405
1667
|
export async function readMacOsBrowserOwnedTabMetadata(
|
|
@@ -1407,11 +1669,24 @@ export async function readMacOsBrowserOwnedTabMetadata(
|
|
|
1407
1669
|
ref: MacOsBrowserTabRef,
|
|
1408
1670
|
timeoutMs = DEFAULT_NATIVE_TIMEOUT_MS,
|
|
1409
1671
|
): Promise<MacOsBrowserMetadata> {
|
|
1410
|
-
const browser = browserDefinition(product);
|
|
1411
1672
|
const resolvedRef = await resolveCurrentMacOsBrowserTabRef(product, ref, timeoutMs);
|
|
1673
|
+
return await readResolvedMacOsBrowserOwnedTabMetadata(product, resolvedRef, timeoutMs);
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1676
|
+
/**
|
|
1677
|
+
* Read one exact native tab whose stable identity is already authoritative for
|
|
1678
|
+
* the caller. The targeted AppleScript still fails closed when that tab id is
|
|
1679
|
+
* gone, but does not perform another full browser inventory.
|
|
1680
|
+
*/
|
|
1681
|
+
export async function readResolvedMacOsBrowserOwnedTabMetadata(
|
|
1682
|
+
product: MacOsBrowserProduct,
|
|
1683
|
+
ref: MacOsBrowserTabRef,
|
|
1684
|
+
timeoutMs = DEFAULT_NATIVE_TIMEOUT_MS,
|
|
1685
|
+
): Promise<MacOsBrowserMetadata> {
|
|
1686
|
+
const browser = browserDefinition(product);
|
|
1412
1687
|
return parseMetadata(product, await runBrowserAutomationText(
|
|
1413
|
-
{ action: 'metadata', product, ref
|
|
1414
|
-
targetMetadataScript(browser,
|
|
1688
|
+
{ action: 'metadata', product, ref },
|
|
1689
|
+
targetMetadataScript(browser, ref),
|
|
1415
1690
|
[],
|
|
1416
1691
|
timeoutMs,
|
|
1417
1692
|
));
|
|
@@ -1481,12 +1756,13 @@ export async function createMacOsBrowserOwnedPageForProduct(
|
|
|
1481
1756
|
product: MacOsBrowserProduct,
|
|
1482
1757
|
url: string,
|
|
1483
1758
|
attempts: MacOsBrowserAttachAttempt[],
|
|
1759
|
+
preferredWindowId?: string,
|
|
1484
1760
|
timeoutMs = DEFAULT_NATIVE_TIMEOUT_MS,
|
|
1485
1761
|
): Promise<{ page: MacOsAppleEventsPage; attachment: MacOsBrowserAttachment }> {
|
|
1486
1762
|
const browser = browserDefinition(product);
|
|
1487
1763
|
const creationEvidence = await runCreateTabAutomation(
|
|
1488
1764
|
{ action: 'create_tab', product, url },
|
|
1489
|
-
createOwnedTabScript(browser),
|
|
1765
|
+
createOwnedTabScript(browser, preferredWindowId),
|
|
1490
1766
|
[url],
|
|
1491
1767
|
timeoutMs,
|
|
1492
1768
|
);
|
|
@@ -1544,12 +1820,28 @@ export async function closeMacOsBrowserOwnedTab(
|
|
|
1544
1820
|
ref: MacOsBrowserTabRef,
|
|
1545
1821
|
timeoutMs = DEFAULT_NATIVE_TIMEOUT_MS,
|
|
1546
1822
|
): Promise<void> {
|
|
1547
|
-
const browser = browserDefinition(product);
|
|
1548
1823
|
try {
|
|
1549
1824
|
const resolvedRef = await resolveCurrentMacOsBrowserTabRef(product, ref, timeoutMs);
|
|
1825
|
+
await closeResolvedMacOsBrowserOwnedTab(product, resolvedRef, timeoutMs);
|
|
1826
|
+
} finally {
|
|
1827
|
+
invalidateMacOsBrowserPageHandle(product, ref);
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1831
|
+
/**
|
|
1832
|
+
* Close one exact native tab whose stable identity was already proven by the
|
|
1833
|
+
* caller's live inventory snapshot. This deliberately does not inventory again.
|
|
1834
|
+
*/
|
|
1835
|
+
export async function closeResolvedMacOsBrowserOwnedTab(
|
|
1836
|
+
product: MacOsBrowserProduct,
|
|
1837
|
+
ref: MacOsBrowserTabRef,
|
|
1838
|
+
timeoutMs = DEFAULT_NATIVE_TIMEOUT_MS,
|
|
1839
|
+
): Promise<void> {
|
|
1840
|
+
const browser = browserDefinition(product);
|
|
1841
|
+
try {
|
|
1550
1842
|
await runBrowserAutomationText(
|
|
1551
|
-
{ action: 'close_tab', product, ref
|
|
1552
|
-
closeOwnedTabScript(browser,
|
|
1843
|
+
{ action: 'close_tab', product, ref },
|
|
1844
|
+
closeOwnedTabScript(browser, ref),
|
|
1553
1845
|
[],
|
|
1554
1846
|
timeoutMs,
|
|
1555
1847
|
);
|