@moretea-labs/forge 1.8.0 → 1.8.2
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 +73 -7
- package/CHANGELOG.md +34 -0
- package/CLAUDE.md +17 -2
- package/CONTRIBUTING.md +3 -2
- package/README.en.md +24 -3
- package/README.md +10 -6
- package/README.zh-CN.md +5 -3
- package/THIRD_PARTY_NOTICES.md +1 -2
- package/adapters/chatgpt/browser-delivery-host.ts +7 -1
- package/adapters/chatgpt/browser-delivery-runtime.ts +531 -56
- package/adapters/chatgpt/controller-binding-store.ts +101 -22
- package/adapters/chatgpt/controller-round-host.ts +15 -25
- package/adapters/chatgpt/controller-round-settlement-store.ts +58 -4
- package/adapters/chatgpt/provider-delivery.ts +229 -2
- package/adapters/chatgpt/work-conversation-binding-store.ts +99 -54
- package/adapters/computer/chatgpt-extension-target.ts +708 -0
- package/adapters/computer/chrome-extension/background.js +541 -0
- package/adapters/computer/chrome-extension/content.js +402 -0
- package/adapters/computer/chrome-extension/core.js +24 -0
- package/adapters/computer/chrome-extension/manifest.json +32 -0
- package/adapters/computer/desktop-operator-discovery.ts +11 -31
- package/adapters/computer/desktop-operator-provider.ts +18 -6
- package/adapters/computer/interaction-target-authority.ts +178 -24
- package/adapters/mcp/access-mode.ts +18 -39
- package/adapters/mcp/auth.ts +2 -7
- package/adapters/mcp/instructions.ts +6 -5
- package/adapters/mcp/multi-repository.ts +10 -47
- package/adapters/mcp/oauth.ts +73 -0
- package/adapters/mcp/paths.ts +4 -1
- package/adapters/mcp/runtime-gateway/bounded-result-runtime.ts +62 -0
- package/adapters/mcp/runtime-gateway/cognition-settlement.ts +201 -0
- package/adapters/mcp/runtime-gateway/context-adapter.ts +490 -113
- package/adapters/mcp/runtime-gateway/context-pack-sidecar.ts +83 -0
- package/adapters/mcp/runtime-gateway/controller-authority-adapter.ts +20 -5
- package/adapters/mcp/runtime-gateway/core-capability-adapter.ts +258 -0
- package/adapters/mcp/runtime-gateway/engineering-preconditions.ts +10 -27
- package/adapters/mcp/runtime-gateway/engineering-tool-contract.ts +15 -0
- package/adapters/mcp/runtime-gateway/execution-tools.ts +14 -54
- package/adapters/mcp/runtime-gateway/gateway-execution-adapter.ts +2 -1
- package/adapters/mcp/runtime-gateway/plugin-adapter.ts +132 -47
- package/adapters/mcp/runtime-gateway/process-tools.ts +173 -23
- package/adapters/mcp/runtime-gateway/protected-computer-adapter.ts +16 -4
- package/adapters/mcp/runtime-gateway/recovery-adapter.ts +69 -52
- package/adapters/mcp/runtime-gateway/repository-compat-adapter.ts +4 -35
- package/adapters/mcp/runtime-gateway/result-adapter.ts +10 -4
- package/adapters/mcp/runtime-gateway/router.ts +19 -507
- package/adapters/mcp/runtime-gateway/routing-policy.ts +506 -0
- package/adapters/mcp/runtime-gateway/runtime-observation-adapter.ts +15 -66
- package/adapters/mcp/runtime-gateway/runtime-readiness-observation.ts +218 -0
- package/adapters/mcp/runtime-gateway/runtime-tool-definitions.ts +123 -178
- package/adapters/mcp/runtime-gateway/runtime-tools.ts +11 -5
- package/adapters/mcp/runtime-gateway/scheduler-adapter.ts +37 -1
- package/adapters/mcp/runtime-gateway/shared-adapter.ts +20 -0
- package/adapters/mcp/runtime-gateway/status-inbox-adapter.ts +416 -270
- package/adapters/mcp/runtime-gateway/typescript-navigation-sidecar.ts +140 -0
- package/adapters/mcp/runtime-gateway/work-adapter.ts +262 -3123
- package/adapters/mcp/runtime-gateway/work-controller-operations.ts +257 -0
- package/adapters/mcp/runtime-gateway/work-detail-projection.ts +60 -0
- package/adapters/mcp/runtime-gateway/work-input-wire-migration.ts +229 -0
- package/adapters/mcp/runtime-gateway/work-learning-operations.ts +145 -0
- package/adapters/mcp/runtime-gateway/work-list-projection.ts +38 -0
- package/adapters/mcp/runtime-gateway/work-plan-operations.ts +382 -0
- package/adapters/mcp/runtime-gateway/work-repair-adapter.ts +308 -0
- package/adapters/mcp/runtime-gateway/work-requirement-operations.ts +148 -0
- package/adapters/mcp/runtime-gateway/work-semantic-operations.ts +320 -0
- package/adapters/mcp/runtime-gateway/work-workflow-operations.ts +113 -0
- package/adapters/mcp/runtime-gateway/workflow-supervisor-adapter.ts +180 -0
- package/adapters/mcp/server.ts +91 -26
- package/adapters/mcp/setup.ts +5 -13
- package/adapters/mcp/tool-mapping/access-tools.ts +0 -6
- package/adapters/mcp/tool-mapping/legacy-tool-service.ts +703 -3092
- package/adapters/mcp/tool-mapping/post-finalize-work-attribution.ts +5 -10
- package/adapters/mcp/tool-mapping/repository-tools.ts +170 -213
- package/adapters/mcp/toolset-names.ts +11 -37
- package/adapters/mcp/toolset.ts +19 -92
- package/{src/cli → adapters}/mcp/transports/AGENTS.md +5 -5
- package/{src/cli → adapters}/mcp/transports/CLAUDE.md +5 -5
- package/adapters/mcp/transports/http-observation.ts +377 -0
- package/adapters/mcp/transports/http-post-lifecycle.ts +19 -0
- package/adapters/mcp/transports/http.ts +200 -683
- package/adapters/mcp/transports/oauth-http.ts +322 -0
- package/adapters/mcp/transports/session-registry.ts +6 -0
- package/adapters/mcp/tunnels/openai-secure-tunnel.ts +89 -5
- package/adapters/mcp/types.ts +0 -6
- package/assets/hooks/lib/session-state.sh +0 -38
- package/assets/hooks/post-bash.sh +1 -1
- package/assets/hooks/post-tool-observer.sh +0 -5
- package/assets/hooks/prompt-guard.sh +0 -55
- package/assets/partials/04-project-structure.partial.md +1 -1
- package/assets/partials/07-footer.partial.md +1 -1
- package/assets/partials-agents/02-operating-mode.partial.md +1 -1
- package/assets/partials-agents/08-deep-docs.partial.md +1 -1
- package/assets/plugin-registry.v1.json +6 -4
- package/assets/reference-configs/agentic-development-flow.md +26 -1
- package/assets/reference-configs/external-tooling.md +0 -76
- package/assets/reference-configs/global-working-rules.md +19 -0
- package/assets/reference-configs/release-deploy.md +1 -1
- package/assets/templates/helpers/architecture-queue.sh +1 -1
- package/assets/templates/helpers/check-agent-tooling.sh +1 -327
- package/assets/templates/helpers/check-task-workflow.sh +1 -1
- package/assets/templates/helpers/ensure-task-workflow.sh +0 -14
- package/assets/templates/helpers/migrate-project-template.sh +2 -2
- package/assets/workflow-contract.v1.json +0 -2
- package/docs/README.md +5 -2
- package/docs/architecture/CURRENT.md +205 -51
- package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +14 -5
- package/docs/architecture/decisions/20260823-immediate-controller-relay.md +6 -3
- package/docs/architecture/decisions/20260904-ios-device-migration-baseline.md +42 -0
- package/docs/architecture/decisions/20260907-assistant-learning-loop.md +2 -0
- package/docs/architecture/decisions/20260907-controller-round-transition-policy.md +19 -4
- package/docs/architecture/decisions/20260916-workflow-supervisor-authority.md +249 -0
- package/docs/architecture/decisions/20260917-cognitive-memory-foundation.md +82 -0
- package/docs/architecture/decisions/20260918-stable-candidate-release-lifecycle.md +234 -0
- package/docs/architecture/decisions/20260919-autonomous-work-liveness.md +62 -0
- package/docs/architecture/decisions/20260924-thin-semantic-working-context.md +74 -0
- package/docs/architecture/decisions/20261001-supervisor-turn-authority.md +342 -0
- package/docs/architecture/decisions/20261005-forge-v3-desktop-client-boundary.md +77 -0
- package/docs/architecture/decisions/20261009-exact-code-context-discovery.md +19 -0
- package/docs/architecture/decisions/20261009-generated-xcode-cache-retention.md +37 -0
- package/docs/architecture/decisions/20261011-autonomous-continuation-convergence.md +597 -0
- package/docs/architecture/decisions/20261017-edit-session-finalization-reconciliation.md +17 -0
- package/docs/architecture/decisions/20261019-retire-host-skills.md +16 -0
- package/docs/architecture/diagrams/agentic-dev-plugin-architecture.html +1 -1
- package/docs/architecture/domains/public-surface.md +3 -5
- package/docs/architecture/domains/verification.md +6 -5
- package/docs/architecture/domains/workflow-engine.md +6 -0
- package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +3 -3
- package/docs/architecture/requests/2026-09-04-computer-plugin-workflow-taxonomy.md +4 -4
- package/docs/architecture/reviews/20261015-code-search-runtime-acceptance.md +75 -0
- package/docs/forge-plugin-management.md +16 -4
- package/docs/operations/controller-browser-plugin.md +23 -0
- package/docs/operations/controller-performance-and-502.md +17 -0
- package/docs/operations/controller-reliability-runbook.md +2 -2
- package/docs/operations/features.md +6 -7
- package/docs/operations/features.zh-CN.md +1 -1
- package/docs/operations/github-repository.md +4 -4
- package/docs/operations/github-semantic-release-projection.md +20 -0
- package/docs/operations/homebrew.md +2 -2
- package/docs/operations/mcp-tool-exposure.md +13 -52
- package/docs/operations/releasing.md +2 -0
- package/docs/operations/runtime-performance-diagnostics.md +8 -0
- package/docs/operations/standalone-disaster-recovery.md +15 -7
- package/docs/tutorials/01-install-and-start.zh-CN.md +1 -1
- package/docs/tutorials/03-first-repository-task.md +2 -0
- package/docs/wiki/Computer-and-Plugins.md +78 -0
- package/docs/wiki/Computer-and-Plugins.zh-CN.md +88 -0
- package/docs/wiki/Home.md +16 -2
- package/docs/wiki/Implementation.md +25 -13
- package/docs/wiki/Installation.md +28 -32
- package/docs/wiki/Integrations.md +4 -0
- package/docs/wiki/Quick-Start.md +35 -22
- package/docs/wiki/Releases-and-Upgrades.md +15 -25
- package/docs/wiki/_Sidebar.md +5 -1
- package/package.json +25 -25
- package/packages/kernel/cognition/api/index.ts +6 -0
- package/packages/kernel/cognition/application/activation-service.ts +451 -0
- package/packages/kernel/cognition/application/consolidation-service.ts +185 -0
- package/packages/kernel/cognition/application/legacy-experience-adapter.ts +38 -0
- package/packages/kernel/cognition/application/memory-service.ts +64 -0
- package/packages/kernel/cognition/domain/learning.ts +106 -0
- package/packages/kernel/cognition/domain/memory.ts +254 -0
- package/packages/kernel/controller/api/index.ts +1 -0
- package/packages/kernel/controller/application/continuation-service.ts +281 -0
- package/packages/kernel/controller/application/controller-round-service.ts +12 -0
- package/packages/kernel/controller/domain/controller-round-transition-policy.ts +242 -21
- package/packages/kernel/controller/domain/controller-round.ts +4 -1
- package/packages/kernel/controller/domain/execution-quality.ts +3 -1
- package/packages/kernel/controller/infrastructure/controller-round-store.ts +689 -103
- package/packages/kernel/controller/infrastructure/controller-session-store.ts +348 -97
- package/packages/kernel/controller/ports/controller-host.ts +2 -0
- package/packages/kernel/identity/api/index.ts +10 -0
- package/packages/kernel/identity/domain/activity-projection.ts +43 -0
- package/packages/kernel/identity/domain/capability-broker.ts +60 -0
- package/packages/kernel/identity/domain/grant.ts +72 -0
- package/packages/kernel/identity/domain/owned-resource.ts +116 -0
- package/packages/kernel/identity/domain/user-request.ts +93 -0
- package/packages/kernel/identity/infrastructure/activity-projection-store.ts +87 -0
- package/packages/kernel/identity/infrastructure/capability-broker.ts +81 -0
- package/packages/kernel/identity/infrastructure/grant-store.ts +284 -0
- package/packages/kernel/identity/infrastructure/owned-resource-store.ts +259 -0
- package/packages/kernel/identity/infrastructure/user-request-store.ts +182 -0
- package/packages/kernel/scheduler/api/index.ts +0 -2
- package/packages/kernel/scheduler/application/eligibility.ts +4 -1
- package/packages/kernel/scheduler/application/schedule-service.ts +3 -0
- package/packages/kernel/scheduler/application/settlement.ts +0 -15
- package/packages/kernel/scheduler/domain/schedule.ts +87 -0
- package/packages/kernel/scheduler/infrastructure/schedule-store.ts +166 -143
- package/packages/kernel/work/api/index.ts +3 -2
- package/packages/kernel/work/application/work-service.ts +18 -42
- package/packages/kernel/work/domain/current-task-lineage.ts +104 -0
- package/packages/kernel/work/domain/engineering-design.ts +10 -5
- package/packages/kernel/work/domain/engineering-profile.ts +8 -12
- package/packages/kernel/work/domain/evaluation-promotion-receipt.ts +186 -0
- package/packages/kernel/work/domain/execution-concurrency.ts +19 -26
- package/packages/kernel/work/domain/execution-snapshot.ts +0 -31
- package/packages/kernel/work/domain/implementation-review.ts +14 -331
- package/packages/kernel/work/domain/objective-graph.ts +119 -0
- package/packages/kernel/work/domain/project-engineering-contract.ts +23 -1
- package/packages/kernel/work/domain/repository-completion-receipt.ts +1 -1
- package/packages/kernel/work/domain/state-machine.ts +34 -65
- package/packages/kernel/work/domain/types.ts +57 -51
- package/packages/kernel/work/infrastructure/work-contract-store.ts +847 -729
- package/packages/kernel/work/ports/work-contract-store.ts +5 -2
- package/packages/plugin-runtime/browser/provider-registry.ts +12 -36
- package/packages/plugin-runtime/browser/session-authority.ts +2 -1
- package/packages/plugin-runtime/computer/chatgpt-identity.ts +24 -0
- package/packages/plugin-runtime/computer/conversation-target.ts +153 -0
- package/packages/plugin-runtime/computer/index.ts +2 -0
- package/packages/plugin-runtime/computer/target-authority.ts +26 -1
- package/packages/plugin-runtime/external/unix-jsonl-transport.ts +142 -18
- package/packages/protocols/computer/contract.ts +27 -1
- package/scripts/activate-source-baseline.ts +7 -9
- package/scripts/assemble-template.ts +11 -72
- package/scripts/canary-controller-semantic-wait.ts +12 -24
- package/scripts/check-mcp-compatibility.ts +94 -201
- package/scripts/check-package-identity.mjs +0 -5
- package/scripts/check-runtime-architecture.mjs +921 -239
- package/scripts/forge-local-recovery-helper.mjs +93 -15
- package/scripts/init-project.sh +0 -46
- package/scripts/install-ios-hid-toolchain.sh +60 -0
- package/scripts/install-standalone-recovery.ts +1 -1
- package/scripts/lib/project-init-lib.sh +6 -3
- package/scripts/migrate-windows-wsl-controller-home.ts +2 -0
- package/scripts/open-source-audit-allowlist.txt +1 -3
- package/scripts/run-bounded-command.mjs +5 -0
- package/scripts/run-governed-gate.ts +2 -1
- package/scripts/run-mobile-monitor-bridge.ts +0 -1
- package/scripts/smoke-control-plane-failure-domain.ts +94 -0
- package/scripts/smoke-ios-physical-device.ts +38 -10
- package/scripts/smoke-mcp-http-runtime.ts +12 -8
- package/scripts/smoke-mcp-tool-surface.ts +27 -41
- package/scripts/smoke-runtime-recovery.ts +12 -43
- package/scripts/smoke-schedule-engine.ts +23 -15
- package/scripts/smoke-unattended-transport-recovery.ts +223 -0
- package/scripts/smoke-user-request-continuation-restart.ts +232 -0
- package/scripts/smoke-workflow-supervisor-chrome-adapter.ts +95 -0
- package/scripts/smoke-workflow-supervisor-process-restart.ts +276 -0
- package/scripts/smoke-workflow-supervisor-restart-recovery.ts +150 -0
- package/scripts/smoke-workflow-supervisor.ts +103 -0
- package/scripts/sync-generated-authority.mjs +0 -1
- package/scripts/verify-forge-runtime.sh +2 -1
- package/src/cli/agent-jobs/executor-health.ts +12 -35
- package/src/cli/agent-jobs/integration.ts +20 -51
- package/src/cli/agent-jobs/job-manager.ts +7 -3
- package/src/cli/chatgpt-browser/file-policy.ts +2 -2
- package/src/cli/commands/brain-assistant.ts +27 -13
- package/src/cli/commands/brain.ts +13 -15
- package/src/cli/commands/chatgpt.ts +1 -163
- package/src/cli/commands/doctor.ts +1 -143
- package/src/cli/commands/global-runtime.ts +3 -196
- package/src/cli/commands/init-hook.ts +6 -23
- package/src/cli/commands/init.ts +3 -252
- package/src/cli/commands/mcp.ts +0 -5
- package/src/cli/commands/prompt-guard-decision.ts +0 -2
- package/src/cli/commands/recovery.ts +137 -135
- package/src/cli/commands/repository.ts +17 -1
- package/src/cli/commands/runtime.ts +3 -3
- package/src/cli/commands/setup-execution.ts +41 -0
- package/src/cli/commands/setup-profile.ts +8 -0
- package/src/cli/controller/check-runner.ts +13 -2
- package/src/cli/controller/completion-backlog.ts +3 -3
- package/src/cli/controller/completion-orchestrator.ts +5 -44
- package/src/cli/controller/completion-target.ts +3 -72
- package/src/cli/controller/composite-operations.ts +1 -1
- package/src/cli/controller/context/instruction-context.ts +1 -1
- package/src/cli/controller/context/known-paths.ts +2 -2
- package/src/cli/controller/context/query-planning.ts +11 -4
- package/src/cli/controller/context/rule-resolution.ts +2 -2
- package/src/cli/controller/context/source-materializer.ts +83 -102
- package/src/cli/controller/context/structural-provider.ts +84 -0
- package/src/cli/controller/context/structural.ts +6 -6
- package/src/cli/controller/context/types.ts +8 -9
- package/src/cli/controller/context-pack.ts +107 -84
- package/src/cli/controller/execution-completion.ts +4 -7
- package/src/cli/controller/execution-policy.ts +36 -153
- package/src/cli/controller/governance.ts +2 -3
- package/src/cli/controller/issue-store.ts +4 -99
- package/src/cli/controller/launch-agents.ts +59 -18
- package/src/cli/controller/operational-plan.ts +25 -52
- package/src/cli/controller/runtime-config.ts +5 -1
- package/src/cli/controller/stuck-state-migration.ts +2 -3
- package/src/cli/controller/systemd-user.ts +42 -10
- package/src/cli/editing/edit-session.ts +18 -12
- package/src/cli/github/github.ts +4 -4
- package/src/cli/github/semantic-projection.ts +174 -0
- package/src/cli/hook/prompt-intents.ts +0 -9
- package/src/cli/index.ts +1 -43
- package/src/cli/local-bridge/connector-freshness.ts +1 -12
- package/src/cli/local-bridge/console-automations.ts +19 -14
- package/src/cli/local-bridge/console-view-models.ts +4 -13
- package/src/cli/local-bridge/facade-api.ts +64 -193
- package/src/cli/local-bridge/server.ts +24 -147
- package/src/cli/local-bridge/types.ts +0 -1
- package/src/cli/mcp/oauth-client-retirement.ts +74 -0
- package/src/cli/repositories/command-classifier.ts +0 -9
- package/src/cli/repositories/command-executor.ts +29 -23
- package/src/cli/repositories/command-scope.ts +37 -18
- package/src/cli/repositories/controller-home.ts +48 -0
- package/src/cli/repositories/ephemeral-workspace.ts +20 -30
- package/src/cli/repositories/git-command-executor.ts +2 -2
- package/src/cli/repositories/locks.ts +20 -0
- package/src/cli/repositories/registry.ts +79 -12
- package/src/cli/repositories/safe-patch.ts +2 -12
- package/src/cli/repositories/structured-git.ts +101 -5
- package/src/cli/repository/inspector.ts +185 -343
- package/src/cli/repository/session-cache.ts +92 -6
- package/src/effects/process-runner.ts +17 -1
- package/src/runtime/context/assistant-context.ts +20 -7
- package/src/runtime/context/assistant-work-context.ts +89 -27
- package/src/runtime/context/automatic-learning.ts +565 -0
- package/src/runtime/context/cognitive-attention.ts +173 -0
- package/src/runtime/context/cognitive-skill-canary.ts +158 -0
- package/src/runtime/context/context-closure.ts +46 -9
- package/src/runtime/context/context-pack-process.ts +103 -0
- package/src/runtime/context/context-plane.ts +1 -9
- package/src/runtime/context/direct-controller-learning.ts +298 -0
- package/src/runtime/context/generic-lsp-provider.ts +1 -1
- package/src/runtime/context/semantic-navigation-contract.ts +16 -0
- package/src/runtime/context/semantic-navigation.ts +7 -35
- package/src/runtime/context/typescript-navigation-process.ts +145 -0
- package/src/runtime/context/typescript-navigation.ts +89 -3
- package/src/runtime/control-plane/cleanup-artifact-retention.ts +215 -12
- package/src/runtime/control-plane/concurrency/work-execution-concurrency.ts +9 -47
- package/src/runtime/control-plane/execution/controller-authority-recovery.ts +34 -4
- package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +29 -20
- package/src/runtime/control-plane/execution/execution-identity.ts +23 -3
- package/src/runtime/control-plane/execution/repository-work-attribution.ts +7 -30
- package/src/runtime/control-plane/execution/retained-work-resume.ts +206 -199
- package/src/runtime/control-plane/execution/session-store.ts +31 -1
- package/src/runtime/control-plane/execution/validation.ts +6 -8
- package/src/runtime/control-plane/execution/work-authority-reconciler.ts +13 -42
- package/src/runtime/control-plane/execution/work-check-evidence.ts +137 -0
- package/src/runtime/control-plane/execution/work-completion-authority.ts +30 -85
- package/src/runtime/control-plane/execution/work-delivery-service.ts +616 -0
- package/src/runtime/control-plane/execution/work-evidence-policy.ts +12 -50
- package/src/runtime/control-plane/execution/work-execution-support.ts +50 -149
- package/src/runtime/control-plane/execution/work-handle-authority.ts +197 -110
- package/src/runtime/control-plane/execution/work-handle-store.ts +72 -44
- package/src/runtime/control-plane/execution/work-head-settlement.ts +53 -20
- package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +52 -29
- package/src/runtime/control-plane/execution/work-operation-service.ts +60 -34
- package/src/runtime/control-plane/execution/work-preparation-service.ts +231 -267
- package/src/runtime/control-plane/execution/work-process-evidence.ts +2 -2
- package/src/runtime/control-plane/execution/work-remote-delivery.ts +2 -3
- package/src/runtime/control-plane/execution/work-revision-diff.ts +39 -0
- package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +201 -199
- package/src/runtime/control-plane/execution/work-validation-reconciler.ts +33 -85
- package/src/runtime/control-plane/execution/work-verification-service.ts +406 -50
- package/src/runtime/control-plane/execution/work-verification-snapshot.ts +6 -2
- package/src/runtime/control-plane/facade/capability-registry.ts +364 -37
- package/src/runtime/control-plane/facade/check-normalization.ts +3 -9
- package/src/runtime/control-plane/facade/codex-delegation.ts +10 -11
- package/src/runtime/control-plane/facade/controller-connection.ts +135 -0
- package/src/runtime/control-plane/facade/goal-workloop-access.ts +1 -20
- package/src/runtime/control-plane/facade/goal-workloop.ts +281 -1753
- package/src/runtime/control-plane/facade/handoff-inbox-application.ts +12 -25
- package/src/runtime/control-plane/facade/handoff-inbox-store.ts +256 -52
- package/src/runtime/control-plane/facade/index.ts +0 -1
- package/src/runtime/control-plane/facade/operation-digest.ts +12 -15
- package/src/runtime/control-plane/facade/plan-contract-store.ts +451 -991
- package/src/runtime/control-plane/facade/policy-gate.ts +0 -23
- package/src/runtime/control-plane/facade/repository-work-admission.ts +12 -22
- package/src/runtime/control-plane/facade/requirement-authority.ts +102 -199
- package/src/runtime/control-plane/facade/requirement-board.ts +3 -3
- package/src/runtime/control-plane/facade/rh-work-operation-contract.ts +51 -14
- package/src/runtime/control-plane/facade/self-healing-loop.ts +18 -53
- package/src/runtime/control-plane/facade/suggested-actions.ts +15 -18
- package/src/runtime/control-plane/facade/types.ts +49 -108
- package/src/runtime/control-plane/facade/work-continuation.ts +9 -9
- package/src/runtime/control-plane/generated-cache-retention.ts +206 -59
- package/src/runtime/control-plane/global-scheduler/autonomous-continuation.ts +248 -0
- package/src/runtime/control-plane/global-scheduler/durable-admission.ts +1 -1
- package/src/runtime/control-plane/global-scheduler/maintenance.ts +256 -117
- package/src/runtime/control-plane/global-scheduler/reconciliation.ts +3 -12
- package/src/runtime/control-plane/global-scheduler/scheduler.ts +66 -40
- package/src/runtime/control-plane/global-scheduler/wake-signal.ts +42 -2
- package/src/runtime/control-plane/governance/access-policy.ts +19 -2
- package/src/runtime/control-plane/governance/authorization.ts +20 -3
- package/src/runtime/control-plane/governance/external-effects.ts +1 -1
- package/src/runtime/control-plane/launcher/chatgpt-round-continuation.ts +63 -300
- package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +29 -300
- package/src/runtime/control-plane/launcher/local-conversation-controller.ts +238 -0
- package/src/runtime/control-plane/launcher/provider-mcp-bootstrap.ts +5 -2
- package/src/runtime/control-plane/launcher/thin-launcher.ts +96 -240
- package/src/runtime/control-plane/persistence/cognition-store.ts +820 -0
- package/src/runtime/control-plane/persistence/experience-store.ts +162 -29
- package/src/runtime/control-plane/persistence/requirement-store.ts +216 -74
- package/src/runtime/control-plane/persistence/sqlite-store.ts +113 -6
- package/src/runtime/control-plane/release-retention.ts +135 -47
- package/src/runtime/control-plane/repository-namespace-retention.ts +2 -2
- package/src/runtime/control-plane/runtime-cleanup.ts +295 -107
- package/src/runtime/control-plane/workspace/project-onboarding.ts +80 -0
- package/src/runtime/control-plane/workspace/semantic-sync-service.ts +19 -5
- package/src/runtime/control-plane/workspace/workspace-store.ts +169 -0
- package/src/runtime/diagnostics/incident-repair.ts +313 -146
- package/src/runtime/diagnostics/mcp-timing.ts +114 -0
- package/src/runtime/evidence/artifact-store.ts +158 -40
- package/src/runtime/evidence/evidence-store.ts +112 -8
- package/src/runtime/evidence/output-handle-index.ts +225 -0
- package/src/runtime/evidence/result-store.ts +158 -44
- package/src/runtime/evidence/sensitive-output.ts +22 -2
- package/src/runtime/execution/jobs/child-reference.ts +11 -0
- package/src/runtime/execution/jobs/receipt-recovery.ts +1 -11
- package/src/runtime/execution/jobs/store.ts +3 -4
- package/src/runtime/execution/managed-workspace.ts +57 -0
- package/src/runtime/execution/process-runtime/check-facade.ts +1 -1
- package/src/runtime/execution/process-runtime/check-result-retention.ts +2 -2
- package/src/runtime/execution/process-runtime/check-result.ts +105 -1
- package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +18 -8
- package/src/runtime/execution/process-runtime/command-facade.ts +82 -30
- package/src/runtime/execution/process-runtime/gc.ts +15 -2
- package/src/runtime/execution/process-runtime/handle-index.ts +176 -0
- package/src/runtime/execution/process-runtime/host-command-lane.ts +139 -0
- package/src/runtime/execution/process-runtime/index.ts +3 -0
- package/src/runtime/execution/process-runtime/lightweight-managed.ts +251 -72
- package/src/runtime/execution/process-runtime/persisted-check.ts +3 -3
- package/src/runtime/execution/process-runtime/process-runner-entry.ts +47 -5
- package/src/runtime/execution/process-runtime/process-scope.ts +160 -0
- package/src/runtime/execution/process-runtime/resource-claims.ts +65 -61
- package/src/runtime/execution/process-runtime/runtime.ts +55 -18
- package/src/runtime/execution/process-runtime/store.ts +30 -2
- package/src/runtime/execution/process-runtime/types.ts +6 -1
- package/src/runtime/execution/thin-harness/execution-router.ts +16 -16
- package/src/runtime/execution/thin-harness/fast-executor.ts +2 -2
- package/src/runtime/execution/thin-harness/search-worker.ts +2 -2
- package/src/runtime/execution/workers/executor.ts +3 -8
- package/src/runtime/maintenance/cleanup.ts +41 -5
- package/src/runtime/platform/service-inventory.ts +130 -0
- package/src/runtime/platform/service-manager.ts +8 -0
- package/src/runtime/plugins/action-application.ts +97 -29
- package/src/runtime/plugins/app-store-connect-adapter.ts +290 -18
- package/src/runtime/plugins/browser-adapter.ts +1124 -333
- package/src/runtime/plugins/browser-automation-service.ts +23 -3
- package/src/runtime/plugins/browser-macos-bridge.ts +431 -137
- package/src/runtime/plugins/browser-manifest-surface.ts +47 -12
- package/src/runtime/plugins/browser-native-session-service.ts +63 -13
- package/src/runtime/plugins/browser-registration.ts +18 -0
- package/src/runtime/plugins/browser-runtime.ts +40 -36
- package/src/runtime/plugins/browser-session-authority.ts +2 -2
- package/src/runtime/plugins/browser-session-store.ts +46 -76
- package/src/runtime/plugins/capability-authorization-grants.ts +258 -62
- package/src/runtime/plugins/computer-chatgpt-browser-adapter-installer.ts +228 -0
- package/src/runtime/plugins/computer-registration.ts +298 -20
- package/src/runtime/plugins/desktop-operator-external-policy.ts +36 -4
- package/src/runtime/plugins/desktop-operator-registration.ts +12 -4
- package/src/runtime/plugins/external-adapter.ts +42 -6
- package/src/runtime/plugins/external-registration.ts +21 -1
- package/src/runtime/plugins/github-adapter.ts +30 -3
- package/src/runtime/plugins/gmail-adapter.ts +189 -3
- package/src/runtime/plugins/google-calendar-adapter.ts +2 -2
- package/src/runtime/plugins/google-shared.ts +24 -12
- package/src/runtime/plugins/google-tasks-adapter.ts +2 -2
- package/src/runtime/plugins/ios/remote-xpc-hid.ts +70 -30
- package/src/runtime/plugins/ios-adapter.ts +46 -41
- package/src/runtime/plugins/ios-agent-device.ts +54 -4
- package/src/runtime/plugins/ios-device-ownership.ts +103 -0
- package/src/runtime/plugins/ios-physical-device.ts +497 -79
- package/src/runtime/plugins/lightweight-action.ts +208 -2
- package/src/runtime/plugins/local-system-adapter.ts +12 -100
- package/src/runtime/plugins/managed-process-adapter.ts +12 -5
- package/src/runtime/plugins/plugin-action-sidecar.ts +17 -13
- package/src/runtime/plugins/plugin-management-adapter.ts +1 -1
- package/src/runtime/plugins/store.ts +682 -435
- package/src/runtime/plugins/types.ts +24 -0
- package/src/runtime/plugins/xiaohongshu-publish.ts +16 -0
- package/src/runtime/projections/git-status-sampler.ts +2 -19
- package/src/runtime/projections/invalidation.ts +7 -3
- package/src/runtime/projections/materialized-view.ts +80 -36
- package/src/runtime/recovery/actions.ts +4 -4
- package/src/runtime/recovery/capability-action-application.ts +46 -45
- package/src/runtime/recovery/lifecycle-inventory.ts +30 -40
- package/src/runtime/recovery/maintenance-executor.ts +374 -123
- package/src/runtime/recovery/probe.ts +2 -2
- package/src/runtime/recovery/store.ts +29 -11
- package/src/runtime/release/release-coordinator.ts +312 -0
- package/src/runtime/release/release-session.ts +716 -0
- package/src/runtime/release/release-state-migration.ts +25 -0
- package/src/runtime/resources/leases/store.ts +56 -25
- package/src/runtime/root/computer-composition.ts +191 -6
- package/src/runtime/root/controller-progression-composition.ts +254 -0
- package/src/runtime/root/controller-round-composition.ts +20 -1
- package/src/runtime/root/deployment-topology.ts +106 -0
- package/src/runtime/root/entry.ts +4 -3
- package/src/runtime/root/known-good-recovery.ts +184 -0
- package/src/runtime/root/local-bridge.ts +0 -1
- package/src/runtime/root/mcp-transport.ts +111 -18
- package/src/runtime/root/ownership.ts +261 -9
- package/src/runtime/root/package-connector-service.ts +227 -29
- package/src/runtime/root/package-runtime-release.ts +117 -30
- package/src/runtime/root/package-runtime-service.ts +24 -24
- package/src/runtime/root/release-execution-canary.ts +57 -12
- package/src/runtime/root/release-loader.ts +90 -8
- package/src/runtime/root/release-manifest.ts +80 -40
- package/src/runtime/root/release-materialize.ts +372 -106
- package/src/runtime/root/release-store.ts +395 -36
- package/src/runtime/root/runtime-lane.ts +191 -0
- package/src/runtime/root/runtime.ts +160 -29
- package/src/runtime/root/scheduled-controller-composition.ts +29 -3
- package/src/runtime/root/service-runner.ts +2 -2
- package/src/runtime/root/service.ts +126 -44
- package/src/runtime/root/status.ts +48 -0
- package/src/runtime/root/types.ts +32 -9
- package/src/runtime/root/workflow-supervisor-composition.ts +681 -0
- package/src/runtime/root/workflow-supervisor-runtime.ts +564 -0
- package/src/runtime/root/write-fence.ts +50 -2
- package/src/runtime/safe-tooling/google-credential-store.ts +67 -22
- package/src/runtime/safe-tooling/google-oauth-broker.ts +25 -7
- package/src/runtime/safe-tooling/ios-development.ts +22 -8
- package/src/runtime/safe-tooling/job-summary.ts +1 -1
- package/src/runtime/safe-tooling/workspace-auth.ts +5 -2
- package/src/runtime/shared/atomic-text-file.ts +21 -0
- package/src/runtime/shared/bounded-child-supervisor.ts +9 -1
- package/src/runtime/shared/json-files.ts +8 -3
- package/src/runtime/shared/process-environment.ts +20 -9
- package/src/runtime/shared/response-budget.ts +1 -3
- package/src/runtime/standalone-recovery/controller-home-migration.ts +16 -24
- package/src/runtime/standalone-recovery/core.ts +3792 -417
- package/src/runtime/standalone-recovery/entry.ts +507 -45
- package/src/runtime/standalone-recovery/installer.ts +262 -148
- package/src/runtime/standalone-recovery/mcp-server.ts +29 -193
- package/src/runtime/standalone-recovery/operation-lock.ts +12 -2
- package/src/runtime/standalone-recovery/performance.ts +54 -16
- package/src/runtime/standalone-recovery/release.ts +53 -5
- package/src/runtime/standalone-recovery/service-labels.ts +5 -2
- package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +5 -2
- package/src/runtime/workflow/schedules/browser-probe.ts +17 -6
- package/src/runtime/workflow/schedules/chatgpt-automation-migration.ts +11 -3
- package/src/runtime/workflow/schedules/engine.ts +166 -178
- package/src/runtime/workflow/schedules/pending-activation.ts +11 -4
- package/src/runtime/workflow/schedules/work-continuation.ts +95 -11
- package/src/runtime/workflows/runtime.ts +15 -19
- package/src/testing/test-governance.ts +5 -1
- package/supervisor/chatgpt-conversation.ts +23 -0
- package/supervisor/client.ts +218 -0
- package/supervisor/control-plane.ts +963 -0
- package/supervisor/entry.ts +15 -0
- package/supervisor/forge-validators.ts +147 -0
- package/supervisor/index.ts +5 -0
- package/supervisor/native-browser-adapter.ts +1151 -0
- package/supervisor/native-messaging/host.ts +58 -0
- package/supervisor/native-messaging/manifest.ts +26 -0
- package/supervisor/native-messaging/protocol.ts +27 -0
- package/supervisor/paths.ts +18 -0
- package/supervisor/protocol.ts +250 -0
- package/supervisor/server.ts +412 -0
- package/supervisor/store.ts +1870 -0
- package/supervisor/tsconfig.json +8 -0
- package/supervisor/types.ts +261 -0
- package/SKILL.md +0 -427
- package/adapters/chatgpt/controller-host.ts +0 -119
- package/adapters/mcp/controller-round-compatibility.ts +0 -184
- package/adapters/mcp/frozen-client-semantic-compatibility.ts +0 -292
- package/adapters/mcp/runtime-gateway/work-compat-adapter.ts +0 -502
- package/adapters/mcp/runtime-gateway/work-validation-reconciler.ts +0 -1
- package/adapters/mcp/toolset-selection.ts +0 -41
- package/agents/openai.yaml +0 -4
- package/assets/skill-hooks.json +0 -41
- package/assets/skill-version.json +0 -189
- package/assets/skills/claude-review/SKILL.md +0 -231
- package/assets/skills/codex-review/SKILL.md +0 -103
- package/assets/templates/helpers/check-skill-version.ts +0 -193
- package/packages/kernel/progression/api/index.ts +0 -2
- package/packages/kernel/progression/application/projector.ts +0 -211
- package/packages/kernel/progression/domain/types.ts +0 -116
- package/packages/kernel/progression/index.ts +0 -1
- package/packages/kernel/scheduler/application/continuation-service.ts +0 -212
- package/packages/kernel/scheduler/domain/continuation.ts +0 -38
- package/packages/kernel/scheduler/infrastructure/continuation-dispatch-store.ts +0 -38
- package/packages/kernel/work/domain/admission-policy.ts +0 -34
- package/scripts/benchmark-background-check-overlap.ts +0 -228
- package/scripts/benchmark-computer-hotpath.ts +0 -255
- package/scripts/benchmark-controller-hotpath.ts +0 -212
- package/scripts/benchmark-controller-round2.ts +0 -191
- package/scripts/benchmark-ios-agent-device.ts +0 -511
- package/scripts/benchmark-mcp-host.sh +0 -117
- package/scripts/benchmark-mcp-transport.ts +0 -169
- package/scripts/benchmark-operational-memory-activation.ts +0 -235
- package/scripts/benchmark-operational-shadow.ts +0 -28
- package/scripts/benchmark-quality-harness.ts +0 -146
- package/scripts/benchmark-route-session-concurrency.ts +0 -915
- package/scripts/benchmark-thin-harness-gateway-ab.ts +0 -632
- package/scripts/benchmark-thin-harness-mcp-e2e.ts +0 -498
- package/scripts/benchmark-thin-harness.ts +0 -251
- package/scripts/benchmark-typescript-navigation.ts +0 -186
- package/scripts/benchmark-work-efficiency.ts +0 -334
- package/scripts/build-controller-ui.ts +0 -28
- package/scripts/check-npm-release.sh +0 -32
- package/scripts/check-public-release-surface.sh +0 -19
- package/scripts/check-release-published.sh +0 -57
- package/scripts/check-release-readiness.sh +0 -37
- package/scripts/check-release-version.mjs +0 -74
- package/scripts/check-skill-version.ts +0 -5
- package/scripts/check-tarball-install-smoke.sh +0 -150
- package/scripts/ensure-codegraph.sh +0 -16
- package/scripts/package-source-archive.sh +0 -147
- package/scripts/public-release-files.txt +0 -39
- package/scripts/public-release.ts +0 -174
- package/scripts/publish-release-tarball.sh +0 -27
- package/scripts/route-nl-vs-ts-eval.ts +0 -679
- package/scripts/run-skill-hook.ts +0 -244
- package/scripts/stage-runtime-release.ts +0 -44
- package/scripts/sync-codex-installed-copies.sh +0 -182
- package/src/cli/commands/tools.ts +0 -167
- package/src/cli/controller/progress.ts +0 -656
- package/src/cli/controller/work-mode.ts +0 -181
- package/src/cli/local-bridge/console-assets.ts +0 -17
- package/src/cli/local-bridge/dashboard.ts +0 -17
- package/src/cli/local-bridge/frontend/src/App.tsx +0 -10
- package/src/cli/local-bridge/frontend/src/components/Button.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/components/DetailPane.tsx +0 -3
- package/src/cli/local-bridge/frontend/src/components/SearchField.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/components/SectionHeader.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/components/Segmented.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/components/StatusText.tsx +0 -3
- package/src/cli/local-bridge/frontend/src/design/icons.tsx +0 -11
- package/src/cli/local-bridge/frontend/src/design/tokens.css +0 -8
- package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +0 -153
- package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +0 -37
- package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +0 -183
- package/src/cli/local-bridge/frontend/src/features/repositories/RepositoriesView.tsx +0 -2
- package/src/cli/local-bridge/frontend/src/features/system/SystemView.tsx +0 -2
- package/src/cli/local-bridge/frontend/src/features/work/WorkView.tsx +0 -4
- package/src/cli/local-bridge/frontend/src/lib/api.ts +0 -30
- package/src/cli/local-bridge/frontend/src/lib/format.ts +0 -4
- package/src/cli/local-bridge/frontend/src/lib/routes.ts +0 -7
- package/src/cli/local-bridge/frontend/src/main.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/shell/AppShell.tsx +0 -1
- package/src/cli/local-bridge/frontend/src/shell/CommandBar.tsx +0 -2
- package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +0 -4
- package/src/cli/local-bridge/frontend/src/styles.css +0 -28
- package/src/cli/local-bridge/frontend/src/types.ts +0 -15
- package/src/cli/local-bridge/frontend/src/vite-env.d.ts +0 -1
- package/src/cli/local-bridge/frontend/vite.config.ts +0 -27
- package/src/cli/local-bridge/ui-dist/app.css +0 -1
- package/src/cli/local-bridge/ui-dist/app.js +0 -11228
- package/src/cli/mcp/access-mode.ts +0 -2
- package/src/cli/mcp/access-tools.ts +0 -2
- package/src/cli/mcp/audit.ts +0 -2
- package/src/cli/mcp/auth.ts +0 -2
- package/src/cli/mcp/instructions.ts +0 -2
- package/src/cli/mcp/legacy-context.ts +0 -2
- package/src/cli/mcp/legacy-tool-service.ts +0 -2
- package/src/cli/mcp/multi-repository.ts +0 -2
- package/src/cli/mcp/oauth.ts +0 -2
- package/src/cli/mcp/openai-secure-tunnel.ts +0 -2
- package/src/cli/mcp/paths.ts +0 -2
- package/src/cli/mcp/policy.ts +0 -2
- package/src/cli/mcp/post-finalize-work-attribution.ts +0 -2
- package/src/cli/mcp/proxy-env.ts +0 -2
- package/src/cli/mcp/readiness-projection.ts +0 -2
- package/src/cli/mcp/redaction.ts +0 -2
- package/src/cli/mcp/repo.ts +0 -2
- package/src/cli/mcp/repository-tools.ts +0 -2
- package/src/cli/mcp/server.ts +0 -2
- package/src/cli/mcp/setup.ts +0 -2
- package/src/cli/mcp/tool-capability-cache.ts +0 -2
- package/src/cli/mcp/tool-contract.ts +0 -2
- package/src/cli/mcp/tools.ts +0 -2
- package/src/cli/mcp/toolset-names.ts +0 -2
- package/src/cli/mcp/toolset-selection.ts +0 -2
- package/src/cli/mcp/toolset.ts +0 -2
- package/src/cli/mcp/transports/http.ts +0 -2
- package/src/cli/mcp/transports/session-registry.ts +0 -2
- package/src/cli/mcp/transports/stdio.ts +0 -2
- package/src/cli/mcp/types.ts +0 -2
- package/src/cli/mcp/umbrella-tools.ts +0 -2
- package/src/cli/tools/codegraph.ts +0 -695
- package/src/core/adoption/helper-wrapper-plan.ts +0 -159
- package/src/runtime/context/codegraph-cache-boundary.ts +0 -255
- package/src/runtime/context/codegraph-read-provider.ts +0 -611
- package/src/runtime/context/codegraph-sidecar.cjs +0 -248
- package/src/runtime/control-plane/codegraph-cache-retention.ts +0 -164
- package/src/runtime/control-plane/execution/content-equivalent-commit-authority.ts +0 -169
- package/src/runtime/control-plane/execution/direct-canonical-work-reconciliation.ts +0 -85
- package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +0 -655
- package/src/runtime/control-plane/execution/work-finalization-service.ts +0 -2850
- package/src/runtime/control-plane/execution/work-path-scope.ts +0 -37
- package/src/runtime/control-plane/execution/work-task-receipt.ts +0 -468
- package/src/runtime/control-plane/facade/controller-round-relay.ts +0 -3
- package/src/runtime/control-plane/facade/work-admission-policy.ts +0 -142
- package/src/runtime/control-plane/facade/work-implementation-review.ts +0 -2
- package/src/runtime/control-plane/facade/work-state-machine.ts +0 -2
- package/src/runtime/control-plane/facade/work-task-projection.ts +0 -66
- package/src/runtime/control-plane/routing/index.ts +0 -1
- package/src/runtime/control-plane/routing/route-policy.ts +0 -401
- package/src/runtime/control-plane/routing/workspace-admission.ts +0 -70
- package/src/runtime/gateway/mcp/execution-tools.ts +0 -2
- package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +0 -2
- package/src/runtime/gateway/mcp/persisted-check-process.ts +0 -2
- package/src/runtime/gateway/mcp/process-tools.ts +0 -2
- package/src/runtime/gateway/mcp/router.ts +0 -2
- package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +0 -2
- package/src/runtime/gateway/mcp/runtime-tools.ts +0 -2
- package/src/runtime/gateway/mcp/work-validation-reconciler.ts +0 -2
- package/src/runtime/plugins/browser-provider-registry.ts +0 -2
|
@@ -0,0 +1,402 @@
|
|
|
1
|
+
(() => {
|
|
2
|
+
const core = globalThis.ForgeComputerChatgptCore;
|
|
3
|
+
if (!core) throw new Error('FORGE_COMPUTER_CHATGPT_CORE_MISSING');
|
|
4
|
+
// Declarative document_idle loading and exact-tab receiver recovery can race.
|
|
5
|
+
// Install one listener set per document or one Send could be handled twice.
|
|
6
|
+
if (globalThis.__forgeComputerChatgptContentInstalledV1 === true) return;
|
|
7
|
+
globalThis.__forgeComputerChatgptContentInstalledV1 = true;
|
|
8
|
+
const ASSISTANT = '[data-message-author-role="assistant"], [data-chatgpt-search-unit-key$=":assistant"], [data-content-search-unit-key$=":assistant"]';
|
|
9
|
+
const USER = '[data-message-author-role="user"], [data-chatgpt-search-unit-key$=":user"], [data-content-search-unit-key$=":user"]';
|
|
10
|
+
const COMPOSER = '#prompt-textarea, [data-testid="prompt-textarea"], [data-testid="composer-text-input"], textarea[name="prompt"], textarea[placeholder*="Message"], textarea[placeholder*="消息"], form [contenteditable="true"], div[role="textbox"][contenteditable="true"]';
|
|
11
|
+
const SEND = 'button[data-testid="send-button"], button[aria-label*="Send"], button[aria-label*="发送"], button[data-testid*="send"]';
|
|
12
|
+
const STOP = '[data-testid="stop-button"], [data-testid*="stop-button"], button[aria-label="Stop"], button[aria-label="Stop generating"], button[aria-label="停止"], button[aria-label="停止生成"]';
|
|
13
|
+
const TURN = '[data-testid^="conversation-turn-"]';
|
|
14
|
+
const PROVIDER_ACTIVITY_CHARS = 64 * 1024;
|
|
15
|
+
const PROVIDER_FAILURE_CHARS = 250_000;
|
|
16
|
+
const absoluteChatgptUrl = (href) => {
|
|
17
|
+
try { const url = new URL(String(href ?? ''), location.href); return url.protocol === 'https:' && url.hostname === 'chatgpt.com' ? url.toString() : undefined; }
|
|
18
|
+
catch { return undefined; }
|
|
19
|
+
};
|
|
20
|
+
const visible = (node) => Boolean(node?.getClientRects?.().length);
|
|
21
|
+
/**
|
|
22
|
+
* The hydrated conversation surface is the visible `main`. ChatGPT also
|
|
23
|
+
* renders hidden SSR shells, and reading those into role/progress extraction
|
|
24
|
+
* reports turns that the signed-in page is not actually showing.
|
|
25
|
+
*/
|
|
26
|
+
const conversationRoot = () => {
|
|
27
|
+
const mains = Array.from(document.querySelectorAll('main')).filter(visible);
|
|
28
|
+
return mains.length ? mains[mains.length - 1] : document;
|
|
29
|
+
};
|
|
30
|
+
const discoverProjectLinks = (titles) => {
|
|
31
|
+
const wanted = new Map((Array.isArray(titles) ? titles : []).map((title) => [core.normalizeText(title).toLocaleLowerCase(), core.normalizeText(title)]).filter(([key]) => key));
|
|
32
|
+
const seen = new Set();
|
|
33
|
+
const projects = [];
|
|
34
|
+
for (const anchor of document.querySelectorAll('a[href]')) {
|
|
35
|
+
const title = core.normalizeText(anchor.innerText ?? anchor.textContent);
|
|
36
|
+
const matched = wanted.get(title.toLocaleLowerCase());
|
|
37
|
+
const url = absoluteChatgptUrl(anchor.getAttribute('href'));
|
|
38
|
+
if (!matched || !url || seen.has(`${matched}\n${url}`)) continue;
|
|
39
|
+
seen.add(`${matched}\n${url}`);
|
|
40
|
+
projects.push({ title: matched, url });
|
|
41
|
+
}
|
|
42
|
+
return projects;
|
|
43
|
+
};
|
|
44
|
+
const discoverConversationLinks = () => {
|
|
45
|
+
const seen = new Set();
|
|
46
|
+
const conversations = [];
|
|
47
|
+
for (const anchor of document.querySelectorAll('a[href]')) {
|
|
48
|
+
const parsed = core.parseConversation(absoluteChatgptUrl(anchor.getAttribute('href')) ?? '');
|
|
49
|
+
if (!parsed || seen.has(parsed.conversationId)) continue;
|
|
50
|
+
seen.add(parsed.conversationId);
|
|
51
|
+
const title = core.normalizeText(anchor.innerText ?? anchor.textContent);
|
|
52
|
+
conversations.push({ conversationId: parsed.conversationId, canonicalUrl: parsed.canonicalUrl, ...(title ? { title: title.slice(0, 512) } : {}) });
|
|
53
|
+
}
|
|
54
|
+
return conversations;
|
|
55
|
+
};
|
|
56
|
+
const messageText = (node) => {
|
|
57
|
+
if (!node) return '';
|
|
58
|
+
const semanticContent = node.querySelector?.('[data-chatgpt-selection-message-id]');
|
|
59
|
+
// Message line boundaries carry the final Supervisor receipt. Normalizing
|
|
60
|
+
// them like UI labels destroys the protocol before the owner can parse it.
|
|
61
|
+
return String(semanticContent?.innerText ?? semanticContent?.textContent ?? node.innerText ?? node.textContent ?? '').trim();
|
|
62
|
+
};
|
|
63
|
+
const roleNodes = (selector) => {
|
|
64
|
+
const seen = new Set();
|
|
65
|
+
const result = [];
|
|
66
|
+
for (const node of conversationRoot().querySelectorAll(selector)) {
|
|
67
|
+
const semanticKey = String(node.getAttribute?.('data-chatgpt-search-unit-key') || node.getAttribute?.('data-content-search-unit-key') || '');
|
|
68
|
+
const messageIds = String(node.getAttribute?.('data-chatgpt-search-message-ids') || node.getAttribute?.('data-chatgpt-selection-message-id') || '');
|
|
69
|
+
if (semanticKey || messageIds) {
|
|
70
|
+
const key = `${semanticKey}|${messageIds}`;
|
|
71
|
+
if (seen.has(key)) continue;
|
|
72
|
+
seen.add(key);
|
|
73
|
+
}
|
|
74
|
+
result.push(node);
|
|
75
|
+
}
|
|
76
|
+
return result;
|
|
77
|
+
};
|
|
78
|
+
const latestTurnRole = () => {
|
|
79
|
+
const nodes = conversationRoot().querySelectorAll(`${USER}, ${ASSISTANT}`);
|
|
80
|
+
const node = nodes.item(nodes.length - 1);
|
|
81
|
+
const explicit = node?.getAttribute?.('data-message-author-role');
|
|
82
|
+
if (explicit === 'user' || explicit === 'assistant') return explicit;
|
|
83
|
+
const semanticKey = String(node?.getAttribute?.('data-chatgpt-search-unit-key') || node?.getAttribute?.('data-content-search-unit-key') || '');
|
|
84
|
+
if (semanticKey.endsWith(':user')) return 'user';
|
|
85
|
+
if (semanticKey.endsWith(':assistant')) return 'assistant';
|
|
86
|
+
return undefined;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Provider generation evidence. A visible stop/stream control is searched
|
|
90
|
+
* page-wide because missing it would allow a concurrent submission, but it
|
|
91
|
+
* must be *visible*: the previous query accepted hidden SSR controls, and a
|
|
92
|
+
* page-global `aria-busy` also fires for unrelated profile/route loading, so
|
|
93
|
+
* `aria-busy` is trusted only inside the current conversation turn.
|
|
94
|
+
*/
|
|
95
|
+
const isGenerating = () => {
|
|
96
|
+
if (Array.from(document.querySelectorAll(`${STOP}, [data-is-streaming="true"]`)).some(visible)) return true;
|
|
97
|
+
const turns = conversationRoot().querySelectorAll(TURN);
|
|
98
|
+
const current = turns.length ? turns[turns.length - 1] : undefined;
|
|
99
|
+
if (current && Array.from(current.querySelectorAll('[aria-busy="true"]')).some(visible)) return true;
|
|
100
|
+
return latestTurnRole() === 'user';
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Live progress of the running provider turn. The last *committed* assistant
|
|
104
|
+
* answer cannot change while a new turn runs, so liveness has to read the live
|
|
105
|
+
* turn surface. Without it every turn that outlasts the quiet window was
|
|
106
|
+
* misread as stalled and earned a duplicate provider prompt.
|
|
107
|
+
*/
|
|
108
|
+
const providerActivityText = () => {
|
|
109
|
+
const turns = conversationRoot().querySelectorAll(TURN);
|
|
110
|
+
const current = turns.length ? turns[turns.length - 1] : undefined;
|
|
111
|
+
return core.normalizeText(current?.innerText ?? current?.textContent).slice(-PROVIDER_ACTIVITY_CHARS);
|
|
112
|
+
};
|
|
113
|
+
const providerFailureText = () => {
|
|
114
|
+
// The conversation-capacity banner is not always an ARIA alert.
|
|
115
|
+
// Read visible, short, non-message status nodes only; ordinary conversation
|
|
116
|
+
// history must never be interpreted as a current provider failure.
|
|
117
|
+
const status = Array.from(document.querySelectorAll('[role="alert"], [role="status"], [aria-live="assertive"], [aria-live="polite"]'))
|
|
118
|
+
.filter(visible);
|
|
119
|
+
const capacity = Array.from(conversationRoot().querySelectorAll('p, span, div'))
|
|
120
|
+
// Exclude message subtrees before layout-dependent visibility reads.
|
|
121
|
+
.filter((node) => !node.closest(TURN) && !node.closest('[data-message-author-role]') && visible(node))
|
|
122
|
+
.filter((node) => {
|
|
123
|
+
const text = core.normalizeText(node.innerText ?? node.textContent);
|
|
124
|
+
return text.length <= 250 && /(?:你已达到此对话的长度上限|此对话已达到长度上限|you(?:'ve| have) reached the (?:maximum length for this conversation|conversation length limit)|this conversation has reached its maximum length)/i.test(text);
|
|
125
|
+
});
|
|
126
|
+
return [...status, ...capacity]
|
|
127
|
+
.map((node) => core.normalizeText(node.innerText ?? node.textContent))
|
|
128
|
+
.filter(Boolean).slice(-8).join('\n').slice(-PROVIDER_FAILURE_CHARS);
|
|
129
|
+
};
|
|
130
|
+
// Project pages can retain hidden SSR editors beside the live hydrated one.
|
|
131
|
+
// Resolve one visible editor, preferring the active main, or fail closed:
|
|
132
|
+
// a hidden editor's draft is not proof that the task-owned composer is busy.
|
|
133
|
+
const composer = () => {
|
|
134
|
+
const visibleEditors = Array.from(document.querySelectorAll(COMPOSER))
|
|
135
|
+
.filter((node) => visible(node) && !node.closest?.('[aria-hidden="true"], [hidden], [inert]'));
|
|
136
|
+
const root = conversationRoot();
|
|
137
|
+
const inMain = root === document ? [] : visibleEditors.filter((node) => root.contains?.(node));
|
|
138
|
+
const candidates = inMain.length ? inMain : visibleEditors;
|
|
139
|
+
return candidates.length === 1 ? candidates[0] : undefined;
|
|
140
|
+
};
|
|
141
|
+
// Editor text is a provider payload, not a UI label: preserve its whitespace.
|
|
142
|
+
const exactComposerText = (value) => String(value ?? '').replace(/\r\n?/g, '\n');
|
|
143
|
+
const composerText = (editor = composer()) => {
|
|
144
|
+
const blocks = editor?.isContentEditable ? Array.from(editor.children ?? []) : [];
|
|
145
|
+
// ChatGPT's ProseMirror writes one P block per entered newline but
|
|
146
|
+
// HTMLElement.innerText synthesizes TWO newlines between those blocks.
|
|
147
|
+
// Reconstruct the actual editor payload from its direct paragraphs rather
|
|
148
|
+
// than comparing synthetic layout whitespace to an immutable effect.
|
|
149
|
+
const observed = blocks.length > 0 && blocks.every((block) => block.tagName === 'P')
|
|
150
|
+
? blocks.map((block) => {
|
|
151
|
+
// innerText may insert a *visual* newline around auto-linked URLs or
|
|
152
|
+
// inline styled descendants even inside one ProseMirror paragraph.
|
|
153
|
+
// One direct <p> is one actual editor line: read its text nodes.
|
|
154
|
+
const value = exactComposerText(block.textContent ?? block.innerText);
|
|
155
|
+
return !value.trim() ? '' : value;
|
|
156
|
+
}).join('\n')
|
|
157
|
+
: editor?.value ?? editor?.innerText ?? editor?.textContent;
|
|
158
|
+
const text = exactComposerText(observed);
|
|
159
|
+
// Only whitespace-only *empty* editors collapse; all nonblank text,
|
|
160
|
+
// including leading/trailing spaces and intentional blank lines, remains
|
|
161
|
+
// byte-for-byte subject only to CRLF normalization.
|
|
162
|
+
return text.trim() ? text : '';
|
|
163
|
+
};
|
|
164
|
+
const pageSnapshot = (options = {}) => {
|
|
165
|
+
const userNodes = roleNodes(USER);
|
|
166
|
+
const assistantNodes = roleNodes(ASSISTANT);
|
|
167
|
+
// Reading innerText on the entire page can force layout on every poll.
|
|
168
|
+
// Only collect it when a caller explicitly requests the full page.
|
|
169
|
+
const editor = composer();
|
|
170
|
+
return {
|
|
171
|
+
url: location.href,
|
|
172
|
+
title: document.title,
|
|
173
|
+
latestUserText: messageText(userNodes[userNodes.length - 1]),
|
|
174
|
+
latestAssistantResponse: messageText(assistantNodes[assistantNodes.length - 1]),
|
|
175
|
+
...(options.includeUserHistory === true ? {
|
|
176
|
+
userMessages: userNodes.map(messageText).filter(Boolean),
|
|
177
|
+
assistantMessages: assistantNodes.map(messageText).filter(Boolean),
|
|
178
|
+
} : {}),
|
|
179
|
+
...(editor ? { composerText: composerText(editor) } : {}),
|
|
180
|
+
composerSelectorVersion: 'visible-single-v2',
|
|
181
|
+
composerReplacementContract: 'exact-backed-up-project-draft-v1',
|
|
182
|
+
// Read-only hydration attestation for a NEW Project bootstrap tab.
|
|
183
|
+
// URL/DOM shell visibility alone cannot prove that the React model
|
|
184
|
+
// picker has mounted or that the provider editor is send-ready.
|
|
185
|
+
providerActivityText: providerActivityText(),
|
|
186
|
+
providerFailureText: providerFailureText(),
|
|
187
|
+
...(options.includePageText === true ? { pageText: String(document.body?.innerText ?? '').slice(-500000) } : {}),
|
|
188
|
+
latestTurnRole: latestTurnRole(),
|
|
189
|
+
isGenerating: isGenerating(),
|
|
190
|
+
};
|
|
191
|
+
};
|
|
192
|
+
const writeComposer = (node, prompt) => {
|
|
193
|
+
node.focus();
|
|
194
|
+
if (node instanceof HTMLTextAreaElement || node instanceof HTMLInputElement) {
|
|
195
|
+
const prototype = node instanceof HTMLTextAreaElement ? HTMLTextAreaElement.prototype : HTMLInputElement.prototype;
|
|
196
|
+
const setter = Object.getOwnPropertyDescriptor(prototype, 'value')?.set;
|
|
197
|
+
if (setter) setter.call(node, prompt); else node.value = prompt;
|
|
198
|
+
node.dispatchEvent(new InputEvent('input', { bubbles: true, inputType: 'insertText', data: prompt }));
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (node.isContentEditable) {
|
|
202
|
+
const selection = window.getSelection();
|
|
203
|
+
const range = document.createRange();
|
|
204
|
+
range.selectNodeContents(node);
|
|
205
|
+
selection?.removeAllRanges();
|
|
206
|
+
selection?.addRange(range);
|
|
207
|
+
if (!document.execCommand('insertText', false, prompt)) {
|
|
208
|
+
node.textContent = prompt;
|
|
209
|
+
node.dispatchEvent(new InputEvent('input', { bubbles: true, inputType: 'insertText', data: prompt }));
|
|
210
|
+
}
|
|
211
|
+
selection?.removeAllRanges();
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
const dispatchPrompt = async (prompt, mode = 'send', expectedConversationId, prepareOnly = false, expectedProjectId) => {
|
|
215
|
+
const exactConversationIsCurrent = () => expectedConversationId
|
|
216
|
+
? core.parseConversation(location.href)?.conversationId === expectedConversationId
|
|
217
|
+
: expectedProjectId ? core.projectId(location.href) === expectedProjectId && !core.parseConversation(location.href)
|
|
218
|
+
: true;
|
|
219
|
+
if (!exactConversationIsCurrent()) return { dispatched: false, reason: 'target_identity_changed' };
|
|
220
|
+
if (typeof prompt !== 'string' || !prompt.trim()) return { dispatched: false, reason: 'prompt_required' };
|
|
221
|
+
// This bounded prepare-only envelope is produced by the canonical
|
|
222
|
+
// Supervisor only after an exact 0600 on-device backup and operator marker.
|
|
223
|
+
// It is never part of a sent effect and never authorizes another provider.
|
|
224
|
+
const replacement = /^<<<FORGE_DRAFT_REPLACE_V1:([a-f0-9]{24}):([a-f0-9]{32})>>>\n/.exec(prompt);
|
|
225
|
+
if (replacement && (!prepareOnly || !expectedProjectId || mode !== 'send')) {
|
|
226
|
+
return { dispatched: false, reason: 'composer_replacement_mode_invalid' };
|
|
227
|
+
}
|
|
228
|
+
// Prepare-only exact retirement; never submits or retries the stopped task.
|
|
229
|
+
const retired = /^<<<FORGE_RETIRED_DRAFT_V1:((?:fx|crpe)_[a-zA-Z0-9_-]{8,120}):([a-f0-9]{24})>>>\n/.exec(prompt);
|
|
230
|
+
if (retired && (!prepareOnly || !expectedProjectId || mode !== 'send' || replacement)) {
|
|
231
|
+
return { dispatched: false, reason: 'composer_replacement_mode_invalid' };
|
|
232
|
+
}
|
|
233
|
+
const actualPrompt = replacement ? prompt.slice(replacement[0].length)
|
|
234
|
+
: retired ? prompt.slice(retired[0].length) : prompt;
|
|
235
|
+
if (mode === 'recover') {
|
|
236
|
+
const stop = document.querySelector(STOP);
|
|
237
|
+
if (prepareOnly && stop instanceof HTMLElement) return { prepared: false, reason: 'provider_recovery_stop_pending' };
|
|
238
|
+
if (stop instanceof HTMLElement) {
|
|
239
|
+
if (!exactConversationIsCurrent()) return { dispatched: false, reason: 'target_identity_changed' };
|
|
240
|
+
stop.click();
|
|
241
|
+
for (let attempt = 0; attempt < 20 && document.querySelector(STOP); attempt += 1) {
|
|
242
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
243
|
+
if (!exactConversationIsCurrent()) return { dispatched: false, reason: 'target_identity_changed' };
|
|
244
|
+
}
|
|
245
|
+
if (document.querySelector(STOP)) return { dispatched: false, reason: 'provider_recovery_stop_unconfirmed' };
|
|
246
|
+
}
|
|
247
|
+
} else if (isGenerating()) return { dispatched: false, reason: 'provider_busy' };
|
|
248
|
+
const node = composer();
|
|
249
|
+
if (!node) return { dispatched: false, reason: 'composer_missing' };
|
|
250
|
+
// Project instructions select tools. No @forge UI mention is needed.
|
|
251
|
+
const supervisor = /^(?:@forge\s+)?<<<FORGE_WORKFLOW_EFFECT_V1:(?:fx|crpe)_[a-zA-Z0-9_-]{8,120}>>>/.test(actualPrompt);
|
|
252
|
+
if (supervisor && !expectedConversationId && !expectedProjectId) return { dispatched: false, reason: 'target_identity_unavailable' };
|
|
253
|
+
// Strip only the exact legacy prefix on already-durable effects.
|
|
254
|
+
const payload = supervisor ? actualPrompt.replace(/^@forge\s+(?=<<<FORGE_WORKFLOW_EFFECT_V1:(?:fx|crpe)_[a-zA-Z0-9_-]{8,120}>>>)/, '') : actualPrompt;
|
|
255
|
+
const expected = exactComposerText(payload);
|
|
256
|
+
const existing = composerText();
|
|
257
|
+
// A restored draft belongs to this effect only when it matches precisely.
|
|
258
|
+
// Never overwrite another task's draft or a human-authored message.
|
|
259
|
+
const ownedDrafts = supervisor
|
|
260
|
+
? [expected, expected + '\n', exactComposerText(payload + '\n@'), exactComposerText(payload + '\nforge'), exactComposerText('forge ' + payload)]
|
|
261
|
+
: [expected];
|
|
262
|
+
if (node.querySelector('[plugin-mention-name], [app-mention-name]')) return { dispatched: false, reason: 'composer_has_app_mention' };
|
|
263
|
+
const unowned = Boolean(existing && !ownedDrafts.includes(existing));
|
|
264
|
+
if (unowned && ((!replacement && !retired) || !supervisor)) return { dispatched: false, reason: 'composer_not_empty' };
|
|
265
|
+
if (retired && (!unowned || !existing.startsWith(`<<<FORGE_WORKFLOW_EFFECT_V1:${retired[1]}>>>`))) {
|
|
266
|
+
return { dispatched: false, reason: 'composer_not_empty' };
|
|
267
|
+
}
|
|
268
|
+
if (unowned) {
|
|
269
|
+
// Hash the *currently visible* single editor, not the page or another
|
|
270
|
+
// tab. If it changed since the backup, do not touch it.
|
|
271
|
+
if (!globalThis.crypto?.subtle || !globalThis.TextEncoder) return { dispatched: false, reason: 'composer_replacement_digest_unavailable' };
|
|
272
|
+
const bytes = new TextEncoder().encode('preflight-composer-v1:\0' + existing);
|
|
273
|
+
const digest = new Uint8Array(await crypto.subtle.digest('SHA-256', bytes));
|
|
274
|
+
const prefix = Array.from(digest).map((byte) => byte.toString(16).padStart(2, '0')).join('').slice(0, 24);
|
|
275
|
+
if (prefix !== (replacement ? replacement[1] : retired?.[2])) return { dispatched: false, reason: 'composer_not_empty' };
|
|
276
|
+
}
|
|
277
|
+
if (!exactConversationIsCurrent()) return { dispatched: false, reason: 'target_identity_changed' };
|
|
278
|
+
// Hashing and model-picker hydration yield to page/user edits. Revalidate
|
|
279
|
+
// the same single editor before overwriting any bytes observed above.
|
|
280
|
+
if (composer() !== node || composerText(node) !== existing) return { dispatched: false, reason: 'composer_not_empty' };
|
|
281
|
+
if (existing !== expected && existing !== expected + '\n') writeComposer(node, payload);
|
|
282
|
+
// React may acknowledge the exact draft before it enables Send. Observe
|
|
283
|
+
// this same target for at most two seconds, below the broker deadline;
|
|
284
|
+
// this is read-only readiness, never another write or Send attempt.
|
|
285
|
+
const ready = await new Promise((resolve) => {
|
|
286
|
+
let timer;
|
|
287
|
+
let settled = false;
|
|
288
|
+
const finish = (value) => {
|
|
289
|
+
if (settled) return;
|
|
290
|
+
settled = true;
|
|
291
|
+
observer.disconnect();
|
|
292
|
+
document.removeEventListener('input', check, true);
|
|
293
|
+
clearTimeout(timer);
|
|
294
|
+
resolve(value);
|
|
295
|
+
};
|
|
296
|
+
const check = (expired = false) => {
|
|
297
|
+
if (!exactConversationIsCurrent()) { finish({ reason: 'target_identity_changed' }); return; }
|
|
298
|
+
// ProseMirror may expose one editor-generated final newline. Do not
|
|
299
|
+
// widen matching beyond that break or tolerate another visible draft.
|
|
300
|
+
const text = composerText();
|
|
301
|
+
if (text !== expected && text !== expected + '\n') { finish({ reason: 'composer_write_unconfirmed' }); return; }
|
|
302
|
+
if (isGenerating()) { finish({ reason: 'provider_busy' }); return; }
|
|
303
|
+
const buttons = Array.from(document.querySelectorAll(SEND)).filter(visible);
|
|
304
|
+
const send = buttons.length === 1 ? buttons[0] : undefined;
|
|
305
|
+
if (send && !send.disabled && send.getAttribute('aria-disabled') !== 'true') { finish({ send }); return; }
|
|
306
|
+
if (expired === true) finish({ reason: send ? 'send_button_disabled' : 'send_button_missing' });
|
|
307
|
+
};
|
|
308
|
+
const observer = new MutationObserver(() => check());
|
|
309
|
+
observer.observe(document.documentElement, { childList: true, subtree: true, characterData: true, attributes: true });
|
|
310
|
+
document.addEventListener('input', check, true);
|
|
311
|
+
timer = setTimeout(() => check(true), 2_000);
|
|
312
|
+
check();
|
|
313
|
+
});
|
|
314
|
+
if (!ready.send) return { dispatched: false, reason: ready.reason };
|
|
315
|
+
// Await resumes in a new microtask: retain the exact pre-click fences even
|
|
316
|
+
// if an input/route update was queued alongside the readiness observation.
|
|
317
|
+
if (!exactConversationIsCurrent()) return { dispatched: false, reason: 'target_identity_changed' };
|
|
318
|
+
const text = composerText();
|
|
319
|
+
if (text !== expected && text !== expected + '\n') return { dispatched: false, reason: 'composer_write_unconfirmed' };
|
|
320
|
+
if (isGenerating()) return { dispatched: false, reason: 'provider_busy' };
|
|
321
|
+
const send = ready.send;
|
|
322
|
+
if (!send.isConnected || !visible(send)) return { dispatched: false, reason: 'send_button_missing' };
|
|
323
|
+
if (send.disabled || send.getAttribute('aria-disabled') === 'true') return { dispatched: false, reason: 'send_button_disabled' };
|
|
324
|
+
if (prepareOnly) return { prepared: true };
|
|
325
|
+
// Confirm the committed turn inside the content script, rather than
|
|
326
|
+
// requesting delayed snapshots from the extension background worker.
|
|
327
|
+
const beforeSend = roleNodes(USER).at(-1);
|
|
328
|
+
// Once click starts, an exception cannot prove that the provider did not
|
|
329
|
+
// receive the message. Keep post-click observation failures outcome-unknown.
|
|
330
|
+
try {
|
|
331
|
+
send.click();
|
|
332
|
+
const confirmed = await new Promise((resolve) => {
|
|
333
|
+
// Unobserved submission is unknown, never proof that Send did not run.
|
|
334
|
+
let timer;
|
|
335
|
+
let settled = false;
|
|
336
|
+
const finish = (value) => {
|
|
337
|
+
if (settled) return;
|
|
338
|
+
settled = true;
|
|
339
|
+
observer.disconnect();
|
|
340
|
+
clearTimeout(timer);
|
|
341
|
+
resolve(value);
|
|
342
|
+
};
|
|
343
|
+
const check = () => {
|
|
344
|
+
if (expectedConversationId && !exactConversationIsCurrent()) return;
|
|
345
|
+
const latest = roleNodes(USER).at(-1);
|
|
346
|
+
if (latest && latest !== beforeSend
|
|
347
|
+
&& exactComposerText(messageText(latest)) === expected) finish(true);
|
|
348
|
+
};
|
|
349
|
+
const observer = new MutationObserver(check);
|
|
350
|
+
observer.observe(document.documentElement, { childList: true, subtree: true, characterData: true });
|
|
351
|
+
timer = setTimeout(() => finish(false), 2_000);
|
|
352
|
+
check();
|
|
353
|
+
});
|
|
354
|
+
return { dispatched: true, confirmed };
|
|
355
|
+
} catch {
|
|
356
|
+
return { dispatched: true, confirmed: false };
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
|
|
360
|
+
if (!message || message.type === 'forge-computer-chatgpt-scan') { notify(); sendResponse?.({ ok: true }); return false; }
|
|
361
|
+
if (message.type === 'forge-computer-chatgpt-discovery-scan') {
|
|
362
|
+
sendResponse({ projects: discoverProjectLinks(message.projectTitles), conversations: discoverConversationLinks(), pageUrl: location.href });
|
|
363
|
+
return false;
|
|
364
|
+
}
|
|
365
|
+
if (message.type === 'forge-computer-chatgpt-snapshot') { sendResponse(pageSnapshot(message.options ?? {})); return false; }
|
|
366
|
+
// Read-only exact-tab attestation for bootstrap/draft target guards.
|
|
367
|
+
if (message.type === 'forge-computer-chatgpt-capabilities') {
|
|
368
|
+
sendResponse({ bootstrapTargetGuard: 'project-checked-before-send-v1',
|
|
369
|
+
composerReplacementContract: 'exact-backed-up-project-draft-v1' });
|
|
370
|
+
return false;
|
|
371
|
+
}
|
|
372
|
+
if (message.type === 'forge-computer-chatgpt-prepare') {
|
|
373
|
+
dispatchPrompt(String(message.prompt ?? ''), String(message.mode ?? 'send'), message.expectedConversationId, true, message.expectedProjectId)
|
|
374
|
+
.then((result) => sendResponse(result?.prepared === true
|
|
375
|
+
? { prepared: true }
|
|
376
|
+
: { prepared: false, reason: String(result?.reason ?? 'COMPUTER_CHATGPT_PREPARE_REJECTED') }),
|
|
377
|
+
(error) => sendResponse({ prepared: false, reason: String(error?.message ?? error) }));
|
|
378
|
+
return true;
|
|
379
|
+
}
|
|
380
|
+
if (message.type === 'forge-computer-chatgpt-dispatch') {
|
|
381
|
+
dispatchPrompt(String(message.prompt ?? ''), String(message.mode ?? 'send'), message.expectedConversationId, false, message.expectedProjectId)
|
|
382
|
+
.then(sendResponse, (error) => sendResponse({ dispatched: false, reason: String(error?.message ?? error) }));
|
|
383
|
+
return true;
|
|
384
|
+
}
|
|
385
|
+
return false;
|
|
386
|
+
});
|
|
387
|
+
let timer;
|
|
388
|
+
function notify() {
|
|
389
|
+
clearTimeout(timer);
|
|
390
|
+
timer = setTimeout(() => {
|
|
391
|
+
const current = core.parseConversation(location.href);
|
|
392
|
+
chrome.runtime.sendMessage({
|
|
393
|
+
type: 'forge-computer-chatgpt-page',
|
|
394
|
+
...(current ?? {}),
|
|
395
|
+
pageUrl: location.href,
|
|
396
|
+
isGenerating: isGenerating(),
|
|
397
|
+
}, () => void chrome.runtime.lastError);
|
|
398
|
+
}, 200);
|
|
399
|
+
}
|
|
400
|
+
new MutationObserver(notify).observe(document.documentElement, { subtree: true, childList: true, characterData: true });
|
|
401
|
+
notify();
|
|
402
|
+
})();
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
(() => {
|
|
2
|
+
function normalizeText(value) { return String(value ?? '').replace(/\s+/g, ' ').trim(); }
|
|
3
|
+
function parseConversation(value) {
|
|
4
|
+
try {
|
|
5
|
+
const url = new URL(value);
|
|
6
|
+
if (url.protocol !== 'https:' || url.hostname !== 'chatgpt.com') return null;
|
|
7
|
+
const segments = url.pathname.split('/').filter(Boolean);
|
|
8
|
+
const marker = segments.lastIndexOf('c');
|
|
9
|
+
if (marker < 0 || marker + 2 !== segments.length) return null;
|
|
10
|
+
const conversationId = String(segments[marker + 1] ?? '').trim();
|
|
11
|
+
if (!conversationId || conversationId.length > 256) return null;
|
|
12
|
+
return { conversationId, canonicalUrl: `https://chatgpt.com/${segments.join('/')}` };
|
|
13
|
+
} catch { return null; }
|
|
14
|
+
}
|
|
15
|
+
function projectId(value) {
|
|
16
|
+
try {
|
|
17
|
+
const url = new URL(value);
|
|
18
|
+
if (url.protocol !== 'https:' || url.hostname !== 'chatgpt.com') return null;
|
|
19
|
+
return /^\/g\/(g-p-[a-z0-9]+)(?:-[^/]+)?\/(?:project\/?|c\/[^/]+\/?)$/i.exec(url.pathname)?.[1]?.toLowerCase() ?? null;
|
|
20
|
+
} catch { return null; }
|
|
21
|
+
}
|
|
22
|
+
function sameConversation(a, b) { return Boolean(a && b && a.conversationId === b.conversationId); }
|
|
23
|
+
globalThis.ForgeComputerChatgptCore = Object.freeze({ normalizeText, parseConversation, projectId, sameConversation });
|
|
24
|
+
})();
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"manifest_version": 3,
|
|
3
|
+
"name": "Forge Computer ChatGPT Provider",
|
|
4
|
+
"version": "0.3.3",
|
|
5
|
+
"description": "Computer-owned stable ChatGPT target provider for Forge Runtime.",
|
|
6
|
+
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxFzo1eixjsWsZbN1pBuyzdKinJSAAuzTRavD0xFQFwrTIEQ7hxxueEBEhifpGq9nplNnmxmZvIL7PJycEAYT8mrbyXBLCPR1jQBuL4YR775phnlNVpF3dHX5OWDHLWRnHRgOO1FibQ54fM2rKylr66+x+J6/4C7a9dpiSMuxf3fOStXA6wJb0d7A4E22Q1+GGfWgs0NCyVI5k4aczK+J5Ao61ZXKBr8Qw/FCmwhCcDgQdIpURgoMHkyvQH3ryYWocucjRhMVsU8H65adIIKFHkEhPJCiVY64L6bu6kNR2fpf0yJ1GvI5ota6Hf4NAEi7Yt7PL7i3ISyv3pPQWW1nIwIDAQAB",
|
|
7
|
+
"permissions": [
|
|
8
|
+
"nativeMessaging",
|
|
9
|
+
"storage",
|
|
10
|
+
"tabs",
|
|
11
|
+
"scripting",
|
|
12
|
+
"alarms"
|
|
13
|
+
],
|
|
14
|
+
"host_permissions": [
|
|
15
|
+
"https://chatgpt.com/*"
|
|
16
|
+
],
|
|
17
|
+
"background": {
|
|
18
|
+
"service_worker": "background.js"
|
|
19
|
+
},
|
|
20
|
+
"content_scripts": [
|
|
21
|
+
{
|
|
22
|
+
"matches": [
|
|
23
|
+
"https://chatgpt.com/*"
|
|
24
|
+
],
|
|
25
|
+
"js": [
|
|
26
|
+
"core.js",
|
|
27
|
+
"content.js"
|
|
28
|
+
],
|
|
29
|
+
"run_at": "document_idle"
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
}
|
|
@@ -20,12 +20,11 @@ import {
|
|
|
20
20
|
} from './desktop-operator-contract';
|
|
21
21
|
|
|
22
22
|
export const DESKTOP_OPERATOR_MAX_RESPONSE_BYTES = 4 * 1_048_576;
|
|
23
|
-
const LEGACY_REGISTRATION_CAPABILITIES = ['desktop.observe', 'desktop.interact', 'desktop.capture'] as const;
|
|
24
23
|
let testSocketPath: string | undefined;
|
|
25
24
|
|
|
26
25
|
export interface DesktopOperatorComputerEndpoint {
|
|
27
26
|
socketPath: string;
|
|
28
|
-
source: 'registration' | '
|
|
27
|
+
source: 'registration' | 'test_override';
|
|
29
28
|
healthTimeoutMs: number;
|
|
30
29
|
actionTimeoutMs: number;
|
|
31
30
|
maxResponseBytes: number;
|
|
@@ -33,11 +32,8 @@ export interface DesktopOperatorComputerEndpoint {
|
|
|
33
32
|
capabilityIds: ComputerRuntimeProviderCapabilityId[];
|
|
34
33
|
}
|
|
35
34
|
|
|
36
|
-
export type DesktopOperatorLegacyFallbackMode = 'disabled' | 'unregistered_v0_2';
|
|
37
|
-
|
|
38
35
|
export interface DesktopOperatorComputerProviderOptions {
|
|
39
36
|
lookupRegistration?: ComputerProviderRegistrationLookup;
|
|
40
|
-
legacyFallback?: DesktopOperatorLegacyFallbackMode;
|
|
41
37
|
}
|
|
42
38
|
|
|
43
39
|
export function desktopOperatorComputerSocketPath(accountHome = process.env.HOME?.trim() || homedir()): string {
|
|
@@ -95,16 +91,14 @@ function declaredComputerCapabilities(
|
|
|
95
91
|
COMPUTER_ELEMENT_OBSERVE_CAPABILITY,
|
|
96
92
|
COMPUTER_ELEMENT_ACTION_CAPABILITY,
|
|
97
93
|
].filter((capability): capability is ComputerRuntimeProviderCapabilityId => capabilityIds.has(capability));
|
|
98
|
-
|
|
99
|
-
if (recognized.length === 0 && !legacyRegistrationCompatible) {
|
|
94
|
+
if (recognized.length === 0) {
|
|
100
95
|
throw new ComputerProviderError(
|
|
101
96
|
'PLUGIN_COMPUTER_PROVIDER_CAPABILITY_UNDECLARED',
|
|
102
|
-
'Forge Desktop Operator registration does not declare a supported Computer capability
|
|
97
|
+
'Forge Desktop Operator registration does not declare a supported Unified Computer capability.',
|
|
103
98
|
{
|
|
104
99
|
retryable: false,
|
|
105
100
|
details: {
|
|
106
101
|
supportedComputerCapabilities: [COMPUTER_OBSERVE_CAPABILITY, COMPUTER_INPUT_CAPABILITY, COMPUTER_CONSOLE_UNLOCK_CAPABILITY, COMPUTER_CAPTURE_CAPABILITY, COMPUTER_ELEMENT_OBSERVE_CAPABILITY, COMPUTER_ELEMENT_ACTION_CAPABILITY],
|
|
107
|
-
legacyRequiredCapabilities: [...LEGACY_REGISTRATION_CAPABILITIES],
|
|
108
102
|
registrationRevision: registration.revision,
|
|
109
103
|
},
|
|
110
104
|
},
|
|
@@ -161,27 +155,14 @@ export function resolveDesktopOperatorComputerEndpoint(
|
|
|
161
155
|
const registered = registeredEndpoint(options.lookupRegistration);
|
|
162
156
|
if (registered) return registered;
|
|
163
157
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
legacyFallback: options.legacyFallback ?? 'disabled',
|
|
173
|
-
},
|
|
174
|
-
},
|
|
175
|
-
);
|
|
176
|
-
}
|
|
177
|
-
return {
|
|
178
|
-
socketPath: desktopOperatorComputerSocketPath(),
|
|
179
|
-
source: 'legacy_fallback',
|
|
180
|
-
healthTimeoutMs: 2_000,
|
|
181
|
-
actionTimeoutMs: 30_000,
|
|
182
|
-
maxResponseBytes: DESKTOP_OPERATOR_MAX_RESPONSE_BYTES,
|
|
183
|
-
capabilityIds: [],
|
|
184
|
-
};
|
|
158
|
+
throw new ComputerProviderError(
|
|
159
|
+
'PLUGIN_COMPUTER_PROVIDER_REGISTRATION_REQUIRED',
|
|
160
|
+
'Computer provider registration is required before Forge can use the Desktop Operator.',
|
|
161
|
+
{
|
|
162
|
+
retryable: false,
|
|
163
|
+
details: { providerPluginId: DESKTOP_OPERATOR_PROVIDER_PLUGIN_ID },
|
|
164
|
+
},
|
|
165
|
+
);
|
|
185
166
|
}
|
|
186
167
|
|
|
187
168
|
export function desktopOperatorComputerProviderCapabilities(
|
|
@@ -192,7 +173,6 @@ export function desktopOperatorComputerProviderCapabilities(
|
|
|
192
173
|
const registration = readRegisteredProvider(options.lookupRegistration);
|
|
193
174
|
if (registration) return declaredComputerCapabilities(registration);
|
|
194
175
|
}
|
|
195
|
-
if (options.legacyFallback === 'unregistered_v0_2') return [];
|
|
196
176
|
throw new ComputerProviderError(
|
|
197
177
|
'PLUGIN_COMPUTER_PROVIDER_REGISTRATION_REQUIRED',
|
|
198
178
|
'Computer provider registration is required before capabilities can be declared.',
|
|
@@ -290,22 +290,34 @@ export async function callDesktopOperatorComputerBrowserAutomation(
|
|
|
290
290
|
export function createDesktopOperatorComputerProvider(
|
|
291
291
|
options: DesktopOperatorComputerProviderOptions = {},
|
|
292
292
|
): DesktopOperatorComputerProvider {
|
|
293
|
-
let active: { key: string; binding: DesktopOperatorComputerBinding } | undefined;
|
|
294
|
-
const binding = (): DesktopOperatorComputerBinding => {
|
|
293
|
+
let active: { key: string; binding: DesktopOperatorComputerBinding; observations?: DesktopOperatorComputerBinding } | undefined;
|
|
294
|
+
const binding = (observation = false): DesktopOperatorComputerBinding => {
|
|
295
295
|
const endpoint = resolveDesktopOperatorComputerEndpoint(options);
|
|
296
296
|
const key = endpointBindingKey(endpoint);
|
|
297
|
-
if (active?.key
|
|
298
|
-
|
|
299
|
-
|
|
297
|
+
if (active?.key !== key) {
|
|
298
|
+
active?.binding.close();
|
|
299
|
+
active?.observations?.close();
|
|
300
|
+
active = { key, binding: createBinding(endpoint) };
|
|
301
|
+
}
|
|
302
|
+
// Desktop Operator executes RPCs serially within each socket connection.
|
|
303
|
+
// A slow Browser RPC must not head-of-line block native snapshots/capture.
|
|
304
|
+
// Keep all input, console and legacy Browser requests on their original
|
|
305
|
+
// ordered stream; target/session locks still serialize observation epochs.
|
|
306
|
+
if (observation) return active.observations ??= createBinding(endpoint);
|
|
300
307
|
return active.binding;
|
|
301
308
|
};
|
|
302
309
|
return {
|
|
303
310
|
providerId: DESKTOP_OPERATOR_PROVIDER_PLUGIN_ID,
|
|
304
311
|
capabilities: desktopOperatorComputerProviderCapabilities(options),
|
|
305
|
-
execute: async (request, timeoutMs) => await binding(
|
|
312
|
+
execute: async (request, timeoutMs) => await binding(
|
|
313
|
+
request.capability === COMPUTER_OBSERVE_CAPABILITY
|
|
314
|
+
|| request.capability === COMPUTER_ELEMENT_OBSERVE_CAPABILITY
|
|
315
|
+
|| request.capability === COMPUTER_CAPTURE_CAPABILITY,
|
|
316
|
+
).execute(request, timeoutMs),
|
|
306
317
|
executeBrowserCompatibility: async (request, timeoutMs) => await binding().executeBrowserCompatibility(request, timeoutMs),
|
|
307
318
|
dispose: () => {
|
|
308
319
|
active?.binding.close();
|
|
320
|
+
active?.observations?.close();
|
|
309
321
|
active = undefined;
|
|
310
322
|
},
|
|
311
323
|
};
|