@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,3 +1,4 @@
|
|
|
1
|
+
import { FORGE_INSTANCE_SCOPE_KEY } from '../../src/cli/repositories/controller-home';
|
|
1
2
|
import { withControllerLock } from '../../src/cli/repositories/locks';
|
|
2
3
|
import { readControlPlaneRecord, writeControlPlaneRecord } from '../../src/runtime/control-plane/persistence/sqlite-store';
|
|
3
4
|
import type { ControllerBinding } from '../../packages/kernel/controller/api/index';
|
|
@@ -7,7 +8,8 @@ const NAMESPACE = 'chatgpt_controller_binding';
|
|
|
7
8
|
export interface ChatgptControllerBindingPayload {
|
|
8
9
|
schemaVersion: 1;
|
|
9
10
|
bindingId: string;
|
|
10
|
-
|
|
11
|
+
/** Optional repository provenance only. */
|
|
12
|
+
repoId?: string;
|
|
11
13
|
workId: string;
|
|
12
14
|
sessionId: string;
|
|
13
15
|
browserSessionId?: string;
|
|
@@ -17,39 +19,116 @@ export interface ChatgptControllerBindingPayload {
|
|
|
17
19
|
reasoning?: 'medium' | 'high' | 'xhigh';
|
|
18
20
|
tabPolicy?: 'auto' | 'reuse' | 'new';
|
|
19
21
|
timeoutMs?: number;
|
|
22
|
+
/** Provider transport choice captured by launcher admission; not lifecycle authority. */
|
|
23
|
+
transportConversation?: 'bound' | 'fresh';
|
|
24
|
+
/** Initial provider hint captured for the queued ControllerRound only. */
|
|
25
|
+
continuationPrompt?: string;
|
|
26
|
+
authorizationGrantRefs?: string[];
|
|
20
27
|
createdAt: string;
|
|
21
28
|
updatedAt: string;
|
|
22
29
|
}
|
|
23
30
|
|
|
24
|
-
function
|
|
31
|
+
export function chatgptControllerProviderBindingId(workId: string): string {
|
|
32
|
+
return `chatgpt-controller:${workId}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function canonicalBindingId(workId: string): string {
|
|
36
|
+
return chatgptControllerProviderBindingId(workId);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function legacyBindingId(repoId: string, workId: string): string {
|
|
25
40
|
return `chatgpt-controller:${repoId}:${workId}`;
|
|
26
41
|
}
|
|
27
42
|
|
|
43
|
+
function readBinding(
|
|
44
|
+
controllerHome: string,
|
|
45
|
+
workId: string,
|
|
46
|
+
repoId?: string,
|
|
47
|
+
): { value: ChatgptControllerBindingPayload; revision: number } | undefined {
|
|
48
|
+
const canonicalId = canonicalBindingId(workId);
|
|
49
|
+
const canonical = readControlPlaneRecord<ChatgptControllerBindingPayload>(
|
|
50
|
+
controllerHome,
|
|
51
|
+
NAMESPACE,
|
|
52
|
+
FORGE_INSTANCE_SCOPE_KEY,
|
|
53
|
+
canonicalId,
|
|
54
|
+
);
|
|
55
|
+
const legacy = repoId?.trim()
|
|
56
|
+
? readControlPlaneRecord<ChatgptControllerBindingPayload>(
|
|
57
|
+
controllerHome,
|
|
58
|
+
NAMESPACE,
|
|
59
|
+
repoId.trim(),
|
|
60
|
+
legacyBindingId(repoId.trim(), workId),
|
|
61
|
+
)
|
|
62
|
+
: undefined;
|
|
63
|
+
if (canonical && legacy) {
|
|
64
|
+
const left = canonical.value;
|
|
65
|
+
const right = legacy.value;
|
|
66
|
+
if (left.workId !== right.workId
|
|
67
|
+
|| left.sessionId !== right.sessionId
|
|
68
|
+
|| (left.conversationUrl ?? '') !== (right.conversationUrl ?? '')) {
|
|
69
|
+
throw new Error(`CHATGPT_CONTROLLER_BINDING_COLLISION: ${workId}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return canonical ?? legacy;
|
|
73
|
+
}
|
|
74
|
+
|
|
28
75
|
export function upsertChatgptControllerBinding(
|
|
29
|
-
options: { controllerHome: string; repoId
|
|
76
|
+
options: { controllerHome: string; repoId?: string; now?: () => string },
|
|
30
77
|
input: Omit<ChatgptControllerBindingPayload, 'schemaVersion' | 'bindingId' | 'repoId' | 'createdAt' | 'updatedAt'>,
|
|
31
78
|
): { binding: ControllerBinding; payload: ChatgptControllerBindingPayload } {
|
|
32
|
-
const id =
|
|
33
|
-
return withControllerLock(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
79
|
+
const id = canonicalBindingId(input.workId);
|
|
80
|
+
return withControllerLock(
|
|
81
|
+
options.controllerHome,
|
|
82
|
+
{ scope: 'global', resource: `chatgpt-controller-binding:${input.workId}` },
|
|
83
|
+
`chatgpt-controller-binding:${id}`,
|
|
84
|
+
() => {
|
|
85
|
+
const current = readBinding(options.controllerHome, input.workId, options.repoId);
|
|
86
|
+
const at = options.now?.() ?? new Date().toISOString();
|
|
87
|
+
const payload: ChatgptControllerBindingPayload = {
|
|
88
|
+
...(current?.value ?? {} as ChatgptControllerBindingPayload),
|
|
89
|
+
...input,
|
|
90
|
+
schemaVersion: 1,
|
|
91
|
+
bindingId: id,
|
|
92
|
+
...(options.repoId?.trim() ? { repoId: options.repoId.trim() } : {}),
|
|
93
|
+
createdAt: current?.value.createdAt ?? at,
|
|
94
|
+
updatedAt: at,
|
|
95
|
+
};
|
|
96
|
+
writeControlPlaneRecord(options.controllerHome, {
|
|
97
|
+
namespace: NAMESPACE,
|
|
98
|
+
scope: FORGE_INSTANCE_SCOPE_KEY,
|
|
99
|
+
key: id,
|
|
100
|
+
schemaVersion: 1,
|
|
101
|
+
value: payload,
|
|
102
|
+
action: current ? 'chatgpt_controller_binding_update' : 'chatgpt_controller_binding_create',
|
|
103
|
+
expectedRevision: readControlPlaneRecord<ChatgptControllerBindingPayload>(
|
|
104
|
+
options.controllerHome,
|
|
105
|
+
NAMESPACE,
|
|
106
|
+
FORGE_INSTANCE_SCOPE_KEY,
|
|
107
|
+
id,
|
|
108
|
+
)?.revision ?? null,
|
|
109
|
+
});
|
|
110
|
+
return { binding: { bindingId: id, hostKind: 'chatgpt', adapterRef: id }, payload };
|
|
111
|
+
},
|
|
112
|
+
);
|
|
49
113
|
}
|
|
50
114
|
|
|
51
115
|
export function getChatgptControllerBindingPayload(
|
|
52
|
-
options: { controllerHome: string; repoId
|
|
116
|
+
options: { controllerHome: string; repoId?: string },
|
|
117
|
+
adapterRef: string,
|
|
53
118
|
): ChatgptControllerBindingPayload | undefined {
|
|
54
|
-
|
|
119
|
+
const canonical = readControlPlaneRecord<ChatgptControllerBindingPayload>(
|
|
120
|
+
options.controllerHome,
|
|
121
|
+
NAMESPACE,
|
|
122
|
+
FORGE_INSTANCE_SCOPE_KEY,
|
|
123
|
+
adapterRef,
|
|
124
|
+
)?.value;
|
|
125
|
+
if (canonical) return canonical;
|
|
126
|
+
const repoId = options.repoId?.trim();
|
|
127
|
+
if (!repoId) return undefined;
|
|
128
|
+
return readControlPlaneRecord<ChatgptControllerBindingPayload>(
|
|
129
|
+
options.controllerHome,
|
|
130
|
+
NAMESPACE,
|
|
131
|
+
repoId,
|
|
132
|
+
adapterRef,
|
|
133
|
+
)?.value;
|
|
55
134
|
}
|
|
@@ -14,31 +14,31 @@ export function buildChatgptControllerRoundPrompt(
|
|
|
14
14
|
const snapshot = readControllerRoundContextSnapshot(options, record);
|
|
15
15
|
const requirementLine = snapshot.requirement
|
|
16
16
|
? `Requirement ${snapshot.requirement.requirementId}:state=${snapshot.requirement.state};outcome=${snapshot.requirement.outcomeStatement}`
|
|
17
|
-
:
|
|
17
|
+
: '当前未绑定 durable Requirement。';
|
|
18
18
|
const workLines = snapshot.works.length > 0
|
|
19
19
|
? snapshot.works.map((work) => {
|
|
20
|
-
const summary = `- ${work.workId}:
|
|
20
|
+
const summary = `- ${work.workId}:updated=${work.updatedAt};objective=${work.objective}`;
|
|
21
21
|
if (work.workId !== snapshot.originWorkId || work.acceptanceCriteria.length === 0) return summary;
|
|
22
22
|
return [
|
|
23
23
|
summary,
|
|
24
|
-
' origin Work acceptanceCriteria
|
|
24
|
+
' origin Work acceptanceCriteria:',
|
|
25
25
|
...work.acceptanceCriteria.map((criterion, index) => ` ${index + 1}. ${criterion}`),
|
|
26
26
|
].join('\n');
|
|
27
27
|
}).join('\n')
|
|
28
28
|
: '- 未找到关联 Work 快照';
|
|
29
29
|
const originWork = snapshot.works.find((work) => work.workId === snapshot.originWorkId);
|
|
30
|
-
const terminalOriginGuidance = originWork?.
|
|
31
|
-
? `origin Work ${snapshot.originWorkId}
|
|
30
|
+
const terminalOriginGuidance = originWork?.state === 'completed'
|
|
31
|
+
? `origin Work ${snapshot.originWorkId} 的持久状态已完成。不要重新打开它;重新读取 Requirement/Plan/Work 语义事实,由模型决定是否仍有新的明确工作。`
|
|
32
32
|
: undefined;
|
|
33
33
|
const handoffLines = snapshot.handoffs.length > 0
|
|
34
34
|
? snapshot.handoffs.map((handoff) => `- ${handoff.id}:status=${handoff.status};work=${handoff.workId ?? 'repo'};${handoff.title};reason=${handoff.reason}`).join('\n')
|
|
35
35
|
: '- 当前没有 active linked Handoff';
|
|
36
36
|
return [
|
|
37
|
-
`继续 Forge Requirement
|
|
38
|
-
'
|
|
37
|
+
`继续 Forge ${snapshot.requirement ? `Requirement ${snapshot.requirement.requirementId}` : `Work ${snapshot.originWorkId}`},repo=${snapshot.repoId}。`,
|
|
38
|
+
'下面快照来自本轮 claim-time durable state,用它直接恢复上下文。只有某个事实的新鲜度会实质改变下一次具体 domain action 时,才针对性重新读取;不要把本轮先消耗在重复读取 Requirement/Plan/Work/UserRequest 或 lifecycle bookkeeping 上。',
|
|
39
39
|
requirementLine,
|
|
40
40
|
`关联 Work 快照:\n${workLines}`,
|
|
41
|
-
'origin Work 的 objective 与 acceptanceCriteria
|
|
41
|
+
'origin Work 的 objective 与 acceptanceCriteria 是需要显式检查的 durable semantic contract;语义结论只来自最新事实与模型判断。',
|
|
42
42
|
`Active Handoff 快照:\n${handoffLines}`,
|
|
43
43
|
...(snapshot.assistantContext ? [snapshot.assistantContext] : []),
|
|
44
44
|
...(snapshot.executionQualitySignals?.length ? [
|
|
@@ -46,24 +46,14 @@ export function buildChatgptControllerRoundPrompt(
|
|
|
46
46
|
'Review this evidence before repeating the same operation. Diagnose semantically; record whether an adjustment is justified. Do not infer a bug from edit counts, discard mandatory checks, widen authority or create another supervisor.',
|
|
47
47
|
] : []),
|
|
48
48
|
promptOptions.exactOriginWork
|
|
49
|
-
?
|
|
50
|
-
:
|
|
49
|
+
? `只推进 origin Work ${snapshot.originWorkId} 的既定范围。若存在真实用户授权/判断 blocker,记录一个去重的 UserRequest;否则继续可执行工作。`
|
|
50
|
+
: `origin Work 是 ${snapshot.originWorkId}。不要假设下一步必须继续它;依据最新 semantic state 选择现有或新的明确 Work。`,
|
|
51
51
|
...(terminalOriginGuidance ? [terminalOriginGuidance] : []),
|
|
52
|
-
|
|
53
|
-
'
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
...(snapshot.recoveryReason
|
|
58
|
-
? ['上一轮 ChatGPT 在 liveness grace 到期前没有提交显式 disposition。必须重新读取 durable state,并显式关闭本轮。']
|
|
59
|
-
: []),
|
|
60
|
-
terminalOriginGuidance
|
|
61
|
-
? `terminal predecessor 必须在显式 successor start 完成 mechanical bind 后,再显式提交一次 continue_immediately;得到 pending_release 后仅释放 predecessor。若没有可执行 successor,则按最新 Plan/Requirement 事实使用 wait、带 active Handoff 的 wait_for_user 或 goal_complete。`
|
|
62
|
-
: `如果 Requirement/Goal 需要下一个 controller round,在释放 Work 前提交 continue_immediately,并带 relay_scope_id=${record.relayScopeId}。否则使用 wait、带 active Handoff 的 wait_for_user,或 goal_complete。Frozen MCP client 可使用 controller.disposition:<disposition>:${record.relayScopeId}。`,
|
|
63
|
-
'本轮结束协议是强制的:在向用户输出本轮最终回复之前,必须先提交且仅提交一次 semantic disposition,并完成 controller_release;不得只报告“继续中”“下一步继续”或输出进度后结束本轮。',
|
|
64
|
-
'如果最新 durable state 表明 Requirement/Goal 尚有可执行工作,且不存在真实 external blocker、active Handoff 或必须由用户决定的边界,则必须选择 continue_immediately。wait 只用于真实等待条件;wait_for_user 必须绑定 active Handoff;goal_complete 只用于 Requirement/Goal 已语义完成。',
|
|
65
|
-
'提交 continue_immediately 后必须立即 controller_release 当前 Work。controller_release 是立即续跑的 canonical trigger:Forge 将通过现有 ChatGPT launcher 复用 durable conversation binding 并投递下一 ControllerRound prompt。正常连续推进不得依赖用户再次发送“继续”,也不得用 interval schedule 代替该即时 relay;schedule 只能作为故障恢复/watchdog。',
|
|
66
|
-
'Forge 不得自行推断 semantic next step。现有 Work ownership、Handoff authority 与 external-effect authorization 始终是权威。',
|
|
52
|
+
'Provider/session binding、transport recovery、dedupe、retry 和 continuation bookkeeping 由 Forge 内部维护,不属于模型工作流,也不是 Requirement/Plan/Work 的第二套语义权威。',
|
|
53
|
+
'执行与验证直接使用当前 domain capability;只有 durable 语义实际变化时才更新 Requirement/Plan/Work。Forge 不替模型推断语义 next step。',
|
|
54
|
+
'如果 origin Work 尚未完成且没有真实 UserRequest/外部 blocker,本轮结束前必须完成至少一个直接推进 objective 的具体 domain action,例如源码修改、进程/检查、typed external effect,或对实现决策有实质作用的源码调查。仅汇报状态、重复读取 lifecycle、刷新进度或说明“下一步要做什么”不算推进。',
|
|
55
|
+
'仓库工程、安全、权限和资源 fence 始终有效。若真实外部条件或用户判断阻塞,记录精确 UserRequest/Handoff;不要为了机械续跑创建 sibling Work、PlanStep 或额外 lifecycle。',
|
|
56
|
+
'Presentation-only progress:持续较久或包含多轮工具调用时,在关键阶段用 1–2 句 user-visible 进度说明已确认结果、下一件事或真实 blocker。不要逐工具播报,不要输出 private reasoning / chain-of-thought。',
|
|
67
57
|
].join('\n');
|
|
68
58
|
}
|
|
69
59
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { createHash } from 'crypto';
|
|
1
2
|
import { withControllerLock } from '../../src/cli/repositories/locks';
|
|
2
3
|
import { readControlPlaneRecord, writeControlPlaneRecord } from '../../src/runtime/control-plane/persistence/sqlite-store';
|
|
3
4
|
|
|
4
|
-
// Resource-cleanup evidence only.
|
|
5
|
+
// Resource-cleanup evidence only. Autonomous outer-turn dispatch authority is the Workflow Supervisor Effect ledger; ControllerRound fields are lower-layer/bootstrap compatibility mirrors.
|
|
5
6
|
const NAMESPACE = 'chatgpt_controller_round_settlement';
|
|
6
7
|
|
|
7
8
|
export type ChatgptControllerRoundSettlementStatus =
|
|
@@ -21,15 +22,67 @@ export interface ChatgptControllerRoundSettlement {
|
|
|
21
22
|
status: ChatgptControllerRoundSettlementStatus;
|
|
22
23
|
recordedAt: string;
|
|
23
24
|
error?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Opaque identity of the browser resource and grants used for this settlement
|
|
27
|
+
* attempt. A matching failed attempt must not repeatedly call the provider.
|
|
28
|
+
*/
|
|
29
|
+
attemptIdentity?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function settlementKey(workId: string, relayScopeId: string): string {
|
|
33
|
+
return `${workId}:${relayScopeId}`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Keep browser-session and grant identifiers out of durable settlement evidence
|
|
38
|
+
* while preserving the exact retry boundary: a changed session or grant set may
|
|
39
|
+
* be retried, an unchanged failed attempt may not.
|
|
40
|
+
*/
|
|
41
|
+
export function chatgptControllerRoundSettlementAttemptIdentity(input: {
|
|
42
|
+
browserSessionId: string;
|
|
43
|
+
authorizationGrantRefs?: readonly string[];
|
|
44
|
+
}): string {
|
|
45
|
+
const identity = {
|
|
46
|
+
browserSessionId: input.browserSessionId.trim(),
|
|
47
|
+
authorizationGrantRefs: [...new Set((input.authorizationGrantRefs ?? [])
|
|
48
|
+
.map((grantRef) => grantRef.trim())
|
|
49
|
+
.filter(Boolean))].sort(),
|
|
50
|
+
};
|
|
51
|
+
return `sha256:${createHash('sha256').update(JSON.stringify(identity)).digest('hex')}`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function getChatgptControllerRoundSettlement(
|
|
55
|
+
options: { controllerHome: string; repoId: string },
|
|
56
|
+
input: { workId: string; relayScopeId: string },
|
|
57
|
+
): ChatgptControllerRoundSettlement | undefined {
|
|
58
|
+
return readControlPlaneRecord<ChatgptControllerRoundSettlement>(
|
|
59
|
+
options.controllerHome,
|
|
60
|
+
NAMESPACE,
|
|
61
|
+
options.repoId,
|
|
62
|
+
settlementKey(input.workId, input.relayScopeId),
|
|
63
|
+
)?.value;
|
|
24
64
|
}
|
|
25
65
|
|
|
26
66
|
export function recordChatgptControllerRoundSettlement(
|
|
27
67
|
options: { controllerHome: string; repoId: string; now?: () => string },
|
|
28
|
-
input: {
|
|
68
|
+
input: {
|
|
69
|
+
workId: string;
|
|
70
|
+
relayScopeId: string;
|
|
71
|
+
status: ChatgptControllerRoundSettlementStatus;
|
|
72
|
+
error?: string;
|
|
73
|
+
attemptIdentity?: string;
|
|
74
|
+
},
|
|
29
75
|
): ChatgptControllerRoundSettlement {
|
|
30
|
-
const key =
|
|
76
|
+
const key = settlementKey(input.workId, input.relayScopeId);
|
|
31
77
|
return withControllerLock(options.controllerHome, { scope: 'task', repoId: options.repoId, taskId: `chatgpt-round-settlement-${input.workId}` }, `chatgpt-round-settlement:${key}`, () => {
|
|
32
78
|
const existing = readControlPlaneRecord<ChatgptControllerRoundSettlement>(options.controllerHome, NAMESPACE, options.repoId, key);
|
|
79
|
+
const error = input.error?.trim().slice(0, 2_000) || undefined;
|
|
80
|
+
const attemptIdentity = input.attemptIdentity?.trim().slice(0, 200) || undefined;
|
|
81
|
+
if (
|
|
82
|
+
existing?.value.status === input.status
|
|
83
|
+
&& existing.value.error === error
|
|
84
|
+
&& existing.value.attemptIdentity === attemptIdentity
|
|
85
|
+
) return existing.value;
|
|
33
86
|
const value: ChatgptControllerRoundSettlement = {
|
|
34
87
|
schemaVersion: 1,
|
|
35
88
|
repoId: options.repoId,
|
|
@@ -37,7 +90,8 @@ export function recordChatgptControllerRoundSettlement(
|
|
|
37
90
|
relayScopeId: input.relayScopeId,
|
|
38
91
|
status: input.status,
|
|
39
92
|
recordedAt: options.now?.() ?? new Date().toISOString(),
|
|
40
|
-
...(
|
|
93
|
+
...(error ? { error } : {}),
|
|
94
|
+
...(attemptIdentity ? { attemptIdentity } : {}),
|
|
41
95
|
};
|
|
42
96
|
writeControlPlaneRecord(options.controllerHome, { namespace: NAMESPACE, scope: options.repoId, key, schemaVersion: 1, value, action: 'chatgpt_controller_round_settlement', expectedRevision: existing?.revision ?? null });
|
|
43
97
|
return value;
|
|
@@ -4,6 +4,62 @@ export const DEFAULT_CHATGPT_AUTOMATION_MODEL = 'gpt-5.6';
|
|
|
4
4
|
export const DEFAULT_CHATGPT_AUTOMATION_REASONING = 'high';
|
|
5
5
|
export const DEFAULT_CHATGPT_AUTOMATION_TAB_POLICY = 'auto';
|
|
6
6
|
export const CHATGPT_AUTOMATION_SUBMISSION_OUTCOME_UNKNOWN = 'CHATGPT_AUTOMATION_SUBMISSION_OUTCOME_UNKNOWN';
|
|
7
|
+
export const CHATGPT_AUTOMATION_MESSAGE_DELIVERY_TIMED_OUT = 'CHATGPT_AUTOMATION_MESSAGE_DELIVERY_TIMED_OUT';
|
|
8
|
+
export const CHATGPT_AUTOMATION_RESPONSE_STREAM_UNAVAILABLE = 'CHATGPT_AUTOMATION_RESPONSE_STREAM_UNAVAILABLE';
|
|
9
|
+
export const CHATGPT_AUTOMATION_RATE_LIMITED = 'CHATGPT_AUTOMATION_RATE_LIMITED';
|
|
10
|
+
export const CHATGPT_AUTOMATION_RATE_LIMITED_AFTER_SUBMIT = 'CHATGPT_AUTOMATION_RATE_LIMITED_AFTER_SUBMIT';
|
|
11
|
+
export const CHATGPT_AUTOMATION_CONVERSATION_LIMIT_REACHED = 'CHATGPT_AUTOMATION_CONVERSATION_LIMIT_REACHED';
|
|
12
|
+
|
|
13
|
+
export type ChatgptProviderPageFailureCode =
|
|
14
|
+
| typeof CHATGPT_AUTOMATION_MESSAGE_DELIVERY_TIMED_OUT
|
|
15
|
+
| typeof CHATGPT_AUTOMATION_RESPONSE_STREAM_UNAVAILABLE
|
|
16
|
+
| typeof CHATGPT_AUTOMATION_RATE_LIMITED
|
|
17
|
+
| typeof CHATGPT_AUTOMATION_CONVERSATION_LIMIT_REACHED;
|
|
18
|
+
|
|
19
|
+
function normalizeChatgptProviderPageText(value: string): string {
|
|
20
|
+
return value.replace(/\s+/g, ' ').trim().toLowerCase();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Shared provider-page failure detection used by both direct delivery and durable Supervisor observation. */
|
|
24
|
+
export function chatgptProviderPageFailure(
|
|
25
|
+
bodyText: string | undefined,
|
|
26
|
+
): ChatgptProviderPageFailureCode | undefined {
|
|
27
|
+
const normalized = normalizeChatgptProviderPageText(bodyText ?? '');
|
|
28
|
+
// Dedicated live provider-status text only. Callers must not pass an
|
|
29
|
+
// unrestricted historical conversation transcript into this classifier.
|
|
30
|
+
if (normalized.includes('你已达到此对话的长度上限')
|
|
31
|
+
|| normalized.includes('此对话已达到长度上限')
|
|
32
|
+
|| normalized.includes('you have reached the maximum length for this conversation')
|
|
33
|
+
|| normalized.includes("you've reached the maximum length for this conversation")
|
|
34
|
+
|| normalized.includes('this conversation has reached its maximum length')
|
|
35
|
+
|| normalized.includes('you have reached the conversation length limit')) {
|
|
36
|
+
return CHATGPT_AUTOMATION_CONVERSATION_LIMIT_REACHED;
|
|
37
|
+
}
|
|
38
|
+
if (
|
|
39
|
+
normalized.includes('resume stream unavailable')
|
|
40
|
+
|| normalized.includes('tokenless_resume_unavailable')
|
|
41
|
+
|| normalized.includes('stream recovery polling timed out')
|
|
42
|
+
|| normalized.includes('连接已中断,正在等待完整答复')
|
|
43
|
+
|| normalized.includes('connection interrupted, waiting for the full response')
|
|
44
|
+
|| (normalized.includes('出了点问题') && normalized.includes('请重试'))
|
|
45
|
+
// A standalone current status is termination evidence. The same words in
|
|
46
|
+
// ordinary chat prose or a historical whole-page transcript are not.
|
|
47
|
+
|| /^(?:已分析\s+)?(?:分析已暂停|analysis paused)(?:\s+(?:分析已暂停|analysis paused))*$/.test(normalized)
|
|
48
|
+
) {
|
|
49
|
+
return CHATGPT_AUTOMATION_RESPONSE_STREAM_UNAVAILABLE;
|
|
50
|
+
}
|
|
51
|
+
if (
|
|
52
|
+
normalized.includes('too many requests')
|
|
53
|
+
|| normalized.includes('rate limit exceeded')
|
|
54
|
+
|| (normalized.includes('http 429') && normalized.includes('rate limit'))
|
|
55
|
+
) {
|
|
56
|
+
return CHATGPT_AUTOMATION_RATE_LIMITED;
|
|
57
|
+
}
|
|
58
|
+
return ((normalized.includes('message delivery timed out') && normalized.includes('please try again'))
|
|
59
|
+
|| (normalized.includes('消息传输超时') && normalized.includes('请重试')))
|
|
60
|
+
? CHATGPT_AUTOMATION_MESSAGE_DELIVERY_TIMED_OUT
|
|
61
|
+
: undefined;
|
|
62
|
+
}
|
|
7
63
|
|
|
8
64
|
export type ChatgptAutomationReasoning = 'medium' | 'high' | 'xhigh';
|
|
9
65
|
export type ChatgptAutomationTabPolicy = 'auto' | 'reuse' | 'new';
|
|
@@ -58,6 +114,172 @@ export interface ChatgptProviderDeliveryHost {
|
|
|
58
114
|
dispatch(input: ChatgptProviderDeliveryInput): Promise<ChatgptProviderDeliveryResult>;
|
|
59
115
|
}
|
|
60
116
|
|
|
117
|
+
interface ChatgptProviderDispatchGate {
|
|
118
|
+
tail: Promise<void>;
|
|
119
|
+
queued: number;
|
|
120
|
+
pressureLevel: number;
|
|
121
|
+
cooldownUntilMs: number;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const CHATGPT_PROVIDER_BACKPRESSURE_BASE_MS = 2_000;
|
|
125
|
+
const CHATGPT_PROVIDER_BACKPRESSURE_MAX_MS = 30_000;
|
|
126
|
+
const CHATGPT_PROVIDER_EXPLICIT_RETRY_MAX_MS = 120_000;
|
|
127
|
+
const chatgptProviderDispatchGates = new Map<string, ChatgptProviderDispatchGate>();
|
|
128
|
+
|
|
129
|
+
function providerGateKey(controllerHome: string): string {
|
|
130
|
+
return controllerHome.trim() || 'forge-controller';
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function chatgptProviderDispatchGate(controllerHome: string): ChatgptProviderDispatchGate {
|
|
134
|
+
const key = providerGateKey(controllerHome);
|
|
135
|
+
let gate = chatgptProviderDispatchGates.get(key);
|
|
136
|
+
if (!gate) {
|
|
137
|
+
gate = { tail: Promise.resolve(), queued: 0, pressureLevel: 0, cooldownUntilMs: 0 };
|
|
138
|
+
chatgptProviderDispatchGates.set(key, gate);
|
|
139
|
+
}
|
|
140
|
+
return gate;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function retryAfterDelayMs(message: string | undefined): number | undefined {
|
|
144
|
+
if (!message) return undefined;
|
|
145
|
+
const match = message.match(/\bretry[- ]?after\s*[:=]?\s*(\d+(?:\.\d+)?)\s*(ms|milliseconds?|s|sec(?:ond)?s?)?\b/i);
|
|
146
|
+
if (!match) return undefined;
|
|
147
|
+
const amount = Number(match[1]);
|
|
148
|
+
if (!Number.isFinite(amount) || amount <= 0) return undefined;
|
|
149
|
+
const milliseconds = match[2]?.toLowerCase().startsWith('m') ? amount : amount * 1_000;
|
|
150
|
+
return Math.max(1_000, Math.min(CHATGPT_PROVIDER_EXPLICIT_RETRY_MAX_MS, Math.round(milliseconds)));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** Deterministic jitter keeps concurrent callers from reconverging on one provider boundary after cooldown. */
|
|
154
|
+
export function chatgptProviderBackoffDelayMs(
|
|
155
|
+
pressureLevel: number,
|
|
156
|
+
key = 'chatgpt',
|
|
157
|
+
message?: string,
|
|
158
|
+
): number {
|
|
159
|
+
const explicit = retryAfterDelayMs(message);
|
|
160
|
+
if (explicit !== undefined) return explicit;
|
|
161
|
+
const exponent = Math.max(0, Math.min(8, Math.trunc(pressureLevel) - 1));
|
|
162
|
+
const base = Math.min(CHATGPT_PROVIDER_BACKPRESSURE_MAX_MS, CHATGPT_PROVIDER_BACKPRESSURE_BASE_MS * 2 ** exponent);
|
|
163
|
+
const jitterByte = createHash('sha256').update(`${key}\n${pressureLevel}`).digest()[0] ?? 128;
|
|
164
|
+
const jitter = 0.8 + (jitterByte / 255) * 0.4;
|
|
165
|
+
return Math.max(1_000, Math.min(CHATGPT_PROVIDER_BACKPRESSURE_MAX_MS, Math.round(base * jitter)));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export function chatgptProviderFailureRequiresBackpressure(
|
|
169
|
+
status: ChatgptProviderDeliveryStatus | undefined,
|
|
170
|
+
code?: string,
|
|
171
|
+
message?: string,
|
|
172
|
+
): boolean {
|
|
173
|
+
if (status === 'outcome_unknown') return true;
|
|
174
|
+
const normalized = `${code ?? ''}\n${message ?? ''}`.toUpperCase();
|
|
175
|
+
return normalized.includes('RATE_LIMITED')
|
|
176
|
+
|| normalized.includes('TOO MANY REQUESTS')
|
|
177
|
+
|| normalized.includes('HTTP 429')
|
|
178
|
+
|| normalized.includes('TOKENLESS_RESUME_UNAVAILABLE')
|
|
179
|
+
|| normalized.includes('RESPONSE_STREAM_UNAVAILABLE')
|
|
180
|
+
|| normalized.includes('MESSAGE_DELIVERY_TIMED_OUT');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export function noteChatgptProviderBackpressure(
|
|
184
|
+
controllerHome: string,
|
|
185
|
+
message?: string,
|
|
186
|
+
nowMs = Date.now(),
|
|
187
|
+
): number {
|
|
188
|
+
const key = providerGateKey(controllerHome);
|
|
189
|
+
const gate = chatgptProviderDispatchGate(controllerHome);
|
|
190
|
+
gate.pressureLevel += 1;
|
|
191
|
+
const delayMs = chatgptProviderBackoffDelayMs(gate.pressureLevel, key, message);
|
|
192
|
+
gate.cooldownUntilMs = Math.max(gate.cooldownUntilMs, nowMs + delayMs);
|
|
193
|
+
return delayMs;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export function chatgptProviderBackpressureRemainingMs(
|
|
197
|
+
controllerHome: string,
|
|
198
|
+
nowMs = Date.now(),
|
|
199
|
+
): number {
|
|
200
|
+
const gate = chatgptProviderDispatchGates.get(providerGateKey(controllerHome));
|
|
201
|
+
return gate ? Math.max(0, gate.cooldownUntilMs - nowMs) : 0;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export interface ChatgptProviderDispatchOutcome {
|
|
205
|
+
status?: ChatgptProviderDeliveryStatus;
|
|
206
|
+
code?: string;
|
|
207
|
+
message?: string;
|
|
208
|
+
/**
|
|
209
|
+
* True only when the provider actually accepted this submission. A local
|
|
210
|
+
* transport failure (foreground required, composer missing, transport
|
|
211
|
+
* unavailable) is neither acceptance nor provider backpressure, so it must
|
|
212
|
+
* not clear pressure that a real provider limit established.
|
|
213
|
+
*/
|
|
214
|
+
providerAccepted?: boolean;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* One active Runtime owns one transient ChatGPT provider dispatch lane. This is
|
|
219
|
+
* deliberately mechanical and in-memory: ControllerRound effect identity remains
|
|
220
|
+
* the durable replay fence across Runtime rotation, while provider pressure must
|
|
221
|
+
* not become Work/Plan lifecycle state.
|
|
222
|
+
*
|
|
223
|
+
* Provider rate limiting is an account-level resource, so *every* transport that
|
|
224
|
+
* can submit a provider prompt through this Runtime must enter the same lane and
|
|
225
|
+
* obey the same cooldown. A separate lane that only reads the cooldown still
|
|
226
|
+
* submits concurrently with this one, which is exactly how one ChatGPT account
|
|
227
|
+
* observes request concurrency that no single session produced.
|
|
228
|
+
*/
|
|
229
|
+
export async function withChatgptProviderDispatchLane<T>(
|
|
230
|
+
controllerHome: string,
|
|
231
|
+
operation: () => Promise<T>,
|
|
232
|
+
outcomeOf: (result: T) => ChatgptProviderDispatchOutcome | undefined,
|
|
233
|
+
): Promise<T> {
|
|
234
|
+
const key = providerGateKey(controllerHome);
|
|
235
|
+
const gate = chatgptProviderDispatchGate(controllerHome);
|
|
236
|
+
|
|
237
|
+
const predecessor = gate.tail;
|
|
238
|
+
let release!: () => void;
|
|
239
|
+
gate.tail = new Promise<void>((resolve) => { release = resolve; });
|
|
240
|
+
gate.queued += 1;
|
|
241
|
+
await predecessor;
|
|
242
|
+
|
|
243
|
+
try {
|
|
244
|
+
const waitMs = gate.cooldownUntilMs - Date.now();
|
|
245
|
+
if (waitMs > 0) await new Promise((resolve) => setTimeout(resolve, waitMs));
|
|
246
|
+
|
|
247
|
+
const result = await operation();
|
|
248
|
+
const outcome = outcomeOf(result);
|
|
249
|
+
if (outcome && chatgptProviderFailureRequiresBackpressure(outcome.status, outcome.code, outcome.message)) {
|
|
250
|
+
noteChatgptProviderBackpressure(controllerHome, outcome.message);
|
|
251
|
+
} else if (outcome?.providerAccepted === true) {
|
|
252
|
+
gate.pressureLevel = 0;
|
|
253
|
+
gate.cooldownUntilMs = 0;
|
|
254
|
+
}
|
|
255
|
+
return result;
|
|
256
|
+
} catch (error) {
|
|
257
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
258
|
+
if (chatgptProviderFailureRequiresBackpressure(undefined, undefined, message)) {
|
|
259
|
+
noteChatgptProviderBackpressure(controllerHome, message);
|
|
260
|
+
}
|
|
261
|
+
throw error;
|
|
262
|
+
} finally {
|
|
263
|
+
gate.queued -= 1;
|
|
264
|
+
release();
|
|
265
|
+
if (gate.queued === 0 && gate.pressureLevel === 0 && gate.cooldownUntilMs <= Date.now()) {
|
|
266
|
+
chatgptProviderDispatchGates.delete(key);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/** Controller-relay delivery: one serialized provider prompt submission lane. */
|
|
272
|
+
export async function dispatchWithChatgptProviderBackpressure(
|
|
273
|
+
controllerHome: string,
|
|
274
|
+
dispatch: () => Promise<ChatgptProviderDeliveryResult>,
|
|
275
|
+
): Promise<ChatgptProviderDeliveryResult> {
|
|
276
|
+
return await withChatgptProviderDispatchLane(controllerHome, dispatch, (result) => (
|
|
277
|
+
chatgptProviderFailureRequiresBackpressure(result.status, result.error?.code, result.error?.message)
|
|
278
|
+
? { code: result.error?.code, message: result.error?.message }
|
|
279
|
+
: { providerAccepted: result.status === 'dispatch_confirmed' }
|
|
280
|
+
));
|
|
281
|
+
}
|
|
282
|
+
|
|
61
283
|
const CHATGPT_WAIT_FOR_USER_MARKERS = [
|
|
62
284
|
'LOGIN_REQUIRED',
|
|
63
285
|
'AUTH_REQUIRED',
|
|
@@ -73,7 +295,12 @@ export function classifyChatgptProviderFailure(
|
|
|
73
295
|
message?: string,
|
|
74
296
|
): ChatgptProviderFailureDisposition {
|
|
75
297
|
const normalized = `${code ?? ''}\n${message ?? ''}`.toUpperCase();
|
|
76
|
-
if (
|
|
298
|
+
if (
|
|
299
|
+
normalized.includes('OUTCOME_UNKNOWN')
|
|
300
|
+
|| normalized.includes('MESSAGE_DELIVERY_TIMED_OUT')
|
|
301
|
+
|| normalized.includes('RESPONSE_STREAM_UNAVAILABLE')
|
|
302
|
+
|| normalized.includes('RATE_LIMITED_AFTER_SUBMIT')
|
|
303
|
+
) return 'outcome_unknown';
|
|
77
304
|
if (CHATGPT_WAIT_FOR_USER_MARKERS.some((marker) => normalized.includes(marker))) return 'wait_for_user';
|
|
78
305
|
return 'failed';
|
|
79
306
|
}
|