@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
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
DEFAULT_CHATGPT_AUTOMATION_MODEL,
|
|
8
8
|
DEFAULT_CHATGPT_AUTOMATION_REASONING,
|
|
9
9
|
DEFAULT_CHATGPT_AUTOMATION_TAB_POLICY,
|
|
10
|
+
dispatchWithChatgptProviderBackpressure,
|
|
10
11
|
type ChatgptAutomationReasoning,
|
|
11
12
|
type ChatgptAutomationTabCleanupStatus,
|
|
12
13
|
type ChatgptAutomationTabPolicy,
|
|
@@ -21,16 +22,6 @@ import {
|
|
|
21
22
|
submitChatgptPrompt,
|
|
22
23
|
withChatgptBrowserActionOrigin,
|
|
23
24
|
} from '../../../../adapters/chatgpt/browser-delivery-runtime';
|
|
24
|
-
import { getWorkContract } from '../../../../packages/kernel/work/api/index';
|
|
25
|
-
import { readForgeInstanceIdentity } from '../../../../packages/kernel/identity/api/index';
|
|
26
|
-
import {
|
|
27
|
-
bindChatgptWorkConversation,
|
|
28
|
-
getChatgptWorkConversationBinding,
|
|
29
|
-
hasChatgptConversationIdentity,
|
|
30
|
-
parseChatgptConversationIdentity,
|
|
31
|
-
rebindChatgptWorkConversation,
|
|
32
|
-
type ChatgptWorkConversationBinding,
|
|
33
|
-
} from '../../../../adapters/chatgpt/work-conversation-binding-store';
|
|
34
25
|
|
|
35
26
|
export {
|
|
36
27
|
CHATGPT_AUTOMATION_SUBMISSION_OUTCOME_UNKNOWN,
|
|
@@ -56,48 +47,8 @@ export {
|
|
|
56
47
|
settleWorkChatgptAutomationTab,
|
|
57
48
|
} from '../../../../adapters/chatgpt/browser-delivery-runtime';
|
|
58
49
|
|
|
59
|
-
const LEGACY_CONTROLLER_CHATGPT_SESSION_ID = 'forge-chatgpt-supercontroller';
|
|
60
50
|
export const DEFAULT_CHATGPT_AUTOMATION_PLUGIN_MENTION = '@forge';
|
|
61
51
|
|
|
62
|
-
export class ChatgptExecutionPlacementError extends Error {
|
|
63
|
-
readonly code = 'CHATGPT_EXECUTION_PLACEMENT_MISMATCH';
|
|
64
|
-
readonly targetForgeInstanceId: string;
|
|
65
|
-
readonly currentForgeInstanceId?: string;
|
|
66
|
-
|
|
67
|
-
constructor(targetForgeInstanceId: string, currentForgeInstanceId?: string) {
|
|
68
|
-
super(`CHATGPT_EXECUTION_PLACEMENT_MISMATCH: target=${targetForgeInstanceId} current=${currentForgeInstanceId ?? 'unavailable'}`);
|
|
69
|
-
this.name = 'ChatgptExecutionPlacementError';
|
|
70
|
-
this.targetForgeInstanceId = targetForgeInstanceId;
|
|
71
|
-
this.currentForgeInstanceId = currentForgeInstanceId;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
export interface WorkChatgptContinuationInput {
|
|
77
|
-
controllerHome: string;
|
|
78
|
-
repoId: string;
|
|
79
|
-
repoRoot: string;
|
|
80
|
-
workId: string;
|
|
81
|
-
prompt: string;
|
|
82
|
-
/** Durable per-round capability minted before ChatGPT dispatch. */
|
|
83
|
-
controllerAuthorityId?: string;
|
|
84
|
-
/** Durable semantic relay scope paired with controllerAuthorityId. */
|
|
85
|
-
relayScopeId?: string;
|
|
86
|
-
title?: string;
|
|
87
|
-
browserSessionId?: string;
|
|
88
|
-
conversationUrl?: string;
|
|
89
|
-
model?: string;
|
|
90
|
-
reasoning?: ChatgptAutomationReasoning;
|
|
91
|
-
tabPolicy?: ChatgptAutomationTabPolicy;
|
|
92
|
-
/** Transport-only conversation policy. `fresh` starts a new ChatGPT conversation while preserving the same durable Work/ControllerRound authority. */
|
|
93
|
-
transportConversation?: 'bound' | 'fresh';
|
|
94
|
-
timeoutMs?: number;
|
|
95
|
-
/** Authorization provenance for Browser actions. Immediate/source launches default to chatgpt-action; Scheduler resume must pass schedule. */
|
|
96
|
-
originSurface?: 'chatgpt-action' | 'schedule';
|
|
97
|
-
/** Explicit controller-scoped Browser grant refs already authorized for this Work transport. */
|
|
98
|
-
authorizationGrantRefs?: readonly string[];
|
|
99
|
-
}
|
|
100
|
-
|
|
101
52
|
export interface WorkChatgptContinuationDependencies {
|
|
102
53
|
bridgeRuntime?: boolean;
|
|
103
54
|
browserHost?: ChatgptProviderDeliveryHost;
|
|
@@ -137,27 +88,8 @@ export interface StandaloneChatgptPromptInput {
|
|
|
137
88
|
reasoning?: ChatgptAutomationReasoning;
|
|
138
89
|
tabPolicy?: ChatgptAutomationTabPolicy;
|
|
139
90
|
timeoutMs?: number;
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
function workflowToolAttributionInstruction(input: WorkChatgptContinuationInput): string {
|
|
143
|
-
const workId = input.workId;
|
|
144
|
-
const authorityId = input.controllerAuthorityId?.trim();
|
|
145
|
-
const relayScopeId = input.relayScopeId?.trim();
|
|
146
|
-
const requirementScoped = relayScopeId?.startsWith('requirement:') === true;
|
|
147
|
-
const repositoryAttribution = requirementScoped
|
|
148
|
-
? `本轮普通 repository_command_execute 和 repository_safe_patch_apply 必须显式传入实际被本轮语义选择且已成功 claim 的 repository-change Work 的 work_id;如果仍在推进 origin Work,则使用 work_id=${workId}。不得把只读/编排 Supervisor Work 的 work_id 用来归属 child Work 的源码修改,也不得省略 work_id。`
|
|
149
|
-
: `本轮每一次 repository_command_execute 和 repository_safe_patch_apply 都必须显式传 work_id=${workId},不得省略。`;
|
|
150
|
-
if (authorityId && relayScopeId) {
|
|
151
|
-
return `Forge Workflow 执行契约:精确 Work ${workId}。本次启动的 controller round 已具备 durable controller authority:controller_authority_id=${authorityId},relay_scope_id=${relayScopeId}。第一次 controller_claim 必须使用这组完全相同的 authority;不得先调用不带 scope 的 controller_claim,也不得等待 claim 响应后再生成另一份 authority。如果当前 client 暴露 controller_authority_id 与 relay_scope_id,controller_claim 时必须同时传入。如果当前 frozen client schema 缺少任一字段,调用 rh_work operation=repair, work_id=${workId}, capability_id=controller.round:controller_claim:${authorityId}:${relayScopeId};Forge 会把它映射到同一个 fenced claim。claim 成功后,data.controllerAuthorityId 必须等于 ${authorityId};continue、verify、finalize、stop、controller_release 必须原样沿用同一 durable authority,必要时使用对应 compatibility capability。绝不能把 data.session.sessionId 当作 durable capability,因为 MCP execution session 可能轮换。${repositoryAttribution}唯一例外是 prompt 明确标记为 exact current-source Controller lifecycle invocation 的 repository_command_execute,它必须使用给定 source checkout_id 且不得传 wrapper work_id,因为 CLI 内部 --work-id 与 ControllerRound authority 才是该控制面变更的 fenced authority。`;
|
|
152
|
-
}
|
|
153
|
-
return `Forge Workflow 执行契约:首先 claim 精确 Work ${workId}。从成功的 controller_claim 响应中取得 data.controllerAuthorityId;此后该 Work 的每一次 rh_work lifecycle 调用(continue、verify、finalize、stop、controller_release)都必须把它原样作为 controller_authority_id 传入。如果当前 frozen client schema 不暴露 controller_authority_id,则把同一个 opaque value 作为 session_id compatibility carrier。绝不能把 data.session.sessionId 当作 durable capability,因为 MCP execution session 可能在工具调用之间被替换或失效。本轮每一次 repository_command_execute 和 repository_safe_patch_apply 都必须显式传 work_id=${workId},不得省略;唯一例外是 prompt 明确标记为 exact current-source Controller lifecycle invocation 的 repository_command_execute,它必须使用给定 source checkout_id 且不得传 wrapper work_id,因为 CLI 内部 --work-id 与 ControllerRound authority 才是该控制面变更的 fenced authority。`;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
function controllerRoundAuthorityInputError(input: WorkChatgptContinuationInput): Error | undefined {
|
|
157
|
-
const hasAuthority = Boolean(input.controllerAuthorityId?.trim());
|
|
158
|
-
const hasRelayScope = Boolean(input.relayScopeId?.trim());
|
|
159
|
-
if (hasAuthority === hasRelayScope) return undefined;
|
|
160
|
-
return new Error('CHATGPT_CONTROLLER_ROUND_AUTHORITY_INCOMPLETE: controllerAuthorityId and relayScopeId must be supplied together');
|
|
91
|
+
/** Explicit Browser grant refs already authorized by the owning durable workflow/controller binding. */
|
|
92
|
+
authorizationGrantRefs?: readonly string[];
|
|
161
93
|
}
|
|
162
94
|
|
|
163
95
|
function normalizeModel(value?: string): string {
|
|
@@ -170,12 +102,6 @@ function normalizeReasoning(value?: ChatgptAutomationReasoning): ChatgptAutomati
|
|
|
170
102
|
return value ?? DEFAULT_CHATGPT_AUTOMATION_REASONING;
|
|
171
103
|
}
|
|
172
104
|
|
|
173
|
-
const DEFAULT_CHATGPT_CONTROLLER_REASONING: ChatgptAutomationReasoning = 'xhigh';
|
|
174
|
-
|
|
175
|
-
function normalizeControllerReasoning(value?: ChatgptAutomationReasoning): ChatgptAutomationReasoning {
|
|
176
|
-
return value ?? DEFAULT_CHATGPT_CONTROLLER_REASONING;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
105
|
function normalizeTabPolicy(value?: ChatgptAutomationTabPolicy): ChatgptAutomationTabPolicy {
|
|
180
106
|
return value ?? DEFAULT_CHATGPT_AUTOMATION_TAB_POLICY;
|
|
181
107
|
}
|
|
@@ -195,18 +121,13 @@ function resolveChatgptProviderDeliveryHost(
|
|
|
195
121
|
return { bridgeRuntime, host };
|
|
196
122
|
}
|
|
197
123
|
|
|
198
|
-
export function
|
|
199
|
-
const digest = createHash('sha256').update(
|
|
200
|
-
return `forge-chatgpt-work-${digest}`;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
export function stableChatgptWorkBridgeSessionId(repoId: string, workId: string): string {
|
|
204
|
-
const digest = createHash('sha256').update(`${repoId}\nbridge\n${workId}`).digest('hex').slice(0, 20);
|
|
124
|
+
export function stableChatgptWorkBridgeSessionId(_repoId: string, workId: string): string {
|
|
125
|
+
const digest = createHash('sha256').update(`bridge\n${workId}`).digest('hex').slice(0, 20);
|
|
205
126
|
return `forge-chatgpt-bridge-${digest}`;
|
|
206
127
|
}
|
|
207
128
|
|
|
208
|
-
export function stableStandaloneChatgptBrowserSessionId(
|
|
209
|
-
const digest = createHash('sha256').update(
|
|
129
|
+
export function stableStandaloneChatgptBrowserSessionId(_repoId: string, scopeId: string): string {
|
|
130
|
+
const digest = createHash('sha256').update(`standalone\n${scopeId}`).digest('hex').slice(0, 20);
|
|
210
131
|
return `forge-chatgpt-standalone-${digest}`;
|
|
211
132
|
}
|
|
212
133
|
|
|
@@ -217,23 +138,6 @@ function resolveStandaloneChatgptBrowserSessionId(input: StandaloneChatgptPrompt
|
|
|
217
138
|
return input.browserSessionId?.trim() || stable;
|
|
218
139
|
}
|
|
219
140
|
|
|
220
|
-
export function resolveChatgptWorkBrowserSessionId(input: {
|
|
221
|
-
repoId: string;
|
|
222
|
-
workId: string;
|
|
223
|
-
tabPolicy?: ChatgptAutomationTabPolicy;
|
|
224
|
-
explicitSessionId?: string;
|
|
225
|
-
boundSessionId?: string;
|
|
226
|
-
}): string {
|
|
227
|
-
const policy = normalizeTabPolicy(input.tabPolicy);
|
|
228
|
-
const stable = stableChatgptWorkBrowserSessionId(input.repoId, input.workId);
|
|
229
|
-
if (policy === 'new') return `${stable}-${randomUUID().slice(0, 8)}`;
|
|
230
|
-
const explicit = input.explicitSessionId?.trim();
|
|
231
|
-
if (explicit && explicit !== LEGACY_CONTROLLER_CHATGPT_SESSION_ID) return explicit;
|
|
232
|
-
const bound = input.boundSessionId?.trim();
|
|
233
|
-
if (bound && bound !== LEGACY_CONTROLLER_CHATGPT_SESSION_ID) return bound;
|
|
234
|
-
return stable;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
141
|
export function withForgePluginMention(prompt: string): string {
|
|
238
142
|
const value = prompt.trim();
|
|
239
143
|
if (!value) throw new Error('CHATGPT_AUTOMATION_PROMPT_REQUIRED');
|
|
@@ -260,20 +164,27 @@ export async function runStandaloneChatgptPrompt(
|
|
|
260
164
|
? stableChatgptWorkBridgeSessionId(input.repoId, browserScopeId)
|
|
261
165
|
: resolveStandaloneChatgptBrowserSessionId(input);
|
|
262
166
|
const targetUrl = seedUrl ?? 'https://chatgpt.com/';
|
|
167
|
+
const authorizationGrantRefs = new Set(
|
|
168
|
+
(input.authorizationGrantRefs ?? []).map((ref) => ref.trim()).filter(Boolean),
|
|
169
|
+
);
|
|
263
170
|
|
|
264
171
|
try {
|
|
265
|
-
const delivery = await
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
172
|
+
const delivery = await withChatgptBrowserActionOrigin(
|
|
173
|
+
{ surface: 'chatgpt-action', actor: 'chatgpt-standalone-prompt' },
|
|
174
|
+
() => dispatchWithChatgptProviderBackpressure(input.controllerHome, () => host.dispatch({
|
|
175
|
+
controllerHome: input.controllerHome,
|
|
176
|
+
repoId: input.repoId,
|
|
177
|
+
repoRoot: input.repoRoot ?? process.cwd(),
|
|
178
|
+
workId: browserScopeId,
|
|
179
|
+
prompt: input.prompt,
|
|
180
|
+
browserSessionId: sessionId,
|
|
181
|
+
targetUrl,
|
|
182
|
+
model,
|
|
183
|
+
reasoning,
|
|
184
|
+
timeoutMs: input.timeoutMs,
|
|
185
|
+
})),
|
|
186
|
+
authorizationGrantRefs,
|
|
187
|
+
);
|
|
277
188
|
if (delivery.status !== 'dispatch_confirmed') {
|
|
278
189
|
return {
|
|
279
190
|
status: 'failed',
|
|
@@ -285,6 +196,7 @@ export async function runStandaloneChatgptPrompt(
|
|
|
285
196
|
reasoning,
|
|
286
197
|
tabPolicy,
|
|
287
198
|
executionPreferenceVerified: delivery.executionPreferenceVerified,
|
|
199
|
+
authorizationGrantRefs: [...authorizationGrantRefs],
|
|
288
200
|
providerDeliveryStatus: delivery.status,
|
|
289
201
|
error: delivery.error ?? { code: `CHATGPT_PROVIDER_${delivery.status.toUpperCase()}`, message: delivery.status },
|
|
290
202
|
};
|
|
@@ -322,193 +234,9 @@ export async function runStandaloneChatgptPrompt(
|
|
|
322
234
|
reasoning,
|
|
323
235
|
tabPolicy,
|
|
324
236
|
executionPreferenceVerified: false,
|
|
325
|
-
error: {
|
|
326
|
-
code: error instanceof Error && error.message.includes(':') ? error.message.split(':', 1)[0] : bridgeRuntime ? 'CHATGPT_BRIDGE_DISPATCH_FAILED' : 'CHATGPT_CONTROLLER_BROWSER_FAILED',
|
|
327
|
-
message: error instanceof Error ? error.message : String(error),
|
|
328
|
-
},
|
|
329
|
-
};
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
/**
|
|
334
|
-
* Dispatches a bounded resume prompt to one controller-owned ChatGPT Web tab.
|
|
335
|
-
* Chat history is transport context only. Forge Work/Plan/evidence remain authoritative.
|
|
336
|
-
*/
|
|
337
|
-
export async function runWorkChatgptContinuation(
|
|
338
|
-
input: WorkChatgptContinuationInput,
|
|
339
|
-
dependencies: WorkChatgptContinuationDependencies = {},
|
|
340
|
-
): Promise<WorkChatgptContinuationResult> {
|
|
341
|
-
const store = { controllerHome: input.controllerHome, repoId: input.repoId };
|
|
342
|
-
const existing = getChatgptWorkConversationBinding(store, input.workId);
|
|
343
|
-
const authorizationGrantRefs = new Set(
|
|
344
|
-
[...(existing?.authorizationGrantRefs ?? []), ...(input.authorizationGrantRefs ?? [])]
|
|
345
|
-
.map((ref) => ref.trim())
|
|
346
|
-
.filter(Boolean),
|
|
347
|
-
);
|
|
348
|
-
const transportConversation = input.transportConversation ?? 'bound';
|
|
349
|
-
const seedUrl = transportConversation === 'fresh' ? undefined : input.conversationUrl?.trim() || existing?.conversationUrl;
|
|
350
|
-
const model = normalizeModel(input.model);
|
|
351
|
-
const reasoning = normalizeControllerReasoning(input.reasoning);
|
|
352
|
-
const tabPolicy = transportConversation === 'fresh' ? 'new' : normalizeTabPolicy(input.tabPolicy);
|
|
353
|
-
const { bridgeRuntime, host } = resolveChatgptProviderDeliveryHost(dependencies);
|
|
354
|
-
const authorityInputError = controllerRoundAuthorityInputError(input);
|
|
355
|
-
if (authorityInputError) {
|
|
356
|
-
const browserSessionId = bridgeRuntime
|
|
357
|
-
? stableChatgptWorkBridgeSessionId(input.repoId, input.workId)
|
|
358
|
-
: resolveChatgptWorkBrowserSessionId({
|
|
359
|
-
repoId: input.repoId,
|
|
360
|
-
workId: input.workId,
|
|
361
|
-
tabPolicy,
|
|
362
|
-
explicitSessionId: input.browserSessionId,
|
|
363
|
-
boundSessionId: existing?.latestBrowserSessionId,
|
|
364
|
-
});
|
|
365
|
-
return {
|
|
366
|
-
status: 'failed',
|
|
367
|
-
provider: bridgeRuntime ? 'chatgpt-bridge' : 'controller-browser',
|
|
368
|
-
browserSessionId,
|
|
369
|
-
conversationUrl: seedUrl,
|
|
370
|
-
conversationId: existing?.conversationId,
|
|
371
|
-
localAlias: existing?.localAlias,
|
|
372
|
-
resumedFromBinding: Boolean(existing),
|
|
373
|
-
model,
|
|
374
|
-
reasoning,
|
|
375
|
-
tabPolicy,
|
|
376
|
-
executionPreferenceVerified: false,
|
|
377
237
|
authorizationGrantRefs: [...authorizationGrantRefs],
|
|
378
238
|
error: {
|
|
379
|
-
code: '
|
|
380
|
-
message: authorityInputError.message,
|
|
381
|
-
},
|
|
382
|
-
};
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
const sessionId = resolveChatgptWorkBrowserSessionId({
|
|
386
|
-
repoId: input.repoId,
|
|
387
|
-
workId: input.workId,
|
|
388
|
-
tabPolicy,
|
|
389
|
-
explicitSessionId: input.browserSessionId,
|
|
390
|
-
boundSessionId: existing?.latestBrowserSessionId,
|
|
391
|
-
});
|
|
392
|
-
let binding: ChatgptWorkConversationBinding | undefined = existing;
|
|
393
|
-
const deliverySessionId = bridgeRuntime
|
|
394
|
-
? stableChatgptWorkBridgeSessionId(input.repoId, input.workId)
|
|
395
|
-
: sessionId;
|
|
396
|
-
|
|
397
|
-
try {
|
|
398
|
-
const work = getWorkContract(store, input.workId);
|
|
399
|
-
if (!work || work.repoId !== input.repoId) {
|
|
400
|
-
throw new Error(`CHATGPT_WORK_CONTRACT_NOT_FOUND: ${input.repoId}:${input.workId}`);
|
|
401
|
-
}
|
|
402
|
-
const targetForgeInstanceId = work.executionPlacement?.forgeInstanceId?.trim();
|
|
403
|
-
if (targetForgeInstanceId) {
|
|
404
|
-
const currentForgeInstanceId = readForgeInstanceIdentity(input.controllerHome)?.instanceId?.trim();
|
|
405
|
-
if (currentForgeInstanceId !== targetForgeInstanceId) {
|
|
406
|
-
throw new ChatgptExecutionPlacementError(targetForgeInstanceId, currentForgeInstanceId);
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
if (!bridgeRuntime && seedUrl && !binding && hasChatgptConversationIdentity(seedUrl)) {
|
|
410
|
-
binding = bindChatgptWorkConversation(store, {
|
|
411
|
-
workId: input.workId,
|
|
412
|
-
conversationUrl: seedUrl,
|
|
413
|
-
latestBrowserSessionId: deliverySessionId,
|
|
414
|
-
authorizationGrantRefs: [...authorizationGrantRefs],
|
|
415
|
-
localAlias: input.title,
|
|
416
|
-
});
|
|
417
|
-
}
|
|
418
|
-
const targetUrl = transportConversation === 'fresh' ? 'https://chatgpt.com/' : binding?.conversationUrl ?? seedUrl ?? 'https://chatgpt.com/';
|
|
419
|
-
const renderedPrompt = `${workflowToolAttributionInstruction(input)}\n\n${input.prompt}`;
|
|
420
|
-
const delivery = await withChatgptBrowserActionOrigin(
|
|
421
|
-
{ surface: input.originSurface ?? 'chatgpt-action', actor: 'chatgpt-work-continuation' },
|
|
422
|
-
() => host.dispatch({
|
|
423
|
-
controllerHome: input.controllerHome,
|
|
424
|
-
repoId: input.repoId,
|
|
425
|
-
repoRoot: input.repoRoot,
|
|
426
|
-
workId: input.workId,
|
|
427
|
-
prompt: renderedPrompt,
|
|
428
|
-
browserSessionId: deliverySessionId,
|
|
429
|
-
targetUrl,
|
|
430
|
-
model,
|
|
431
|
-
reasoning,
|
|
432
|
-
timeoutMs: input.timeoutMs,
|
|
433
|
-
}),
|
|
434
|
-
authorizationGrantRefs,
|
|
435
|
-
);
|
|
436
|
-
const observedUrl = delivery.conversationUrl ?? targetUrl;
|
|
437
|
-
const mayPersistObservedConversation = delivery.status === 'dispatch_confirmed' || delivery.status === 'outcome_unknown';
|
|
438
|
-
if (mayPersistObservedConversation && /\/c\/[^/?#]+/.test(observedUrl)) {
|
|
439
|
-
const observedIdentity = parseChatgptConversationIdentity(observedUrl);
|
|
440
|
-
binding = binding && binding.conversationId !== observedIdentity.conversationId
|
|
441
|
-
? rebindChatgptWorkConversation(store, {
|
|
442
|
-
workId: input.workId,
|
|
443
|
-
previousConversationId: binding.conversationId,
|
|
444
|
-
conversationUrl: observedUrl,
|
|
445
|
-
latestBrowserSessionId: delivery.browserSessionId,
|
|
446
|
-
authorizationGrantRefs: [...authorizationGrantRefs],
|
|
447
|
-
localAlias: binding.localAlias ?? input.title,
|
|
448
|
-
})
|
|
449
|
-
: bindChatgptWorkConversation(store, {
|
|
450
|
-
workId: input.workId,
|
|
451
|
-
conversationUrl: observedUrl,
|
|
452
|
-
latestBrowserSessionId: delivery.browserSessionId,
|
|
453
|
-
authorizationGrantRefs: [...authorizationGrantRefs],
|
|
454
|
-
localAlias: binding?.localAlias ?? input.title,
|
|
455
|
-
});
|
|
456
|
-
}
|
|
457
|
-
if (delivery.status !== 'dispatch_confirmed') {
|
|
458
|
-
return {
|
|
459
|
-
status: 'failed',
|
|
460
|
-
provider: delivery.provider,
|
|
461
|
-
browserSessionId: delivery.browserSessionId,
|
|
462
|
-
conversationUrl: binding?.conversationUrl ?? delivery.conversationUrl ?? seedUrl,
|
|
463
|
-
conversationId: binding?.conversationId,
|
|
464
|
-
localAlias: binding?.localAlias,
|
|
465
|
-
resumedFromBinding: Boolean(existing),
|
|
466
|
-
model,
|
|
467
|
-
reasoning,
|
|
468
|
-
tabPolicy,
|
|
469
|
-
executionPreferenceVerified: delivery.executionPreferenceVerified,
|
|
470
|
-
authorizationGrantRefs: [...authorizationGrantRefs],
|
|
471
|
-
providerDeliveryStatus: delivery.status,
|
|
472
|
-
error: delivery.error ?? { code: `CHATGPT_PROVIDER_${delivery.status.toUpperCase()}`, message: delivery.status },
|
|
473
|
-
};
|
|
474
|
-
}
|
|
475
|
-
return {
|
|
476
|
-
status: 'dispatched',
|
|
477
|
-
provider: delivery.provider,
|
|
478
|
-
browserSessionId: delivery.browserSessionId,
|
|
479
|
-
conversationUrl: binding?.conversationUrl ?? observedUrl,
|
|
480
|
-
conversationId: binding?.conversationId,
|
|
481
|
-
localAlias: binding?.localAlias,
|
|
482
|
-
resumedFromBinding: Boolean(existing),
|
|
483
|
-
model,
|
|
484
|
-
reasoning,
|
|
485
|
-
tabPolicy,
|
|
486
|
-
executionPreferenceVerified: delivery.executionPreferenceVerified,
|
|
487
|
-
authorizationGrantRefs: [...authorizationGrantRefs],
|
|
488
|
-
providerDeliveryStatus: delivery.status,
|
|
489
|
-
};
|
|
490
|
-
} catch (error) {
|
|
491
|
-
const provider = bridgeRuntime ? 'chatgpt-bridge' : 'controller-browser';
|
|
492
|
-
const fallbackSessionId = bridgeRuntime ? deliverySessionId : sessionId;
|
|
493
|
-
return {
|
|
494
|
-
status: 'failed',
|
|
495
|
-
provider,
|
|
496
|
-
browserSessionId: fallbackSessionId,
|
|
497
|
-
conversationUrl: binding?.conversationUrl ?? seedUrl,
|
|
498
|
-
conversationId: binding?.conversationId,
|
|
499
|
-
localAlias: binding?.localAlias,
|
|
500
|
-
resumedFromBinding: Boolean(existing),
|
|
501
|
-
model,
|
|
502
|
-
reasoning,
|
|
503
|
-
tabPolicy,
|
|
504
|
-
executionPreferenceVerified: false,
|
|
505
|
-
authorizationGrantRefs: [...authorizationGrantRefs],
|
|
506
|
-
error: {
|
|
507
|
-
code: error instanceof ChatgptExecutionPlacementError
|
|
508
|
-
? error.code
|
|
509
|
-
: error instanceof Error && error.message.includes(':')
|
|
510
|
-
? error.message.split(':', 1)[0]
|
|
511
|
-
: bridgeRuntime ? 'CHATGPT_BRIDGE_DISPATCH_FAILED' : 'CHATGPT_CONTROLLER_BROWSER_FAILED',
|
|
239
|
+
code: error instanceof Error && error.message.includes(':') ? error.message.split(':', 1)[0] : bridgeRuntime ? 'CHATGPT_BRIDGE_DISPATCH_FAILED' : 'CHATGPT_CONTROLLER_BROWSER_FAILED',
|
|
512
240
|
message: error instanceof Error ? error.message : String(error),
|
|
513
241
|
},
|
|
514
242
|
};
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import { mkdirSync } from 'fs';
|
|
3
|
+
import { tmpdir } from 'os';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import { redactProcessOutput } from '../../../effects/process-runner';
|
|
6
|
+
import { resolveProviderMcpBootstrap } from './provider-mcp-bootstrap';
|
|
7
|
+
import {
|
|
8
|
+
buildCodexControllerInvocation,
|
|
9
|
+
launcherProcessEnvironment,
|
|
10
|
+
resolveLauncherExecutable,
|
|
11
|
+
} from './thin-launcher';
|
|
12
|
+
|
|
13
|
+
const LOCAL_CONVERSATION_TIMEOUT_MS = 5 * 60_000;
|
|
14
|
+
const LOCAL_CONVERSATION_MAX_OUTPUT_BYTES = 4 * 1024 * 1024;
|
|
15
|
+
const LOCAL_CONVERSATION_MAX_PROMPT_CHARS = 20_000;
|
|
16
|
+
const LOCAL_CONVERSATION_ID = /^[A-Za-z0-9._:-]{1,160}$/;
|
|
17
|
+
|
|
18
|
+
export interface LocalConversationProviderStatus {
|
|
19
|
+
provider: 'codex';
|
|
20
|
+
status: 'ready' | 'not_configured' | 'unavailable';
|
|
21
|
+
label: string;
|
|
22
|
+
detail: string;
|
|
23
|
+
streaming: boolean;
|
|
24
|
+
tools: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface LocalConversationSendInput {
|
|
28
|
+
controllerHome: string;
|
|
29
|
+
conversationId: string;
|
|
30
|
+
providerSessionId?: string;
|
|
31
|
+
prompt: string;
|
|
32
|
+
repoId?: string;
|
|
33
|
+
timeoutMs?: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface LocalConversationSendResult {
|
|
37
|
+
provider: 'codex';
|
|
38
|
+
status: 'completed';
|
|
39
|
+
conversationId: string;
|
|
40
|
+
providerSessionId: string;
|
|
41
|
+
output: string;
|
|
42
|
+
toolActivityCount: number;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface ParsedCodexConversationEvents {
|
|
46
|
+
providerSessionId?: string;
|
|
47
|
+
output?: string;
|
|
48
|
+
toolActivityCount: number;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function record(value: unknown): Record<string, unknown> | undefined {
|
|
52
|
+
return value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : undefined;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function boundedTimeout(value: number | undefined): number {
|
|
56
|
+
if (!Number.isFinite(value)) return LOCAL_CONVERSATION_TIMEOUT_MS;
|
|
57
|
+
return Math.max(5_000, Math.min(10 * 60_000, Math.trunc(value!)));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function agentMessageText(item: Record<string, unknown>): string | undefined {
|
|
61
|
+
if (typeof item.text === 'string' && item.text.trim()) return item.text.trim();
|
|
62
|
+
if (typeof item.output_text === 'string' && item.output_text.trim()) return item.output_text.trim();
|
|
63
|
+
if (!Array.isArray(item.content)) return undefined;
|
|
64
|
+
const text = item.content.map((entry) => {
|
|
65
|
+
const content = record(entry);
|
|
66
|
+
if (!content) return '';
|
|
67
|
+
if (typeof content.text === 'string') return content.text;
|
|
68
|
+
if (typeof content.output_text === 'string') return content.output_text;
|
|
69
|
+
return '';
|
|
70
|
+
}).filter(Boolean).join('\n').trim();
|
|
71
|
+
return text || undefined;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function parseCodexConversationJsonl(stdout: string): ParsedCodexConversationEvents {
|
|
75
|
+
let providerSessionId: string | undefined;
|
|
76
|
+
let output: string | undefined;
|
|
77
|
+
let toolActivityCount = 0;
|
|
78
|
+
for (const line of stdout.split(/\r?\n/)) {
|
|
79
|
+
const trimmed = line.trim();
|
|
80
|
+
if (!trimmed.startsWith('{')) continue;
|
|
81
|
+
let event: Record<string, unknown> | undefined;
|
|
82
|
+
try { event = record(JSON.parse(trimmed)); } catch { continue; }
|
|
83
|
+
if (!event) continue;
|
|
84
|
+
const type = typeof event.type === 'string' ? event.type : '';
|
|
85
|
+
if (type === 'thread.started' && typeof event.thread_id === 'string' && event.thread_id.trim()) {
|
|
86
|
+
providerSessionId = event.thread_id.trim();
|
|
87
|
+
}
|
|
88
|
+
if (type !== 'item.completed') continue;
|
|
89
|
+
const item = record(event.item);
|
|
90
|
+
if (!item) continue;
|
|
91
|
+
const itemType = typeof item.type === 'string' ? item.type : '';
|
|
92
|
+
if (itemType === 'agent_message') {
|
|
93
|
+
output = agentMessageText(item) ?? output;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (['mcp_tool_call', 'command_execution', 'file_change', 'web_search'].includes(itemType)) {
|
|
97
|
+
toolActivityCount += 1;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return { providerSessionId, output, toolActivityCount };
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function localConversationCwd(): string {
|
|
104
|
+
const root = join(tmpdir(), 'forge-local-controller');
|
|
105
|
+
mkdirSync(root, { recursive: true, mode: 0o700 });
|
|
106
|
+
return root;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function conversationPrompt(prompt: string, repoId?: string): string {
|
|
110
|
+
return [
|
|
111
|
+
'You are the Forge Desktop local controller.',
|
|
112
|
+
'Use the injected Forge MCP capabilities for repository, Runtime, and other Forge operations. Do not create Requirement, Plan, Work, ControllerRound, or a scheduled continuation unless the user explicitly requests that durable lifecycle.',
|
|
113
|
+
repoId
|
|
114
|
+
? `Attached repository: ${repoId}. Pass repo_id=${repoId} to Forge capabilities that require repository scope.`
|
|
115
|
+
: 'No repository is attached. Do not guess a repository identity.',
|
|
116
|
+
'',
|
|
117
|
+
prompt,
|
|
118
|
+
].join('\n');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function readLocalConversationProviderStatus(cwd: string = process.cwd()): LocalConversationProviderStatus {
|
|
122
|
+
try {
|
|
123
|
+
resolveLauncherExecutable({ controllerType: 'codex', cwd });
|
|
124
|
+
return {
|
|
125
|
+
provider: 'codex',
|
|
126
|
+
status: 'ready',
|
|
127
|
+
label: 'Codex 已连接',
|
|
128
|
+
detail: '使用 Codex CLI 的现有登录;Forge 操作通过当前 Runtime MCP capability 执行。',
|
|
129
|
+
streaming: false,
|
|
130
|
+
tools: true,
|
|
131
|
+
};
|
|
132
|
+
} catch (error) {
|
|
133
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
134
|
+
const missing = message.startsWith('LAUNCHER_EXECUTABLE_UNAVAILABLE');
|
|
135
|
+
return {
|
|
136
|
+
provider: 'codex',
|
|
137
|
+
status: missing ? 'not_configured' : 'unavailable',
|
|
138
|
+
label: missing ? 'Codex CLI 未安装' : 'Codex 暂不可用',
|
|
139
|
+
detail: missing ? '安装并登录 Codex CLI 后即可使用本地会话。' : message,
|
|
140
|
+
streaming: false,
|
|
141
|
+
tools: false,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function runCodexConversation(
|
|
147
|
+
executable: string,
|
|
148
|
+
args: string[],
|
|
149
|
+
env: NodeJS.ProcessEnv,
|
|
150
|
+
cwd: string,
|
|
151
|
+
timeoutMs: number,
|
|
152
|
+
): Promise<{ stdout: string; stderr: string }> {
|
|
153
|
+
return new Promise((resolve, reject) => {
|
|
154
|
+
const child = spawn(executable, args, {
|
|
155
|
+
cwd,
|
|
156
|
+
env,
|
|
157
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
158
|
+
});
|
|
159
|
+
let stdout = '';
|
|
160
|
+
let stderr = '';
|
|
161
|
+
let settled = false;
|
|
162
|
+
const fail = (error: Error) => {
|
|
163
|
+
if (settled) return;
|
|
164
|
+
settled = true;
|
|
165
|
+
clearTimeout(timer);
|
|
166
|
+
reject(error);
|
|
167
|
+
};
|
|
168
|
+
const append = (current: string, chunk: unknown, stream: 'stdout' | 'stderr'): string => {
|
|
169
|
+
const next = `${current}${Buffer.isBuffer(chunk) ? chunk.toString('utf8') : String(chunk ?? '')}`;
|
|
170
|
+
if (Buffer.byteLength(next, 'utf8') > LOCAL_CONVERSATION_MAX_OUTPUT_BYTES) {
|
|
171
|
+
child.kill('SIGTERM');
|
|
172
|
+
fail(new Error(`LOCAL_CONVERSATION_${stream.toUpperCase()}_TOO_LARGE`));
|
|
173
|
+
return current;
|
|
174
|
+
}
|
|
175
|
+
return next;
|
|
176
|
+
};
|
|
177
|
+
child.stdout?.on('data', (chunk) => { stdout = append(stdout, chunk, 'stdout'); });
|
|
178
|
+
child.stderr?.on('data', (chunk) => { stderr = append(stderr, chunk, 'stderr'); });
|
|
179
|
+
child.once('error', (error) => fail(new Error(`LOCAL_CONVERSATION_PROVIDER_START_FAILED: ${error.message}`)));
|
|
180
|
+
child.once('close', (code, signal) => {
|
|
181
|
+
if (settled) return;
|
|
182
|
+
settled = true;
|
|
183
|
+
clearTimeout(timer);
|
|
184
|
+
if (code !== 0) {
|
|
185
|
+
const detail = redactProcessOutput(stderr.trim() || stdout.trim()).replace(/\s+/g, ' ').slice(0, 1200);
|
|
186
|
+
reject(new Error(`LOCAL_CONVERSATION_PROVIDER_FAILED: code=${String(code ?? 'null')} signal=${signal ?? 'none'}${detail ? `; ${detail}` : ''}`));
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
resolve({ stdout, stderr });
|
|
190
|
+
});
|
|
191
|
+
const timer = setTimeout(() => {
|
|
192
|
+
child.kill('SIGTERM');
|
|
193
|
+
fail(new Error('LOCAL_CONVERSATION_PROVIDER_TIMEOUT'));
|
|
194
|
+
}, timeoutMs);
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export async function sendLocalConversation(input: LocalConversationSendInput): Promise<LocalConversationSendResult> {
|
|
199
|
+
const conversationId = input.conversationId.trim();
|
|
200
|
+
const prompt = input.prompt.trim();
|
|
201
|
+
const providerSessionId = input.providerSessionId?.trim();
|
|
202
|
+
const repoId = input.repoId?.trim();
|
|
203
|
+
if (!LOCAL_CONVERSATION_ID.test(conversationId)) throw new Error('LOCAL_CONVERSATION_ID_INVALID');
|
|
204
|
+
if (!prompt || prompt.length > LOCAL_CONVERSATION_MAX_PROMPT_CHARS) throw new Error('LOCAL_CONVERSATION_PROMPT_INVALID');
|
|
205
|
+
if (providerSessionId && !LOCAL_CONVERSATION_ID.test(providerSessionId)) throw new Error('LOCAL_CONVERSATION_PROVIDER_SESSION_INVALID');
|
|
206
|
+
if (repoId && repoId.length > 256) throw new Error('LOCAL_CONVERSATION_REPOSITORY_INVALID');
|
|
207
|
+
|
|
208
|
+
const cwd = localConversationCwd();
|
|
209
|
+
const executable = resolveLauncherExecutable({ controllerType: 'codex', cwd });
|
|
210
|
+
const bootstrap = resolveProviderMcpBootstrap(input.controllerHome, 'codex', `local-${conversationId}`);
|
|
211
|
+
const invocation = buildCodexControllerInvocation({
|
|
212
|
+
executable,
|
|
213
|
+
prompt: conversationPrompt(prompt, repoId),
|
|
214
|
+
mcpBootstrap: bootstrap,
|
|
215
|
+
sandbox: 'read-only',
|
|
216
|
+
resumeSessionId: providerSessionId,
|
|
217
|
+
json: true,
|
|
218
|
+
});
|
|
219
|
+
const completed = await runCodexConversation(
|
|
220
|
+
invocation.executable,
|
|
221
|
+
invocation.args,
|
|
222
|
+
launcherProcessEnvironment(bootstrap.env),
|
|
223
|
+
cwd,
|
|
224
|
+
boundedTimeout(input.timeoutMs),
|
|
225
|
+
);
|
|
226
|
+
const parsed = parseCodexConversationJsonl(completed.stdout);
|
|
227
|
+
const resolvedProviderSessionId = parsed.providerSessionId ?? providerSessionId;
|
|
228
|
+
if (!resolvedProviderSessionId) throw new Error('LOCAL_CONVERSATION_PROVIDER_SESSION_MISSING');
|
|
229
|
+
if (!parsed.output?.trim()) throw new Error('LOCAL_CONVERSATION_RESPONSE_MISSING');
|
|
230
|
+
return {
|
|
231
|
+
provider: 'codex',
|
|
232
|
+
status: 'completed',
|
|
233
|
+
conversationId,
|
|
234
|
+
providerSessionId: resolvedProviderSessionId,
|
|
235
|
+
output: parsed.output.trim(),
|
|
236
|
+
toolActivityCount: parsed.toolActivityCount,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
@@ -73,8 +73,11 @@ export function codexMcpConfigArgs(bootstrap: ProviderMcpBootstrap): string[] {
|
|
|
73
73
|
.map(([key, value]) => `${JSON.stringify(key)}=${JSON.stringify(value)}`)
|
|
74
74
|
.join(',')}}`;
|
|
75
75
|
return [
|
|
76
|
+
// Replace the entire table: Codex rejects a merged URL + persisted stdio
|
|
77
|
+
// transport even when command/args are overridden separately.
|
|
78
|
+
'-c', `mcp_servers.forge={url=${JSON.stringify(bootstrap.url)}, bearer_token_env_var=${JSON.stringify(bootstrap.bearerTokenEnvVar)}, http_headers=${headerTable}}`,
|
|
79
|
+
// Keep the explicit URL override visible for diagnostics; the complete
|
|
80
|
+
// table above has already removed the persisted stdio transport.
|
|
76
81
|
'-c', `mcp_servers.forge.url=${JSON.stringify(bootstrap.url)}`,
|
|
77
|
-
'-c', `mcp_servers.forge.bearer_token_env_var=${JSON.stringify(bootstrap.bearerTokenEnvVar)}`,
|
|
78
|
-
'-c', `mcp_servers.forge.http_headers=${headerTable}`,
|
|
79
82
|
];
|
|
80
83
|
}
|