@moretea-labs/forge 1.7.2 → 1.8.0
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 +58 -62
- package/CHANGELOG.md +26 -0
- package/CLAUDE.md +42 -62
- package/README.md +2 -2
- package/SKILL.md +0 -1
- package/THIRD_PARTY_NOTICES.md +5 -2
- package/adapters/browser/index.ts +2 -0
- package/adapters/chatgpt/browser-delivery-host.ts +71 -0
- package/adapters/chatgpt/browser-delivery-runtime.ts +783 -0
- package/adapters/chatgpt/controller-binding-store.ts +55 -0
- package/adapters/chatgpt/controller-host.ts +119 -0
- package/adapters/chatgpt/controller-round-host.ts +78 -0
- package/adapters/chatgpt/controller-round-settlement-store.ts +45 -0
- package/adapters/chatgpt/provider-delivery.ts +113 -0
- package/adapters/chatgpt/work-conversation-binding-store.ts +192 -0
- package/adapters/chatgpt/wsl-bridge-delivery-host.ts +63 -0
- package/adapters/computer/desktop-operator-contract.ts +7 -0
- package/adapters/computer/desktop-operator-discovery.ts +201 -0
- package/adapters/computer/desktop-operator-negotiation.ts +174 -0
- package/adapters/computer/desktop-operator-provider.ts +312 -0
- package/adapters/computer/index.ts +1 -0
- package/adapters/computer/interaction-target-authority.ts +944 -0
- package/adapters/controller-process/binding-store.ts +34 -0
- package/adapters/controller-process/controller-host.ts +26 -0
- package/adapters/mcp/access-mode.ts +132 -0
- package/adapters/mcp/audit.ts +32 -0
- package/adapters/mcp/auth.ts +407 -0
- package/adapters/mcp/controller-round-compatibility.ts +184 -0
- package/adapters/mcp/frozen-client-semantic-compatibility.ts +292 -0
- package/adapters/mcp/instructions.ts +36 -0
- package/adapters/mcp/legacy-context.ts +18 -0
- package/adapters/mcp/multi-repository.ts +437 -0
- package/adapters/mcp/oauth.ts +391 -0
- package/adapters/mcp/paths.ts +140 -0
- package/adapters/mcp/policy.ts +232 -0
- package/adapters/mcp/proxy-env.ts +62 -0
- package/adapters/mcp/readiness-projection.ts +24 -0
- package/adapters/mcp/redaction.ts +21 -0
- package/adapters/mcp/repo.ts +24 -0
- package/adapters/mcp/runtime-gateway/artifact-adapter.ts +52 -0
- package/adapters/mcp/runtime-gateway/context-adapter.ts +829 -0
- package/adapters/mcp/runtime-gateway/controller-authority-adapter.ts +191 -0
- package/adapters/mcp/runtime-gateway/engineering-preconditions.ts +147 -0
- package/adapters/mcp/runtime-gateway/execution-control-adapter.ts +28 -0
- package/adapters/mcp/runtime-gateway/execution-tools.ts +207 -0
- package/adapters/mcp/runtime-gateway/filesystem-adapter.ts +38 -0
- package/adapters/mcp/runtime-gateway/gateway-execution-adapter.ts +411 -0
- package/adapters/mcp/runtime-gateway/legacy-ios-tool-adapter.ts +105 -0
- package/adapters/mcp/runtime-gateway/maintenance-adapter.ts +44 -0
- package/adapters/mcp/runtime-gateway/model-adapter.ts +63 -0
- package/adapters/mcp/runtime-gateway/persisted-check-process.ts +3 -0
- package/adapters/mcp/runtime-gateway/plugin-adapter.ts +308 -0
- package/adapters/mcp/runtime-gateway/process-tools.ts +289 -0
- package/adapters/mcp/runtime-gateway/protected-computer-adapter.ts +76 -0
- package/adapters/mcp/runtime-gateway/recovery-adapter.ts +268 -0
- package/adapters/mcp/runtime-gateway/recovery-client-adapter.ts +70 -0
- package/adapters/mcp/runtime-gateway/recovery-tool-contract.ts +99 -0
- package/adapters/mcp/runtime-gateway/repository-compat-adapter.ts +110 -0
- package/adapters/mcp/runtime-gateway/result-adapter.ts +108 -0
- package/adapters/mcp/runtime-gateway/router.ts +728 -0
- package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +1251 -0
- package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +634 -0
- package/adapters/mcp/runtime-gateway/runtime-tool-shared.ts +27 -0
- package/adapters/mcp/runtime-gateway/runtime-tools.ts +68 -0
- package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +186 -0
- package/adapters/mcp/runtime-gateway/shared-adapter.ts +25 -0
- package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +870 -0
- package/adapters/mcp/runtime-gateway/work-adapter.ts +3186 -0
- package/adapters/mcp/runtime-gateway/work-compat-adapter.ts +502 -0
- package/adapters/mcp/runtime-gateway/work-validation-reconciler.ts +1 -0
- package/adapters/mcp/server.ts +1048 -0
- package/adapters/mcp/setup.ts +791 -0
- package/adapters/mcp/tool-capability-cache.ts +87 -0
- package/adapters/mcp/tool-mapping/access-tools.ts +387 -0
- package/adapters/mcp/tool-mapping/legacy-tool-service.ts +5265 -0
- package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +150 -0
- package/adapters/mcp/tool-mapping/repository-tools.ts +1691 -0
- package/adapters/mcp/tool-mapping/tools.ts +9 -0
- package/adapters/mcp/tool-mapping/umbrella-tools.ts +117 -0
- package/adapters/mcp/toolset-names.ts +74 -0
- package/adapters/mcp/toolset-selection.ts +41 -0
- package/adapters/mcp/toolset.ts +336 -0
- package/adapters/mcp/transports/http.ts +1456 -0
- package/adapters/mcp/transports/session-registry.ts +513 -0
- package/adapters/mcp/transports/stdio.ts +8 -0
- package/adapters/mcp/tunnels/openai-secure-tunnel.ts +139 -0
- package/adapters/mcp/types.ts +41 -0
- package/assets/AGENTS.md +2 -16
- package/assets/CLAUDE.md +2 -16
- package/assets/hooks/AGENTS.md +3 -14
- package/assets/hooks/CLAUDE.md +3 -14
- package/assets/hooks/hook-input.sh +9 -2
- package/assets/hooks/lib/workflow-state.sh +28 -10
- package/assets/hooks/prompt-guard.sh +63 -37
- package/assets/hooks/security-sentinel.sh +2 -1
- package/assets/hooks/session-start-context.sh +7 -5
- package/assets/hooks/stop-orchestrator.sh +13 -3
- package/assets/initializer-question-pack.v4.json +11 -7
- package/assets/partials/05-workflow.partial.md +18 -73
- package/assets/partials/07-footer.partial.md +1 -1
- package/assets/partials-agents/02-operating-mode.partial.md +1 -2
- package/assets/partials-agents/04-task-protocol.partial.md +14 -59
- package/assets/partials-agents/06-quality-safety.partial.md +11 -16
- package/assets/partials-agents/08-deep-docs.partial.md +1 -2
- package/assets/plan-map.json +11 -11
- package/assets/plugin-registry.v1.json +9 -3
- package/assets/plugin-trust-policy.v1.json +6 -0
- package/assets/recovery/ForgeRecovery.ps1 +100 -0
- package/assets/recovery/forge-wsl-rescue +271 -0
- package/assets/reference-configs/development-protocol.md +11 -15
- package/assets/reference-configs/document-generation.md +1 -1
- package/assets/reference-configs/global-working-rules.md +9 -1
- package/assets/reference-configs/harness-overview.md +22 -112
- package/assets/reference-configs/hook-operations.md +1 -1
- package/assets/reference-configs/sprint-contracts.md +2 -2
- package/assets/skill-version.json +2 -2
- package/assets/templates/helpers/architecture-event.ts +3 -34
- package/assets/templates/helpers/architecture-queue.sh +61 -10
- package/assets/templates/helpers/archive-workflow.sh +90 -180
- package/assets/templates/helpers/capability-config.ts +8 -11
- package/assets/templates/helpers/capability-resolver.ts +37 -19
- package/assets/templates/helpers/capture-plan.sh +2 -2
- package/assets/templates/helpers/check-architecture-sync.sh +1 -9
- package/assets/templates/helpers/check-task-sync.sh +82 -11
- package/assets/templates/helpers/check-task-workflow.sh +1 -3
- package/assets/templates/helpers/context-contract-sync.sh +1 -12
- package/assets/templates/helpers/contract-worktree.sh +26 -24
- package/assets/templates/helpers/ensure-task-workflow.sh +6 -8
- package/assets/templates/helpers/inspect-project-state.ts +1 -1
- package/assets/templates/helpers/migrate-project-template.sh +1 -1
- package/assets/templates/helpers/migrate-workflow-docs.ts +53 -239
- package/assets/templates/helpers/new-plan.sh +2 -2
- package/assets/templates/helpers/plan-to-todo.sh +3 -31
- package/assets/templates/helpers/sprint-backlog.sh +1 -1
- package/assets/templates/helpers/switch-plan.sh +1 -1
- package/assets/templates/helpers/workflow-contract.ts +1 -0
- package/assets/workflow-contract.v1.json +63 -171
- package/assets/workflows/xiaohongshu/xiaohongshu.collect-metrics.v1.draft.json +118 -0
- package/assets/workflows/xiaohongshu/xiaohongshu.publish-image-note.v1.draft.json +316 -0
- package/assets/workflows/xiaohongshu/xiaohongshu.publish-long-text.v1.draft.json +324 -0
- package/docs/architecture/CURRENT.md +148 -13
- package/docs/architecture/EVOLUTION.md +13 -0
- package/docs/architecture/decisions/20260801-controller-home-sqlite-state.md +2 -1
- package/docs/architecture/decisions/20260831-independent-windows-wsl-host-rescue.md +59 -0
- package/docs/architecture/decisions/20260904-ios-device-migration-baseline.md +120 -0
- package/docs/architecture/decisions/20260904-repository-runtime-data-boundary.md +42 -0
- package/docs/architecture/decisions/20260907-assistant-learning-loop.md +35 -0
- package/docs/architecture/decisions/20260907-controller-round-transition-policy.md +296 -0
- package/docs/architecture/decisions/20260907-maintenance-diagnosis-bounded-read.md +39 -0
- package/docs/architecture/domains/verification.md +7 -0
- package/docs/architecture/domains/workflow-engine.md +1 -1
- package/docs/architecture/index.md +3 -3
- package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +19 -8
- package/docs/architecture/requests/2026-09-04-computer-plugin-workflow-taxonomy.md +124 -0
- package/docs/forge-chatgpt-mcp-setup.md +5 -3
- package/docs/forge-plugin-management.md +20 -4
- package/docs/forge-runtime-self-healing-loop.md +2 -0
- package/docs/operations/benchmark-cross-version-freeze.md +38 -0
- package/docs/operations/controller-browser-plugin.md +3 -1
- package/docs/operations/homebrew.md +2 -2
- package/docs/operations/platform-support.md +16 -8
- package/docs/operations/platform-support.zh-CN.md +2 -2
- package/docs/operations/standalone-disaster-recovery.md +26 -1
- package/docs/operations/uu-remote-rescue.md +41 -0
- package/docs/operations/windows-wsl-host-rescue.md +133 -0
- package/docs/public-usage-guide.md +1 -1
- package/docs/public-usage-guide.zh-CN.md +1 -1
- package/docs/tutorials/01-install-and-start.md +1 -1
- package/docs/tutorials/01-install-and-start.zh-CN.md +1 -1
- package/docs/tutorials/02-connect-chatgpt.md +4 -4
- package/docs/tutorials/02-connect-chatgpt.zh-CN.md +4 -4
- package/docs/wiki/Implementation.md +1 -1
- package/package.json +23 -14
- package/packages/kernel/controller/api/index.ts +2 -0
- package/packages/kernel/controller/application/controller-round-service.ts +29 -0
- package/packages/kernel/controller/application/controller-service.ts +30 -0
- package/packages/kernel/controller/domain/controller-round-transition-policy.ts +308 -0
- package/packages/kernel/controller/domain/controller-round.ts +107 -0
- package/packages/kernel/controller/domain/execution-quality.ts +133 -0
- package/packages/kernel/controller/domain/types.ts +56 -0
- package/packages/kernel/controller/index.ts +1 -0
- package/packages/kernel/controller/infrastructure/controller-binding-store.ts +84 -0
- package/packages/kernel/controller/infrastructure/controller-round-store.ts +1384 -0
- package/packages/kernel/controller/infrastructure/controller-session-store.ts +578 -0
- package/packages/kernel/controller/ports/controller-host.ts +16 -0
- package/packages/kernel/goal/api/index.ts +1 -0
- package/packages/kernel/goal/domain/types.ts +40 -0
- package/packages/kernel/goal/index.ts +1 -0
- package/packages/kernel/identity/api/index.ts +5 -0
- package/packages/kernel/identity/application/identity-service.ts +67 -0
- package/packages/kernel/identity/domain/scope.ts +63 -0
- package/packages/kernel/identity/domain/semantic-sync.ts +81 -0
- package/packages/kernel/identity/domain/types.ts +44 -0
- package/packages/kernel/identity/domain/workspace.ts +56 -0
- package/packages/kernel/identity/index.ts +1 -0
- package/packages/kernel/identity/infrastructure/identity-store.ts +75 -0
- package/packages/kernel/memory/api/index.ts +5 -0
- package/packages/kernel/memory/application/experience-service.ts +118 -0
- package/packages/kernel/memory/application/outcome-service.ts +77 -0
- package/packages/kernel/memory/domain/experience.ts +103 -0
- package/packages/kernel/memory/domain/operational-prior.ts +92 -0
- package/packages/kernel/memory/index.ts +1 -0
- package/packages/kernel/progression/api/index.ts +2 -0
- package/packages/kernel/progression/application/projector.ts +211 -0
- package/packages/kernel/progression/domain/types.ts +116 -0
- package/packages/kernel/progression/index.ts +1 -0
- package/packages/kernel/scheduler/api/index.ts +6 -0
- package/packages/kernel/scheduler/application/continuation-service.ts +212 -0
- package/packages/kernel/scheduler/application/eligibility.ts +252 -0
- package/packages/kernel/scheduler/application/schedule-service.ts +24 -0
- package/packages/kernel/scheduler/application/settlement.ts +197 -0
- package/packages/kernel/scheduler/domain/continuation.ts +38 -0
- package/packages/kernel/scheduler/domain/schedule.ts +149 -0
- package/packages/kernel/scheduler/index.ts +1 -0
- package/packages/kernel/scheduler/infrastructure/continuation-dispatch-store.ts +38 -0
- package/packages/kernel/scheduler/infrastructure/schedule-store.ts +785 -0
- package/packages/kernel/work/api/index.ts +15 -0
- package/packages/kernel/work/application/work-service.ts +148 -0
- package/packages/kernel/work/domain/admission-policy.ts +34 -0
- package/packages/kernel/work/domain/check-receipt.ts +43 -0
- package/packages/kernel/work/domain/context-closure-receipt.ts +32 -0
- package/packages/kernel/work/domain/engineering-contracts.ts +157 -0
- package/packages/kernel/work/domain/engineering-design.ts +281 -0
- package/packages/kernel/work/domain/engineering-profile.ts +242 -0
- package/packages/kernel/work/domain/execution-concurrency.ts +254 -0
- package/packages/kernel/work/domain/execution-snapshot.ts +33 -0
- package/packages/kernel/work/domain/implementation-review.ts +510 -0
- package/packages/kernel/work/domain/project-engineering-contract.ts +202 -0
- package/packages/kernel/work/domain/repository-completion-receipt.ts +73 -0
- package/packages/kernel/work/domain/state-machine.ts +259 -0
- package/packages/kernel/work/domain/types.ts +528 -0
- package/packages/kernel/work/index.ts +1 -0
- package/packages/kernel/work/infrastructure/work-contract-store.ts +1876 -0
- package/packages/kernel/work/ports/work-contract-store.ts +18 -0
- package/packages/plugin-runtime/browser/index.ts +3 -0
- package/packages/plugin-runtime/browser/provider-registry.ts +110 -0
- package/packages/plugin-runtime/browser/runtime-contract.ts +150 -0
- package/packages/plugin-runtime/browser/session-authority.ts +61 -0
- package/packages/plugin-runtime/computer/index.ts +6 -0
- package/packages/plugin-runtime/computer/provider-error.ts +26 -0
- package/packages/plugin-runtime/computer/provider-registration.ts +52 -0
- package/packages/plugin-runtime/computer/provider-registry.ts +63 -0
- package/packages/plugin-runtime/computer/provider.ts +19 -0
- package/packages/plugin-runtime/computer/target-authority.ts +190 -0
- package/packages/plugin-runtime/computer/target-persistence.ts +54 -0
- package/packages/plugin-runtime/external/index.ts +1 -0
- package/packages/plugin-runtime/external/unix-jsonl-transport.ts +457 -0
- package/packages/plugin-runtime/index.ts +3 -0
- package/packages/protocols/browser/index.ts +1 -0
- package/packages/protocols/browser/session.ts +98 -0
- package/packages/protocols/computer/contract.ts +199 -0
- package/packages/protocols/computer/index.ts +1 -0
- package/packages/protocols/failure/contract.ts +158 -0
- package/packages/protocols/failure/index.ts +1 -0
- package/packages/protocols/handoff/index.ts +1 -0
- package/packages/protocols/handoff/status.ts +22 -0
- package/packages/protocols/mcp/execution-context.ts +11 -0
- package/packages/protocols/mcp/index.ts +2 -0
- package/packages/protocols/mcp/tool-contract.ts +42 -0
- package/packages/workflow-runtime/api/index.ts +2 -0
- package/packages/workflow-runtime/application/interpreter.ts +342 -0
- package/packages/workflow-runtime/domain/workflow-asset.ts +223 -0
- package/packages/workflow-runtime/index.ts +1 -0
- package/scripts/assemble-template.ts +1 -1
- package/scripts/benchmark-computer-hotpath.ts +255 -0
- package/scripts/benchmark-controller-round2.ts +54 -2
- package/scripts/benchmark-ios-agent-device.ts +3 -6
- package/scripts/benchmark-mcp-transport.ts +3 -4
- package/scripts/benchmark-operational-memory-activation.ts +235 -0
- package/scripts/benchmark-operational-shadow.ts +28 -0
- package/scripts/bootstrap-runtime-maintenance-recovery.sh +4 -1
- package/scripts/canary-chatgpt-provider-delivery.ts +97 -0
- package/scripts/canary-controller-semantic-wait.ts +195 -0
- package/scripts/canary-global-hook.sh +2 -2
- package/scripts/check-mcp-compatibility.ts +173 -7
- package/scripts/check-platform-support.mjs +28 -2
- package/scripts/check-public-docs.sh +1 -1
- package/scripts/check-release-readiness.sh +1 -1
- package/scripts/check-repository-hygiene.mjs +92 -0
- package/scripts/check-runtime-architecture.mjs +1206 -95
- package/scripts/check-source-duplication.mjs +9 -1
- package/scripts/check-tarball-install-smoke.sh +98 -15
- package/scripts/controller-ngrok-rotation.sh +5 -4
- package/scripts/create-project-dirs.sh +10 -74
- package/scripts/forge-local-recovery-helper.mjs +204 -0
- package/scripts/forge-uu-remote-rescue-helper.d.mts +31 -0
- package/scripts/forge-uu-remote-rescue-helper.mjs +409 -0
- package/scripts/forge-windows-host-recovery-helper.mjs +136 -0
- package/scripts/hook-shim.sh +2 -2
- package/scripts/init-project.sh +12 -70
- package/scripts/install-desktop-operator-registration.ts +4 -2
- package/scripts/install-independent-windows-wsl-recovery.ts +125 -0
- package/scripts/install-standalone-recovery.ts +122 -10
- package/scripts/install-uu-remote-rescue-registration.ts +74 -0
- package/scripts/install-windows-host-recovery-registration.ts +22 -0
- package/scripts/lib/controller-home-env.sh +6 -3
- package/scripts/lib/project-init-lib.sh +39 -582
- package/scripts/migrate-chatgpt-automation-schedules.ts +2 -2
- package/scripts/migrate-windows-wsl-controller-home.ts +306 -0
- package/scripts/open-source-audit-allowlist.txt +12 -1
- package/scripts/portability-bindings.mjs +70 -0
- package/scripts/run-bounded-command.mjs +55 -0
- package/scripts/run-bun-test-file.ts +22 -6
- package/scripts/run-governed-gate.ts +4 -1
- package/scripts/smoke-mcp-http-runtime.ts +1 -1
- package/scripts/smoke-runtime-recovery.ts +34 -1
- package/scripts/smoke-schedule-engine.ts +1 -1
- package/scripts/stage-runtime-release.ts +6 -1
- package/scripts/test-governance.ts +51 -2
- package/src/cli/agent-jobs/job-manager.ts +10 -1
- package/src/cli/chatgpt-browser/bind-server.ts +2 -1
- package/src/cli/chatgpt-browser/binding.ts +20 -10
- package/src/cli/chatgpt-browser/bridge-extension.ts +75 -0
- package/src/cli/chatgpt-browser/bridge-provider.ts +376 -11
- package/src/cli/chatgpt-browser/engine.ts +10 -11
- package/src/cli/chatgpt-browser/native-provider.ts +24 -83
- package/src/cli/chatgpt-browser/oracle-provider.ts +5 -3
- package/src/cli/chatgpt-browser/types.ts +1 -0
- package/src/cli/commands/bootstrap-control.ts +334 -0
- package/src/cli/commands/brain-assistant.ts +38 -0
- package/src/cli/commands/brain.ts +193 -40
- package/src/cli/commands/chatgpt.ts +127 -0
- package/src/cli/commands/computer.ts +437 -0
- package/src/cli/commands/doctor.ts +18 -1
- package/src/cli/commands/init-hook.ts +71 -61
- package/src/cli/commands/init.ts +3 -1
- package/src/cli/commands/mcp.ts +16 -10
- package/src/cli/commands/plugin.ts +38 -12
- package/src/cli/commands/recovery.ts +493 -80
- package/src/cli/commands/runtime.ts +9 -4
- package/src/cli/commands/setup-profile.ts +89 -39
- package/src/cli/commands/status.ts +2 -1
- package/src/cli/controller/check-runner.ts +487 -98
- package/src/cli/controller/context/types.ts +7 -1
- package/src/cli/controller/context-pack.ts +23 -3
- package/src/cli/controller/issue-store.ts +1 -1
- package/src/cli/controller/systemd-user.ts +110 -0
- package/src/cli/controller/types.ts +10 -70
- package/src/cli/controller/worklog.ts +67 -13
- package/src/cli/editing/edit-operation-contract.ts +92 -0
- package/src/cli/editing/edit-session.ts +289 -13
- package/src/cli/github/plugin.ts +17 -12
- package/src/cli/hook/route-registry.ts +3 -5
- package/src/cli/hook/runtime.ts +49 -3
- package/src/cli/index.ts +3 -0
- package/src/cli/local-bridge/connector-freshness.ts +2 -2
- package/src/cli/local-bridge/console-automations.ts +2 -2
- package/src/cli/local-bridge/facade-api.ts +41 -14
- package/src/cli/local-bridge/job-store.ts +1 -1
- package/src/cli/local-bridge/server.ts +24 -27
- package/src/cli/mcp/access-mode.ts +2 -132
- package/src/cli/mcp/access-tools.ts +2 -387
- package/src/cli/mcp/audit.ts +2 -32
- package/src/cli/mcp/auth.ts +2 -404
- package/src/cli/mcp/instructions.ts +2 -34
- package/src/cli/mcp/legacy-context.ts +2 -16
- package/src/cli/mcp/legacy-tool-service.ts +2 -5308
- package/src/cli/mcp/multi-repository.ts +2 -436
- package/src/cli/mcp/oauth.ts +2 -375
- package/src/cli/mcp/openai-secure-tunnel.ts +2 -0
- package/src/cli/mcp/paths.ts +2 -140
- package/src/cli/mcp/policy.ts +2 -232
- package/src/cli/mcp/post-finalize-work-attribution.ts +2 -150
- package/src/cli/mcp/proxy-env.ts +2 -62
- package/src/cli/mcp/readiness-projection.ts +2 -24
- package/src/cli/mcp/redaction.ts +2 -21
- package/src/cli/mcp/repo.ts +2 -24
- package/src/cli/mcp/repository-tools.ts +2 -1613
- package/src/cli/mcp/server.ts +2 -951
- package/src/cli/mcp/setup.ts +2 -737
- package/src/cli/mcp/tool-capability-cache.ts +2 -87
- package/src/cli/mcp/tool-contract.ts +2 -14
- package/src/cli/mcp/tools.ts +2 -9
- package/src/cli/mcp/toolset-names.ts +2 -70
- package/src/cli/mcp/toolset-selection.ts +2 -41
- package/src/cli/mcp/toolset.ts +2 -336
- package/src/cli/mcp/transports/AGENTS.md +1 -10
- package/src/cli/mcp/transports/CLAUDE.md +1 -10
- package/src/cli/mcp/transports/http.ts +2 -1414
- package/src/cli/mcp/transports/session-registry.ts +2 -490
- package/src/cli/mcp/transports/stdio.ts +2 -8
- package/src/cli/mcp/types.ts +2 -41
- package/src/cli/mcp/umbrella-tools.ts +2 -117
- package/src/cli/repositories/command-executor.ts +64 -18
- package/src/cli/repositories/command-scope.ts +117 -1
- package/src/cli/repositories/controller-home.ts +119 -1
- package/src/cli/repositories/identity.ts +13 -0
- package/src/cli/repositories/registry.ts +68 -49
- package/src/cli/repositories/repository-snapshot.ts +53 -7
- package/src/cli/repositories/runtime-storage.ts +27 -2
- package/src/cli/repositories/safe-patch.ts +34 -38
- package/src/cli/repositories/selected-path-actions.ts +22 -2
- package/src/cli/repositories/structured-git.ts +105 -25
- package/src/cli/runtime/helper-runner.ts +7 -0
- package/src/cli/runtime-invocation.ts +8 -1
- package/src/cli/tools/codegraph.ts +44 -25
- package/src/core/adoption/manifest-templates.ts +1 -1
- package/src/core/adoption/plan.ts +3 -26
- package/src/core/adoption/workflow-contract-plan.ts +17 -9
- package/src/effects/process-runner.ts +8 -14
- package/src/runtime/context/assistant-context.ts +154 -0
- package/src/runtime/context/assistant-work-context.ts +147 -0
- package/src/runtime/context/codegraph-cache-boundary.ts +255 -0
- package/src/runtime/context/codegraph-read-provider.ts +55 -22
- package/src/runtime/context/codegraph-sidecar.cjs +8 -1
- package/src/runtime/context/context-closure.ts +268 -0
- package/src/runtime/context/context-plane.ts +211 -0
- package/src/runtime/context/project-engineering-contract.ts +60 -0
- package/src/runtime/control-plane/bootstrap/capability-provider.ts +74 -0
- package/src/runtime/control-plane/bootstrap/control-api.ts +57 -0
- package/src/runtime/control-plane/bootstrap/index.ts +5 -0
- package/src/runtime/control-plane/bootstrap/state-machine.ts +141 -0
- package/src/runtime/control-plane/bootstrap/store.ts +21 -0
- package/src/runtime/control-plane/bootstrap/types.ts +87 -0
- package/src/runtime/control-plane/cleanup-artifact-retention.ts +328 -0
- package/src/runtime/control-plane/codegraph-cache-retention.ts +164 -0
- package/src/runtime/control-plane/concurrency/work-execution-concurrency.ts +320 -0
- package/src/runtime/control-plane/execution/content-equivalent-commit-authority.ts +169 -0
- package/src/runtime/control-plane/execution/controller-authority-recovery.ts +350 -0
- package/src/runtime/control-plane/execution/direct-canonical-work-reconciliation.ts +85 -0
- package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +369 -99
- package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +103 -15
- package/src/runtime/control-plane/execution/implementation-review-content.ts +95 -0
- package/src/runtime/control-plane/execution/repository-work-attribution.ts +2 -2
- package/src/runtime/control-plane/execution/retained-work-resume.ts +336 -6
- package/src/runtime/control-plane/execution/validation.ts +28 -3
- package/src/runtime/control-plane/execution/work-authority-reconciler.ts +116 -0
- package/src/runtime/control-plane/execution/work-completion-authority.ts +44 -2
- package/src/runtime/control-plane/execution/work-evidence-policy.ts +34 -3
- package/src/runtime/control-plane/execution/work-execution-support.ts +42 -22
- package/src/runtime/control-plane/execution/work-finalization-service.ts +1103 -166
- package/src/runtime/control-plane/execution/work-handle-authority.ts +219 -22
- package/src/runtime/control-plane/execution/work-handle-store.ts +77 -0
- package/src/runtime/control-plane/execution/work-head-settlement.ts +75 -0
- package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +145 -23
- package/src/runtime/control-plane/execution/work-operation-service.ts +49 -13
- package/src/runtime/control-plane/execution/work-preparation-service.ts +31 -15
- package/src/runtime/control-plane/execution/work-remote-delivery.ts +1 -1
- package/src/runtime/control-plane/execution/work-task-receipt.ts +20 -1
- package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +407 -76
- package/src/runtime/control-plane/execution/work-validation-reconciler.ts +88 -18
- package/src/runtime/control-plane/execution/work-verification-context.ts +1 -1
- package/src/runtime/control-plane/execution/work-verification-service.ts +258 -4
- package/src/runtime/control-plane/execution/work-verification-snapshot.ts +200 -15
- package/src/runtime/control-plane/facade/capability-registry.ts +21 -10
- package/src/runtime/control-plane/facade/controller-round-relay.ts +3 -1118
- package/src/runtime/control-plane/facade/controller-session-store.ts +2 -488
- package/src/runtime/control-plane/facade/goal-workloop-access.ts +6 -3
- package/src/runtime/control-plane/facade/goal-workloop.ts +972 -137
- package/src/runtime/control-plane/facade/handoff-inbox-application.ts +158 -0
- package/src/runtime/control-plane/facade/handoff-inbox-store.ts +10 -0
- package/src/runtime/control-plane/facade/index.ts +4 -2
- package/src/runtime/control-plane/facade/operation-digest.ts +22 -58
- package/src/runtime/control-plane/facade/plan-contract-store.ts +1004 -38
- package/src/runtime/control-plane/facade/repository-work-admission.ts +19 -1
- package/src/runtime/control-plane/facade/requirement-authority.ts +218 -0
- package/src/runtime/control-plane/facade/requirement-board.ts +6 -1
- package/src/runtime/control-plane/facade/rh-work-operation-contract.ts +48 -0
- package/src/runtime/control-plane/facade/semantic-admission.ts +8 -16
- package/src/runtime/control-plane/facade/suggested-actions.ts +4 -1
- package/src/runtime/control-plane/facade/types.ts +189 -532
- package/src/runtime/control-plane/facade/work-admission-policy.ts +84 -35
- package/src/runtime/control-plane/facade/work-contract-store.ts +2 -1043
- package/src/runtime/control-plane/facade/work-implementation-review.ts +2 -0
- package/src/runtime/control-plane/facade/work-state-machine.ts +2 -250
- package/src/runtime/control-plane/generated-cache-retention.ts +239 -18
- package/src/runtime/control-plane/global-scheduler/durable-admission.ts +12 -1
- package/src/runtime/control-plane/global-scheduler/maintenance.ts +76 -13
- package/src/runtime/control-plane/global-scheduler/periodic-cleanup-entry.ts +55 -0
- package/src/runtime/control-plane/global-scheduler/periodic-cleanup-process.ts +98 -0
- package/src/runtime/control-plane/global-scheduler/reconciliation.ts +1 -1
- package/src/runtime/control-plane/global-scheduler/scheduler-worker-entry.ts +10 -0
- package/src/runtime/control-plane/global-scheduler/scheduler.ts +173 -81
- package/src/runtime/control-plane/global-scheduler/worker-launch.ts +18 -6
- package/src/runtime/control-plane/launcher/chatgpt-round-continuation.ts +397 -0
- package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +2 -177
- package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +301 -560
- package/src/runtime/control-plane/launcher/provider-mcp-bootstrap.ts +20 -4
- package/src/runtime/control-plane/launcher/thin-launcher.ts +50 -4
- package/src/runtime/control-plane/lifecycle-retention-metrics.ts +60 -0
- package/src/runtime/control-plane/persistence/experience-store.ts +169 -0
- package/src/runtime/control-plane/persistence/operational-prior-store.ts +348 -0
- package/src/runtime/control-plane/persistence/requirement-store.ts +30 -22
- package/src/runtime/control-plane/persistence/sqlite-store.ts +545 -76
- package/src/runtime/control-plane/persistence/workflow-content-store.ts +98 -0
- package/src/runtime/control-plane/persistence/workflow-registry-store.ts +186 -0
- package/src/runtime/control-plane/persistence/workflow-run-store.ts +123 -0
- package/src/runtime/control-plane/release-retention.ts +56 -16
- package/src/runtime/control-plane/repository-namespace-retention.ts +208 -0
- package/src/runtime/control-plane/routing/route-policy.ts +19 -0
- package/src/runtime/control-plane/runtime-cleanup.ts +574 -37
- package/src/runtime/control-plane/runtime-generation.ts +6 -0
- package/src/runtime/control-plane/workspace/semantic-sync-service.ts +465 -0
- package/src/runtime/control-plane/workspace/workspace-store.ts +80 -0
- package/src/runtime/diagnostics/incident-repair.ts +406 -0
- package/src/runtime/diagnostics/mcp-timing.ts +125 -6
- package/src/runtime/diagnostics/performance.ts +6 -14
- package/src/runtime/diagnostics/read-only-tool.ts +1 -1
- package/src/runtime/evidence/artifact-store.ts +65 -2
- package/src/runtime/evidence/operational-shadow.ts +38 -0
- package/src/runtime/evidence/process-check-receipt.ts +5 -43
- package/src/runtime/evidence/sensitive-output.ts +4 -4
- package/src/runtime/execution/jobs/receipt-recovery.ts +1 -1
- package/src/runtime/execution/jobs/store.ts +121 -2
- package/src/runtime/execution/managed-workspace.ts +55 -5
- package/src/runtime/execution/process-runtime/canary.ts +19 -5
- package/src/runtime/execution/process-runtime/check-classification.ts +48 -0
- package/src/runtime/execution/process-runtime/check-facade.ts +23 -9
- package/src/runtime/execution/process-runtime/check-receipt.ts +1 -1
- package/src/runtime/execution/process-runtime/check-result-retention.ts +132 -0
- package/src/runtime/execution/process-runtime/check-result.ts +73 -2
- package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +42 -3
- package/src/runtime/execution/process-runtime/check-storage.ts +187 -0
- package/src/runtime/execution/process-runtime/command-facade.ts +38 -87
- package/src/runtime/execution/process-runtime/index.ts +1 -0
- package/src/runtime/execution/process-runtime/interactive-admission.ts +2 -1
- package/src/runtime/execution/process-runtime/lightweight-managed.ts +32 -1
- package/src/runtime/execution/process-runtime/persisted-check.ts +128 -21
- package/src/runtime/execution/process-runtime/resource-claims.ts +60 -3
- package/src/runtime/execution/process-runtime/runtime.ts +132 -15
- package/src/runtime/execution/process-runtime/types.ts +22 -0
- package/src/runtime/execution/workers/executor.ts +16 -13
- package/src/runtime/execution/workers/worker-entry.ts +1 -1
- package/src/runtime/gateway/mcp/execution-tools.ts +2 -207
- package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +2 -61
- package/src/runtime/gateway/mcp/persisted-check-process.ts +2 -3
- package/src/runtime/gateway/mcp/process-tools.ts +2 -289
- package/src/runtime/gateway/mcp/router.ts +2 -1125
- package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +2 -565
- package/src/runtime/gateway/mcp/runtime-tools.ts +2 -6655
- package/src/runtime/gateway/mcp/work-validation-reconciler.ts +2 -1
- package/src/runtime/maintenance/cleanup.ts +38 -24
- package/src/runtime/platform/browser-product-discovery.ts +174 -0
- package/src/runtime/platform/computer-platform.ts +14 -0
- package/src/runtime/platform/executable-discovery.ts +54 -0
- package/src/runtime/platform/fetch-http-server.ts +90 -0
- package/src/runtime/platform/service-manager.ts +138 -0
- package/src/runtime/platform/windows-host-discovery.ts +118 -0
- package/src/runtime/platform/windows-recovery-deployment.ts +67 -0
- package/src/runtime/plugins/action-application.ts +135 -0
- package/src/runtime/plugins/app-store-connect-adapter.ts +9 -21
- package/src/runtime/plugins/browser-adapter.ts +140 -100
- package/src/runtime/plugins/browser-automation-service.ts +15 -36
- package/src/runtime/plugins/browser-macos-bridge.ts +69 -21
- package/src/runtime/plugins/browser-manifest-surface.ts +30 -6
- package/src/runtime/plugins/browser-native-session-service.ts +1 -1
- package/src/runtime/plugins/browser-provider-registry.ts +2 -109
- package/src/runtime/plugins/browser-registration.ts +16 -0
- package/src/runtime/plugins/browser-runtime-contract.ts +2 -154
- package/src/runtime/plugins/browser-runtime.ts +41 -9
- package/src/runtime/plugins/browser-session-authority.ts +101 -291
- package/src/runtime/plugins/browser-session-legacy-migration.ts +203 -0
- package/src/runtime/plugins/browser-session-store.ts +229 -36
- package/src/runtime/plugins/browser-session-types.ts +2 -98
- package/src/runtime/plugins/capability-authorization-grants.ts +17 -0
- package/src/runtime/plugins/catalog-trust.ts +82 -0
- package/src/runtime/plugins/computer-registration.ts +839 -0
- package/src/runtime/plugins/config-store.ts +119 -0
- package/src/runtime/plugins/desktop-operator-external-policy.ts +932 -0
- package/src/runtime/plugins/desktop-operator-registration.ts +111 -8
- package/src/runtime/plugins/errors.ts +8 -1
- package/src/runtime/plugins/external-adapter.ts +45 -322
- package/src/runtime/plugins/external-provider-policy.ts +48 -0
- package/src/runtime/plugins/external-registration.ts +9 -1
- package/src/runtime/plugins/external-unix-socket-probe.cjs +9 -3
- package/src/runtime/plugins/external-unix-socket.ts +64 -193
- package/src/runtime/plugins/first-party-external-registration.ts +163 -0
- package/src/runtime/plugins/first-party-registry.ts +3 -1
- package/src/runtime/plugins/github-adapter.ts +1 -2
- package/src/runtime/plugins/gmail-adapter.ts +6 -6
- package/src/runtime/plugins/google-calendar-adapter.ts +6 -6
- package/src/runtime/plugins/google-shared.ts +31 -46
- package/src/runtime/plugins/google-tasks-adapter.ts +6 -6
- package/src/runtime/plugins/ios-adapter.ts +1 -2
- package/src/runtime/plugins/local-system-adapter.ts +180 -0
- package/src/runtime/plugins/macos-capability-broker.ts +15 -105
- package/src/runtime/plugins/resend-adapter.ts +15 -24
- package/src/runtime/plugins/store.ts +493 -51
- package/src/runtime/plugins/types.ts +8 -1
- package/src/runtime/plugins/uu-remote-rescue-registration.ts +155 -0
- package/src/runtime/plugins/windows-host-recovery-install.ts +68 -0
- package/src/runtime/plugins/windows-host-recovery-registration.ts +85 -0
- package/src/runtime/plugins/xiaohongshu-publish.ts +86 -430
- package/src/runtime/projections/controller-context.ts +12 -6
- package/src/runtime/projections/git-status-sampler.ts +73 -22
- package/src/runtime/projections/materialized-view.ts +14 -8
- package/src/runtime/recovery/capability-action-application.ts +228 -0
- package/src/runtime/recovery/index.ts +3 -0
- package/src/runtime/recovery/lifecycle-inventory.ts +338 -0
- package/src/runtime/recovery/local-jobs-repair.ts +14 -14
- package/src/runtime/recovery/maintenance-executor.ts +358 -76
- package/src/runtime/recovery/quarantine-retention.ts +256 -0
- package/src/runtime/release/identity.ts +6 -0
- package/src/runtime/resources/leases/store.ts +1 -1
- package/src/runtime/root/active-execution-power-assertion.ts +139 -0
- package/src/runtime/root/assistant-learning-loop.ts +45 -0
- package/src/runtime/root/browser-session-composition.ts +59 -0
- package/src/runtime/root/computer-composition.ts +191 -0
- package/src/runtime/root/computer-target-composition.ts +16 -0
- package/src/runtime/root/computer-target-persistence.ts +39 -0
- package/src/runtime/root/controller-round-composition.ts +107 -0
- package/src/runtime/root/controller-services.ts +2 -0
- package/src/runtime/root/entry.ts +4 -3
- package/src/runtime/root/gateway-adapter.ts +3 -3
- package/src/runtime/root/local-bridge.ts +5 -2
- package/src/runtime/root/mcp-transport.ts +5 -5
- package/src/runtime/root/package-connector-service.ts +108 -56
- package/src/runtime/root/package-runtime-release.ts +85 -18
- package/src/runtime/root/package-runtime-service.ts +60 -97
- package/src/runtime/root/release-execution-canary.ts +71 -0
- package/src/runtime/root/release-loader.ts +68 -0
- package/src/runtime/root/release-manifest.ts +106 -2
- package/src/runtime/root/release-materialize.ts +103 -4
- package/src/runtime/root/release-store.ts +31 -2
- package/src/runtime/root/runtime.ts +240 -25
- package/src/runtime/root/scheduled-controller-composition.ts +51 -0
- package/src/runtime/root/scheduler.ts +12 -4
- package/src/runtime/root/service-runner.ts +1 -1
- package/src/runtime/root/service.ts +41 -16
- package/src/runtime/root/status.ts +1 -0
- package/src/runtime/root/types.ts +24 -1
- package/src/runtime/shared/local-bridge-surface.ts +1 -1
- package/src/runtime/shared/process-environment.ts +19 -4
- package/src/runtime/shared/storage-capacity.ts +68 -0
- package/src/runtime/standalone-recovery/controller-home-migration.ts +1116 -0
- package/src/runtime/standalone-recovery/core.ts +984 -230
- package/src/runtime/standalone-recovery/entry.ts +182 -51
- package/src/runtime/standalone-recovery/independent-host-rescue.ts +172 -0
- package/src/runtime/standalone-recovery/installer.ts +212 -104
- package/src/runtime/standalone-recovery/mcp-server.ts +243 -0
- package/src/runtime/standalone-recovery/mutation-identity-contract.ts +21 -0
- package/src/runtime/standalone-recovery/operation-lock.ts +160 -0
- package/src/runtime/standalone-recovery/performance.ts +135 -0
- package/src/runtime/standalone-recovery/release.ts +5 -0
- package/src/runtime/watchdog/workflow-watchdog.ts +1 -1
- package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +1 -1
- package/src/runtime/workflow/schedules/engine.ts +191 -343
- package/src/runtime/workflow/schedules/pending-activation.ts +1 -1
- package/src/runtime/workflow/schedules/settlement.ts +2 -191
- package/src/runtime/workflow/schedules/store.ts +2 -607
- package/src/runtime/workflow/schedules/types.ts +2 -127
- package/src/runtime/workflow/schedules/work-continuation.ts +180 -15
- package/src/runtime/workflows/first-party/xiaohongshu.ts +122 -0
- package/src/runtime/workflows/runtime.ts +486 -0
- package/src/testing/test-governance.ts +90 -29
- package/assets/templates/helpers/archive-architecture-request.sh +0 -244
- package/docs/architecture/history/README.md +0 -7
- package/docs/architecture/history/chatgpt-handoff-facade.md +0 -397
- package/docs/architecture/history/global-hook-runtime.md +0 -166
- package/docs/architecture/history/ios-semantic-automation-provider-v2.md +0 -170
- package/docs/architecture/requests/archive/2026/20260528-154740-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-154816-assets-hooks-assets-hooks-hook-input-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-161851-ai-harness-workflow-contract-json-ai-harness-workflow-contract-json.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-161853-scripts-check-task-workflow-sh-scripts-check-task-workflow-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-161911-assets-workflow-contract-v1-json-assets-workflow-contract-v1-json.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-222416-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-222444-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-222457-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-222648-ai-hooks-ai-hooks-pre-edit-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-222705-ai-hooks-ai-hooks-worktree-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-222726-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-222727-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-224736-ai-hooks-ai-hooks-hook-input-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-233259-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-233335-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-233456-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-233457-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-233637-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260528-233638-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260529-000322-root-package-json.md +0 -59
- package/docs/architecture/requests/archive/2026/20260529-004238-ai-hooks-ai-hooks-lib-workflow-state-sh.md +0 -59
- package/docs/architecture/requests/archive/2026/20260529-020654-ai-harness-policy-json-ai-harness-policy-json.md +0 -63
- package/docs/architecture/requests/archive/2026/20260529-094236-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -60
- package/docs/architecture/requests/archive/2026/20260529-094323-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -60
- package/docs/architecture/requests/archive/2026/20260529-094331-ai-hooks-ai-hooks-prompt-guard-sh.md +0 -60
- package/docs/architecture/requests/archive/2026/20260529-094339-assets-hooks-assets-hooks-prompt-guard-sh.md +0 -60
- package/docs/architecture/requests/archive/2026/20260529-094430-assets-hooks-assets-hooks-session-start-context-sh.md +0 -60
- package/docs/architecture/requests/archive/2026/20260529-094446-ai-hooks-ai-hooks-session-start-context-sh.md +0 -60
- package/docs/architecture/requests/archive/2026/20260613-002040-runtime-harness-hook-adapters.md +0 -68
- package/docs/architecture/requests/archive/2026/root.md +0 -68
- package/docs/architecture/requests/archive/2026/runtime-harness-hook-adapters.md +0 -76
- package/docs/architecture/requests/archive/2026/verification-evals-checks.md +0 -68
- package/docs/architecture/requests/archive/2026/workflow-engine-contract-assets.md +0 -69
- package/scripts/archive-architecture-request.sh +0 -4
- package/scripts/run-skill-evals.ts +0 -1022
|
@@ -1,7 +1,28 @@
|
|
|
1
1
|
import { createHash, randomUUID } from 'crypto';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { isWslWindowsRuntime } from '../../../cli/chatgpt-browser/bridge-provider';
|
|
3
|
+
import { createChatgptBrowserDeliveryHost } from '../../../../adapters/chatgpt/browser-delivery-host';
|
|
4
|
+
import { createChatgptWslBridgeDeliveryHost } from '../../../../adapters/chatgpt/wsl-bridge-delivery-host';
|
|
5
|
+
import {
|
|
6
|
+
CHATGPT_AUTOMATION_SUBMISSION_OUTCOME_UNKNOWN,
|
|
7
|
+
DEFAULT_CHATGPT_AUTOMATION_MODEL,
|
|
8
|
+
DEFAULT_CHATGPT_AUTOMATION_REASONING,
|
|
9
|
+
DEFAULT_CHATGPT_AUTOMATION_TAB_POLICY,
|
|
10
|
+
type ChatgptAutomationReasoning,
|
|
11
|
+
type ChatgptAutomationTabCleanupStatus,
|
|
12
|
+
type ChatgptAutomationTabPolicy,
|
|
13
|
+
type ChatgptProviderDeliveryHost,
|
|
14
|
+
type ChatgptProviderDeliveryStatus,
|
|
15
|
+
} from '../../../../adapters/chatgpt/provider-delivery';
|
|
16
|
+
import {
|
|
17
|
+
closeChatgptAutomationTabAfterDispatch,
|
|
18
|
+
ensureChatgptExecutionPreference,
|
|
19
|
+
ensureControllerChatgptBrowser,
|
|
20
|
+
navigateWorkConversation,
|
|
21
|
+
submitChatgptPrompt,
|
|
22
|
+
withChatgptBrowserActionOrigin,
|
|
23
|
+
} from '../../../../adapters/chatgpt/browser-delivery-runtime';
|
|
24
|
+
import { getWorkContract } from '../../../../packages/kernel/work/api/index';
|
|
25
|
+
import { readForgeInstanceIdentity } from '../../../../packages/kernel/identity/api/index';
|
|
5
26
|
import {
|
|
6
27
|
bindChatgptWorkConversation,
|
|
7
28
|
getChatgptWorkConversationBinding,
|
|
@@ -9,25 +30,48 @@ import {
|
|
|
9
30
|
parseChatgptConversationIdentity,
|
|
10
31
|
rebindChatgptWorkConversation,
|
|
11
32
|
type ChatgptWorkConversationBinding,
|
|
12
|
-
} from '
|
|
33
|
+
} from '../../../../adapters/chatgpt/work-conversation-binding-store';
|
|
34
|
+
|
|
35
|
+
export {
|
|
36
|
+
CHATGPT_AUTOMATION_SUBMISSION_OUTCOME_UNKNOWN,
|
|
37
|
+
DEFAULT_CHATGPT_AUTOMATION_MODEL,
|
|
38
|
+
DEFAULT_CHATGPT_AUTOMATION_REASONING,
|
|
39
|
+
DEFAULT_CHATGPT_AUTOMATION_TAB_POLICY,
|
|
40
|
+
type ChatgptAutomationReasoning,
|
|
41
|
+
type ChatgptAutomationTabCleanupStatus,
|
|
42
|
+
type ChatgptAutomationTabPolicy,
|
|
43
|
+
type ChatgptProviderDeliveryStatus,
|
|
44
|
+
} from '../../../../adapters/chatgpt/provider-delivery';
|
|
45
|
+
export {
|
|
46
|
+
chatgptAutomationControlQueryLimit,
|
|
47
|
+
chatgptAutomationControlWaitBudgets,
|
|
48
|
+
chatgptAutomationNavigationRequiresReplacement,
|
|
49
|
+
chatgptAutomationPageFailure,
|
|
50
|
+
chatgptAutomationReasoningLevelFromLabel,
|
|
51
|
+
chatgptBrowserActionArgs,
|
|
52
|
+
chatgptBrowserActionResult,
|
|
53
|
+
chatgptOutboundMessageMatchesPrompt,
|
|
54
|
+
isChatgptConversationUrl,
|
|
55
|
+
reconciledNewChatgptOpenPageSessionId,
|
|
56
|
+
settleWorkChatgptAutomationTab,
|
|
57
|
+
} from '../../../../adapters/chatgpt/browser-delivery-runtime';
|
|
13
58
|
|
|
14
59
|
const LEGACY_CONTROLLER_CHATGPT_SESSION_ID = 'forge-chatgpt-supercontroller';
|
|
15
|
-
export const DEFAULT_CHATGPT_AUTOMATION_MODEL = 'gpt-5.6';
|
|
16
|
-
export const DEFAULT_CHATGPT_AUTOMATION_REASONING = 'high';
|
|
17
|
-
export const DEFAULT_CHATGPT_AUTOMATION_TAB_POLICY = 'auto';
|
|
18
60
|
export const DEFAULT_CHATGPT_AUTOMATION_PLUGIN_MENTION = '@forge';
|
|
19
|
-
const CHATGPT_PROMPT_SELECTOR = 'div#prompt-textarea[contenteditable="true"]';
|
|
20
|
-
const CHATGPT_SEND_SELECTOR = '[data-testid="send-button"], button[aria-label*="Send"], button[data-testid*="send"]';
|
|
21
|
-
const CHATGPT_INTELLIGENCE_CONTROL_SELECTORS = [
|
|
22
|
-
'main button, main [role="button"]',
|
|
23
|
-
'button, [role="button"]',
|
|
24
|
-
] as const;
|
|
25
|
-
const CHATGPT_CAPABILITY_SLIDER_SELECTOR = '[role="slider"]';
|
|
26
|
-
const CHATGPT_CAPABILITY_MENUITEM_SELECTOR = '[role="menuitem"][aria-keyshortcuts~="ArrowLeft"][aria-keyshortcuts~="ArrowRight"]';
|
|
27
61
|
|
|
28
|
-
export
|
|
29
|
-
|
|
30
|
-
|
|
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
|
+
|
|
31
75
|
|
|
32
76
|
export interface WorkChatgptContinuationInput {
|
|
33
77
|
controllerHome: string;
|
|
@@ -35,18 +79,34 @@ export interface WorkChatgptContinuationInput {
|
|
|
35
79
|
repoRoot: string;
|
|
36
80
|
workId: string;
|
|
37
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;
|
|
38
86
|
title?: string;
|
|
39
87
|
browserSessionId?: string;
|
|
40
88
|
conversationUrl?: string;
|
|
41
89
|
model?: string;
|
|
42
90
|
reasoning?: ChatgptAutomationReasoning;
|
|
43
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';
|
|
44
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
|
+
export interface WorkChatgptContinuationDependencies {
|
|
102
|
+
bridgeRuntime?: boolean;
|
|
103
|
+
browserHost?: ChatgptProviderDeliveryHost;
|
|
104
|
+
wslHost?: ChatgptProviderDeliveryHost;
|
|
45
105
|
}
|
|
46
106
|
|
|
47
107
|
export interface WorkChatgptContinuationResult {
|
|
48
108
|
status: 'dispatched' | 'failed';
|
|
49
|
-
provider: 'controller-browser';
|
|
109
|
+
provider: 'controller-browser' | 'chatgpt-bridge';
|
|
50
110
|
browserSessionId: string;
|
|
51
111
|
conversationUrl?: string;
|
|
52
112
|
conversationId?: string;
|
|
@@ -56,6 +116,9 @@ export interface WorkChatgptContinuationResult {
|
|
|
56
116
|
reasoning: ChatgptAutomationReasoning;
|
|
57
117
|
tabPolicy: ChatgptAutomationTabPolicy;
|
|
58
118
|
executionPreferenceVerified: boolean;
|
|
119
|
+
authorizationGrantRefs?: string[];
|
|
120
|
+
/** Typed provider delivery disposition. Present when provider dispatch was attempted; callers must not infer this from error strings. */
|
|
121
|
+
providerDeliveryStatus?: ChatgptProviderDeliveryStatus;
|
|
59
122
|
tabCleanupStatus?: ChatgptAutomationTabCleanupStatus;
|
|
60
123
|
tabCleanupError?: { code: string; message: string };
|
|
61
124
|
error?: { code: string; message: string };
|
|
@@ -64,6 +127,8 @@ export interface WorkChatgptContinuationResult {
|
|
|
64
127
|
export interface StandaloneChatgptPromptInput {
|
|
65
128
|
controllerHome: string;
|
|
66
129
|
repoId: string;
|
|
130
|
+
/** Optional transport context only; current browser/bridge hosts do not derive semantic authority from this path. */
|
|
131
|
+
repoRoot?: string;
|
|
67
132
|
scopeId: string;
|
|
68
133
|
prompt: string;
|
|
69
134
|
browserSessionId?: string;
|
|
@@ -74,61 +139,25 @@ export interface StandaloneChatgptPromptInput {
|
|
|
74
139
|
timeoutMs?: number;
|
|
75
140
|
}
|
|
76
141
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export function chatgptBrowserActionArgs(actionId: string, args: Record<string, unknown>): Record<string, unknown> {
|
|
91
|
-
if (actionId === 'configure' || actionId === 'list_sessions' || actionId === 'reconcile_sessions') return args;
|
|
92
|
-
return { ...args, ...CHATGPT_BROWSER_TRANSPORT_OVERRIDES };
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
async function controllerBrowserAction(
|
|
96
|
-
controllerHome: string,
|
|
97
|
-
workId: string,
|
|
98
|
-
actionId: string,
|
|
99
|
-
args: Record<string, unknown>,
|
|
100
|
-
timeoutMs?: number,
|
|
101
|
-
): Promise<Record<string, unknown>> {
|
|
102
|
-
const repository = controllerPluginRepository(controllerHome);
|
|
103
|
-
const repoRoot = repository.canonicalRoot ?? repository.localRoot;
|
|
104
|
-
if (!repoRoot) throw new Error('CHATGPT_CONTROLLER_BROWSER_ROOT_UNAVAILABLE');
|
|
105
|
-
return executeBrowserPluginAction({
|
|
106
|
-
controllerHome,
|
|
107
|
-
repoId: repository.repoId,
|
|
108
|
-
repoRoot,
|
|
109
|
-
pluginId: 'browser',
|
|
110
|
-
actionId,
|
|
111
|
-
requestId: requestId(workId, actionId),
|
|
112
|
-
args: chatgptBrowserActionArgs(actionId, args),
|
|
113
|
-
timeoutMs,
|
|
114
|
-
origin: { surface: 'schedule', actor: 'chatgpt-work-continuation' },
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
async function ensureControllerChatgptBrowser(controllerHome: string, workId: string): Promise<void> {
|
|
119
|
-
const repository = controllerPluginRepository(controllerHome);
|
|
120
|
-
const repoRoot = repository.canonicalRoot ?? repository.localRoot;
|
|
121
|
-
if (!repoRoot) throw new Error('CHATGPT_CONTROLLER_BROWSER_ROOT_UNAVAILABLE');
|
|
122
|
-
// Browser configure is not a read: it persists configuration and closes managed
|
|
123
|
-
// contexts. Scheduled continuations must not disturb an already-enabled provider
|
|
124
|
-
// merely to prove it is available. Only enable it when the persisted authority is
|
|
125
|
-
// explicitly disabled; action-level transport overrides still fail closed later.
|
|
126
|
-
if (buildBrowserPluginManifest(0, undefined, repoRoot).enabled) return;
|
|
127
|
-
await controllerBrowserAction(controllerHome, workId, 'configure', { enabled: true });
|
|
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。`;
|
|
128
154
|
}
|
|
129
155
|
|
|
130
|
-
function
|
|
131
|
-
|
|
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');
|
|
132
161
|
}
|
|
133
162
|
|
|
134
163
|
function normalizeModel(value?: string): string {
|
|
@@ -141,15 +170,41 @@ function normalizeReasoning(value?: ChatgptAutomationReasoning): ChatgptAutomati
|
|
|
141
170
|
return value ?? DEFAULT_CHATGPT_AUTOMATION_REASONING;
|
|
142
171
|
}
|
|
143
172
|
|
|
173
|
+
const DEFAULT_CHATGPT_CONTROLLER_REASONING: ChatgptAutomationReasoning = 'xhigh';
|
|
174
|
+
|
|
175
|
+
function normalizeControllerReasoning(value?: ChatgptAutomationReasoning): ChatgptAutomationReasoning {
|
|
176
|
+
return value ?? DEFAULT_CHATGPT_CONTROLLER_REASONING;
|
|
177
|
+
}
|
|
178
|
+
|
|
144
179
|
function normalizeTabPolicy(value?: ChatgptAutomationTabPolicy): ChatgptAutomationTabPolicy {
|
|
145
180
|
return value ?? DEFAULT_CHATGPT_AUTOMATION_TAB_POLICY;
|
|
146
181
|
}
|
|
147
182
|
|
|
183
|
+
function resolveChatgptProviderDeliveryHost(
|
|
184
|
+
dependencies: WorkChatgptContinuationDependencies = {},
|
|
185
|
+
): { bridgeRuntime: boolean; host: ChatgptProviderDeliveryHost } {
|
|
186
|
+
const bridgeRuntime = dependencies.bridgeRuntime ?? isWslWindowsRuntime();
|
|
187
|
+
const host = bridgeRuntime
|
|
188
|
+
? dependencies.wslHost ?? createChatgptWslBridgeDeliveryHost()
|
|
189
|
+
: dependencies.browserHost ?? createChatgptBrowserDeliveryHost({
|
|
190
|
+
ensureBrowser: ensureControllerChatgptBrowser,
|
|
191
|
+
navigate: navigateWorkConversation,
|
|
192
|
+
ensureExecutionPreference: ensureChatgptExecutionPreference,
|
|
193
|
+
submitPrompt: submitChatgptPrompt,
|
|
194
|
+
});
|
|
195
|
+
return { bridgeRuntime, host };
|
|
196
|
+
}
|
|
197
|
+
|
|
148
198
|
export function stableChatgptWorkBrowserSessionId(repoId: string, workId: string): string {
|
|
149
199
|
const digest = createHash('sha256').update(`${repoId}\n${workId}`).digest('hex').slice(0, 20);
|
|
150
200
|
return `forge-chatgpt-work-${digest}`;
|
|
151
201
|
}
|
|
152
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);
|
|
205
|
+
return `forge-chatgpt-bridge-${digest}`;
|
|
206
|
+
}
|
|
207
|
+
|
|
153
208
|
export function stableStandaloneChatgptBrowserSessionId(repoId: string, scopeId: string): string {
|
|
154
209
|
const digest = createHash('sha256').update(`${repoId}\nstandalone\n${scopeId}`).digest('hex').slice(0, 20);
|
|
155
210
|
return `forge-chatgpt-standalone-${digest}`;
|
|
@@ -179,411 +234,6 @@ export function resolveChatgptWorkBrowserSessionId(input: {
|
|
|
179
234
|
return stable;
|
|
180
235
|
}
|
|
181
236
|
|
|
182
|
-
interface BrowserQueryMatch {
|
|
183
|
-
text?: string;
|
|
184
|
-
selectorHint?: string;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
function queryMatches(result: Record<string, unknown> | undefined): BrowserQueryMatch[] {
|
|
188
|
-
if (!result || !Array.isArray(result.matches)) return [];
|
|
189
|
-
return result.matches.filter((value): value is BrowserQueryMatch => Boolean(value) && typeof value === 'object');
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
function matchText(value: BrowserQueryMatch): string {
|
|
193
|
-
return typeof value.text === 'string' ? value.text.trim() : '';
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
function matchSelector(value: BrowserQueryMatch | undefined): string | undefined {
|
|
197
|
-
return typeof value?.selectorHint === 'string' && value.selectorHint.trim() ? value.selectorHint.trim() : undefined;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
function normalizeExecutionControlLabel(label: string | undefined): string {
|
|
201
|
-
return (label ?? '').trim().toLowerCase().replace(/[\s_-]+/g, '');
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
export function chatgptAutomationReasoningLevelFromLabel(label: string | undefined): ChatgptAutomationReasoning | undefined {
|
|
205
|
-
const normalized = normalizeExecutionControlLabel(label);
|
|
206
|
-
if (!normalized) return undefined;
|
|
207
|
-
|
|
208
|
-
const exact = new Map<string, ChatgptAutomationReasoning>([
|
|
209
|
-
['medium', 'medium'], ['中', 'medium'], ['中等', 'medium'],
|
|
210
|
-
['high', 'high'], ['高', 'high'],
|
|
211
|
-
['xhigh', 'xhigh'], ['extrahigh', 'xhigh'], ['超高', 'xhigh'], ['极高', 'xhigh'],
|
|
212
|
-
]);
|
|
213
|
-
const exactLevel = exact.get(normalized);
|
|
214
|
-
if (exactLevel) return exactLevel;
|
|
215
|
-
|
|
216
|
-
const hasReasoningContext = ['reasoning', 'thinking', '推理', '思考']
|
|
217
|
-
.some((token) => normalized.includes(token));
|
|
218
|
-
if (!hasReasoningContext) return undefined;
|
|
219
|
-
if (['xhigh', 'extrahigh', '超高', '极高'].some((token) => normalized.includes(token))) return 'xhigh';
|
|
220
|
-
if (['medium', '中等'].some((token) => normalized.includes(token))) return 'medium';
|
|
221
|
-
if (['high', '高'].some((token) => normalized.includes(token))) return 'high';
|
|
222
|
-
return undefined;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
function modelLabelMatches(label: string | undefined, model: string): boolean {
|
|
226
|
-
if (model !== DEFAULT_CHATGPT_AUTOMATION_MODEL || !label) return false;
|
|
227
|
-
const normalized = normalizeExecutionControlLabel(label);
|
|
228
|
-
return normalized.includes('5.6sol') || normalized.includes('gpt5.6sol');
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
function reasoningLabelMatches(label: string | undefined, reasoning: ChatgptAutomationReasoning): boolean {
|
|
232
|
-
return chatgptAutomationReasoningLevelFromLabel(label) === reasoning;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
function isReasoningControlLabel(label: string | undefined): boolean {
|
|
236
|
-
return reasoningLabelMatches(label, 'medium')
|
|
237
|
-
|| reasoningLabelMatches(label, 'high')
|
|
238
|
-
|| reasoningLabelMatches(label, 'xhigh');
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
function reasoningSliderValue(reasoning: ChatgptAutomationReasoning): number {
|
|
242
|
-
if (reasoning === 'medium') return 2;
|
|
243
|
-
if (reasoning === 'high') return 3;
|
|
244
|
-
return 4;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
async function findChatgptIntelligenceControl(
|
|
248
|
-
controllerHome: string,
|
|
249
|
-
workId: string,
|
|
250
|
-
browserSessionId: string,
|
|
251
|
-
timeoutMs?: number,
|
|
252
|
-
): Promise<BrowserQueryMatch | undefined> {
|
|
253
|
-
for (const selector of CHATGPT_INTELLIGENCE_CONTROL_SELECTORS) {
|
|
254
|
-
const result = await controllerBrowserAction(controllerHome, workId, 'query_all', {
|
|
255
|
-
session_id: browserSessionId,
|
|
256
|
-
selector,
|
|
257
|
-
// Prefer the composer/main region so sidebar history cannot crowd the
|
|
258
|
-
// reasoning control out of a bounded query. Keep a larger global fallback
|
|
259
|
-
// for ChatGPT layouts that place the control outside <main>.
|
|
260
|
-
limit: chatgptAutomationControlQueryLimit(selector),
|
|
261
|
-
timeout_ms: timeoutMs ?? 60_000,
|
|
262
|
-
}, timeoutMs);
|
|
263
|
-
const match = queryMatches(result).find((candidate) => {
|
|
264
|
-
const label = matchText(candidate);
|
|
265
|
-
return modelLabelMatches(label, DEFAULT_CHATGPT_AUTOMATION_MODEL) || isReasoningControlLabel(label);
|
|
266
|
-
});
|
|
267
|
-
if (match) return match;
|
|
268
|
-
}
|
|
269
|
-
return undefined;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
export function chatgptAutomationControlQueryLimit(selector: string): number {
|
|
273
|
-
// Long tool-heavy conversations can contribute well over 80 buttons before
|
|
274
|
-
// the composer controls. Keep the preferred <main> scan bounded but large
|
|
275
|
-
// enough that the current reasoning control is not crowded out by history.
|
|
276
|
-
return selector.startsWith('main ') ? 160 : 320;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
export function chatgptAutomationControlWaitBudgets(timeoutMs?: number): { waitBudgetMs: number; probeTimeoutMs: number } {
|
|
280
|
-
const waitBudgetMs = Math.min(Math.max(timeoutMs ?? 30_000, 1_000), 30_000);
|
|
281
|
-
// Native Chrome attachment has a few seconds of Apple Events/DOM latency on
|
|
282
|
-
// long conversations. Keep each probe bounded while allowing a real query to
|
|
283
|
-
// complete; the total readiness window remains capped at 30 seconds.
|
|
284
|
-
return { waitBudgetMs, probeTimeoutMs: Math.min(waitBudgetMs, 5_000) };
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
async function waitForChatgptIntelligenceControl(
|
|
288
|
-
controllerHome: string,
|
|
289
|
-
workId: string,
|
|
290
|
-
browserSessionId: string,
|
|
291
|
-
timeoutMs?: number,
|
|
292
|
-
): Promise<BrowserQueryMatch | undefined> {
|
|
293
|
-
const { waitBudgetMs, probeTimeoutMs } = chatgptAutomationControlWaitBudgets(timeoutMs);
|
|
294
|
-
const deadline = Date.now() + waitBudgetMs;
|
|
295
|
-
do {
|
|
296
|
-
const control = await findChatgptIntelligenceControl(controllerHome, workId, browserSessionId, probeTimeoutMs);
|
|
297
|
-
if (control) return control;
|
|
298
|
-
if (Date.now() >= deadline) break;
|
|
299
|
-
await new Promise((resolveWait) => setTimeout(resolveWait, 500));
|
|
300
|
-
} while (Date.now() < deadline);
|
|
301
|
-
return undefined;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
export function chatgptAutomationPageFailure(
|
|
305
|
-
bodyText: string | undefined,
|
|
306
|
-
composerAvailable: boolean,
|
|
307
|
-
): 'CHATGPT_AUTOMATION_LOGIN_REQUIRED' | 'CHATGPT_AUTOMATION_COMPOSER_UNAVAILABLE' | undefined {
|
|
308
|
-
if (composerAvailable) return undefined;
|
|
309
|
-
const normalized = (bodyText ?? '').toLowerCase();
|
|
310
|
-
const loginMarkers = [
|
|
311
|
-
'log in', 'sign up', 'continue with google', 'continue with apple',
|
|
312
|
-
'登录', '登陆', '注册', '使用 google 继续', '使用 apple 继续',
|
|
313
|
-
];
|
|
314
|
-
return loginMarkers.some((marker) => normalized.includes(marker))
|
|
315
|
-
? 'CHATGPT_AUTOMATION_LOGIN_REQUIRED'
|
|
316
|
-
: 'CHATGPT_AUTOMATION_COMPOSER_UNAVAILABLE';
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
async function assertChatgptAutomationComposerReady(
|
|
320
|
-
controllerHome: string,
|
|
321
|
-
workId: string,
|
|
322
|
-
browserSessionId: string,
|
|
323
|
-
timeoutMs?: number,
|
|
324
|
-
): Promise<void> {
|
|
325
|
-
const composerResult = await controllerBrowserAction(controllerHome, workId, 'query_all', {
|
|
326
|
-
session_id: browserSessionId,
|
|
327
|
-
selector: CHATGPT_PROMPT_SELECTOR,
|
|
328
|
-
limit: 1,
|
|
329
|
-
timeout_ms: Math.min(timeoutMs ?? 5_000, 5_000),
|
|
330
|
-
}, timeoutMs).catch(() => undefined);
|
|
331
|
-
const composerAvailable = queryMatches(composerResult).length > 0;
|
|
332
|
-
if (composerAvailable) return;
|
|
333
|
-
|
|
334
|
-
const bodyResult = await controllerBrowserAction(controllerHome, workId, 'get_text', {
|
|
335
|
-
session_id: browserSessionId,
|
|
336
|
-
selector: 'body',
|
|
337
|
-
max_chars: 4_000,
|
|
338
|
-
timeout_ms: Math.min(timeoutMs ?? 5_000, 5_000),
|
|
339
|
-
}, timeoutMs).catch(() => undefined);
|
|
340
|
-
const failure = chatgptAutomationPageFailure(stringField(bodyResult?.text), composerAvailable);
|
|
341
|
-
throw new Error(failure ?? 'CHATGPT_AUTOMATION_COMPOSER_UNAVAILABLE');
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
async function ensureChatgptExecutionPreference(
|
|
345
|
-
controllerHome: string,
|
|
346
|
-
workId: string,
|
|
347
|
-
browserSessionId: string,
|
|
348
|
-
model: string,
|
|
349
|
-
reasoning: ChatgptAutomationReasoning,
|
|
350
|
-
timeoutMs?: number,
|
|
351
|
-
): Promise<boolean> {
|
|
352
|
-
if (model !== DEFAULT_CHATGPT_AUTOMATION_MODEL) throw new Error(`CHATGPT_AUTOMATION_MODEL_UNSUPPORTED:${model}`);
|
|
353
|
-
let control = await waitForChatgptIntelligenceControl(controllerHome, workId, browserSessionId, timeoutMs);
|
|
354
|
-
if (!control) {
|
|
355
|
-
await assertChatgptAutomationComposerReady(controllerHome, workId, browserSessionId, timeoutMs);
|
|
356
|
-
throw new Error('CHATGPT_AUTOMATION_INTELLIGENCE_CONTROL_UNAVAILABLE');
|
|
357
|
-
}
|
|
358
|
-
// Current ChatGPT UI exposes the reasoning level (for example `高`) on the
|
|
359
|
-
// composer control instead of the model label. The model remains fail-closed
|
|
360
|
-
// through normalizeModel above; only the user-adjustable reasoning control is
|
|
361
|
-
// required to be observable in the page before unattended dispatch proceeds.
|
|
362
|
-
if (reasoningLabelMatches(matchText(control), reasoning)) return true;
|
|
363
|
-
let controlSelector = matchSelector(control);
|
|
364
|
-
if (!controlSelector) throw new Error('CHATGPT_AUTOMATION_INTELLIGENCE_CONTROL_UNAVAILABLE');
|
|
365
|
-
|
|
366
|
-
const expanded = await controllerBrowserAction(controllerHome, workId, 'get_attribute', {
|
|
367
|
-
session_id: browserSessionId,
|
|
368
|
-
selector: controlSelector,
|
|
369
|
-
attribute: 'aria-expanded',
|
|
370
|
-
timeout_ms: timeoutMs ?? 60_000,
|
|
371
|
-
}, timeoutMs).catch(() => undefined);
|
|
372
|
-
if (stringField(expanded?.value) !== 'true') {
|
|
373
|
-
await controllerBrowserAction(controllerHome, workId, 'press', {
|
|
374
|
-
session_id: browserSessionId,
|
|
375
|
-
selector: controlSelector,
|
|
376
|
-
key: 'ArrowDown',
|
|
377
|
-
timeout_ms: timeoutMs ?? 60_000,
|
|
378
|
-
post_action_wait_ms: 150,
|
|
379
|
-
}, timeoutMs);
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
const currentValueResult = await controllerBrowserAction(controllerHome, workId, 'get_attribute', {
|
|
383
|
-
session_id: browserSessionId,
|
|
384
|
-
selector: CHATGPT_CAPABILITY_SLIDER_SELECTOR,
|
|
385
|
-
attribute: 'aria-valuenow',
|
|
386
|
-
timeout_ms: timeoutMs ?? 60_000,
|
|
387
|
-
}, timeoutMs).catch(() => undefined);
|
|
388
|
-
const currentValue = Number(stringField(currentValueResult?.value));
|
|
389
|
-
const targetValue = reasoningSliderValue(reasoning);
|
|
390
|
-
if (!Number.isInteger(currentValue) || currentValue < 0 || currentValue > 4) {
|
|
391
|
-
throw new Error(`CHATGPT_AUTOMATION_REASONING_STATE_UNAVAILABLE:${reasoning}`);
|
|
392
|
-
}
|
|
393
|
-
const direction = targetValue > currentValue ? 'ArrowRight' : 'ArrowLeft';
|
|
394
|
-
for (let index = 0; index < Math.abs(targetValue - currentValue); index += 1) {
|
|
395
|
-
await controllerBrowserAction(controllerHome, workId, 'press', {
|
|
396
|
-
session_id: browserSessionId,
|
|
397
|
-
selector: CHATGPT_CAPABILITY_MENUITEM_SELECTOR,
|
|
398
|
-
key: direction,
|
|
399
|
-
timeout_ms: timeoutMs ?? 60_000,
|
|
400
|
-
post_action_wait_ms: 120,
|
|
401
|
-
}, timeoutMs);
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
const verifiedValueResult = await controllerBrowserAction(controllerHome, workId, 'get_attribute', {
|
|
405
|
-
session_id: browserSessionId,
|
|
406
|
-
selector: CHATGPT_CAPABILITY_SLIDER_SELECTOR,
|
|
407
|
-
attribute: 'aria-valuenow',
|
|
408
|
-
timeout_ms: timeoutMs ?? 60_000,
|
|
409
|
-
}, timeoutMs).catch(() => undefined);
|
|
410
|
-
if (Number(stringField(verifiedValueResult?.value)) !== targetValue) {
|
|
411
|
-
throw new Error(`CHATGPT_AUTOMATION_REASONING_NOT_VERIFIED:${reasoning}`);
|
|
412
|
-
}
|
|
413
|
-
control = await findChatgptIntelligenceControl(controllerHome, workId, browserSessionId, timeoutMs) ?? control;
|
|
414
|
-
if (isReasoningControlLabel(matchText(control)) && !reasoningLabelMatches(matchText(control), reasoning)) {
|
|
415
|
-
throw new Error(`CHATGPT_AUTOMATION_REASONING_NOT_VERIFIED:${reasoning}`);
|
|
416
|
-
}
|
|
417
|
-
controlSelector = matchSelector(control) ?? controlSelector;
|
|
418
|
-
await controllerBrowserAction(controllerHome, workId, 'press', {
|
|
419
|
-
session_id: browserSessionId,
|
|
420
|
-
selector: controlSelector,
|
|
421
|
-
key: 'Escape',
|
|
422
|
-
timeout_ms: timeoutMs ?? 60_000,
|
|
423
|
-
post_action_wait_ms: 100,
|
|
424
|
-
}, timeoutMs).catch(() => undefined);
|
|
425
|
-
return true;
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
function resultUrl(result: Record<string, unknown>): string | undefined {
|
|
429
|
-
return stringField(result.url)
|
|
430
|
-
?? stringField((result.session as Record<string, unknown> | undefined)?.url);
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
function resultSessionId(result: Record<string, unknown>): string | undefined {
|
|
434
|
-
return stringField(result.session_id)
|
|
435
|
-
?? stringField((result.session as Record<string, unknown> | undefined)?.sessionId);
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
export function chatgptAutomationNavigationRequiresReplacement(error: unknown): boolean {
|
|
439
|
-
if (!(error instanceof Error)) return false;
|
|
440
|
-
return [
|
|
441
|
-
'BROWSER_AUTOMATION_BACKGROUND_NAVIGATION_REQUIRES_REPLACEMENT',
|
|
442
|
-
'PLUGIN_BROWSER_SESSION_STATE_LOST',
|
|
443
|
-
'PLUGIN_SESSION_NOT_FOUND',
|
|
444
|
-
'PLUGIN_BROWSER_NATIVE_TAB_IDENTITY_UNPROVEN',
|
|
445
|
-
].some((marker) => error.message.includes(marker));
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
async function closeChatgptAutomationTabAfterDispatch(
|
|
449
|
-
controllerHome: string,
|
|
450
|
-
workId: string,
|
|
451
|
-
browserSessionId: string,
|
|
452
|
-
timeoutMs?: number,
|
|
453
|
-
): Promise<{ status: ChatgptAutomationTabCleanupStatus; error?: { code: string; message: string } }> {
|
|
454
|
-
try {
|
|
455
|
-
const closed = await controllerBrowserAction(controllerHome, workId, 'close_page', {
|
|
456
|
-
session_id: browserSessionId,
|
|
457
|
-
}, Math.min(timeoutMs ?? 15_000, 15_000));
|
|
458
|
-
if (closed.preservedUserOwnedTab === true) return { status: 'preserved_user_owned' };
|
|
459
|
-
if (closed.resourceClosed === true) return { status: 'closed' };
|
|
460
|
-
return { status: 'session_closed' };
|
|
461
|
-
} catch (error) {
|
|
462
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
463
|
-
return {
|
|
464
|
-
status: 'failed',
|
|
465
|
-
error: {
|
|
466
|
-
code: error instanceof Error && error.message.includes(':') ? error.message.split(':', 1)[0] : 'CHATGPT_AUTOMATION_TAB_CLEANUP_FAILED',
|
|
467
|
-
message,
|
|
468
|
-
},
|
|
469
|
-
};
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
/**
|
|
474
|
-
* Settles the browser resource for one completed Work-bound ChatGPT round.
|
|
475
|
-
* Conversation identity is durable in the Work binding and intentionally
|
|
476
|
-
* survives this ephemeral tab/session cleanup. Browser ownership policy keeps
|
|
477
|
-
* user-owned native tabs intact.
|
|
478
|
-
*/
|
|
479
|
-
export async function settleWorkChatgptAutomationTab(input: {
|
|
480
|
-
controllerHome: string;
|
|
481
|
-
workId: string;
|
|
482
|
-
browserSessionId: string;
|
|
483
|
-
timeoutMs?: number;
|
|
484
|
-
}): Promise<{ status: ChatgptAutomationTabCleanupStatus; error?: { code: string; message: string } }> {
|
|
485
|
-
return closeChatgptAutomationTabAfterDispatch(
|
|
486
|
-
input.controllerHome,
|
|
487
|
-
input.workId,
|
|
488
|
-
input.browserSessionId,
|
|
489
|
-
input.timeoutMs,
|
|
490
|
-
);
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
export function isChatgptConversationUrl(value: string): boolean {
|
|
494
|
-
try {
|
|
495
|
-
const url = new URL(value);
|
|
496
|
-
return url.protocol === 'https:'
|
|
497
|
-
&& ['chatgpt.com', 'www.chatgpt.com', 'chat.openai.com'].includes(url.hostname)
|
|
498
|
-
&& /\/c\/[^/?#]+/.test(url.pathname);
|
|
499
|
-
} catch {
|
|
500
|
-
return false;
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
async function navigateWorkConversation(
|
|
505
|
-
controllerHome: string,
|
|
506
|
-
workId: string,
|
|
507
|
-
browserSessionId: string,
|
|
508
|
-
targetUrl: string,
|
|
509
|
-
timeoutMs?: number,
|
|
510
|
-
): Promise<{ submissionTargetUrl: string; recoveredFromStaleBinding: boolean; browserSessionId: string }> {
|
|
511
|
-
const navigate = async (sessionId: string, url: string) => controllerBrowserAction(controllerHome, workId, 'navigate', {
|
|
512
|
-
session_id: sessionId,
|
|
513
|
-
url,
|
|
514
|
-
wait_until: 'domcontentloaded',
|
|
515
|
-
timeout_ms: timeoutMs ?? 60_000,
|
|
516
|
-
retries: 1,
|
|
517
|
-
}, timeoutMs);
|
|
518
|
-
const openReplacement = async (url: string): Promise<string> => {
|
|
519
|
-
const opened = await controllerBrowserAction(controllerHome, workId, 'open_page', {
|
|
520
|
-
url,
|
|
521
|
-
wait_until: 'domcontentloaded',
|
|
522
|
-
timeout_ms: timeoutMs ?? 60_000,
|
|
523
|
-
retries: 1,
|
|
524
|
-
}, timeoutMs);
|
|
525
|
-
const replacementSessionId = resultSessionId(opened);
|
|
526
|
-
if (!replacementSessionId) throw new Error('CHATGPT_AUTOMATION_REPLACEMENT_SESSION_NOT_CONFIRMED');
|
|
527
|
-
return replacementSessionId;
|
|
528
|
-
};
|
|
529
|
-
try {
|
|
530
|
-
await navigate(browserSessionId, targetUrl);
|
|
531
|
-
return { submissionTargetUrl: targetUrl, recoveredFromStaleBinding: false, browserSessionId };
|
|
532
|
-
} catch (error) {
|
|
533
|
-
if (chatgptAutomationNavigationRequiresReplacement(error)) {
|
|
534
|
-
const replacementSessionId = await openReplacement(targetUrl);
|
|
535
|
-
return { submissionTargetUrl: targetUrl, recoveredFromStaleBinding: false, browserSessionId: replacementSessionId };
|
|
536
|
-
}
|
|
537
|
-
if (!isChatgptConversationUrl(targetUrl)) throw error;
|
|
538
|
-
try {
|
|
539
|
-
await navigate(browserSessionId, 'https://chatgpt.com/');
|
|
540
|
-
return { submissionTargetUrl: 'https://chatgpt.com/', recoveredFromStaleBinding: true, browserSessionId };
|
|
541
|
-
} catch (fallbackError) {
|
|
542
|
-
if (!chatgptAutomationNavigationRequiresReplacement(fallbackError)) throw fallbackError;
|
|
543
|
-
const replacementSessionId = await openReplacement('https://chatgpt.com/');
|
|
544
|
-
return { submissionTargetUrl: 'https://chatgpt.com/', recoveredFromStaleBinding: true, browserSessionId: replacementSessionId };
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
async function submitChatgptPrompt(
|
|
550
|
-
controllerHome: string,
|
|
551
|
-
workId: string,
|
|
552
|
-
browserSessionId: string,
|
|
553
|
-
prompt: string,
|
|
554
|
-
targetUrl: string,
|
|
555
|
-
timeoutMs?: number,
|
|
556
|
-
): Promise<string> {
|
|
557
|
-
await controllerBrowserAction(controllerHome, workId, 'fill', {
|
|
558
|
-
session_id: browserSessionId,
|
|
559
|
-
selector: CHATGPT_PROMPT_SELECTOR,
|
|
560
|
-
text: withForgePluginMention(prompt),
|
|
561
|
-
timeout_ms: timeoutMs ?? 60_000,
|
|
562
|
-
post_action_wait_ms: 100,
|
|
563
|
-
}, timeoutMs);
|
|
564
|
-
const sent = await controllerBrowserAction(controllerHome, workId, 'click', {
|
|
565
|
-
session_id: browserSessionId,
|
|
566
|
-
selector: CHATGPT_SEND_SELECTOR,
|
|
567
|
-
timeout_ms: timeoutMs ?? 60_000,
|
|
568
|
-
post_action_wait_ms: 1_000,
|
|
569
|
-
}, timeoutMs);
|
|
570
|
-
let observedUrl = resultUrl(sent) ?? targetUrl;
|
|
571
|
-
if (/\/c\/[^/?#]+/.test(observedUrl)) return observedUrl;
|
|
572
|
-
const deadline = Date.now() + Math.min(Math.max(timeoutMs ?? 8_000, 2_000), 8_000);
|
|
573
|
-
do {
|
|
574
|
-
const observed = await controllerBrowserAction(controllerHome, workId, 'query_all', {
|
|
575
|
-
session_id: browserSessionId,
|
|
576
|
-
selector: 'main',
|
|
577
|
-
limit: 1,
|
|
578
|
-
timeout_ms: Math.min(timeoutMs ?? 3_000, 3_000),
|
|
579
|
-
}, timeoutMs).catch(() => undefined);
|
|
580
|
-
observedUrl = observed ? resultUrl(observed) ?? observedUrl : observedUrl;
|
|
581
|
-
if (/\/c\/[^/?#]+/.test(observedUrl)) return observedUrl;
|
|
582
|
-
await new Promise((resolveWait) => setTimeout(resolveWait, 250));
|
|
583
|
-
} while (Date.now() < deadline);
|
|
584
|
-
throw new Error(`CHATGPT_AUTOMATION_SUBMISSION_NOT_CONFIRMED:${observedUrl}`);
|
|
585
|
-
}
|
|
586
|
-
|
|
587
237
|
export function withForgePluginMention(prompt: string): string {
|
|
588
238
|
const value = prompt.trim();
|
|
589
239
|
if (!value) throw new Error('CHATGPT_AUTOMATION_PROMPT_REQUIRED');
|
|
@@ -596,63 +246,75 @@ export function withForgePluginMention(prompt: string): string {
|
|
|
596
246
|
* ChatGPT browser path without creating or requiring a WorkContract. The scope
|
|
597
247
|
* id is only a stable browser correlation key (for example a Schedule id).
|
|
598
248
|
*/
|
|
599
|
-
export async function runStandaloneChatgptPrompt(
|
|
249
|
+
export async function runStandaloneChatgptPrompt(
|
|
250
|
+
input: StandaloneChatgptPromptInput,
|
|
251
|
+
dependencies: WorkChatgptContinuationDependencies = {},
|
|
252
|
+
): Promise<WorkChatgptContinuationResult> {
|
|
600
253
|
const model = normalizeModel(input.model);
|
|
601
254
|
const reasoning = normalizeReasoning(input.reasoning);
|
|
602
255
|
const tabPolicy = normalizeTabPolicy(input.tabPolicy);
|
|
603
|
-
const sessionId = resolveStandaloneChatgptBrowserSessionId(input);
|
|
604
256
|
const browserScopeId = `standalone:${input.scopeId}`;
|
|
605
257
|
const seedUrl = input.conversationUrl?.trim();
|
|
258
|
+
const { bridgeRuntime, host } = resolveChatgptProviderDeliveryHost(dependencies);
|
|
259
|
+
const sessionId = bridgeRuntime
|
|
260
|
+
? stableChatgptWorkBridgeSessionId(input.repoId, browserScopeId)
|
|
261
|
+
: resolveStandaloneChatgptBrowserSessionId(input);
|
|
262
|
+
const targetUrl = seedUrl ?? 'https://chatgpt.com/';
|
|
606
263
|
|
|
607
264
|
try {
|
|
608
|
-
await
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
input.
|
|
612
|
-
browserScopeId,
|
|
613
|
-
|
|
265
|
+
const delivery = await host.dispatch({
|
|
266
|
+
controllerHome: input.controllerHome,
|
|
267
|
+
repoId: input.repoId,
|
|
268
|
+
repoRoot: input.repoRoot ?? process.cwd(),
|
|
269
|
+
workId: browserScopeId,
|
|
270
|
+
prompt: input.prompt,
|
|
271
|
+
browserSessionId: sessionId,
|
|
614
272
|
targetUrl,
|
|
615
|
-
input.timeoutMs,
|
|
616
|
-
);
|
|
617
|
-
const executionPreferenceVerified = await ensureChatgptExecutionPreference(
|
|
618
|
-
input.controllerHome,
|
|
619
|
-
browserScopeId,
|
|
620
|
-
navigation.browserSessionId,
|
|
621
273
|
model,
|
|
622
274
|
reasoning,
|
|
623
|
-
input.timeoutMs,
|
|
624
|
-
);
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
275
|
+
timeoutMs: input.timeoutMs,
|
|
276
|
+
});
|
|
277
|
+
if (delivery.status !== 'dispatch_confirmed') {
|
|
278
|
+
return {
|
|
279
|
+
status: 'failed',
|
|
280
|
+
provider: delivery.provider,
|
|
281
|
+
browserSessionId: delivery.browserSessionId,
|
|
282
|
+
conversationUrl: delivery.conversationUrl ?? seedUrl,
|
|
283
|
+
resumedFromBinding: false,
|
|
284
|
+
model,
|
|
285
|
+
reasoning,
|
|
286
|
+
tabPolicy,
|
|
287
|
+
executionPreferenceVerified: delivery.executionPreferenceVerified,
|
|
288
|
+
providerDeliveryStatus: delivery.status,
|
|
289
|
+
error: delivery.error ?? { code: `CHATGPT_PROVIDER_${delivery.status.toUpperCase()}`, message: delivery.status },
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
const tabCleanup = delivery.provider === 'controller-browser'
|
|
293
|
+
? await closeChatgptAutomationTabAfterDispatch(
|
|
294
|
+
input.controllerHome,
|
|
295
|
+
browserScopeId,
|
|
296
|
+
delivery.browserSessionId,
|
|
297
|
+
input.timeoutMs,
|
|
298
|
+
)
|
|
299
|
+
: undefined;
|
|
639
300
|
return {
|
|
640
301
|
status: 'dispatched',
|
|
641
|
-
provider:
|
|
642
|
-
browserSessionId:
|
|
643
|
-
conversationUrl:
|
|
302
|
+
provider: delivery.provider,
|
|
303
|
+
browserSessionId: delivery.browserSessionId,
|
|
304
|
+
conversationUrl: delivery.conversationUrl ?? targetUrl,
|
|
644
305
|
resumedFromBinding: false,
|
|
645
306
|
model,
|
|
646
307
|
reasoning,
|
|
647
308
|
tabPolicy,
|
|
648
|
-
executionPreferenceVerified,
|
|
649
|
-
|
|
650
|
-
...(tabCleanup
|
|
309
|
+
executionPreferenceVerified: delivery.executionPreferenceVerified,
|
|
310
|
+
providerDeliveryStatus: delivery.status,
|
|
311
|
+
...(tabCleanup ? { tabCleanupStatus: tabCleanup.status } : {}),
|
|
312
|
+
...(tabCleanup?.error ? { tabCleanupError: tabCleanup.error } : {}),
|
|
651
313
|
};
|
|
652
314
|
} catch (error) {
|
|
653
315
|
return {
|
|
654
316
|
status: 'failed',
|
|
655
|
-
provider: 'controller-browser',
|
|
317
|
+
provider: bridgeRuntime ? 'chatgpt-bridge' : 'controller-browser',
|
|
656
318
|
browserSessionId: sessionId,
|
|
657
319
|
conversationUrl: seedUrl,
|
|
658
320
|
resumedFromBinding: false,
|
|
@@ -661,7 +323,7 @@ export async function runStandaloneChatgptPrompt(input: StandaloneChatgptPromptI
|
|
|
661
323
|
tabPolicy,
|
|
662
324
|
executionPreferenceVerified: false,
|
|
663
325
|
error: {
|
|
664
|
-
code: error instanceof Error && error.message.includes(':') ? error.message.split(':', 1)[0] : 'CHATGPT_CONTROLLER_BROWSER_FAILED',
|
|
326
|
+
code: error instanceof Error && error.message.includes(':') ? error.message.split(':', 1)[0] : bridgeRuntime ? 'CHATGPT_BRIDGE_DISPATCH_FAILED' : 'CHATGPT_CONTROLLER_BROWSER_FAILED',
|
|
665
327
|
message: error instanceof Error ? error.message : String(error),
|
|
666
328
|
},
|
|
667
329
|
};
|
|
@@ -672,13 +334,54 @@ export async function runStandaloneChatgptPrompt(input: StandaloneChatgptPromptI
|
|
|
672
334
|
* Dispatches a bounded resume prompt to one controller-owned ChatGPT Web tab.
|
|
673
335
|
* Chat history is transport context only. Forge Work/Plan/evidence remain authoritative.
|
|
674
336
|
*/
|
|
675
|
-
export async function runWorkChatgptContinuation(
|
|
337
|
+
export async function runWorkChatgptContinuation(
|
|
338
|
+
input: WorkChatgptContinuationInput,
|
|
339
|
+
dependencies: WorkChatgptContinuationDependencies = {},
|
|
340
|
+
): Promise<WorkChatgptContinuationResult> {
|
|
676
341
|
const store = { controllerHome: input.controllerHome, repoId: input.repoId };
|
|
677
342
|
const existing = getChatgptWorkConversationBinding(store, input.workId);
|
|
678
|
-
const
|
|
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;
|
|
679
350
|
const model = normalizeModel(input.model);
|
|
680
|
-
const reasoning =
|
|
681
|
-
const tabPolicy = normalizeTabPolicy(input.tabPolicy);
|
|
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
|
+
authorizationGrantRefs: [...authorizationGrantRefs],
|
|
378
|
+
error: {
|
|
379
|
+
code: 'CHATGPT_CONTROLLER_ROUND_AUTHORITY_INCOMPLETE',
|
|
380
|
+
message: authorityInputError.message,
|
|
381
|
+
},
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
|
|
682
385
|
const sessionId = resolveChatgptWorkBrowserSessionId({
|
|
683
386
|
repoId: input.repoId,
|
|
684
387
|
workId: input.workId,
|
|
@@ -687,63 +390,92 @@ export async function runWorkChatgptContinuation(input: WorkChatgptContinuationI
|
|
|
687
390
|
boundSessionId: existing?.latestBrowserSessionId,
|
|
688
391
|
});
|
|
689
392
|
let binding: ChatgptWorkConversationBinding | undefined = existing;
|
|
393
|
+
const deliverySessionId = bridgeRuntime
|
|
394
|
+
? stableChatgptWorkBridgeSessionId(input.repoId, input.workId)
|
|
395
|
+
: sessionId;
|
|
690
396
|
|
|
691
397
|
try {
|
|
692
398
|
const work = getWorkContract(store, input.workId);
|
|
693
399
|
if (!work || work.repoId !== input.repoId) {
|
|
694
400
|
throw new Error(`CHATGPT_WORK_CONTRACT_NOT_FOUND: ${input.repoId}:${input.workId}`);
|
|
695
401
|
}
|
|
696
|
-
|
|
697
|
-
if (
|
|
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)) {
|
|
698
410
|
binding = bindChatgptWorkConversation(store, {
|
|
699
411
|
workId: input.workId,
|
|
700
412
|
conversationUrl: seedUrl,
|
|
701
|
-
latestBrowserSessionId:
|
|
413
|
+
latestBrowserSessionId: deliverySessionId,
|
|
414
|
+
authorizationGrantRefs: [...authorizationGrantRefs],
|
|
702
415
|
localAlias: input.title,
|
|
703
416
|
});
|
|
704
417
|
}
|
|
705
|
-
const targetUrl = binding?.conversationUrl ?? seedUrl ?? 'https://chatgpt.com/';
|
|
706
|
-
const
|
|
707
|
-
|
|
708
|
-
input.
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
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,
|
|
720
435
|
);
|
|
721
|
-
const observedUrl =
|
|
722
|
-
|
|
436
|
+
const observedUrl = delivery.conversationUrl ?? targetUrl;
|
|
437
|
+
const mayPersistObservedConversation = delivery.status === 'dispatch_confirmed' || delivery.status === 'outcome_unknown';
|
|
438
|
+
if (mayPersistObservedConversation && /\/c\/[^/?#]+/.test(observedUrl)) {
|
|
723
439
|
const observedIdentity = parseChatgptConversationIdentity(observedUrl);
|
|
724
440
|
binding = binding && binding.conversationId !== observedIdentity.conversationId
|
|
725
441
|
? rebindChatgptWorkConversation(store, {
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
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
|
+
})
|
|
732
449
|
: bindChatgptWorkConversation(store, {
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
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
|
+
};
|
|
738
474
|
}
|
|
739
|
-
// Work-bound dispatch keeps the Forge-owned automation tab/session alive for
|
|
740
|
-
// the launched semantic Controller round. The exact Controller release path
|
|
741
|
-
// settles it after an explicit disposition. Closing here would race the new
|
|
742
|
-
// ChatGPT round and make dispatch success look like round completion.
|
|
743
475
|
return {
|
|
744
476
|
status: 'dispatched',
|
|
745
|
-
provider:
|
|
746
|
-
browserSessionId:
|
|
477
|
+
provider: delivery.provider,
|
|
478
|
+
browserSessionId: delivery.browserSessionId,
|
|
747
479
|
conversationUrl: binding?.conversationUrl ?? observedUrl,
|
|
748
480
|
conversationId: binding?.conversationId,
|
|
749
481
|
localAlias: binding?.localAlias,
|
|
@@ -751,13 +483,17 @@ export async function runWorkChatgptContinuation(input: WorkChatgptContinuationI
|
|
|
751
483
|
model,
|
|
752
484
|
reasoning,
|
|
753
485
|
tabPolicy,
|
|
754
|
-
executionPreferenceVerified,
|
|
486
|
+
executionPreferenceVerified: delivery.executionPreferenceVerified,
|
|
487
|
+
authorizationGrantRefs: [...authorizationGrantRefs],
|
|
488
|
+
providerDeliveryStatus: delivery.status,
|
|
755
489
|
};
|
|
756
490
|
} catch (error) {
|
|
491
|
+
const provider = bridgeRuntime ? 'chatgpt-bridge' : 'controller-browser';
|
|
492
|
+
const fallbackSessionId = bridgeRuntime ? deliverySessionId : sessionId;
|
|
757
493
|
return {
|
|
758
494
|
status: 'failed',
|
|
759
|
-
provider
|
|
760
|
-
browserSessionId:
|
|
495
|
+
provider,
|
|
496
|
+
browserSessionId: fallbackSessionId,
|
|
761
497
|
conversationUrl: binding?.conversationUrl ?? seedUrl,
|
|
762
498
|
conversationId: binding?.conversationId,
|
|
763
499
|
localAlias: binding?.localAlias,
|
|
@@ -766,8 +502,13 @@ export async function runWorkChatgptContinuation(input: WorkChatgptContinuationI
|
|
|
766
502
|
reasoning,
|
|
767
503
|
tabPolicy,
|
|
768
504
|
executionPreferenceVerified: false,
|
|
505
|
+
authorizationGrantRefs: [...authorizationGrantRefs],
|
|
769
506
|
error: {
|
|
770
|
-
code: error instanceof
|
|
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',
|
|
771
512
|
message: error instanceof Error ? error.message : String(error),
|
|
772
513
|
},
|
|
773
514
|
};
|