@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
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createHash, randomUUID } from 'crypto';
|
|
2
2
|
import type {
|
|
3
|
+
ComputerApplicationLaunchProvenance,
|
|
3
4
|
ComputerApplicationTarget,
|
|
4
5
|
ComputerApplicationStableIdentity,
|
|
5
6
|
ComputerApplicationTargetLease,
|
|
@@ -11,6 +12,7 @@ import {
|
|
|
11
12
|
COMPUTER_ELEMENT_OBSERVE_CAPABILITY,
|
|
12
13
|
COMPUTER_INPUT_CAPABILITY,
|
|
13
14
|
COMPUTER_OBSERVE_CAPABILITY,
|
|
15
|
+
type ComputerConsoleUnlockCommandRequest,
|
|
14
16
|
type ComputerConsoleUnlockPrepareRequest,
|
|
15
17
|
type ComputerConsoleUnlockRequest,
|
|
16
18
|
type ComputerElementSemanticAction,
|
|
@@ -48,6 +50,10 @@ const DESKTOP_ELEMENT_OBSERVE_ACTION = 'desktop_element_observe';
|
|
|
48
50
|
const DESKTOP_ELEMENT_ACTION_ACTION = 'desktop_element_action';
|
|
49
51
|
export const COMPUTER_CONSOLE_UNLOCK_PREPARE_ACTION = 'console_unlock_prepare';
|
|
50
52
|
export const COMPUTER_CONSOLE_UNLOCK_ACTION = 'console_unlock';
|
|
53
|
+
export const COMPUTER_CONSOLE_UNLOCK_ENROLL_ACTION = 'console_unlock_enroll';
|
|
54
|
+
export const COMPUTER_CONSOLE_UNLOCK_STATUS_ACTION = 'console_unlock_status';
|
|
55
|
+
export const COMPUTER_CONSOLE_UNLOCK_RECOVER_ACTION = 'console_unlock_recover';
|
|
56
|
+
export const COMPUTER_CONSOLE_UNLOCK_REVOKE_ACTION = 'console_unlock_revoke';
|
|
51
57
|
const DEFAULT_CONSOLE_UNLOCK_TIMEOUT_MS = 15_000;
|
|
52
58
|
const MAX_CONSOLE_UNLOCK_TIMEOUT_MS = 30_000;
|
|
53
59
|
const CONSOLE_CREDENTIAL_HANDLE_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
@@ -69,6 +75,10 @@ const DESKTOP_PRODUCT_ACTION_IDS = new Set([
|
|
|
69
75
|
DESKTOP_ELEMENT_ACTION_ACTION,
|
|
70
76
|
COMPUTER_CONSOLE_UNLOCK_PREPARE_ACTION,
|
|
71
77
|
COMPUTER_CONSOLE_UNLOCK_ACTION,
|
|
78
|
+
COMPUTER_CONSOLE_UNLOCK_ENROLL_ACTION,
|
|
79
|
+
COMPUTER_CONSOLE_UNLOCK_STATUS_ACTION,
|
|
80
|
+
COMPUTER_CONSOLE_UNLOCK_RECOVER_ACTION,
|
|
81
|
+
COMPUTER_CONSOLE_UNLOCK_REVOKE_ACTION,
|
|
72
82
|
]);
|
|
73
83
|
|
|
74
84
|
function providerActionDescriptor(actionId: string): AssistantPluginActionDescriptor {
|
|
@@ -178,6 +188,31 @@ export async function executeProtectedConsoleUnlockInvocation(
|
|
|
178
188
|
};
|
|
179
189
|
}
|
|
180
190
|
|
|
191
|
+
export async function executeProtectedConsoleUnlockLifecycle(
|
|
192
|
+
action: 'console_unlock_enroll' | 'console_unlock_status' | 'console_unlock_recover' | 'console_unlock_revoke',
|
|
193
|
+
input: ProtectedConsoleUnlockPreparationInput,
|
|
194
|
+
controllerHome: string,
|
|
195
|
+
): Promise<Record<string, unknown>> {
|
|
196
|
+
requireConsoleUnlockAuthorization(input.confirmAuthorization);
|
|
197
|
+
const invocationId = randomUUID();
|
|
198
|
+
const request: ComputerConsoleUnlockCommandRequest = {
|
|
199
|
+
capability: COMPUTER_CONSOLE_UNLOCK_CAPABILITY,
|
|
200
|
+
action,
|
|
201
|
+
};
|
|
202
|
+
const providerResult = await executeRuntimeComputerConsoleUnlock(
|
|
203
|
+
request,
|
|
204
|
+
{ kind: 'explicit_single_use', confirmed: true, invocationId },
|
|
205
|
+
boundedConsoleUnlockTimeoutMs(input.timeoutMs),
|
|
206
|
+
controllerHome,
|
|
207
|
+
);
|
|
208
|
+
return {
|
|
209
|
+
capability: COMPUTER_CONSOLE_UNLOCK_CAPABILITY,
|
|
210
|
+
action,
|
|
211
|
+
invocationId,
|
|
212
|
+
...providerResult,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
181
216
|
function desktopProductActions(): AssistantPluginActionDescriptor[] {
|
|
182
217
|
const open = providerActionDescriptor('desktop_session_open');
|
|
183
218
|
const close = providerActionDescriptor('desktop_session_close');
|
|
@@ -240,6 +275,70 @@ function desktopProductActions(): AssistantPluginActionDescriptor[] {
|
|
|
240
275
|
additionalProperties: false,
|
|
241
276
|
},
|
|
242
277
|
},
|
|
278
|
+
{
|
|
279
|
+
actionId: COMPUTER_CONSOLE_UNLOCK_ENROLL_ACTION,
|
|
280
|
+
title: 'Enable unattended console recovery',
|
|
281
|
+
description: 'Enroll provider-local unattended console recovery. Credential collection and Keychain persistence remain entirely inside the native provider.',
|
|
282
|
+
readOnly: false,
|
|
283
|
+
risk: 'workspace_write',
|
|
284
|
+
confirmation: 'authorization',
|
|
285
|
+
defaultTimeoutMs: DEFAULT_CONSOLE_UNLOCK_TIMEOUT_MS,
|
|
286
|
+
cancellable: true,
|
|
287
|
+
idempotent: false,
|
|
288
|
+
executionMode: 'direct_non_persistent',
|
|
289
|
+
foregroundEffect: 'required',
|
|
290
|
+
scopes: ['console.unlock'],
|
|
291
|
+
resourceClaims: [],
|
|
292
|
+
argumentsSchema: { type: 'object', properties: {}, additionalProperties: false },
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
actionId: COMPUTER_CONSOLE_UNLOCK_STATUS_ACTION,
|
|
296
|
+
title: 'Read unattended console recovery status',
|
|
297
|
+
description: 'Read whether provider-local unattended console recovery is enrolled and available without exposing credential material.',
|
|
298
|
+
readOnly: true,
|
|
299
|
+
risk: 'readonly',
|
|
300
|
+
confirmation: 'authorization',
|
|
301
|
+
defaultTimeoutMs: DEFAULT_CONSOLE_UNLOCK_TIMEOUT_MS,
|
|
302
|
+
cancellable: true,
|
|
303
|
+
idempotent: true,
|
|
304
|
+
executionMode: 'direct_non_persistent',
|
|
305
|
+
foregroundEffect: 'none',
|
|
306
|
+
scopes: ['console.unlock'],
|
|
307
|
+
resourceClaims: [],
|
|
308
|
+
argumentsSchema: { type: 'object', properties: {}, additionalProperties: false },
|
|
309
|
+
},
|
|
310
|
+
{
|
|
311
|
+
actionId: COMPUTER_CONSOLE_UNLOCK_RECOVER_ACTION,
|
|
312
|
+
title: 'Recover locked macOS console',
|
|
313
|
+
description: 'Recover an already-locked console using only the provider-local enrolled credential. No password or credential handle enters Forge.',
|
|
314
|
+
readOnly: false,
|
|
315
|
+
risk: 'workspace_write',
|
|
316
|
+
confirmation: 'authorization',
|
|
317
|
+
defaultTimeoutMs: DEFAULT_CONSOLE_UNLOCK_TIMEOUT_MS,
|
|
318
|
+
cancellable: true,
|
|
319
|
+
idempotent: false,
|
|
320
|
+
executionMode: 'direct_non_persistent',
|
|
321
|
+
foregroundEffect: 'required',
|
|
322
|
+
scopes: ['console.unlock'],
|
|
323
|
+
resourceClaims: [],
|
|
324
|
+
argumentsSchema: { type: 'object', properties: {}, additionalProperties: false },
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
actionId: COMPUTER_CONSOLE_UNLOCK_REVOKE_ACTION,
|
|
328
|
+
title: 'Disable unattended console recovery',
|
|
329
|
+
description: 'Delete the provider-local unattended console recovery credential and disable future recovery.',
|
|
330
|
+
readOnly: false,
|
|
331
|
+
risk: 'workspace_write',
|
|
332
|
+
confirmation: 'authorization',
|
|
333
|
+
defaultTimeoutMs: DEFAULT_CONSOLE_UNLOCK_TIMEOUT_MS,
|
|
334
|
+
cancellable: true,
|
|
335
|
+
idempotent: true,
|
|
336
|
+
executionMode: 'direct_non_persistent',
|
|
337
|
+
foregroundEffect: 'none',
|
|
338
|
+
scopes: ['console.unlock'],
|
|
339
|
+
resourceClaims: [],
|
|
340
|
+
argumentsSchema: { type: 'object', properties: {}, additionalProperties: false },
|
|
341
|
+
},
|
|
243
342
|
{
|
|
244
343
|
actionId: DESKTOP_ELEMENT_OBSERVE_ACTION,
|
|
245
344
|
title: 'Observe Computer elements',
|
|
@@ -318,7 +417,7 @@ function desktopProductPermissions(ready: boolean): AssistantPluginPermissionSco
|
|
|
318
417
|
{ scope: 'desktop.observe', mode: 'read', description: 'Observe bounded desktop accessibility state.', granted: ready, required: false },
|
|
319
418
|
{ scope: 'desktop.interact', mode: 'write', description: 'Perform bounded semantic desktop interaction.', granted: ready, required: false },
|
|
320
419
|
{ scope: 'desktop.capture', mode: 'read', description: 'Capture an authorized desktop target.', granted: ready, required: false },
|
|
321
|
-
{ scope: 'console.unlock', mode: 'write', description: '
|
|
420
|
+
{ scope: 'console.unlock', mode: 'write', description: 'Use provider-local temporary unlock or explicitly enrolled unattended console recovery.', granted: ready, required: false },
|
|
322
421
|
];
|
|
323
422
|
}
|
|
324
423
|
|
|
@@ -330,7 +429,7 @@ function desktopProductCapabilities(): AssistantPluginCapability[] {
|
|
|
330
429
|
{ capabilityId: 'computer.capture.v1', title: 'Computer capture', description: 'Capture authorized desktop state.', scopes: ['desktop.capture'], actions: ['desktop_screenshot'] },
|
|
331
430
|
{ capabilityId: COMPUTER_ELEMENT_OBSERVE_CAPABILITY, title: 'Computer element observation', description: 'Observe exact provider-neutral semantic element snapshots for a Forge-owned target.', scopes: ['desktop.observe'], actions: [DESKTOP_ELEMENT_OBSERVE_ACTION] },
|
|
332
431
|
{ capabilityId: COMPUTER_ELEMENT_ACTION_CAPABILITY, title: 'Computer element action', description: 'Act on exact observed element refs with observation-epoch fencing.', scopes: ['desktop.interact'], actions: [DESKTOP_ELEMENT_ACTION_ACTION] },
|
|
333
|
-
{ capabilityId: COMPUTER_CONSOLE_UNLOCK_CAPABILITY, title: 'Protected console unlock', description: '
|
|
432
|
+
{ capabilityId: COMPUTER_CONSOLE_UNLOCK_CAPABILITY, title: 'Protected console unlock', description: 'Keep console credential material provider-local while supporting temporary one-shot unlock and opt-in unattended recovery.', scopes: ['console.unlock'], actions: [COMPUTER_CONSOLE_UNLOCK_PREPARE_ACTION, COMPUTER_CONSOLE_UNLOCK_ACTION, COMPUTER_CONSOLE_UNLOCK_ENROLL_ACTION, COMPUTER_CONSOLE_UNLOCK_STATUS_ACTION, COMPUTER_CONSOLE_UNLOCK_RECOVER_ACTION, COMPUTER_CONSOLE_UNLOCK_REVOKE_ACTION] },
|
|
334
433
|
];
|
|
335
434
|
}
|
|
336
435
|
|
|
@@ -367,7 +466,6 @@ function buildComputerManifest(
|
|
|
367
466
|
sourceOfTruth: [
|
|
368
467
|
...browser.authority.sourceOfTruth,
|
|
369
468
|
'controllerHome:sqlite/computer_interaction_target',
|
|
370
|
-
'controllerHome:system/plugins/external/registrations/desktop_operator.json',
|
|
371
469
|
],
|
|
372
470
|
},
|
|
373
471
|
enabled: browser.enabled || desktop?.enabled === true,
|
|
@@ -384,15 +482,20 @@ function buildComputerManifest(
|
|
|
384
482
|
checkedAt,
|
|
385
483
|
ready,
|
|
386
484
|
probed: browser.health.probed || desktop?.health.probed === true,
|
|
387
|
-
errors: ready ? [] : [
|
|
485
|
+
errors: ready ? [] : [
|
|
486
|
+
...browser.health.errors,
|
|
487
|
+
...(desktopSupported && !desktopReady ? ['Native Computer capabilities are unavailable or not ready.'] : []),
|
|
488
|
+
],
|
|
388
489
|
warnings: [
|
|
389
490
|
...browser.health.warnings,
|
|
390
|
-
...(desktopSupported
|
|
491
|
+
...(desktopSupported
|
|
492
|
+
? (desktopReady ? [] : ['Native Computer capability diagnostics are available through the internal platform provider.'])
|
|
493
|
+
: [`Native Desktop Computer capabilities are unsupported on ${platform}.`]),
|
|
391
494
|
],
|
|
392
495
|
details: {
|
|
393
496
|
partial: !ready && partial,
|
|
394
497
|
browser: { ready: browserReady, state: browser.health.state },
|
|
395
|
-
desktop: { supported: desktopSupported, ready: desktopReady, state: desktop?.health.state ?? (desktopSupported ? 'not_installed' : 'unsupported')
|
|
498
|
+
desktop: { supported: desktopSupported, ready: desktopReady, state: desktop?.health.state ?? (desktopSupported ? 'not_installed' : 'unsupported') },
|
|
396
499
|
},
|
|
397
500
|
},
|
|
398
501
|
permissions: [...browser.permissions, ...desktopProductPermissions(desktopReady)],
|
|
@@ -618,10 +721,12 @@ async function rebindProviderSession(
|
|
|
618
721
|
{ retryable: false, details: { targetId: target.targetId, stableIdentity: target.stableIdentity } },
|
|
619
722
|
);
|
|
620
723
|
}
|
|
724
|
+
const processId = providerProcessId(rebound);
|
|
621
725
|
lease.bind({
|
|
622
726
|
providerId: DESKTOP_PROVIDER_ID,
|
|
623
727
|
providerSessionId: interactionId,
|
|
624
728
|
observedAt: new Date().toISOString(),
|
|
729
|
+
...(processId !== undefined ? { processId } : {}),
|
|
625
730
|
});
|
|
626
731
|
return interactionId;
|
|
627
732
|
}
|
|
@@ -638,6 +743,55 @@ async function ensureProviderBinding(
|
|
|
638
743
|
return rebindProviderSession(input, lease, provider);
|
|
639
744
|
}
|
|
640
745
|
|
|
746
|
+
function providerProcessId(result: Record<string, unknown>): number | undefined {
|
|
747
|
+
const value = result.pid ?? result.process_id;
|
|
748
|
+
if (value === undefined) return undefined;
|
|
749
|
+
if (typeof value !== 'number' || !Number.isInteger(value) || value <= 0 || value > 2_147_483_647) {
|
|
750
|
+
throw new AssistantPluginError(
|
|
751
|
+
'PLUGIN_COMPUTER_TARGET_PROCESS_ID_INVALID',
|
|
752
|
+
'Native Computer provider returned an invalid application process identifier.',
|
|
753
|
+
{ retryable: false, details: { processId: value } },
|
|
754
|
+
);
|
|
755
|
+
}
|
|
756
|
+
return value;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
function explicitLaunchProvenanceFromProviderResult(
|
|
760
|
+
result: Record<string, unknown>,
|
|
761
|
+
processId: number | undefined,
|
|
762
|
+
): ComputerApplicationLaunchProvenance | undefined {
|
|
763
|
+
const rawOwnership = result.applicationOwnership ?? result.application_ownership;
|
|
764
|
+
const rawOwnedPid = result.ownedProcessIdentifier ?? result.owned_process_identifier;
|
|
765
|
+
if (rawOwnership === undefined && rawOwnedPid === undefined) return undefined;
|
|
766
|
+
if (rawOwnership === 'preexisting' && rawOwnedPid === undefined) return { kind: 'preexisting' };
|
|
767
|
+
if (rawOwnership === 'provider_launched'
|
|
768
|
+
&& typeof rawOwnedPid === 'number'
|
|
769
|
+
&& Number.isInteger(rawOwnedPid)
|
|
770
|
+
&& rawOwnedPid > 0
|
|
771
|
+
&& rawOwnedPid <= 2_147_483_647
|
|
772
|
+
&& processId === rawOwnedPid) {
|
|
773
|
+
return { kind: 'provider_launched', processId: rawOwnedPid };
|
|
774
|
+
}
|
|
775
|
+
throw new AssistantPluginError(
|
|
776
|
+
'PLUGIN_COMPUTER_TARGET_LAUNCH_PROVENANCE_INVALID',
|
|
777
|
+
'Native Computer provider returned inconsistent application launch provenance.',
|
|
778
|
+
{ retryable: false, details: { applicationOwnership: rawOwnership, ownedProcessIdentifier: rawOwnedPid, processId } },
|
|
779
|
+
);
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
function inheritedLaunchProvenance(
|
|
783
|
+
controllerHome: string,
|
|
784
|
+
processId: number | undefined,
|
|
785
|
+
): ComputerApplicationLaunchProvenance | undefined {
|
|
786
|
+
if (processId === undefined) return undefined;
|
|
787
|
+
const owner = computerTargetAuthority.listAllApplications(controllerHome).find((target) =>
|
|
788
|
+
target.launchProvenance?.kind === 'provider_launched'
|
|
789
|
+
&& target.launchProvenance.processId === processId
|
|
790
|
+
&& target.providerBinding?.processId === processId,
|
|
791
|
+
);
|
|
792
|
+
return owner ? { kind: 'provider_launched', processId } : undefined;
|
|
793
|
+
}
|
|
794
|
+
|
|
641
795
|
function stableIdentityFromProviderResult(
|
|
642
796
|
result: Record<string, unknown>,
|
|
643
797
|
requested: ComputerApplicationStableIdentity,
|
|
@@ -689,10 +843,35 @@ async function openDesktopTarget(
|
|
|
689
843
|
}
|
|
690
844
|
throw error;
|
|
691
845
|
}
|
|
846
|
+
let processId: number | undefined;
|
|
847
|
+
let explicitProvenance: ComputerApplicationLaunchProvenance | undefined;
|
|
692
848
|
try {
|
|
849
|
+
processId = providerProcessId(opened);
|
|
850
|
+
explicitProvenance = explicitLaunchProvenanceFromProviderResult(opened, processId);
|
|
851
|
+
} catch (error) {
|
|
852
|
+
try {
|
|
853
|
+
await provider.executeAction(providerInput(input, 'desktop_session_close', { interaction_id: interactionId }, 'target-open-provenance-compensate'));
|
|
854
|
+
} catch (cleanupError) {
|
|
855
|
+
throw new AssistantPluginError('PLUGIN_COMPUTER_TARGET_LAUNCH_PROVENANCE_CLEANUP_UNKNOWN', 'Computer target launch provenance was invalid and provider-session cleanup could not be confirmed.', {
|
|
856
|
+
retryable: false,
|
|
857
|
+
details: { cause: error instanceof Error ? error.message : String(error), cleanupCause: cleanupError instanceof Error ? cleanupError.message : String(cleanupError) },
|
|
858
|
+
});
|
|
859
|
+
}
|
|
860
|
+
throw error;
|
|
861
|
+
}
|
|
862
|
+
try {
|
|
863
|
+
const launchProvenance = explicitProvenance?.kind === 'provider_launched'
|
|
864
|
+
? explicitProvenance
|
|
865
|
+
: inheritedLaunchProvenance(input.controllerHome, processId) ?? explicitProvenance;
|
|
693
866
|
const target = computerTargetAuthority.create(input.controllerHome, {
|
|
694
867
|
stableIdentity,
|
|
695
|
-
|
|
868
|
+
...(launchProvenance ? { launchProvenance } : {}),
|
|
869
|
+
providerBinding: {
|
|
870
|
+
providerId: DESKTOP_PROVIDER_ID,
|
|
871
|
+
providerSessionId: interactionId,
|
|
872
|
+
observedAt: new Date().toISOString(),
|
|
873
|
+
...(processId !== undefined ? { processId } : {}),
|
|
874
|
+
},
|
|
696
875
|
});
|
|
697
876
|
return {
|
|
698
877
|
targetId: target.targetId,
|
|
@@ -730,7 +909,27 @@ async function closeDesktopTarget(
|
|
|
730
909
|
);
|
|
731
910
|
}
|
|
732
911
|
if (provider) {
|
|
733
|
-
|
|
912
|
+
const activeTargets = computerTargetAuthority.listAllApplications(input.controllerHome);
|
|
913
|
+
const anotherActiveTargetUsesBinding = activeTargets.some((candidate) =>
|
|
914
|
+
candidate.targetId !== target.targetId
|
|
915
|
+
&& candidate.providerBinding?.providerId === target.providerBinding?.providerId
|
|
916
|
+
&& candidate.providerBinding?.providerSessionId === target.providerBinding?.providerSessionId,
|
|
917
|
+
);
|
|
918
|
+
if (!anotherActiveTargetUsesBinding) {
|
|
919
|
+
const ownedProcessId = target.launchProvenance?.kind === 'provider_launched'
|
|
920
|
+
? target.launchProvenance.processId
|
|
921
|
+
: undefined;
|
|
922
|
+
const anotherActiveTargetUsesOwnedProcess = ownedProcessId !== undefined
|
|
923
|
+
&& activeTargets.some((candidate) =>
|
|
924
|
+
candidate.targetId !== target.targetId && candidate.providerBinding?.processId === ownedProcessId,
|
|
925
|
+
);
|
|
926
|
+
await provider.executeAction(providerInput(input, 'desktop_session_close', {
|
|
927
|
+
interaction_id: target.providerBinding.providerSessionId,
|
|
928
|
+
...(ownedProcessId !== undefined && !anotherActiveTargetUsesOwnedProcess
|
|
929
|
+
? { terminate_owned_pid: ownedProcessId }
|
|
930
|
+
: {}),
|
|
931
|
+
}, 'target-close-provider'));
|
|
932
|
+
}
|
|
734
933
|
}
|
|
735
934
|
// A missing registration is authoritative absence only because provider uninstall
|
|
736
935
|
// must stop/remove its native lifecycle before the registration is deleted.
|
|
@@ -796,7 +995,7 @@ function targetAuthorization(identity: ComputerApplicationStableIdentity): Assis
|
|
|
796
995
|
}
|
|
797
996
|
|
|
798
997
|
async function resolveDesktopAuthorizationContext(input: AssistantPluginActionExecutionInput): Promise<AssistantPluginAuthorizationContext | undefined> {
|
|
799
|
-
if (
|
|
998
|
+
if ([COMPUTER_CONSOLE_UNLOCK_PREPARE_ACTION, COMPUTER_CONSOLE_UNLOCK_ACTION, COMPUTER_CONSOLE_UNLOCK_ENROLL_ACTION, COMPUTER_CONSOLE_UNLOCK_STATUS_ACTION, COMPUTER_CONSOLE_UNLOCK_RECOVER_ACTION, COMPUTER_CONSOLE_UNLOCK_REVOKE_ACTION].includes(input.actionId)) return undefined;
|
|
800
999
|
if (input.actionId === DESKTOP_TARGET_OPEN_ACTION) return targetAuthorization(stableIdentityFromArgs(input.args));
|
|
801
1000
|
const targetId = typeof input.args.target_id === 'string' ? input.args.target_id.trim() : '';
|
|
802
1001
|
if (targetId) return targetAuthorization(computerTargetAuthority.require(input.controllerHome, targetId).stableIdentity);
|
|
@@ -819,15 +1018,27 @@ export const computerPluginAdapter: AssistantPluginAdapter = {
|
|
|
819
1018
|
return executeBrowserPluginAction({ ...input, pluginId: 'browser' });
|
|
820
1019
|
}
|
|
821
1020
|
if (input.actionId === COMPUTER_CONSOLE_UNLOCK_PREPARE_ACTION) {
|
|
822
|
-
return executeProtectedConsoleUnlockPreparation({ confirmAuthorization: true, timeoutMs: input.timeoutMs }, input.controllerHome);
|
|
1021
|
+
return executeProtectedConsoleUnlockPreparation({ confirmAuthorization: input.confirmAuthorization === true, timeoutMs: input.timeoutMs }, input.controllerHome);
|
|
823
1022
|
}
|
|
824
1023
|
if (input.actionId === COMPUTER_CONSOLE_UNLOCK_ACTION) {
|
|
825
1024
|
return executeProtectedConsoleUnlockInvocation({
|
|
826
1025
|
credentialHandle: typeof input.args.credential_handle === 'string' ? input.args.credential_handle : '',
|
|
827
|
-
confirmAuthorization: true,
|
|
1026
|
+
confirmAuthorization: input.confirmAuthorization === true,
|
|
828
1027
|
timeoutMs: input.timeoutMs,
|
|
829
1028
|
}, input.controllerHome);
|
|
830
1029
|
}
|
|
1030
|
+
if (input.actionId === COMPUTER_CONSOLE_UNLOCK_ENROLL_ACTION) {
|
|
1031
|
+
return executeProtectedConsoleUnlockLifecycle('console_unlock_enroll', { confirmAuthorization: input.confirmAuthorization === true, timeoutMs: input.timeoutMs }, input.controllerHome);
|
|
1032
|
+
}
|
|
1033
|
+
if (input.actionId === COMPUTER_CONSOLE_UNLOCK_STATUS_ACTION) {
|
|
1034
|
+
return executeProtectedConsoleUnlockLifecycle('console_unlock_status', { confirmAuthorization: input.confirmAuthorization === true, timeoutMs: input.timeoutMs }, input.controllerHome);
|
|
1035
|
+
}
|
|
1036
|
+
if (input.actionId === COMPUTER_CONSOLE_UNLOCK_RECOVER_ACTION) {
|
|
1037
|
+
return executeProtectedConsoleUnlockLifecycle('console_unlock_recover', { confirmAuthorization: input.confirmAuthorization === true, timeoutMs: input.timeoutMs }, input.controllerHome);
|
|
1038
|
+
}
|
|
1039
|
+
if (input.actionId === COMPUTER_CONSOLE_UNLOCK_REVOKE_ACTION) {
|
|
1040
|
+
return executeProtectedConsoleUnlockLifecycle('console_unlock_revoke', { confirmAuthorization: input.confirmAuthorization === true, timeoutMs: input.timeoutMs }, input.controllerHome);
|
|
1041
|
+
}
|
|
831
1042
|
if (input.actionId === DESKTOP_TARGET_CLOSE_ACTION) return closeDesktopTarget(input, optionalDesktopProvider(input));
|
|
832
1043
|
const provider = desktopProvider(input);
|
|
833
1044
|
if (input.actionId === DESKTOP_TARGET_OPEN_ACTION) return openDesktopTarget(input, provider);
|
|
@@ -178,14 +178,46 @@ async function observeDesktopPointerTarget(
|
|
|
178
178
|
return { frame, point, ...(reboundSelector ? { reboundSelector } : {}) };
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
+
function focusedAxNodes(root: Record<string, unknown> | undefined): Record<string, unknown>[] {
|
|
182
|
+
if (!root) return [];
|
|
183
|
+
const focused: Record<string, unknown>[] = [];
|
|
184
|
+
const visit = (node: Record<string, unknown>): void => {
|
|
185
|
+
if (node.focused === true) focused.push(node);
|
|
186
|
+
for (const child of recordArray(node.children)) visit(child);
|
|
187
|
+
};
|
|
188
|
+
visit(root);
|
|
189
|
+
return focused;
|
|
190
|
+
}
|
|
191
|
+
|
|
181
192
|
function exactFocusedDesktopWindowId(observation: Record<string, unknown>): number | undefined {
|
|
182
193
|
const snapshot = recordValue(observation.snapshot);
|
|
183
194
|
const root = recordValue(snapshot?.root);
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
|
|
195
|
+
const axWindows = recordArray(root?.children).filter((window) => firstString(window, 'role') === 'AXWindow');
|
|
196
|
+
const explicitFocused = axWindows.filter((window) => window.focused === true);
|
|
197
|
+
let focusedAxWindow: Record<string, unknown> | undefined;
|
|
198
|
+
if (explicitFocused.length === 1) {
|
|
199
|
+
focusedAxWindow = explicitFocused[0];
|
|
200
|
+
} else if (explicitFocused.length > 1) {
|
|
201
|
+
return undefined;
|
|
202
|
+
} else {
|
|
203
|
+
// Chromium-family apps can expose the system-frontmost window with
|
|
204
|
+
// AXWindow.focused=false while a descendant/control in that window is the
|
|
205
|
+
// unique focused AX node. Recover the same window only from unique bounded
|
|
206
|
+
// geometry; any ambiguity still fails closed.
|
|
207
|
+
const focusedNodes = focusedAxNodes(root).filter((node) => firstString(node, 'role') !== 'AXApplication');
|
|
208
|
+
if (focusedNodes.length !== 1) return undefined;
|
|
209
|
+
const focusedFrame = desktopFrame(focusedNodes[0]?.frame);
|
|
210
|
+
if (!focusedFrame) return undefined;
|
|
211
|
+
const point = desktopFrameCenter(focusedFrame);
|
|
212
|
+
const containingWindows = axWindows.filter((window) => {
|
|
213
|
+
const frame = desktopFrame(window.frame);
|
|
214
|
+
return Boolean(frame && frameContainsPoint(frame, point.x, point.y));
|
|
215
|
+
});
|
|
216
|
+
if (containingWindows.length !== 1) return undefined;
|
|
217
|
+
focusedAxWindow = containingWindows[0];
|
|
218
|
+
}
|
|
187
219
|
|
|
188
|
-
const focusedTitle = firstString(
|
|
220
|
+
const focusedTitle = firstString(focusedAxWindow, 'title');
|
|
189
221
|
if (!focusedTitle) return undefined;
|
|
190
222
|
const matches = recordArray(observation.windows).filter((window) => {
|
|
191
223
|
const windowId = firstNumber(window, 'windowId', 'window_id');
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
import type { ExternalPluginRegistrationInput } from './external-registration';
|
|
10
10
|
import type { AssistantPluginActionDescriptor } from './types';
|
|
11
11
|
|
|
12
|
-
const CONTROLLER_WRITE = [{ resource: '
|
|
12
|
+
const CONTROLLER_WRITE = [{ resource: 'provider-state' as const, mode: 'write' as const }];
|
|
13
13
|
const SELECTOR_SCHEMA = {
|
|
14
14
|
type: 'object',
|
|
15
15
|
properties: {
|
|
@@ -436,10 +436,10 @@ export function desktopOperatorActions(): AssistantPluginActionDescriptor[] {
|
|
|
436
436
|
{
|
|
437
437
|
actionId: 'desktop_session_close',
|
|
438
438
|
title: 'Close desktop session',
|
|
439
|
-
description: 'Close one Desktop Operator interaction session
|
|
439
|
+
description: 'Close one Desktop Operator interaction session. Application termination is disabled by default and requires an exact Controller-owned process id.',
|
|
440
440
|
readOnly: false,
|
|
441
441
|
risk: 'workspace_write',
|
|
442
|
-
confirmation: '
|
|
442
|
+
confirmation: 'authorization',
|
|
443
443
|
defaultTimeoutMs: 5_000,
|
|
444
444
|
cancellable: true,
|
|
445
445
|
idempotent: true,
|
|
@@ -447,7 +447,15 @@ export function desktopOperatorActions(): AssistantPluginActionDescriptor[] {
|
|
|
447
447
|
resourceClaims: CONTROLLER_WRITE,
|
|
448
448
|
argumentsSchema: {
|
|
449
449
|
type: 'object',
|
|
450
|
-
properties: {
|
|
450
|
+
properties: {
|
|
451
|
+
interaction_id: { type: 'string' },
|
|
452
|
+
terminate_owned_pid: {
|
|
453
|
+
type: 'integer',
|
|
454
|
+
minimum: 1,
|
|
455
|
+
maximum: 2_147_483_647,
|
|
456
|
+
description: 'Exact provider-launched process id that the durable Computer target authority has decided is no longer used by another active target.',
|
|
457
|
+
},
|
|
458
|
+
},
|
|
451
459
|
required: ['interaction_id'],
|
|
452
460
|
additionalProperties: false,
|
|
453
461
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AssistantPluginError } from './errors';
|
|
2
|
-
import {
|
|
2
|
+
import { externalPluginRegistrationSetIdentity, listExternalPluginRegistrations, type ExternalPluginRegistration } from './external-registration';
|
|
3
3
|
import { callExternalUnixSocket, probeExternalUnixSocketSync, type ExternalUnixSocketCallOptions } from './external-unix-socket';
|
|
4
4
|
import { executeManagedPluginProcess, executeManagedPluginProcessSync, type ManagedPluginProcessSpec } from './managed-process-adapter';
|
|
5
5
|
import { activateAndVerifyFrontmostApplication, restartVerifiedUserLaunchAgent, startVerifiedUserLaunchAgent, stopVerifiedUserLaunchAgent } from './local-system-adapter';
|
|
@@ -149,6 +149,17 @@ function managedSpec(registration: ExternalPluginRegistration): ManagedPluginPro
|
|
|
149
149
|
};
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
+
function providerActionTimeoutMs(
|
|
153
|
+
registration: ExternalPluginRegistration,
|
|
154
|
+
actionId: string,
|
|
155
|
+
explicitTimeoutMs: number | undefined,
|
|
156
|
+
): number | undefined {
|
|
157
|
+
if (explicitTimeoutMs !== undefined) return explicitTimeoutMs;
|
|
158
|
+
if (actionId === 'manifest' || actionId === 'health') return registration.transport.healthTimeoutMs;
|
|
159
|
+
return registration.actions.find((action) => action.actionId === actionId)?.defaultTimeoutMs
|
|
160
|
+
?? registration.transport.actionTimeoutMs;
|
|
161
|
+
}
|
|
162
|
+
|
|
152
163
|
function probeProvider(
|
|
153
164
|
registration: ExternalPluginRegistration,
|
|
154
165
|
requestId: string,
|
|
@@ -185,15 +196,17 @@ async function callProvider(
|
|
|
185
196
|
requestId,
|
|
186
197
|
method: isProviderMethod ? actionId : 'execute',
|
|
187
198
|
params: isProviderMethod ? undefined : { action: actionId, arguments: args },
|
|
188
|
-
timeoutMs:
|
|
199
|
+
timeoutMs: providerActionTimeoutMs(registration, actionId, timeoutMs),
|
|
189
200
|
signal,
|
|
190
201
|
}));
|
|
191
202
|
}
|
|
203
|
+
const descriptor = registration.actions.find((action) => action.actionId === actionId);
|
|
192
204
|
return await (dependencies.managedCall ?? executeManagedPluginProcess)(managedSpec(registration), {
|
|
193
205
|
requestId,
|
|
194
206
|
actionId,
|
|
195
207
|
input: args,
|
|
196
|
-
timeoutMs:
|
|
208
|
+
timeoutMs: providerActionTimeoutMs(registration, actionId, timeoutMs),
|
|
209
|
+
effectOutcomeOnTimeout: descriptor && !descriptor.readOnly ? 'outcome_unknown' : 'failed',
|
|
197
210
|
signal,
|
|
198
211
|
});
|
|
199
212
|
}
|
|
@@ -256,13 +269,36 @@ function externalProviderPolicyContext(
|
|
|
256
269
|
};
|
|
257
270
|
}
|
|
258
271
|
|
|
272
|
+
interface ExternalPluginAdapterSnapshot {
|
|
273
|
+
registrationSetIdentity: string;
|
|
274
|
+
adapters: readonly AssistantPluginAdapter[];
|
|
275
|
+
byPluginId: ReadonlyMap<string, AssistantPluginAdapter>;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const externalPluginAdapterSnapshots = new Map<string, ExternalPluginAdapterSnapshot>();
|
|
279
|
+
|
|
280
|
+
function externalPluginAdapterSnapshot(controllerHome: string): ExternalPluginAdapterSnapshot {
|
|
281
|
+
const registrationSetIdentity = externalPluginRegistrationSetIdentity(controllerHome);
|
|
282
|
+
const cached = externalPluginAdapterSnapshots.get(controllerHome);
|
|
283
|
+
if (cached?.registrationSetIdentity === registrationSetIdentity) return cached;
|
|
284
|
+
|
|
285
|
+
const adapters = listExternalPluginRegistrations(controllerHome)
|
|
286
|
+
.map((registration) => createExternalPluginAdapter(registration));
|
|
287
|
+
const snapshot: ExternalPluginAdapterSnapshot = {
|
|
288
|
+
registrationSetIdentity,
|
|
289
|
+
adapters,
|
|
290
|
+
byPluginId: new Map(adapters.map((adapter) => [adapter.pluginId, adapter])),
|
|
291
|
+
};
|
|
292
|
+
externalPluginAdapterSnapshots.set(controllerHome, snapshot);
|
|
293
|
+
return snapshot;
|
|
294
|
+
}
|
|
295
|
+
|
|
259
296
|
export function getExternalPluginAdapter(controllerHome: string, pluginId: string): AssistantPluginAdapter | undefined {
|
|
260
|
-
|
|
261
|
-
return registration ? createExternalPluginAdapter(registration) : undefined;
|
|
297
|
+
return externalPluginAdapterSnapshot(controllerHome).byPluginId.get(pluginId);
|
|
262
298
|
}
|
|
263
299
|
|
|
264
300
|
export function listExternalPluginAdapters(controllerHome: string): AssistantPluginAdapter[] {
|
|
265
|
-
return
|
|
301
|
+
return [...externalPluginAdapterSnapshot(controllerHome).adapters];
|
|
266
302
|
}
|
|
267
303
|
|
|
268
304
|
export function createExternalPluginAdapter(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createHash } from 'crypto';
|
|
2
|
-
import { existsSync, mkdirSync, readdirSync, rmSync } from 'fs';
|
|
2
|
+
import { existsSync, mkdirSync, readdirSync, rmSync, statSync } from 'fs';
|
|
3
3
|
import { isAbsolute, join } from 'path';
|
|
4
4
|
import { controllerSystemRoot, ensureControllerHome } from '../../cli/repositories/controller-home';
|
|
5
5
|
import { readJsonFile, sanitizeFileComponent, writeJsonAtomic } from '../shared/json-files';
|
|
@@ -98,6 +98,26 @@ export function externalPluginRegistrationPath(controllerHome: string, pluginId:
|
|
|
98
98
|
return join(registrationRoot(controllerHome), `${sanitizeFileComponent(pluginId)}.json`);
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
export function externalPluginRegistrationSetIdentity(controllerHome: string): string {
|
|
102
|
+
const root = registrationRoot(controllerHome);
|
|
103
|
+
if (!existsSync(root)) return 'absent';
|
|
104
|
+
const names = readdirSync(root, { withFileTypes: true })
|
|
105
|
+
.filter((entry) => entry.isFile() && entry.name.endsWith('.json'))
|
|
106
|
+
.map((entry) => entry.name)
|
|
107
|
+
.sort((left, right) => left.localeCompare(right));
|
|
108
|
+
return names.map((name) => {
|
|
109
|
+
const path = join(root, name);
|
|
110
|
+
try {
|
|
111
|
+
const stat = statSync(path, { bigint: true });
|
|
112
|
+
return `${name}:${stat.dev}:${stat.ino}:${stat.size}:${stat.mtimeNs}:${stat.ctimeNs}`;
|
|
113
|
+
} catch {
|
|
114
|
+
// A concurrent registration replacement/removal is itself an identity
|
|
115
|
+
// change. Do not reuse the prior adapter snapshot across that race.
|
|
116
|
+
return `${name}:changed`;
|
|
117
|
+
}
|
|
118
|
+
}).join('|');
|
|
119
|
+
}
|
|
120
|
+
|
|
101
121
|
function boundedInteger(value: number | undefined, fallback: number, min: number, max: number): number {
|
|
102
122
|
if (typeof value !== 'number' || !Number.isFinite(value)) return fallback;
|
|
103
123
|
return Math.min(Math.max(Math.trunc(value), min), max);
|
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
AssistantPluginPermissionScope,
|
|
8
8
|
} from './types';
|
|
9
9
|
import { AssistantPluginError } from './errors';
|
|
10
|
+
import { importStoredGoogleClientSecretFromClipboard } from '../safe-tooling/google-credential-store';
|
|
10
11
|
import {
|
|
11
12
|
type GmailPluginConfig,
|
|
12
13
|
encodeBase64Url,
|
|
@@ -127,6 +128,24 @@ function gmailActions(): AssistantPluginActionDescriptor[] {
|
|
|
127
128
|
additionalProperties: false,
|
|
128
129
|
},
|
|
129
130
|
},
|
|
131
|
+
{
|
|
132
|
+
actionId: 'import_oauth_client_secret_from_clipboard',
|
|
133
|
+
title: 'Import Gmail OAuth client secret',
|
|
134
|
+
description: 'Consume the current macOS clipboard once, store the OAuth client secret in Keychain, clear the clipboard, and never return credential material.',
|
|
135
|
+
readOnly: false,
|
|
136
|
+
risk: 'workspace_write',
|
|
137
|
+
confirmation: 'authorization',
|
|
138
|
+
defaultTimeoutMs: 10_000,
|
|
139
|
+
cancellable: false,
|
|
140
|
+
idempotent: false,
|
|
141
|
+
scopes: ['gmail.readonly'],
|
|
142
|
+
resourceClaims: [{ resource: 'provider-state', mode: 'write' }],
|
|
143
|
+
argumentsSchema: {
|
|
144
|
+
type: 'object',
|
|
145
|
+
properties: {},
|
|
146
|
+
additionalProperties: false,
|
|
147
|
+
},
|
|
148
|
+
},
|
|
130
149
|
{
|
|
131
150
|
actionId: 'list_messages',
|
|
132
151
|
title: 'List Gmail messages',
|
|
@@ -668,7 +687,7 @@ function gmailProvider(config: GmailPluginConfig, repoRoot?: string): GmailProvi
|
|
|
668
687
|
export function buildGmailPluginManifest(previousRevision = 0, previousUpdatedAt?: string, repoRoot?: string, context?: AssistantPluginBuildContext): AssistantPluginManifest {
|
|
669
688
|
const root = repoRoot ?? process.cwd();
|
|
670
689
|
const config = loadGmailPluginConfig(root, context);
|
|
671
|
-
const auth = resolveGoogleAuth('gmail', config, { repoRoot: root });
|
|
690
|
+
const auth = resolveGoogleAuth('gmail', config, { repoRoot: root, controllerHome: context?.controllerHome });
|
|
672
691
|
const state = pluginStateFromGoogleAuth(config, auth);
|
|
673
692
|
return {
|
|
674
693
|
schemaVersion: 1,
|
|
@@ -714,9 +733,11 @@ export async function executeGmailPluginAction(input: AssistantPluginActionExecu
|
|
|
714
733
|
});
|
|
715
734
|
return {
|
|
716
735
|
config,
|
|
717
|
-
auth: resolveGoogleAuth('gmail', config, { repoRoot: input.repoRoot }),
|
|
736
|
+
auth: resolveGoogleAuth('gmail', config, { repoRoot: input.repoRoot, controllerHome: input.controllerHome }),
|
|
718
737
|
};
|
|
719
738
|
}
|
|
739
|
+
case 'import_oauth_client_secret_from_clipboard':
|
|
740
|
+
return importStoredGoogleClientSecretFromClipboard('gmail');
|
|
720
741
|
case 'list_messages':
|
|
721
742
|
return gmailProvider(current, input.repoRoot).listMessages(input.args, current);
|
|
722
743
|
case 'get_message':
|
|
@@ -394,7 +394,7 @@ function calendarProvider(config: GoogleCalendarPluginConfig, repoRoot?: string)
|
|
|
394
394
|
export function buildGoogleCalendarPluginManifest(previousRevision = 0, previousUpdatedAt?: string, repoRoot?: string, context?: AssistantPluginBuildContext): AssistantPluginManifest {
|
|
395
395
|
const root = repoRoot ?? process.cwd();
|
|
396
396
|
const config = loadGoogleCalendarPluginConfig(root, context);
|
|
397
|
-
const auth = resolveGoogleAuth('calendar', config, { repoRoot: root });
|
|
397
|
+
const auth = resolveGoogleAuth('calendar', config, { repoRoot: root, controllerHome: context?.controllerHome });
|
|
398
398
|
const state = pluginStateFromGoogleAuth(config, auth);
|
|
399
399
|
return {
|
|
400
400
|
schemaVersion: 1,
|
|
@@ -441,7 +441,7 @@ export async function executeGoogleCalendarPluginAction(input: AssistantPluginAc
|
|
|
441
441
|
});
|
|
442
442
|
return {
|
|
443
443
|
config,
|
|
444
|
-
auth: resolveGoogleAuth('calendar', config, { repoRoot: input.repoRoot }),
|
|
444
|
+
auth: resolveGoogleAuth('calendar', config, { repoRoot: input.repoRoot, controllerHome: input.controllerHome }),
|
|
445
445
|
};
|
|
446
446
|
}
|
|
447
447
|
case 'list_events':
|