@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
|
@@ -6,7 +6,7 @@ import type {
|
|
|
6
6
|
} from './types';
|
|
7
7
|
import { AssistantPluginError, toAssistantPluginError } from './errors';
|
|
8
8
|
import { bootstrapManagedRuntimeEnv } from '../shared/managed-env';
|
|
9
|
-
import { readStoredGoogleRefreshToken } from '../safe-tooling/google-credential-store';
|
|
9
|
+
import { readStoredGoogleClientSecret, readStoredGoogleRefreshToken } from '../safe-tooling/google-credential-store';
|
|
10
10
|
import { readRepositoryPluginConfig, writeRepositoryPluginConfig, type RepositoryPluginConfigContext } from './config-store';
|
|
11
11
|
|
|
12
12
|
export type GoogleProviderKind = 'mock' | 'google-workspace';
|
|
@@ -128,8 +128,15 @@ function refreshCredential(service: GoogleService): { name: string; value: strin
|
|
|
128
128
|
return stored ? { name: stored.source, value: stored.token } : undefined;
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
+
function clientSecretCredential(service: GoogleService): { name: string; value: string } | undefined {
|
|
132
|
+
const fromEnv = firstEnv(clientSecretEnvNames(service));
|
|
133
|
+
if (fromEnv) return fromEnv;
|
|
134
|
+
const stored = readStoredGoogleClientSecret(service);
|
|
135
|
+
return stored ? { name: stored.source, value: stored.secret } : undefined;
|
|
136
|
+
}
|
|
137
|
+
|
|
131
138
|
function refreshCredentialsReady(service: GoogleService): boolean {
|
|
132
|
-
return Boolean(refreshCredential(service) && firstEnv(clientIdEnvNames(service))
|
|
139
|
+
return Boolean(refreshCredential(service) && firstEnv(clientIdEnvNames(service)));
|
|
133
140
|
}
|
|
134
141
|
|
|
135
142
|
export function installGoogleAccessToken(service: GoogleService, accessToken: string, expiresInSeconds = 3600, source = 'oauth'): void {
|
|
@@ -289,9 +296,9 @@ function tokenEnvNames(service: GoogleService): string[] {
|
|
|
289
296
|
export function resolveGoogleAuth(
|
|
290
297
|
service: GoogleService,
|
|
291
298
|
config: GooglePluginConfig,
|
|
292
|
-
options: { repoRoot?: string } = {},
|
|
299
|
+
options: { repoRoot?: string; controllerHome?: string } = {},
|
|
293
300
|
): GoogleAuthState {
|
|
294
|
-
bootstrapManagedRuntimeEnv({ repoRoot: options.repoRoot });
|
|
301
|
+
bootstrapManagedRuntimeEnv({ repoRoot: options.repoRoot, controllerHome: options.controllerHome });
|
|
295
302
|
if (config.provider === 'mock') {
|
|
296
303
|
return {
|
|
297
304
|
provider: 'mock', ready: true, authenticated: true, probed: true,
|
|
@@ -428,8 +435,8 @@ function serviceBaseUrl(service: GoogleService): string {
|
|
|
428
435
|
async function refreshGoogleAccessToken(service: GoogleService, timeoutMs: number): Promise<string | undefined> {
|
|
429
436
|
const refreshToken = refreshCredential(service);
|
|
430
437
|
const clientId = firstEnv(clientIdEnvNames(service));
|
|
431
|
-
const clientSecret =
|
|
432
|
-
if (!refreshToken || !clientId
|
|
438
|
+
const clientSecret = clientSecretCredential(service);
|
|
439
|
+
if (!refreshToken || !clientId) return undefined;
|
|
433
440
|
const controller = new AbortController();
|
|
434
441
|
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
435
442
|
try {
|
|
@@ -437,8 +444,8 @@ async function refreshGoogleAccessToken(service: GoogleService, timeoutMs: numbe
|
|
|
437
444
|
grant_type: 'refresh_token',
|
|
438
445
|
refresh_token: refreshToken.value,
|
|
439
446
|
client_id: clientId.value,
|
|
440
|
-
client_secret: clientSecret.value,
|
|
441
447
|
});
|
|
448
|
+
if (clientSecret) body.set('client_secret', clientSecret.value);
|
|
442
449
|
const response = await fetch('https://oauth2.googleapis.com/token', {
|
|
443
450
|
method: 'POST',
|
|
444
451
|
headers: { 'content-type': 'application/x-www-form-urlencoded', accept: 'application/json' },
|
|
@@ -457,7 +457,7 @@ function tasksProvider(config: GoogleTasksPluginConfig, repoRoot?: string): Task
|
|
|
457
457
|
export function buildGoogleTasksPluginManifest(previousRevision = 0, previousUpdatedAt?: string, repoRoot?: string, context?: AssistantPluginBuildContext): AssistantPluginManifest {
|
|
458
458
|
const root = repoRoot ?? process.cwd();
|
|
459
459
|
const config = loadGoogleTasksPluginConfig(root, context);
|
|
460
|
-
const auth = resolveGoogleAuth('tasks', config, { repoRoot: root });
|
|
460
|
+
const auth = resolveGoogleAuth('tasks', config, { repoRoot: root, controllerHome: context?.controllerHome });
|
|
461
461
|
const state = pluginStateFromGoogleAuth(config, auth);
|
|
462
462
|
return {
|
|
463
463
|
schemaVersion: 1,
|
|
@@ -504,7 +504,7 @@ export async function executeGoogleTasksPluginAction(input: AssistantPluginActio
|
|
|
504
504
|
});
|
|
505
505
|
return {
|
|
506
506
|
config,
|
|
507
|
-
auth: resolveGoogleAuth('tasks', config, { repoRoot: input.repoRoot }),
|
|
507
|
+
auth: resolveGoogleAuth('tasks', config, { repoRoot: input.repoRoot, controllerHome: input.controllerHome }),
|
|
508
508
|
};
|
|
509
509
|
}
|
|
510
510
|
case 'list_tasklists':
|
|
@@ -345,7 +345,7 @@ function actions(): AssistantPluginActionDescriptor[] {
|
|
|
345
345
|
description: 'Capture a simulator screenshot into controller artifact storage.',
|
|
346
346
|
readOnly: false,
|
|
347
347
|
risk: 'workspace_write',
|
|
348
|
-
confirmation: '
|
|
348
|
+
confirmation: 'authorization',
|
|
349
349
|
defaultTimeoutMs: 60_000,
|
|
350
350
|
cancellable: true,
|
|
351
351
|
idempotent: false,
|
|
@@ -2,16 +2,22 @@ import { createHash } from 'crypto';
|
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'fs';
|
|
3
3
|
import { dirname, join, resolve } from 'path';
|
|
4
4
|
import type { RepositoryRecord } from '../../cli/repositories/types';
|
|
5
|
-
import { repositoryControllerRoot } from '../../cli/repositories/controller-home';
|
|
5
|
+
import { controllerSystemRoot, repositoryControllerRoot } from '../../cli/repositories/controller-home';
|
|
6
6
|
import { resolveTrustedNodeExecutable } from '../shared/trusted-node-executable';
|
|
7
7
|
import { startLightweightInternalProcess, waitForLightweightProcess } from '../execution/process-runtime/lightweight-managed';
|
|
8
|
+
import { getProcessHandle, spawnManagedProcess, waitForProcess } from '../execution/process-runtime/runtime';
|
|
9
|
+
import { getProcessRecord, getProcessRequestBinding } from '../execution/process-runtime/store';
|
|
8
10
|
import type { ProcessHandle } from '../execution/process-runtime/types';
|
|
11
|
+
import { FORGE_INSTANCE_PROCESS_SCOPE_KEY } from '../execution/process-runtime/process-scope';
|
|
12
|
+
import type { ResolvedExecutionIdentity } from '../control-plane/execution/execution-identity';
|
|
9
13
|
import type { AssistantPluginActionRequest } from './types';
|
|
10
14
|
|
|
11
15
|
interface LightweightPluginActionEnvelope {
|
|
12
16
|
schemaVersion: 1;
|
|
13
17
|
controllerHome: string;
|
|
14
|
-
|
|
18
|
+
/** Legacy repository envelope coordinate; absent for ForgeInstance-scoped controller plugins. */
|
|
19
|
+
repoId?: string;
|
|
20
|
+
scope?: { kind: 'controller' } | { kind: 'repository'; repoId: string };
|
|
15
21
|
request: Omit<AssistantPluginActionRequest, 'signal'>;
|
|
16
22
|
}
|
|
17
23
|
|
|
@@ -28,6 +34,18 @@ function envelopeBytes(controllerHome: string, repository: RepositoryRecord, req
|
|
|
28
34
|
schemaVersion: 1,
|
|
29
35
|
controllerHome,
|
|
30
36
|
repoId: repository.repoId,
|
|
37
|
+
scope: { kind: 'repository', repoId: repository.repoId },
|
|
38
|
+
request: serializableRequest,
|
|
39
|
+
};
|
|
40
|
+
return `${JSON.stringify(envelope)}\n`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function controllerEnvelopeBytes(controllerHome: string, request: AssistantPluginActionRequest): string {
|
|
44
|
+
const { signal: _signal, ...serializableRequest } = request;
|
|
45
|
+
const envelope: LightweightPluginActionEnvelope = {
|
|
46
|
+
schemaVersion: 1,
|
|
47
|
+
controllerHome,
|
|
48
|
+
scope: { kind: 'controller' },
|
|
31
49
|
request: serializableRequest,
|
|
32
50
|
};
|
|
33
51
|
return `${JSON.stringify(envelope)}\n`;
|
|
@@ -142,6 +160,194 @@ export async function startLightweightPluginAction(input: {
|
|
|
142
160
|
return { handle, requestSha256 };
|
|
143
161
|
}
|
|
144
162
|
|
|
163
|
+
export async function startManagedControllerPluginAction(input: {
|
|
164
|
+
controllerHome: string;
|
|
165
|
+
request: AssistantPluginActionRequest;
|
|
166
|
+
interactiveWaitMs?: number;
|
|
167
|
+
timeoutMs: number;
|
|
168
|
+
}): Promise<LightweightPluginActionStart> {
|
|
169
|
+
const scopeKey = FORGE_INSTANCE_PROCESS_SCOPE_KEY;
|
|
170
|
+
const requestToken = createHash('sha256')
|
|
171
|
+
.update(`${scopeKey}\u0000${input.request.requestId}`)
|
|
172
|
+
.digest('hex')
|
|
173
|
+
.slice(0, 24);
|
|
174
|
+
const instanceRoot = controllerSystemRoot(input.controllerHome);
|
|
175
|
+
const requestRoot = join(instanceRoot, 'plugin-action-processes');
|
|
176
|
+
const requestPath = join(requestRoot, `${requestToken}.request.json`);
|
|
177
|
+
const bytes = controllerEnvelopeBytes(input.controllerHome, input.request);
|
|
178
|
+
const requestSha256 = createHash('sha256').update(bytes).digest('hex');
|
|
179
|
+
const existingBinding = getProcessRequestBinding(input.controllerHome, scopeKey, undefined, input.request.requestId);
|
|
180
|
+
if (existingBinding) {
|
|
181
|
+
if (existsSync(requestPath)) {
|
|
182
|
+
const existingBytes = readFileSync(requestPath, 'utf8');
|
|
183
|
+
if (createHash('sha256').update(existingBytes).digest('hex') !== requestSha256) {
|
|
184
|
+
throw new Error(`PROCESS_REQUEST_CONFLICT: plugin request ${input.request.requestId} already has different arguments`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
const existing = getProcessHandle(input.controllerHome, scopeKey, existingBinding.processId);
|
|
188
|
+
if (!existing) throw new Error(`PROCESS_REQUEST_INCOMPLETE: plugin request ${input.request.requestId} is bound to missing process ${existingBinding.processId}; refusing re-execution`);
|
|
189
|
+
const processRecord = getProcessRecord(input.controllerHome, scopeKey, existingBinding.processId);
|
|
190
|
+
if (processRecord?.origin?.requestSemanticFingerprint && processRecord.origin.requestSemanticFingerprint !== requestSha256) {
|
|
191
|
+
throw new Error(`PROCESS_REQUEST_CONFLICT: plugin request ${input.request.requestId} already has different arguments`);
|
|
192
|
+
}
|
|
193
|
+
return { handle: { ...existing, deduplicated: true, requestId: input.request.requestId }, requestSha256 };
|
|
194
|
+
}
|
|
195
|
+
if (existsSync(requestPath)) {
|
|
196
|
+
const existingBytes = readFileSync(requestPath, 'utf8');
|
|
197
|
+
if (createHash('sha256').update(existingBytes).digest('hex') !== requestSha256) {
|
|
198
|
+
throw new Error(`PROCESS_REQUEST_CONFLICT: plugin request ${input.request.requestId} already has different arguments`);
|
|
199
|
+
}
|
|
200
|
+
} else {
|
|
201
|
+
privateAtomicWrite(requestPath, bytes);
|
|
202
|
+
}
|
|
203
|
+
const invocation = resolveLightweightPluginActionRuntimeInvocation();
|
|
204
|
+
const executionIdentity: ResolvedExecutionIdentity = Object.freeze({
|
|
205
|
+
schemaVersion: 1 as const,
|
|
206
|
+
authority: 'forge_instance' as const,
|
|
207
|
+
repositoryId: scopeKey,
|
|
208
|
+
checkoutId: scopeKey,
|
|
209
|
+
canonicalRoot: instanceRoot,
|
|
210
|
+
});
|
|
211
|
+
const handle = await spawnManagedProcess({
|
|
212
|
+
controllerHome: input.controllerHome,
|
|
213
|
+
repoId: scopeKey,
|
|
214
|
+
principalId: input.request.origin.actor?.trim() || undefined,
|
|
215
|
+
executionIdentity,
|
|
216
|
+
commandId: `plugin-action:${input.request.requestId}`,
|
|
217
|
+
trustedRuntimeChild: 'plugin_action_sidecar',
|
|
218
|
+
command: {
|
|
219
|
+
kind: 'argv',
|
|
220
|
+
executable: invocation.executable,
|
|
221
|
+
args: [...invocation.argsPrefix, '--request', requestPath, '--expected-sha256', requestSha256],
|
|
222
|
+
cwd: instanceRoot,
|
|
223
|
+
},
|
|
224
|
+
interactiveWaitMs: Math.max(0, input.interactiveWaitMs ?? 750),
|
|
225
|
+
timeoutMs: input.timeoutMs,
|
|
226
|
+
maxOutputBytes: 64 * 1024,
|
|
227
|
+
origin: {
|
|
228
|
+
surface: 'mcp',
|
|
229
|
+
toolName: 'plugin_action_execute',
|
|
230
|
+
requestId: input.request.requestId,
|
|
231
|
+
requestSemanticFingerprint: requestSha256,
|
|
232
|
+
correlationId: input.request.workId,
|
|
233
|
+
},
|
|
234
|
+
signal: input.request.signal,
|
|
235
|
+
});
|
|
236
|
+
return { handle, requestSha256 };
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export async function startManagedPluginAction(input: {
|
|
240
|
+
controllerHome: string;
|
|
241
|
+
repository: RepositoryRecord;
|
|
242
|
+
request: AssistantPluginActionRequest;
|
|
243
|
+
interactiveWaitMs?: number;
|
|
244
|
+
timeoutMs: number;
|
|
245
|
+
}): Promise<LightweightPluginActionStart> {
|
|
246
|
+
const requestToken = createHash('sha256')
|
|
247
|
+
.update(`${input.repository.repoId}\u0000${input.request.requestId}`)
|
|
248
|
+
.digest('hex')
|
|
249
|
+
.slice(0, 24);
|
|
250
|
+
const requestRoot = join(repositoryControllerRoot(input.controllerHome, input.repository.repoId), 'plugin-action-processes');
|
|
251
|
+
const requestPath = join(requestRoot, `${requestToken}.request.json`);
|
|
252
|
+
const bytes = envelopeBytes(input.controllerHome, input.repository, input.request);
|
|
253
|
+
const requestSha256 = createHash('sha256').update(bytes).digest('hex');
|
|
254
|
+
|
|
255
|
+
const existingBinding = getProcessRequestBinding(
|
|
256
|
+
input.controllerHome,
|
|
257
|
+
input.repository.repoId,
|
|
258
|
+
input.repository.activeCheckoutId,
|
|
259
|
+
input.request.requestId,
|
|
260
|
+
);
|
|
261
|
+
if (existingBinding) {
|
|
262
|
+
if (existsSync(requestPath)) {
|
|
263
|
+
const existingBytes = readFileSync(requestPath, 'utf8');
|
|
264
|
+
const existingSha256 = createHash('sha256').update(existingBytes).digest('hex');
|
|
265
|
+
if (existingSha256 !== requestSha256) {
|
|
266
|
+
throw new Error(`PROCESS_REQUEST_CONFLICT: plugin request ${input.request.requestId} already has different arguments`);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
const existing = getProcessHandle(input.controllerHome, input.repository.repoId, existingBinding.processId);
|
|
270
|
+
if (!existing) {
|
|
271
|
+
throw new Error(`PROCESS_REQUEST_INCOMPLETE: plugin request ${input.request.requestId} is bound to missing process ${existingBinding.processId}; refusing re-execution`);
|
|
272
|
+
}
|
|
273
|
+
const processRecord = getProcessRecord(input.controllerHome, input.repository.repoId, existingBinding.processId);
|
|
274
|
+
if (processRecord?.origin?.requestSemanticFingerprint && processRecord.origin.requestSemanticFingerprint !== requestSha256) {
|
|
275
|
+
throw new Error(`PROCESS_REQUEST_CONFLICT: plugin request ${input.request.requestId} already has different arguments`);
|
|
276
|
+
}
|
|
277
|
+
return { handle: { ...existing, deduplicated: true, requestId: input.request.requestId }, requestSha256 };
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (existsSync(requestPath)) {
|
|
281
|
+
const existingBytes = readFileSync(requestPath, 'utf8');
|
|
282
|
+
const existingSha256 = createHash('sha256').update(existingBytes).digest('hex');
|
|
283
|
+
if (existingSha256 !== requestSha256) {
|
|
284
|
+
throw new Error(`PROCESS_REQUEST_CONFLICT: plugin request ${input.request.requestId} already has different arguments`);
|
|
285
|
+
}
|
|
286
|
+
} else {
|
|
287
|
+
privateAtomicWrite(requestPath, bytes);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const invocation = resolveLightweightPluginActionRuntimeInvocation();
|
|
291
|
+
const executionIdentity: ResolvedExecutionIdentity = Object.freeze({
|
|
292
|
+
schemaVersion: 1 as const,
|
|
293
|
+
authority: 'ephemeral_workspace' as const,
|
|
294
|
+
repositoryId: input.repository.repoId,
|
|
295
|
+
checkoutId: input.repository.activeCheckoutId,
|
|
296
|
+
canonicalRoot: input.repository.canonicalRoot,
|
|
297
|
+
...(input.request.workId ? { workId: input.request.workId } : {}),
|
|
298
|
+
});
|
|
299
|
+
const handle = await spawnManagedProcess({
|
|
300
|
+
controllerHome: input.controllerHome,
|
|
301
|
+
repoId: input.repository.repoId,
|
|
302
|
+
checkoutId: input.repository.activeCheckoutId,
|
|
303
|
+
executionIdentity,
|
|
304
|
+
workId: input.request.workId,
|
|
305
|
+
commandId: `plugin-action:${input.request.requestId}`,
|
|
306
|
+
trustedRuntimeChild: 'plugin_action_sidecar',
|
|
307
|
+
command: {
|
|
308
|
+
kind: 'argv',
|
|
309
|
+
executable: invocation.executable,
|
|
310
|
+
args: [
|
|
311
|
+
...invocation.argsPrefix,
|
|
312
|
+
'--request', requestPath,
|
|
313
|
+
'--expected-sha256', requestSha256,
|
|
314
|
+
],
|
|
315
|
+
cwd: input.repository.canonicalRoot,
|
|
316
|
+
},
|
|
317
|
+
interactiveWaitMs: Math.max(0, input.interactiveWaitMs ?? 750),
|
|
318
|
+
timeoutMs: input.timeoutMs,
|
|
319
|
+
maxOutputBytes: 64 * 1024,
|
|
320
|
+
origin: {
|
|
321
|
+
surface: 'mcp',
|
|
322
|
+
toolName: 'plugin_action_execute',
|
|
323
|
+
requestId: input.request.requestId,
|
|
324
|
+
requestSemanticFingerprint: requestSha256,
|
|
325
|
+
correlationId: input.request.workId,
|
|
326
|
+
},
|
|
327
|
+
signal: input.request.signal,
|
|
328
|
+
});
|
|
329
|
+
return { handle, requestSha256 };
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
export async function waitManagedControllerPluginAction(
|
|
333
|
+
controllerHome: string,
|
|
334
|
+
processId: string,
|
|
335
|
+
timeoutMs: number,
|
|
336
|
+
signal?: AbortSignal,
|
|
337
|
+
): Promise<ProcessHandle> {
|
|
338
|
+
return waitForProcess(controllerHome, FORGE_INSTANCE_PROCESS_SCOPE_KEY, processId, { timeoutMs, signal });
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
export async function waitManagedPluginAction(
|
|
342
|
+
controllerHome: string,
|
|
343
|
+
repoId: string,
|
|
344
|
+
processId: string,
|
|
345
|
+
timeoutMs: number,
|
|
346
|
+
signal?: AbortSignal,
|
|
347
|
+
): Promise<ProcessHandle> {
|
|
348
|
+
return waitForProcess(controllerHome, repoId, processId, { timeoutMs, signal });
|
|
349
|
+
}
|
|
350
|
+
|
|
145
351
|
export async function waitLightweightPluginAction(
|
|
146
352
|
controllerHome: string,
|
|
147
353
|
repoId: string,
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
} from 'fs';
|
|
17
17
|
import { dirname, extname, join, resolve } from 'path';
|
|
18
18
|
import { forgeRuntimeServicePaths } from '../root/service';
|
|
19
|
+
import { installWorkflowSupervisorBrowserAdapter, inspectWorkflowSupervisorBrowserAdapter } from './computer-chatgpt-browser-adapter-installer';
|
|
19
20
|
import { createRecoveryConfig, loadRecoveryConfig, repairPublicTunnel } from '../standalone-recovery/core';
|
|
20
21
|
import { activateRecoveryRelease, recoverySourceIdentity, stageRecoveryRelease } from '../standalone-recovery/installer';
|
|
21
22
|
import { readCurrentRecoveryRelease, type RecoveryReleaseDescriptor } from '../standalone-recovery/release';
|
|
@@ -78,6 +79,8 @@ export interface LocalSystemPluginHooks {
|
|
|
78
79
|
signalProcess?: (pid: number, signal: NodeJS.Signals) => void;
|
|
79
80
|
scheduleLaunchAgentRestart?: (service: string) => { pid: number };
|
|
80
81
|
upgradeStandaloneRecovery?: (controllerHome: string) => Promise<Record<string, unknown>>;
|
|
82
|
+
installWorkflowSupervisorBrowserAdapter?: typeof installWorkflowSupervisorBrowserAdapter;
|
|
83
|
+
inspectWorkflowSupervisorBrowserAdapter?: typeof inspectWorkflowSupervisorBrowserAdapter;
|
|
81
84
|
repairPublicTunnel?: typeof repairPublicTunnel;
|
|
82
85
|
recoverySourceIdentity?: typeof recoverySourceIdentity;
|
|
83
86
|
stageRecoveryRelease?: typeof stageRecoveryRelease;
|
|
@@ -802,6 +805,7 @@ async function repairStandaloneRecoveryTunnel(controllerHome: string): Promise<R
|
|
|
802
805
|
function actions(): AssistantPluginActionDescriptor[] {
|
|
803
806
|
const controllerRead = [{ resource: 'repo-state' as const, mode: 'read' as const }];
|
|
804
807
|
const controllerWrite = [{ resource: 'repo-state' as const, mode: 'write' as const }];
|
|
808
|
+
const providerWrite = [{ resource: 'provider-state' as const, mode: 'write' as const }];
|
|
805
809
|
const targetProperties = {
|
|
806
810
|
target_key: { type: 'string' },
|
|
807
811
|
path: { type: 'string' },
|
|
@@ -815,6 +819,8 @@ function actions(): AssistantPluginActionDescriptor[] {
|
|
|
815
819
|
{ actionId: 'start_user_launch_agent', title: 'Start verified user LaunchAgent', description: 'Bootstrap or start one exact current-user LaunchAgent from ~/Library/LaunchAgents only after the installed plist matches the expected program identity.', readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 30_000, cancellable: true, idempotent: true, scopes: ['local-system.process'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: { label: { type: 'string' }, expected_program_contains: { type: 'string' } }, required: ['label', 'expected_program_contains'], additionalProperties: false } },
|
|
816
820
|
{ actionId: 'upgrade_standalone_recovery', title: 'Upgrade standalone Recovery', description: 'Upgrade the installed standalone Recovery from its configured primary Runtime source using the existing immutable Recovery release authority. No caller source path or command is accepted.', readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 240_000, cancellable: false, idempotent: true, scopes: ['local-system.process'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: {}, additionalProperties: false } },
|
|
817
821
|
{ actionId: 'repair_standalone_recovery_tunnel', title: 'Repair standalone Recovery tunnel', description: 'Repair only the installed standalone Recovery public tunnel using its existing configured tunnel identity and Recovery repair authority. No caller tunnel identity, path, executable, or command is accepted.', readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 60_000, cancellable: false, idempotent: true, scopes: ['local-system.process'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: {}, additionalProperties: false } },
|
|
822
|
+
{ actionId: 'workflow_supervisor_browser_adapter_status', title: 'Workflow Supervisor browser adapter status', description: 'Inspect the Controller-owned Workflow Supervisor Chrome adapter projection and exact package-derived Native Messaging registration.', readOnly: true, risk: 'readonly', confirmation: 'none', defaultTimeoutMs: 15_000, cancellable: true, idempotent: true, scopes: ['local-system.browser-adapter'], resourceClaims: [], argumentsSchema: { type: 'object', properties: {}, additionalProperties: false } },
|
|
823
|
+
{ actionId: 'install_workflow_supervisor_browser_adapter', title: 'Install Workflow Supervisor browser adapter', description: 'Project the active immutable Runtime browser adapter into Controller-owned paths and register Native Messaging only for the extension package-derived stable id. No caller path, command, extension id, or browser profile is accepted.', readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 30_000, cancellable: false, idempotent: true, scopes: ['local-system.browser-adapter'], resourceClaims: providerWrite, argumentsSchema: { type: 'object', properties: {}, additionalProperties: false } },
|
|
818
824
|
{ actionId: 'open_application', title: 'Open application', description: 'Open one macOS application by name or bundle id in the background without stealing foreground focus.', readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 30_000, cancellable: true, idempotent: false, scopes: ['local-system.open'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: { app_name: { type: 'string' }, bundle_id: { type: 'string' } }, additionalProperties: false } },
|
|
819
825
|
{ actionId: 'list_targets', title: 'List filesystem targets', description: 'List active expiring local filesystem grants.', readOnly: true, risk: 'readonly', confirmation: 'none', defaultTimeoutMs: 10_000, cancellable: true, idempotent: true, scopes: ['local-system.files.read'], resourceClaims: controllerRead, argumentsSchema: { type: 'object', properties: {}, additionalProperties: false } },
|
|
820
826
|
{ actionId: 'authorize_target', title: 'Authorize filesystem target', description: 'Authorize an expiring filesystem target. By default, a path inside a Git project authorizes the whole project/repository root; use scope=directory only when intentionally granting a narrower directory.', readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 15_000, cancellable: true, idempotent: true, scopes: ['local-system.files.write'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: { target_key: { type: 'string' }, root_path: { type: 'string' }, scope: { type: 'string', enum: ['auto', 'project', 'directory'] }, expires_in_minutes: { type: 'number' }, reason: { type: 'string' }, access: { type: 'string', enum: ['read_only', 'read_write'] } }, required: ['target_key', 'root_path', 'reason'], additionalProperties: false } },
|
|
@@ -825,7 +831,7 @@ function actions(): AssistantPluginActionDescriptor[] {
|
|
|
825
831
|
{ actionId: 'delete_file', title: 'Delete file', description: 'Delete one exact regular file below an authorized read-write target. Arbitrary recursive or directory deletion is never exposed.', readOnly: false, risk: 'destructive', confirmation: 'strong_confirmation', requiredConfirmationText: 'delete-local-system-file', defaultTimeoutMs: 15_000, cancellable: true, idempotent: false, scopes: ['local-system.files.write'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: targetProperties, required: ['target_key', 'path'], additionalProperties: false } },
|
|
826
832
|
{ actionId: 'delete_empty_directory', title: 'Delete empty directory', description: 'Delete one exact empty directory below an authorized read-write target. Target roots and recursive directory deletion are never allowed.', readOnly: false, risk: 'destructive', confirmation: 'strong_confirmation', requiredConfirmationText: 'delete-local-system-empty-directory', defaultTimeoutMs: 15_000, cancellable: true, idempotent: false, scopes: ['local-system.files.write'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: targetProperties, required: ['target_key', 'path'], additionalProperties: false } },
|
|
827
833
|
{ actionId: 'initialize_git', title: 'Initialize local Git repository', description: 'Run only git init inside an authorized read-write target without registering it in Repository Registry.', readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 30_000, cancellable: true, idempotent: true, scopes: ['local-system.files.write'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: { target_key: { type: 'string' }, cwd: { type: 'string' }, initial_branch: { type: 'string' } }, required: ['target_key'], additionalProperties: false } },
|
|
828
|
-
{ actionId: 'execute_command', title: 'Execute target command', description: 'Execute one bounded typed-argv command inside an authorized target
|
|
834
|
+
{ actionId: 'execute_command', title: 'Execute target command', description: 'Execute one bounded typed-argv command inside an authorized filesystem target. This is the narrow target-scoped alternative to broad ForgeInstance process_exec: shell strings, target escapes, destructive/remote writes, and Git mutations other than the dedicated initialize_git action are denied.', readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 30_000, cancellable: true, idempotent: false, scopes: ['local-system.files.read', 'local-system.files.write'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: { target_key: { type: 'string' }, command: { type: 'array', items: { type: 'string' } }, cwd: { type: 'string' }, max_output_bytes: { type: 'number' } }, required: ['target_key', 'command'], additionalProperties: false } },
|
|
829
835
|
{ actionId: 'execute_project_script', title: 'Execute verified project script', description: 'Execute one exact script below an authorized read-write target through a fixed interpreter after its SHA-256 digest and strong confirmation match. Eval flags and shell command strings are never accepted.', readOnly: false, risk: 'destructive', confirmation: 'strong_confirmation', requiredConfirmationText: 'execute-local-system-project-script', defaultTimeoutMs: 30_000, cancellable: true, idempotent: false, scopes: ['local-system.files.read', 'local-system.files.write'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: { target_key: { type: 'string' }, runtime: { type: 'string', enum: ['node', 'bun', 'python3', 'ruby', 'bash', 'sh'] }, script_path: { type: 'string' }, expected_sha256: { type: 'string' }, arguments: { type: 'array', items: { type: 'string' } }, cwd: { type: 'string' }, max_output_bytes: { type: 'number' } }, required: ['target_key', 'runtime', 'script_path', 'expected_sha256'], additionalProperties: false } },
|
|
830
836
|
{ actionId: 'create_directory', title: 'Create directory', description: 'Create a directory below an authorized target without leaving that root.', readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 15_000, cancellable: true, idempotent: true, scopes: ['local-system.files.write'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: targetProperties, required: ['target_key', 'path'], additionalProperties: false } },
|
|
831
837
|
{ actionId: 'copy_file', title: 'Copy file', description: 'Copy a file between authorized targets without overwriting.', readOnly: false, risk: 'workspace_write', confirmation: 'authorization', defaultTimeoutMs: 30_000, cancellable: true, idempotent: false, scopes: ['local-system.files.write'], resourceClaims: controllerWrite, argumentsSchema: { type: 'object', properties: { source_target_key: { type: 'string' }, source_path: { type: 'string' }, destination_target_key: { type: 'string' }, destination_path: { type: 'string' } }, required: ['source_target_key', 'source_path', 'destination_target_key', 'destination_path'], additionalProperties: false } },
|
|
@@ -859,6 +865,7 @@ function permissions(): AssistantPluginPermissionScope[] {
|
|
|
859
865
|
{ scope: 'local-system.read', mode: 'read', description: 'Read bounded local process and memory diagnostics.', granted: true, required: true },
|
|
860
866
|
{ scope: 'local-system.process', mode: 'write', description: 'Terminate one verified PID or control one verified current-user LaunchAgent after explicit authorization.', granted: true, required: false },
|
|
861
867
|
{ scope: 'local-system.open', mode: 'write', description: 'Open applications or authorized files.', granted: true, required: false },
|
|
868
|
+
{ scope: 'local-system.browser-adapter', mode: 'write', description: 'Install and inspect the Controller-owned Workflow Supervisor Chrome adapter and exact Native Messaging registration.', granted: true, required: false },
|
|
862
869
|
{ scope: 'local-system.files.read', mode: 'read', description: 'Read files only below active target grants.', granted: true, required: false },
|
|
863
870
|
{ scope: 'local-system.files.write', mode: 'write', description: 'Create, copy, move, rename, or explicitly delete bounded files and empty directories below active read-write target grants.', granted: true, required: false },
|
|
864
871
|
];
|
|
@@ -870,6 +877,7 @@ function capabilities(): AssistantPluginCapability[] {
|
|
|
870
877
|
{ capabilityId: 'local-system-process-control', title: 'Verified process lifecycle', description: 'Terminate one verified PID or stop/start/restart one verified macOS user LaunchAgent without exposing arbitrary shell execution.', scopes: ['local-system.process'], actions: ['terminate_process', 'restart_user_launch_agent', 'stop_user_launch_agent', 'start_user_launch_agent'] },
|
|
871
878
|
{ capabilityId: 'local-system-recovery-upgrade', title: 'Managed standalone Recovery upgrade', description: 'Upgrade standalone Recovery only from its installed configured source through the immutable Recovery release and rollback authority.', scopes: ['local-system.process'], actions: ['upgrade_standalone_recovery'] },
|
|
872
879
|
{ capabilityId: 'local-system-recovery-tunnel-repair', title: 'Managed standalone Recovery tunnel repair', description: 'Repair only the installed Recovery public tunnel through the existing Recovery tunnel repair authority when the Recovery transport itself is unreachable.', scopes: ['local-system.process'], actions: ['repair_standalone_recovery_tunnel'] },
|
|
880
|
+
{ capabilityId: 'local-system-workflow-supervisor-browser-adapter', title: 'Workflow Supervisor browser adapter', description: 'Inspect or install the stateless Chrome adapter projection used by the Goal-level Workflow Supervisor authority.', scopes: ['local-system.browser-adapter'], actions: ['workflow_supervisor_browser_adapter_status', 'install_workflow_supervisor_browser_adapter'] },
|
|
873
881
|
{ capabilityId: 'local-system-open', title: 'Open local applications and files', description: 'Open applications and authorized files without arbitrary shell access.', scopes: ['local-system.open'], actions: ['open_application', 'reveal_in_finder', 'open_file'] },
|
|
874
882
|
{ capabilityId: 'local-system-files', title: 'Authorized local files', description: 'Use expiring target grants for bounded local file operations and typed-argv commands without repository registration.', scopes: ['local-system.files.read', 'local-system.files.write'], actions: ['list_targets', 'authorize_target', 'revoke_target', 'list_directory', 'read_text', 'write_text', 'delete_file', 'delete_empty_directory', 'initialize_git', 'execute_command', 'execute_project_script', 'create_directory', 'copy_file', 'move_file', 'rename_file'] },
|
|
875
883
|
];
|
|
@@ -884,7 +892,7 @@ export function buildLocalSystemPluginManifest(previousRevision = 0, previousUpd
|
|
|
884
892
|
pluginId: PLUGIN_ID,
|
|
885
893
|
provider: 'local-macos',
|
|
886
894
|
displayName: 'Local System Assistant',
|
|
887
|
-
pluginVersion: '1.5.
|
|
895
|
+
pluginVersion: '1.5.3',
|
|
888
896
|
authority: { strategy: 'derived', duplicateStateAllowed: false, sourceOfTruth: ['controllerHome:system/local-system'] },
|
|
889
897
|
enabled: true,
|
|
890
898
|
lifecycle: { state: currentHealth.ready ? 'enabled' : 'degraded', reason: currentHealth.ready ? 'Local system capabilities are ready.' : currentHealth.warnings[0] },
|
|
@@ -927,6 +935,8 @@ export async function executeLocalSystemPluginAction(input: AssistantPluginActio
|
|
|
927
935
|
case 'start_user_launch_agent': return startVerifiedUserLaunchAgent(input.args.label, input.args.expected_program_contains);
|
|
928
936
|
case 'upgrade_standalone_recovery': return await upgradeStandaloneRecovery(input.controllerHome);
|
|
929
937
|
case 'repair_standalone_recovery_tunnel': return await repairStandaloneRecoveryTunnel(input.controllerHome);
|
|
938
|
+
case 'workflow_supervisor_browser_adapter_status': return (hooks.inspectWorkflowSupervisorBrowserAdapter ?? inspectWorkflowSupervisorBrowserAdapter)(input.controllerHome, { repository: { repoId: input.repoId, repoRoot: input.repoRoot } }) as unknown as Record<string, unknown>;
|
|
939
|
+
case 'install_workflow_supervisor_browser_adapter': return (hooks.installWorkflowSupervisorBrowserAdapter ?? installWorkflowSupervisorBrowserAdapter)(input.controllerHome, { repository: { repoId: input.repoId, repoRoot: input.repoRoot } }) as unknown as Record<string, unknown>;
|
|
930
940
|
case 'open_application': {
|
|
931
941
|
const appName = optionalString(input.args, 'app_name');
|
|
932
942
|
const bundleId = optionalString(input.args, 'bundle_id');
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { spawn, spawnSync } from 'child_process';
|
|
2
2
|
import { existsSync, statSync } from 'fs';
|
|
3
3
|
import { dirname, isAbsolute, resolve } from 'path';
|
|
4
|
-
import {
|
|
4
|
+
import { MAX_PLUGIN_ACTION_TIMEOUT_MS } from '../../../packages/plugin-runtime/external/index';
|
|
5
|
+
import { AssistantPluginError, type AssistantPluginEffectOutcome } from './errors';
|
|
5
6
|
|
|
6
7
|
export const MANAGED_PLUGIN_PROTOCOL_VERSION = 1;
|
|
7
8
|
const DEFAULT_MAX_REQUEST_BYTES = 1_048_576;
|
|
8
9
|
const DEFAULT_MAX_RESPONSE_BYTES = 1_048_576;
|
|
9
10
|
const DEFAULT_MAX_STDERR_CHARS = 8_000;
|
|
10
11
|
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
11
|
-
const MAX_TIMEOUT_MS = 120_000;
|
|
12
12
|
|
|
13
13
|
interface ManagedPluginHandshake {
|
|
14
14
|
schemaVersion: 1;
|
|
@@ -60,12 +60,14 @@ export interface ManagedPluginProcessRequest {
|
|
|
60
60
|
actionId: string;
|
|
61
61
|
input: Record<string, unknown>;
|
|
62
62
|
timeoutMs?: number;
|
|
63
|
+
effectOutcomeOnTimeout?: AssistantPluginEffectOutcome;
|
|
63
64
|
signal?: AbortSignal;
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
function managedError(code: string, message: string, options: { retryable?: boolean; details?: Record<string, unknown> } = {}): AssistantPluginError {
|
|
67
|
+
function managedError(code: string, message: string, options: { retryable?: boolean; effectOutcome?: AssistantPluginEffectOutcome; details?: Record<string, unknown> } = {}): AssistantPluginError {
|
|
67
68
|
return new AssistantPluginError(code, message, {
|
|
68
69
|
retryable: options.retryable ?? true,
|
|
70
|
+
effectOutcome: options.effectOutcome,
|
|
69
71
|
details: options.details,
|
|
70
72
|
});
|
|
71
73
|
}
|
|
@@ -73,7 +75,7 @@ function managedError(code: string, message: string, options: { retryable?: bool
|
|
|
73
75
|
function boundedTimeout(spec: ManagedPluginProcessSpec, request: ManagedPluginProcessRequest): number {
|
|
74
76
|
const requested = request.timeoutMs ?? spec.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
75
77
|
if (!Number.isFinite(requested)) return DEFAULT_TIMEOUT_MS;
|
|
76
|
-
return Math.min(Math.max(Math.trunc(requested), 50),
|
|
78
|
+
return Math.min(Math.max(Math.trunc(requested), 50), MAX_PLUGIN_ACTION_TIMEOUT_MS);
|
|
77
79
|
}
|
|
78
80
|
|
|
79
81
|
function minimalEnvironment(runtimeExecutable: string): NodeJS.ProcessEnv {
|
|
@@ -257,6 +259,7 @@ export async function executeManagedPluginProcess(
|
|
|
257
259
|
let stdoutBytes = 0;
|
|
258
260
|
let stderr = '';
|
|
259
261
|
let handshakeReceived = false;
|
|
262
|
+
let requestDispatched = false;
|
|
260
263
|
let settled = false;
|
|
261
264
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
262
265
|
let killTimer: ReturnType<typeof setTimeout> | undefined;
|
|
@@ -298,6 +301,7 @@ export async function executeManagedPluginProcess(
|
|
|
298
301
|
if (!handshakeReceived) {
|
|
299
302
|
validateHandshake(parsed, spec);
|
|
300
303
|
handshakeReceived = true;
|
|
304
|
+
requestDispatched = true;
|
|
301
305
|
child.stdin.end(`${requestEnvelope}\n`);
|
|
302
306
|
return;
|
|
303
307
|
}
|
|
@@ -318,7 +322,10 @@ export async function executeManagedPluginProcess(
|
|
|
318
322
|
};
|
|
319
323
|
|
|
320
324
|
timer = setTimeout(() => {
|
|
321
|
-
fail(managedError('PLUGIN_MANAGED_PROCESS_TIMEOUT', 'Managed plugin helper timed out.', {
|
|
325
|
+
fail(managedError('PLUGIN_MANAGED_PROCESS_TIMEOUT', 'Managed plugin helper timed out.', {
|
|
326
|
+
retryable: true,
|
|
327
|
+
effectOutcome: requestDispatched ? request.effectOutcomeOnTimeout : 'failed',
|
|
328
|
+
}));
|
|
322
329
|
}, boundedTimeout(spec, request));
|
|
323
330
|
request.signal?.addEventListener('abort', onAbort, { once: true });
|
|
324
331
|
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createHash } from 'crypto';
|
|
3
|
-
import { readFileSync, rmSync } from 'fs';
|
|
3
|
+
import { readFileSync, rmSync, writeFileSync } from 'fs';
|
|
4
4
|
import { getRepository } from '../../cli/repositories/registry';
|
|
5
5
|
import type { AssistantPluginActionRequest } from './types';
|
|
6
|
-
import { submitAssistantPluginAction } from './store';
|
|
6
|
+
import { submitAssistantPluginAction, submitControllerPluginAction } from './store';
|
|
7
7
|
|
|
8
8
|
interface Envelope {
|
|
9
9
|
schemaVersion: 1;
|
|
10
10
|
controllerHome: string;
|
|
11
|
-
repoId
|
|
11
|
+
repoId?: string;
|
|
12
|
+
scope?: { kind: 'controller' } | { kind: 'repository'; repoId: string };
|
|
12
13
|
request: Omit<AssistantPluginActionRequest, 'signal'>;
|
|
13
14
|
}
|
|
14
15
|
|
|
@@ -30,13 +31,16 @@ export async function runPluginActionSidecar(argv = process.argv.slice(2)): Prom
|
|
|
30
31
|
}
|
|
31
32
|
const envelope = JSON.parse(bytes) as Envelope;
|
|
32
33
|
if (envelope.schemaVersion !== 1) throw new Error('PLUGIN_ACTION_REQUEST_VERSION_UNSUPPORTED');
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
const controllerScoped = envelope.scope?.kind === 'controller';
|
|
35
|
+
const repoId = envelope.scope?.kind === 'repository' ? envelope.scope.repoId : envelope.repoId;
|
|
36
|
+
const submitted = controllerScoped
|
|
37
|
+
? await submitControllerPluginAction(envelope.controllerHome, envelope.request)
|
|
38
|
+
: await submitAssistantPluginAction(
|
|
39
|
+
envelope.controllerHome,
|
|
40
|
+
getRepository(repoId ?? '', envelope.controllerHome),
|
|
41
|
+
envelope.request,
|
|
42
|
+
);
|
|
43
|
+
writeFileSync(1, `${JSON.stringify({
|
|
40
44
|
ok: true,
|
|
41
45
|
requestId: submitted.receipt.requestId,
|
|
42
46
|
receiptId: submitted.receipt.receiptId,
|
|
@@ -51,9 +55,9 @@ export async function runPluginActionSidecar(argv = process.argv.slice(2)): Prom
|
|
|
51
55
|
const direct = typeof process.argv[1] === 'string' && process.argv[1].includes('plugin-action-sidecar');
|
|
52
56
|
if (direct) {
|
|
53
57
|
void runPluginActionSidecar()
|
|
54
|
-
.then((code) => { process.
|
|
58
|
+
.then((code) => { process.exit(code); })
|
|
55
59
|
.catch((error) => {
|
|
56
|
-
|
|
57
|
-
process.
|
|
60
|
+
writeFileSync(2, `${error instanceof Error ? error.message : String(error)}\n`);
|
|
61
|
+
process.exit(1);
|
|
58
62
|
});
|
|
59
63
|
}
|
|
@@ -129,7 +129,7 @@ export function buildPluginManagementManifest(previousRevision = 0, previousUpda
|
|
|
129
129
|
return {
|
|
130
130
|
schemaVersion: 1, manifestVersion: 1, revision: Math.max(1, previousRevision || 1), pluginId: PLUGIN_ID,
|
|
131
131
|
provider: 'forge-controller', displayName: 'Forge Plugin Management', pluginVersion: '1.0.0',
|
|
132
|
-
authority: { strategy: 'derived', duplicateStateAllowed: false, sourceOfTruth: ['controller-home:plugins/external/registrations', 'controller-home:system/
|
|
132
|
+
authority: { strategy: 'derived', duplicateStateAllowed: false, sourceOfTruth: ['controller-home:plugins/external/registrations', 'controller-home:system/authorization-grants/grants.json'] },
|
|
133
133
|
enabled: true, lifecycle: { state: 'enabled', reason: 'Canonical external plugin registration authority is available.' },
|
|
134
134
|
health: { state: 'ready', checkedAt: now(), ready: true, probed: true, errors: [], warnings: [] },
|
|
135
135
|
permissions: permissions(), capabilities: capabilities(), actions: actions(), updatedAt: previousUpdatedAt ?? now(),
|