@moretea-labs/forge 1.6.0 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +4 -0
- package/CHANGELOG.md +39 -0
- package/CLAUDE.md +4 -0
- package/README.md +2 -2
- package/README.zh-CN.md +1 -1
- package/SKILL.md +2 -2
- package/THIRD_PARTY_NOTICES.md +1 -1
- package/agents/openai.yaml +1 -1
- package/assets/hooks/hook-input.sh +11 -8
- package/assets/hooks/lib/session-state.sh +10 -7
- package/assets/hooks/lib/workflow-state.sh +13 -177
- package/assets/hooks/post-tool-observer.sh +8 -2
- package/assets/hooks/prompt-guard.sh +5 -81
- package/assets/hooks/session-start-context.sh +56 -1
- package/assets/partials/05-workflow.partial.md +1 -1
- package/assets/partials-agents/02-operating-mode.partial.md +2 -0
- package/assets/partials-agents/03-orchestration.partial.md +1 -1
- package/assets/plugin-registry.v1.json +3 -3
- package/assets/reference-configs/document-generation.md +1 -1
- package/assets/reference-configs/harness-overview.md +1 -1
- package/assets/reference-configs/sprint-contracts.md +3 -3
- package/assets/skill-version.json +2 -2
- package/assets/templates/contract.template.md +2 -7
- package/assets/templates/helpers/capture-plan.sh +2 -2
- package/assets/templates/helpers/check-architecture-sync.sh +17 -0
- package/assets/templates/helpers/check-task-workflow.sh +4 -4
- package/assets/templates/helpers/contract-worktree.sh +1 -21
- package/assets/templates/helpers/ensure-task-workflow.sh +11 -36
- package/assets/templates/helpers/inspect-project-state.ts +8 -6
- package/assets/templates/helpers/migrate-project-template.sh +22 -45
- package/assets/templates/helpers/migrate-workflow-docs.ts +9 -7
- package/assets/templates/helpers/new-plan.sh +1 -1
- package/assets/templates/helpers/plan-to-todo.sh +12 -37
- package/assets/templates/helpers/ship-worktrees.sh +2 -29
- package/assets/templates/helpers/verify-contract.sh +1 -111
- package/assets/templates/helpers/verify-sprint.sh +3 -180
- package/assets/templates/helpers/workflow-contract.ts +5 -1
- package/assets/templates/plan.template.md +1 -1
- package/assets/templates/review.template.md +9 -34
- package/assets/workflow-contract.v1.json +10 -19
- package/docs/README.md +10 -10
- package/docs/architecture/CURRENT.md +178 -0
- package/docs/architecture/EVOLUTION.md +42 -0
- package/docs/architecture/current/README.md +4 -156
- package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +2 -2
- package/docs/architecture/decisions/20260823-immediate-controller-relay.md +53 -0
- package/docs/architecture/decisions/20260826-browser-runtime-v2.md +73 -0
- package/docs/architecture/history/README.md +7 -0
- package/docs/architecture/{chatgpt-handoff-facade.md → history/chatgpt-handoff-facade.md} +4 -0
- package/docs/architecture/{global-hook-runtime.md → history/global-hook-runtime.md} +7 -3
- package/docs/architecture/{ios-semantic-automation-provider-v2.md → history/ios-semantic-automation-provider-v2.md} +6 -2
- package/docs/architecture/history.md +3 -34
- package/docs/architecture/index.md +15 -98
- package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +1 -1
- package/docs/architecture/reviews/2026-08-22-semantic-harness-convergence-acceptance.md +39 -0
- package/docs/architecture/versions/1.6.md +38 -0
- package/docs/architecture/versions/1.7.md +41 -0
- package/docs/forge-chatgpt-browser-engine.md +2 -2
- package/docs/forge-chatgpt-mcp-setup.md +4 -28
- package/docs/forge-chatgpt-supervised-automation.md +3 -3
- package/docs/forge-github-issue-launcher.md +1 -1
- package/docs/forge-plugin-management.md +1 -1
- package/docs/forge-runtime-self-healing-loop.md +1 -1
- package/docs/operations/controller-browser-plugin.md +26 -6
- package/docs/operations/controller-performance-and-502.md +143 -0
- package/docs/operations/controller-reliability-runbook.md +1 -1
- package/docs/operations/features.md +2 -2
- package/docs/operations/github-repository.md +1 -1
- package/docs/operations/homebrew.md +2 -2
- package/docs/operations/mcp-tool-exposure.md +5 -3
- package/docs/wiki/Architecture.md +6 -6
- package/docs/wiki/Implementation.md +2 -2
- package/docs/wiki/Integrations.md +2 -2
- package/docs/wiki/Work-Lifecycle.md +1 -1
- package/package.json +33 -11
- package/scripts/activate-source-baseline.ts +17 -13
- package/scripts/architecture-event.ts +2 -820
- package/scripts/architecture-queue.sh +2 -645
- package/scripts/archive-architecture-request.sh +2 -242
- package/scripts/archive-workflow.sh +1 -291
- package/scripts/benchmark-background-check-overlap.ts +228 -0
- package/scripts/benchmark-mcp-host.sh +117 -0
- package/scripts/benchmark-mcp-transport.ts +170 -0
- package/scripts/benchmark-quality-harness.ts +146 -0
- package/scripts/benchmark-route-session-concurrency.ts +207 -6
- package/scripts/benchmark-thin-harness-mcp-e2e.ts +7 -1
- package/scripts/benchmark-typescript-navigation.ts +186 -0
- package/scripts/benchmark-work-efficiency.ts +334 -0
- package/scripts/capability-config.ts +2 -392
- package/scripts/capability-resolver.ts +2 -503
- package/scripts/capture-plan.sh +1 -332
- package/scripts/check-agent-tooling.sh +2 -1558
- package/scripts/check-architecture-sync.sh +2 -371
- package/scripts/check-brain-manifest.sh +2 -253
- package/scripts/check-context-files.sh +2 -47
- package/scripts/check-deploy-sql-order.sh +2 -115
- package/scripts/check-mcp-compatibility.ts +14 -0
- package/scripts/check-runtime-architecture.mjs +349 -79
- package/scripts/check-skill-version.ts +3 -191
- package/scripts/check-source-duplication.mjs +61 -0
- package/scripts/check-stable-baseline.ts +92 -0
- package/scripts/check-task-sync.sh +2 -63
- package/scripts/check-task-workflow.sh +2 -1000
- package/scripts/codex-handoff-resume.sh +2 -267
- package/scripts/context-contract-sync.sh +2 -514
- package/scripts/contract-run.ts +2 -463
- package/scripts/contract-worktree.sh +1 -722
- package/scripts/ensure-task-workflow.sh +1 -1225
- package/scripts/host-temporary-cloud-mcp-e2e.sh +265 -0
- package/scripts/inspect-project-state.ts +4 -279
- package/scripts/install-standalone-recovery.ts +24 -0
- package/scripts/lib/project-init-lib.sh +22 -46
- package/scripts/lib/run-forge-helper.sh +19 -0
- package/scripts/lib/run-forge-helper.ts +26 -0
- package/scripts/migrate-project-template.sh +1 -1189
- package/scripts/migrate-workflow-docs.ts +4 -412
- package/scripts/new-plan.sh +1 -180
- package/scripts/new-spec.sh +1 -47
- package/scripts/new-sprint.sh +1 -46
- package/scripts/plan-to-todo.sh +1 -796
- package/scripts/prepare-codex-handoff.sh +2 -201
- package/scripts/prepare-handoff.sh +1 -78
- package/scripts/refresh-current-status.sh +2 -467
- package/scripts/run-governed-gate.ts +5 -1
- package/scripts/select-agent-context-blocks.sh +2 -64
- package/scripts/ship-worktrees.sh +1 -558
- package/scripts/smoke-ios-physical-device.ts +4 -2
- package/scripts/smoke-runtime-recovery.ts +1 -35
- package/scripts/smoke-schedule-engine.ts +1 -20
- package/scripts/sprint-backlog.sh +1 -834
- package/scripts/stage-runtime-release.ts +2 -1
- package/scripts/summarize-failures.sh +2 -123
- package/scripts/switch-plan.sh +1 -150
- package/scripts/sync-brain-docs.sh +2 -379
- package/scripts/sync-generated-authority.mjs +175 -0
- package/scripts/verify-contract.sh +2 -703
- package/scripts/verify-forge-runtime.sh +0 -1
- package/scripts/verify-sprint.sh +1 -677
- package/scripts/workflow-contract.ts +4 -205
- package/scripts/workstream-sync.sh +2 -261
- package/src/cli/agent-jobs/executor-health.ts +1 -1
- package/src/cli/commands/init-hook.ts +3 -3
- package/src/cli/commands/mcp.ts +9 -5
- package/src/cli/commands/plugin.ts +12 -3
- package/src/cli/commands/recovery.ts +25 -3
- package/src/cli/commands/runtime.ts +55 -3
- package/src/cli/commands/security.ts +12 -1
- package/src/cli/commands/setup-profile.ts +31 -21
- package/src/cli/controller/check-runner.ts +113 -5
- package/src/cli/controller/composite-result.ts +1 -1
- package/src/cli/controller/context/focus.ts +51 -0
- package/src/cli/controller/context/instruction-context.ts +114 -0
- package/src/cli/controller/context/known-paths.ts +76 -0
- package/src/cli/controller/context/query-planning.ts +110 -0
- package/src/cli/controller/context/rule-resolution.ts +532 -0
- package/src/cli/controller/context/source-materializer.ts +278 -0
- package/src/cli/controller/context/structural.ts +16 -0
- package/src/cli/controller/context/types.ts +286 -0
- package/src/cli/controller/context-pack.ts +828 -487
- package/src/cli/controller/launch-agents.ts +77 -2
- package/src/cli/controller/operational-plan.ts +2 -2
- package/src/cli/controller/work-mode.ts +6 -4
- package/src/cli/editing/edit-session.ts +60 -7
- package/src/cli/github/contracts.ts +16 -0
- package/src/cli/github/github.ts +135 -16
- package/src/cli/github/session.ts +2 -1
- package/src/cli/installer/managed-entries.ts +15 -1
- package/src/cli/local-bridge/console-automations.ts +54 -78
- package/src/cli/local-bridge/console-view-models.ts +1 -35
- package/src/cli/local-bridge/facade-api.ts +37 -264
- package/src/cli/local-bridge/frontend/src/App.tsx +3 -3
- package/src/cli/local-bridge/frontend/src/features/automations/AutomationsView.tsx +23 -13
- package/src/cli/local-bridge/frontend/src/features/capabilities/CapabilitiesView.tsx +37 -4
- package/src/cli/local-bridge/frontend/src/features/overview/OverviewView.tsx +6 -4
- package/src/cli/local-bridge/frontend/src/lib/api.ts +1 -6
- package/src/cli/local-bridge/frontend/src/lib/routes.ts +1 -1
- package/src/cli/local-bridge/frontend/src/shell/Sidebar.tsx +2 -2
- package/src/cli/local-bridge/frontend/src/styles.css +1 -1
- package/src/cli/local-bridge/frontend/src/types.ts +5 -8
- package/src/cli/local-bridge/job-store.ts +1 -490
- package/src/cli/local-bridge/server.ts +2 -515
- package/src/cli/local-bridge/ui-dist/app.css +1 -1
- package/src/cli/local-bridge/ui-dist/app.js +3703 -3757
- package/src/cli/mcp/auth.ts +5 -5
- package/src/cli/mcp/instructions.ts +3 -2
- package/src/cli/mcp/legacy-tool-service.ts +10 -222
- package/src/cli/mcp/multi-repository.ts +16 -5
- package/src/cli/mcp/oauth.ts +175 -26
- package/src/cli/mcp/post-finalize-work-attribution.ts +150 -0
- package/src/cli/mcp/repository-tools.ts +282 -146
- package/src/cli/mcp/server.ts +586 -116
- package/src/cli/mcp/tool-capability-cache.ts +1 -1
- package/src/cli/mcp/tool-contract.ts +14 -0
- package/src/cli/mcp/toolset-selection.ts +1 -1
- package/src/cli/mcp/toolset.ts +44 -7
- package/src/cli/mcp/transports/http.ts +124 -14
- package/src/cli/mcp/transports/session-registry.ts +43 -5
- package/src/cli/mcp/types.ts +3 -3
- package/src/cli/repositories/command-classifier.ts +103 -21
- package/src/cli/repositories/command-executor.ts +78 -526
- package/src/cli/repositories/command-process.ts +108 -0
- package/src/cli/repositories/command-scope.ts +99 -41
- package/src/cli/repositories/controller-home.ts +7 -8
- package/src/cli/repositories/git-command-executor.ts +2 -0
- package/src/cli/repositories/locks.ts +53 -16
- package/src/cli/repositories/repository-snapshot.ts +124 -0
- package/src/cli/repositories/selected-path-actions.ts +17 -9
- package/src/cli/repositories/structured-git.ts +118 -6
- package/src/cli/repository/inspector.ts +563 -65
- package/src/cli/repository/session-cache.ts +58 -17
- package/src/cli/v81-entry.ts +1 -4
- package/src/effects/fs-transaction.ts +85 -17
- package/src/runtime/context/codegraph-read-provider.ts +233 -2
- package/src/runtime/context/codegraph-sidecar.cjs +74 -40
- package/src/runtime/context/generic-lsp-provider.ts +355 -0
- package/src/runtime/context/lsp-client.ts +283 -0
- package/src/runtime/context/semantic-navigation-contract.ts +61 -0
- package/src/runtime/context/semantic-navigation.ts +223 -0
- package/src/runtime/context/swift-navigation.ts +565 -0
- package/src/runtime/context/typescript-navigation.ts +226 -0
- package/src/runtime/control-plane/dispatch-priority.ts +28 -0
- package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +48 -16
- package/src/runtime/control-plane/execution/edit-validation-coordinator.ts +86 -24
- package/src/runtime/control-plane/execution/repository-work-attribution.ts +106 -0
- package/src/runtime/control-plane/execution/retained-work-resume.ts +203 -0
- package/src/runtime/control-plane/execution/session-store.ts +18 -0
- package/src/runtime/control-plane/execution/verification-evidence.ts +58 -3
- package/src/runtime/control-plane/execution/work-completion-authority.ts +58 -0
- package/src/runtime/control-plane/execution/work-evidence-policy.ts +200 -0
- package/src/runtime/control-plane/execution/work-execution-support.ts +386 -0
- package/src/runtime/control-plane/execution/work-finalization-service.ts +1913 -0
- package/src/runtime/control-plane/execution/work-handle-authority.ts +96 -0
- package/src/runtime/control-plane/execution/work-handle-store.ts +27 -2
- package/src/runtime/control-plane/execution/work-lifecycle-audit.ts +258 -0
- package/src/runtime/control-plane/execution/work-operation-service.ts +468 -0
- package/src/runtime/control-plane/execution/work-path-scope.ts +37 -0
- package/src/runtime/control-plane/execution/work-preparation-service.ts +479 -0
- package/src/runtime/control-plane/execution/work-process-evidence.ts +129 -0
- package/src/runtime/control-plane/execution/work-remote-delivery.ts +215 -0
- package/src/runtime/control-plane/execution/work-task-receipt.ts +22 -18
- package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +156 -11
- package/src/runtime/control-plane/execution/work-validation-reconciler.ts +22 -14
- package/src/runtime/control-plane/execution/work-verification-context.ts +56 -0
- package/src/runtime/control-plane/execution/work-verification-service.ts +388 -0
- package/src/runtime/control-plane/execution/work-verification-snapshot.ts +90 -9
- package/src/runtime/control-plane/facade/capability-registry.ts +129 -25
- package/src/runtime/control-plane/facade/controller-round-relay.ts +1118 -0
- package/src/runtime/control-plane/facade/controller-session-store.ts +302 -12
- package/src/runtime/control-plane/facade/goal-workloop-access.ts +17 -1
- package/src/runtime/control-plane/facade/goal-workloop.ts +928 -190
- package/src/runtime/control-plane/facade/index.ts +3 -0
- package/src/runtime/control-plane/facade/plan-contract-store.ts +275 -42
- package/src/runtime/control-plane/facade/repository-work-admission.ts +147 -0
- package/src/runtime/control-plane/facade/requirement-authority.ts +83 -0
- package/src/runtime/control-plane/facade/semantic-admission.ts +205 -0
- package/src/runtime/control-plane/facade/suggested-actions.ts +5 -1
- package/src/runtime/control-plane/facade/types.ts +90 -10
- package/src/runtime/control-plane/facade/work-contract-store.ts +157 -261
- package/src/runtime/control-plane/facade/work-state-machine.ts +250 -0
- package/src/runtime/control-plane/generated-cache-retention.ts +271 -0
- package/src/runtime/control-plane/global-scheduler/config.ts +44 -0
- package/src/runtime/control-plane/global-scheduler/dispatch-capacity.ts +80 -0
- package/src/runtime/control-plane/global-scheduler/durable-admission.ts +46 -0
- package/src/runtime/control-plane/global-scheduler/maintenance.ts +152 -0
- package/src/runtime/control-plane/global-scheduler/projection-refresh.ts +84 -0
- package/src/runtime/control-plane/global-scheduler/reconciliation.ts +3 -3
- package/src/runtime/control-plane/global-scheduler/scheduler.ts +278 -543
- package/src/runtime/control-plane/global-scheduler/source-scan.ts +59 -0
- package/src/runtime/control-plane/global-scheduler/state.ts +88 -0
- package/src/runtime/control-plane/global-scheduler/worker-attachment.ts +57 -0
- package/src/runtime/control-plane/global-scheduler/worker-exit-decision.ts +38 -0
- package/src/runtime/control-plane/global-scheduler/worker-exit-reconciler.ts +175 -0
- package/src/runtime/control-plane/global-scheduler/worker-launch.ts +111 -0
- package/src/runtime/control-plane/global-scheduler/worker-lifecycle-store.ts +64 -0
- package/src/runtime/control-plane/global-scheduler/worker-lifecycle.ts +150 -0
- package/src/runtime/control-plane/global-scheduler/worker-process.ts +119 -0
- package/src/runtime/control-plane/global-scheduler/worker-stderr.ts +60 -0
- package/src/runtime/control-plane/launcher/chatgpt-work-binding-store.ts +63 -0
- package/src/runtime/control-plane/launcher/chatgpt-work-continuation.ts +365 -117
- package/src/runtime/control-plane/launcher/launch-reservation-store.ts +89 -0
- package/src/runtime/control-plane/launcher/thin-launcher.ts +244 -11
- package/src/runtime/control-plane/persistence/controller-home-migration.ts +487 -0
- package/src/runtime/control-plane/persistence/requirement-store.ts +0 -12
- package/src/runtime/control-plane/persistence/sqlite-store.ts +33 -2
- package/src/runtime/control-plane/release-retention.ts +62 -2
- package/src/runtime/control-plane/repo-actor/registry.ts +4 -2
- package/src/runtime/control-plane/routing/route-policy.ts +24 -21
- package/src/runtime/control-plane/routing/workspace-admission.ts +70 -0
- package/src/runtime/control-plane/runtime-status-client.ts +0 -2
- package/src/runtime/diagnostics/mcp-timing.ts +13 -0
- package/src/runtime/diagnostics/mcp-transport-benchmark.ts +129 -0
- package/src/runtime/diagnostics/performance.ts +24 -1
- package/src/runtime/evidence/event-ledger.ts +1 -1
- package/src/runtime/evidence/process-check-execution.ts +18 -0
- package/src/runtime/execution/jobs/child-reference.ts +6 -2
- package/src/runtime/execution/jobs/store.ts +58 -4
- package/src/runtime/execution/jobs/types.ts +1 -1
- package/src/runtime/execution/managed-workspace.ts +203 -1
- package/src/runtime/execution/process-runtime/check-facade.ts +51 -4
- package/src/runtime/execution/process-runtime/check-result.ts +88 -0
- package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +7 -1
- package/src/runtime/execution/process-runtime/check-scheduling.ts +114 -0
- package/src/runtime/execution/process-runtime/command-facade.ts +367 -40
- package/src/runtime/execution/process-runtime/gc.ts +38 -6
- package/src/runtime/execution/process-runtime/lightweight-managed.ts +1201 -0
- package/src/runtime/execution/process-runtime/persisted-check.ts +51 -5
- package/src/runtime/execution/process-runtime/resource-claims.ts +10 -6
- package/src/runtime/execution/process-runtime/runtime.ts +53 -3
- package/src/runtime/execution/process-runtime/store.ts +1 -0
- package/src/runtime/execution/process-runtime/types.ts +4 -12
- package/src/runtime/execution/thin-harness/async-process.ts +12 -2
- package/src/runtime/execution/thin-harness/search-worker.ts +54 -5
- package/src/runtime/execution/work-activity.ts +21 -0
- package/src/runtime/execution/workers/executor.ts +18 -61
- package/src/runtime/gateway/mcp/execution-tools.ts +35 -1852
- package/src/runtime/gateway/mcp/legacy-ios-tool-adapter.ts +61 -0
- package/src/runtime/gateway/mcp/process-tools.ts +83 -37
- package/src/runtime/gateway/mcp/router.ts +186 -84
- package/src/runtime/gateway/mcp/runtime-tool-definitions.ts +565 -0
- package/src/runtime/gateway/mcp/runtime-tools.ts +2378 -1947
- package/src/runtime/plugins/app-store-connect-adapter.ts +216 -47
- package/src/runtime/plugins/browser-adapter.ts +2662 -829
- package/src/runtime/plugins/browser-automation-service.ts +10 -0
- package/src/runtime/plugins/browser-handoff-host.ts +2 -25
- package/src/runtime/plugins/browser-handoff.ts +110 -5
- package/src/runtime/plugins/browser-macos-bridge.ts +701 -63
- package/src/runtime/plugins/browser-manifest-surface.ts +603 -0
- package/src/runtime/plugins/browser-native-session-service.ts +222 -0
- package/src/runtime/plugins/browser-node-bridge.ts +6 -34
- package/src/runtime/plugins/browser-provider-registry.ts +109 -0
- package/src/runtime/plugins/browser-runtime-contract.ts +154 -0
- package/src/runtime/plugins/browser-runtime.ts +193 -0
- package/src/runtime/plugins/browser-session-authority.ts +332 -0
- package/src/runtime/plugins/browser-session-store.ts +121 -0
- package/src/runtime/plugins/browser-session-types.ts +98 -0
- package/src/runtime/plugins/capability-authorization-grants.ts +354 -0
- package/src/runtime/plugins/desktop-operator-registration.ts +10 -4
- package/src/runtime/plugins/external-adapter.ts +358 -3
- package/src/runtime/plugins/external-unix-socket.ts +7 -1
- package/src/runtime/plugins/first-party-registry.ts +2 -0
- package/src/runtime/plugins/github-adapter.ts +125 -0
- package/src/runtime/plugins/ios/agent-device-provider.ts +1 -1
- package/src/runtime/plugins/ios/agent-device-typed-provider.ts +52 -9
- package/src/runtime/plugins/ios/remote-xpc-hid.ts +1171 -0
- package/src/runtime/plugins/ios-adapter.ts +106 -16
- package/src/runtime/plugins/ios-agent-device.ts +234 -64
- package/src/runtime/plugins/ios-physical-device.ts +1143 -392
- package/src/runtime/plugins/lightweight-action.ts +153 -0
- package/src/runtime/plugins/local-system-adapter.ts +123 -6
- package/src/runtime/plugins/macos-capability-broker.ts +47 -9
- package/src/runtime/plugins/plugin-action-sidecar.ts +59 -0
- package/src/runtime/plugins/plugin-management-adapter.ts +49 -8
- package/src/runtime/plugins/resend-adapter.ts +1 -1
- package/src/runtime/plugins/store.ts +330 -33
- package/src/runtime/plugins/types.ts +38 -3
- package/src/runtime/plugins/xiaohongshu-publish.ts +515 -0
- package/src/runtime/projections/git-status-sampler.ts +16 -16
- package/src/runtime/projections/materialized-view.ts +28 -10
- package/src/runtime/recovery/maintenance-executor.ts +426 -25
- package/src/runtime/root/mcp-transport.ts +180 -10
- package/src/runtime/root/package-connector-service.ts +230 -10
- package/src/runtime/root/package-runtime-release.ts +143 -17
- package/src/runtime/root/package-runtime-service.ts +461 -22
- package/src/runtime/root/release-manifest.ts +144 -18
- package/src/runtime/root/release-materialize.ts +125 -32
- package/src/runtime/root/release-store.ts +48 -11
- package/src/runtime/root/runtime.ts +23 -5
- package/src/runtime/root/service.ts +100 -29
- package/src/runtime/root/types.ts +12 -0
- package/src/runtime/safe-tooling/ios-development.ts +321 -63
- package/src/runtime/shared/trusted-executable.ts +62 -0
- package/src/runtime/shared/trusted-node-executable.ts +48 -0
- package/src/runtime/standalone-recovery/core.ts +1079 -240
- package/src/runtime/standalone-recovery/entry.ts +100 -24
- package/src/runtime/standalone-recovery/installer.ts +20 -4
- package/src/runtime/standalone-recovery/service-labels.ts +2 -0
- package/src/runtime/standalone-recovery/watchdog-heartbeat.ts +160 -0
- package/src/runtime/workflow/schedules/browser-probe.ts +81 -3
- package/src/runtime/workflow/schedules/engine.ts +364 -202
- package/src/runtime/workflow/schedules/github-issue-watch.ts +158 -0
- package/src/runtime/workflow/schedules/settlement.ts +64 -17
- package/src/runtime/workflow/schedules/store.ts +209 -19
- package/src/runtime/workflow/schedules/types.ts +2 -4
- package/src/runtime/workflow/schedules/work-continuation.ts +26 -13
- package/src/testing/test-governance.ts +8 -40
- package/assets/reference-configs/heartbeat-triage.md +0 -57
- package/assets/templates/helpers/harness-trace-grade.sh +0 -150
- package/assets/templates/helpers/heartbeat-triage.sh +0 -361
- package/assets/templates/helpers/maintenance-triage.sh +0 -167
- package/docs/architecture/current/approved-target-architecture.zh-CN.md +0 -1501
- package/docs/architecture/current/architecture-invariants.md +0 -331
- package/docs/architecture/current/automation-and-schedule-engine.md +0 -459
- package/docs/architecture/current/codegraph-context-provider.md +0 -238
- package/docs/architecture/current/control-plane-authority-inventory.md +0 -94
- package/docs/architecture/current/controller-repository-decoupling.md +0 -148
- package/docs/architecture/current/dispatch-and-agent-strategy.md +0 -373
- package/docs/architecture/current/entity-model.md +0 -612
- package/docs/architecture/current/external-plugin-governance.md +0 -396
- package/docs/architecture/current/failure-recovery.md +0 -447
- package/docs/architecture/current/governance.md +0 -213
- package/docs/architecture/current/human-interaction-plane.md +0 -87
- package/docs/architecture/current/implementation-status.md +0 -128
- package/docs/architecture/current/job-and-run-lifecycle.md +0 -413
- package/docs/architecture/current/legacy-governance.md +0 -58
- package/docs/architecture/current/local-workspace-target-grants.md +0 -70
- package/docs/architecture/current/migration-roadmap.md +0 -105
- package/docs/architecture/current/multi-repository-execution.md +0 -371
- package/docs/architecture/current/operations-runbook.md +0 -45
- package/docs/architecture/current/peer-supercontroller-runtime.md +0 -32
- package/docs/architecture/current/personal-assistant-plugin-baseline.md +0 -206
- package/docs/architecture/current/repository-access-modes.md +0 -102
- package/docs/architecture/current/route-policy.md +0 -15
- package/docs/architecture/current/route-session-concurrency.md +0 -85
- package/docs/architecture/current/runtime-architecture-simplification.md +0 -214
- package/docs/architecture/current/runtime-directory-map.md +0 -49
- package/docs/architecture/current/runtime-health-and-resource-lifecycle.md +0 -85
- package/docs/architecture/current/scheduler-and-resource-claims.md +0 -422
- package/docs/architecture/current/session-aware-execution-and-authorization.md +0 -77
- package/docs/architecture/current/system-overview.md +0 -169
- package/docs/architecture/current/target-requirements-traceability.md +0 -202
- package/docs/architecture/current/thin-harness-governance-policy.md +0 -32
- package/docs/architecture/current/thin-harness-v1.md +0 -321
- package/docs/architecture/current/verification-and-release-gates.md +0 -391
- package/docs/forge-autonomous-goal-loop.md +0 -9
- package/docs/forge-provider-configuration.md +0 -7
- package/docs/operations/chatgpt-personal-assistant-runtime.md +0 -93
- package/docs/operations/gmail-assistant-routines.md +0 -186
- package/docs/operations/personal-assistant-operator-guide.md +0 -61
- package/docs/operations/provider-configuration.md +0 -31
- package/scripts/harness-trace-grade.sh +0 -150
- package/scripts/heartbeat-triage.sh +0 -361
- package/scripts/maintenance-triage.sh +0 -167
- package/src/cli/local-bridge/frontend/src/features/settings/SettingsView.tsx +0 -2
- package/src/cli/repositories/goal-registry.ts +0 -239
- package/src/runtime/assistant/action-proposals.ts +0 -279
- package/src/runtime/assistant/intent.ts +0 -395
- package/src/runtime/assistant/model-provider.ts +0 -460
- package/src/runtime/assistant/openapi.ts +0 -223
- package/src/runtime/assistant/policy.ts +0 -89
- package/src/runtime/assistant/readiness.ts +0 -258
- package/src/runtime/assistant/routine-runtime.ts +0 -477
- package/src/runtime/assistant/schedule-binding.ts +0 -171
- package/src/runtime/assistant/standing-grants.ts +0 -375
- package/src/runtime/assistant/store.ts +0 -243
- package/src/runtime/assistant/types.ts +0 -135
- package/src/runtime/control-plane/goal-loop/config-facade.ts +0 -700
- package/src/runtime/control-plane/goal-loop/config-store.ts +0 -570
- package/src/runtime/control-plane/goal-loop/config-types.ts +0 -213
- package/src/runtime/control-plane/goal-loop/executor-router.ts +0 -109
- package/src/runtime/control-plane/goal-loop/failure-taxonomy.ts +0 -149
- package/src/runtime/control-plane/goal-loop/goal-contract-store.ts +0 -304
- package/src/runtime/control-plane/goal-loop/goal-loop-engine.ts +0 -1001
- package/src/runtime/control-plane/goal-loop/handoff-packet.ts +0 -160
- package/src/runtime/control-plane/goal-loop/index.ts +0 -13
- package/src/runtime/control-plane/goal-loop/local-tools.ts +0 -290
- package/src/runtime/control-plane/goal-loop/policy-gates.ts +0 -203
- package/src/runtime/control-plane/goal-loop/provider-dispatch.ts +0 -93
- package/src/runtime/control-plane/goal-loop/provider-registry.ts +0 -545
- package/src/runtime/control-plane/goal-loop/types.ts +0 -378
- package/src/runtime/control-plane/startup-recovery.ts +0 -198
- package/src/runtime/gateway/mcp/resource-policy.ts +0 -186
- package/src/runtime/personal-assistant/gmail-triage-manager.ts +0 -231
- package/src/runtime/personal-assistant/reporting-runtime.ts +0 -344
- package/src/runtime/personal-assistant/triage-runtime.ts +0 -748
- package/src/runtime/workflow/findings/store.ts +0 -204
- package/src/runtime/workflow/findings/types.ts +0 -58
- package/src/runtime/workflow/portfolio/engine.ts +0 -20
- package/src/runtime/workflow/portfolio/store.ts +0 -185
- package/src/runtime/workflow/portfolio/types.ts +0 -29
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { createHash } from 'crypto';
|
|
1
2
|
import { AssistantPluginError } from './errors';
|
|
2
3
|
import { getExternalPluginRegistration, listExternalPluginRegistrations, type ExternalPluginRegistration } from './external-registration';
|
|
3
4
|
import { callExternalUnixSocket, probeExternalUnixSocketSync, type ExternalUnixSocketCallOptions } from './external-unix-socket';
|
|
4
5
|
import { executeManagedPluginProcess, executeManagedPluginProcessSync, type ManagedPluginProcessSpec } from './managed-process-adapter';
|
|
5
|
-
import { restartVerifiedUserLaunchAgent, startVerifiedUserLaunchAgent, stopVerifiedUserLaunchAgent } from './local-system-adapter';
|
|
6
|
-
import type { AssistantPluginActionDescriptor, AssistantPluginAdapter, AssistantPluginCapability, AssistantPluginHealth, AssistantPluginManifest, AssistantPluginPermissionScope } from './types';
|
|
6
|
+
import { activateAndVerifyFrontmostApplication, restartVerifiedUserLaunchAgent, startVerifiedUserLaunchAgent, stopVerifiedUserLaunchAgent } from './local-system-adapter';
|
|
7
|
+
import type { AssistantPluginActionDescriptor, AssistantPluginAdapter, AssistantPluginAuthorizationContext, AssistantPluginCapability, AssistantPluginHealth, AssistantPluginManifest, AssistantPluginPermissionScope } from './types';
|
|
7
8
|
|
|
8
9
|
interface ProviderManifest {
|
|
9
10
|
id: string;
|
|
@@ -31,6 +32,7 @@ export interface ExternalPluginAdapterDependencies {
|
|
|
31
32
|
startVerifiedUserLaunchAgent?: (label: unknown, expectedProgram: unknown) => Record<string, unknown>;
|
|
32
33
|
stopVerifiedUserLaunchAgent?: (label: unknown, expectedProgram: unknown) => Record<string, unknown>;
|
|
33
34
|
restartVerifiedUserLaunchAgent?: (label: unknown, expectedProgram: unknown) => Record<string, unknown>;
|
|
35
|
+
activateAndVerifyFrontmostApplication?: typeof activateAndVerifyFrontmostApplication;
|
|
34
36
|
now?: () => Date;
|
|
35
37
|
}
|
|
36
38
|
|
|
@@ -59,7 +61,10 @@ function parseProviderManifest(value: Record<string, unknown>, registration: Ext
|
|
|
59
61
|
if (manifest.protocolVersion !== registration.protocolVersion) throw providerError('EXTERNAL_PLUGIN_PROTOCOL_MISMATCH', `Expected provider protocol ${registration.protocolVersion}, received ${manifest.protocolVersion || 'unknown'}.`);
|
|
60
62
|
if (manifest.scope !== registration.scope) throw providerError('EXTERNAL_PLUGIN_SCOPE_MISMATCH', `Expected provider scope ${registration.scope}, received ${manifest.scope || 'unknown'}.`);
|
|
61
63
|
if (manifest.provider !== registration.provider) throw providerError('EXTERNAL_PLUGIN_PROVIDER_MISMATCH', `Expected provider ${registration.provider}, received ${manifest.provider || 'unknown'}.`);
|
|
62
|
-
const missingActions = registration.actions
|
|
64
|
+
const missingActions = registration.actions
|
|
65
|
+
.map((action) => action.actionId)
|
|
66
|
+
.filter((actionId) => !(registration.pluginId === 'desktop_operator' && ['desktop_pointer_click', 'desktop_foreground_pointer_click'].includes(actionId)))
|
|
67
|
+
.filter((actionId) => !manifest.actions.includes(actionId));
|
|
63
68
|
if (missingActions.length > 0) throw providerError('EXTERNAL_PLUGIN_ACTION_MISMATCH', `Provider is missing registered actions: ${missingActions.join(', ')}.`);
|
|
64
69
|
return manifest;
|
|
65
70
|
}
|
|
@@ -189,6 +194,212 @@ async function callProvider(
|
|
|
189
194
|
});
|
|
190
195
|
}
|
|
191
196
|
|
|
197
|
+
function externalProviderAuthorizationContext(registration: ExternalPluginRegistration): AssistantPluginAuthorizationContext {
|
|
198
|
+
return {
|
|
199
|
+
target: {
|
|
200
|
+
kind: 'external-provider',
|
|
201
|
+
id: registration.pluginId,
|
|
202
|
+
identityFingerprint: registration.registrationFingerprint,
|
|
203
|
+
},
|
|
204
|
+
expiresInMinutes: 30 * 24 * 60,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function desktopApplicationAuthorizationContext(
|
|
209
|
+
registration: ExternalPluginRegistration,
|
|
210
|
+
stableApplicationId: string,
|
|
211
|
+
): AssistantPluginAuthorizationContext {
|
|
212
|
+
const normalized = stableApplicationId.trim();
|
|
213
|
+
return {
|
|
214
|
+
target: {
|
|
215
|
+
kind: 'desktop-application',
|
|
216
|
+
id: normalized,
|
|
217
|
+
identityFingerprint: createHash('sha256')
|
|
218
|
+
.update(`${registration.registrationFingerprint}\0${normalized}`)
|
|
219
|
+
.digest('hex'),
|
|
220
|
+
},
|
|
221
|
+
expiresInMinutes: 30 * 24 * 60,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function recordArray(value: unknown): Record<string, unknown>[] {
|
|
226
|
+
return Array.isArray(value)
|
|
227
|
+
? value.filter((entry): entry is Record<string, unknown> => Boolean(entry) && typeof entry === 'object' && !Array.isArray(entry))
|
|
228
|
+
: [];
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function firstString(record: Record<string, unknown>, ...keys: string[]): string {
|
|
232
|
+
for (const key of keys) {
|
|
233
|
+
const value = record[key];
|
|
234
|
+
if (typeof value === 'string' && value.trim()) return value.trim();
|
|
235
|
+
}
|
|
236
|
+
return '';
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function firstNumber(record: Record<string, unknown>, ...keys: string[]): number | undefined {
|
|
240
|
+
for (const key of keys) {
|
|
241
|
+
const value = record[key];
|
|
242
|
+
if (typeof value === 'number' && Number.isFinite(value)) return value;
|
|
243
|
+
}
|
|
244
|
+
return undefined;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function desktopSession(status: Record<string, unknown>, interactionId: string): Record<string, unknown> | undefined {
|
|
248
|
+
return recordArray(status.sessions).find((session) => firstString(session, 'interactionId', 'interaction_id') === interactionId);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
async function independentlyEnsureExactFrontmostDesktopApplication(
|
|
252
|
+
bundleId: string,
|
|
253
|
+
appName: string,
|
|
254
|
+
dependencies: ExternalPluginAdapterDependencies,
|
|
255
|
+
): Promise<void> {
|
|
256
|
+
const activateAndVerify = dependencies.activateAndVerifyFrontmostApplication ?? activateAndVerifyFrontmostApplication;
|
|
257
|
+
const proof = await activateAndVerify({ bundleId: bundleId || undefined, appName: appName || undefined });
|
|
258
|
+
const proofBundleId = typeof proof.bundleId === 'string' ? proof.bundleId.trim() : '';
|
|
259
|
+
const proofAppName = typeof proof.appName === 'string' ? proof.appName.trim() : '';
|
|
260
|
+
const proofMatches = bundleId ? proofBundleId === bundleId : proofAppName === appName;
|
|
261
|
+
if (proof.activated !== true || proof.verified !== true || !proofMatches) {
|
|
262
|
+
throw new AssistantPluginError(
|
|
263
|
+
'DESKTOP_ACTIVATION_FALLBACK_IDENTITY_MISMATCH',
|
|
264
|
+
`Forge did not prove the exact requested application ${bundleId || appName} as frontmost.`,
|
|
265
|
+
{ retryable: true, details: { target: { bundleId, appName }, observed: { bundleId: proofBundleId, appName: proofAppName } } },
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
async function openVerifiedDesktopSession(
|
|
271
|
+
registration: ExternalPluginRegistration,
|
|
272
|
+
requestId: string,
|
|
273
|
+
args: Record<string, unknown>,
|
|
274
|
+
timeoutMs: number | undefined,
|
|
275
|
+
signal: AbortSignal | undefined,
|
|
276
|
+
dependencies: ExternalPluginAdapterDependencies,
|
|
277
|
+
): Promise<Record<string, unknown>> {
|
|
278
|
+
const bundleId = typeof args.bundle_id === 'string' ? args.bundle_id.trim() : '';
|
|
279
|
+
const appName = typeof args.app_name === 'string' ? args.app_name.trim() : '';
|
|
280
|
+
if (!bundleId && !appName) {
|
|
281
|
+
throw providerError('DESKTOP_ACTIVATION_TARGET_UNAVAILABLE', 'Activated desktop sessions require an exact bundle id or application name.');
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
let result: Record<string, unknown>;
|
|
285
|
+
let providerActivationError: AssistantPluginError | undefined;
|
|
286
|
+
try {
|
|
287
|
+
result = await callProvider(
|
|
288
|
+
registration,
|
|
289
|
+
requestId,
|
|
290
|
+
'desktop_session_open',
|
|
291
|
+
args,
|
|
292
|
+
timeoutMs,
|
|
293
|
+
signal,
|
|
294
|
+
dependencies,
|
|
295
|
+
);
|
|
296
|
+
} catch (error) {
|
|
297
|
+
if (!(error instanceof AssistantPluginError) || error.code !== 'APP_ACTIVATION_FAILED') throw error;
|
|
298
|
+
providerActivationError = error;
|
|
299
|
+
result = await callProvider(
|
|
300
|
+
registration,
|
|
301
|
+
`${requestId}:fallback-session`,
|
|
302
|
+
'desktop_session_open',
|
|
303
|
+
{ ...(bundleId ? { bundle_id: bundleId } : { app_name: appName }), launch: false, activate: false },
|
|
304
|
+
timeoutMs,
|
|
305
|
+
signal,
|
|
306
|
+
dependencies,
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
try {
|
|
311
|
+
await independentlyEnsureExactFrontmostDesktopApplication(bundleId, appName, dependencies);
|
|
312
|
+
} catch (verificationError) {
|
|
313
|
+
const wrappedCode = providerActivationError ? 'DESKTOP_ACTIVATION_FALLBACK_FAILED' : 'DESKTOP_ACTIVATION_NOT_CONFIRMED';
|
|
314
|
+
const wrappedMessage = providerActivationError
|
|
315
|
+
? `Desktop Operator activation failed and Forge could not independently verify ${bundleId || appName} as frontmost.`
|
|
316
|
+
: `Desktop Operator returned an activated session, but Forge could not independently verify ${bundleId || appName} as frontmost.`;
|
|
317
|
+
if (verificationError instanceof AssistantPluginError) {
|
|
318
|
+
throw new AssistantPluginError(wrappedCode, wrappedMessage, {
|
|
319
|
+
retryable: verificationError.retryable,
|
|
320
|
+
details: {
|
|
321
|
+
...(providerActivationError ? { providerErrorCode: providerActivationError.code } : {}),
|
|
322
|
+
verificationErrorCode: verificationError.code,
|
|
323
|
+
verificationErrorMessage: verificationError.message,
|
|
324
|
+
target: bundleId || appName,
|
|
325
|
+
},
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
throw new AssistantPluginError(wrappedCode, wrappedMessage, {
|
|
329
|
+
retryable: true,
|
|
330
|
+
details: {
|
|
331
|
+
...(providerActivationError ? { providerErrorCode: providerActivationError.code } : {}),
|
|
332
|
+
verificationErrorMessage: String(verificationError),
|
|
333
|
+
target: bundleId || appName,
|
|
334
|
+
},
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
return result;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
async function resolveExternalAuthorizationContext(
|
|
342
|
+
registration: ExternalPluginRegistration,
|
|
343
|
+
input: Parameters<NonNullable<AssistantPluginAdapter['resolveAuthorizationContext']>>[0],
|
|
344
|
+
dependencies: ExternalPluginAdapterDependencies,
|
|
345
|
+
): Promise<AssistantPluginAuthorizationContext | undefined> {
|
|
346
|
+
if (EXTERNAL_PROVIDER_LIFECYCLE_ACTIONS.has(input.actionId)) {
|
|
347
|
+
return externalProviderAuthorizationContext(registration);
|
|
348
|
+
}
|
|
349
|
+
if (registration.pluginId !== 'desktop_operator') return undefined;
|
|
350
|
+
if (input.actionId === 'desktop_permissions_request') {
|
|
351
|
+
return externalProviderAuthorizationContext(registration);
|
|
352
|
+
}
|
|
353
|
+
if (input.actionId === 'desktop_session_open') {
|
|
354
|
+
const bundleId = typeof input.args.bundle_id === 'string' ? input.args.bundle_id.trim() : '';
|
|
355
|
+
return bundleId ? desktopApplicationAuthorizationContext(registration, bundleId) : undefined;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const interactionId = typeof input.args.interaction_id === 'string' ? input.args.interaction_id.trim() : '';
|
|
359
|
+
if (!interactionId) return undefined;
|
|
360
|
+
|
|
361
|
+
const providerManifest = await callProvider(
|
|
362
|
+
registration,
|
|
363
|
+
`${input.requestId}:authorization-target:manifest`,
|
|
364
|
+
'manifest',
|
|
365
|
+
{},
|
|
366
|
+
undefined,
|
|
367
|
+
input.signal,
|
|
368
|
+
dependencies,
|
|
369
|
+
);
|
|
370
|
+
parseProviderManifest(providerManifest, registration);
|
|
371
|
+
const status = await callProvider(
|
|
372
|
+
registration,
|
|
373
|
+
`${input.requestId}:authorization-target:desktop-status`,
|
|
374
|
+
'desktop_status',
|
|
375
|
+
{ limit: 500 },
|
|
376
|
+
input.timeoutMs,
|
|
377
|
+
input.signal,
|
|
378
|
+
dependencies,
|
|
379
|
+
);
|
|
380
|
+
const sessions = Array.isArray(status.sessions) ? status.sessions : [];
|
|
381
|
+
const session = sessions.find((entry) => {
|
|
382
|
+
if (!entry || typeof entry !== 'object' || Array.isArray(entry)) return false;
|
|
383
|
+
const record = entry as Record<string, unknown>;
|
|
384
|
+
const id = typeof record.interactionId === 'string' ? record.interactionId : typeof record.interaction_id === 'string' ? record.interaction_id : '';
|
|
385
|
+
return id === interactionId;
|
|
386
|
+
}) as Record<string, unknown> | undefined;
|
|
387
|
+
if (!session) {
|
|
388
|
+
throw providerError('EXTERNAL_PLUGIN_AUTHORIZATION_TARGET_UNAVAILABLE', `Desktop session ${interactionId} was not found while resolving its stable authorization target.`, false);
|
|
389
|
+
}
|
|
390
|
+
const bundleId = typeof session.bundleIdentifier === 'string' ? session.bundleIdentifier.trim()
|
|
391
|
+
: typeof session.bundle_identifier === 'string' ? session.bundle_identifier.trim()
|
|
392
|
+
: '';
|
|
393
|
+
const appName = typeof session.appName === 'string' ? session.appName.trim()
|
|
394
|
+
: typeof session.app_name === 'string' ? session.app_name.trim()
|
|
395
|
+
: '';
|
|
396
|
+
const stableApplicationId = bundleId || (appName ? `name:${appName.toLowerCase()}` : '');
|
|
397
|
+
if (!stableApplicationId) {
|
|
398
|
+
throw providerError('EXTERNAL_PLUGIN_AUTHORIZATION_TARGET_UNAVAILABLE', `Desktop session ${interactionId} has no stable application identity.`, false);
|
|
399
|
+
}
|
|
400
|
+
return desktopApplicationAuthorizationContext(registration, stableApplicationId);
|
|
401
|
+
}
|
|
402
|
+
|
|
192
403
|
export function getExternalPluginAdapter(controllerHome: string, pluginId: string): AssistantPluginAdapter | undefined {
|
|
193
404
|
const registration = getExternalPluginRegistration(controllerHome, pluginId);
|
|
194
405
|
return registration ? createExternalPluginAdapter(registration) : undefined;
|
|
@@ -211,6 +422,7 @@ export function createExternalPluginAdapter(
|
|
|
211
422
|
return {
|
|
212
423
|
pluginId: registration.pluginId,
|
|
213
424
|
scope: registration.scope,
|
|
425
|
+
resolveAuthorizationContext: (input) => resolveExternalAuthorizationContext(registration, input, dependencies),
|
|
214
426
|
buildManifest(previousRevision = 0, previousUpdatedAt?: string): AssistantPluginManifest {
|
|
215
427
|
const checkedAt = now().toISOString();
|
|
216
428
|
if (!registration.enabled) {
|
|
@@ -305,6 +517,149 @@ export function createExternalPluginAdapter(
|
|
|
305
517
|
);
|
|
306
518
|
parseProviderManifest(providerManifest, registration);
|
|
307
519
|
}
|
|
520
|
+
if (registration.pluginId === 'desktop_operator' && input.actionId === 'desktop_foreground_pointer_click') {
|
|
521
|
+
const sourceInteractionId = typeof input.args.interaction_id === 'string' ? input.args.interaction_id.trim() : '';
|
|
522
|
+
const requestedWindowId = typeof input.args.window_id === 'number' && Number.isInteger(input.args.window_id) ? input.args.window_id : undefined;
|
|
523
|
+
const x = typeof input.args.x === 'number' && Number.isFinite(input.args.x) ? input.args.x : undefined;
|
|
524
|
+
const y = typeof input.args.y === 'number' && Number.isFinite(input.args.y) ? input.args.y : undefined;
|
|
525
|
+
if (!sourceInteractionId || !requestedWindowId || x === undefined || y === undefined) {
|
|
526
|
+
throw providerError('DESKTOP_FOREGROUND_POINTER_ARGUMENT_INVALID', 'desktop_foreground_pointer_click requires interaction_id, window_id, x, and y.');
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
const sourceStatus = await callProvider(
|
|
530
|
+
registration,
|
|
531
|
+
`${input.requestId}:source-status`,
|
|
532
|
+
'desktop_status',
|
|
533
|
+
{ limit: 500 },
|
|
534
|
+
input.timeoutMs,
|
|
535
|
+
input.signal,
|
|
536
|
+
dependencies,
|
|
537
|
+
);
|
|
538
|
+
const sourceSession = desktopSession(sourceStatus, sourceInteractionId);
|
|
539
|
+
if (!sourceSession) {
|
|
540
|
+
throw providerError('DESKTOP_FOREGROUND_POINTER_SESSION_NOT_FOUND', `Desktop session ${sourceInteractionId} is no longer available.`, true);
|
|
541
|
+
}
|
|
542
|
+
const bundleId = firstString(sourceSession, 'bundleIdentifier', 'bundle_id');
|
|
543
|
+
const appName = firstString(sourceSession, 'appName', 'app_name');
|
|
544
|
+
if (!bundleId && !appName) {
|
|
545
|
+
throw providerError('DESKTOP_FOREGROUND_POINTER_TARGET_UNAVAILABLE', `Desktop session ${sourceInteractionId} has no stable application identity.`);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
const activation = await openVerifiedDesktopSession(
|
|
549
|
+
registration,
|
|
550
|
+
`${input.requestId}:activate`,
|
|
551
|
+
{ ...(bundleId ? { bundle_id: bundleId } : { app_name: appName }), launch: false, activate: true },
|
|
552
|
+
input.timeoutMs,
|
|
553
|
+
input.signal,
|
|
554
|
+
dependencies,
|
|
555
|
+
);
|
|
556
|
+
const activationInteractionId = firstString(activation, 'interactionId', 'interaction_id');
|
|
557
|
+
if (!activationInteractionId) {
|
|
558
|
+
throw providerError('DESKTOP_ACTIVATION_SESSION_MISSING', 'Desktop Operator activated the application without returning a bound interaction session.', true);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
const screenshot = await callProvider(
|
|
562
|
+
registration,
|
|
563
|
+
`${input.requestId}:screenshot`,
|
|
564
|
+
'desktop_screenshot',
|
|
565
|
+
{
|
|
566
|
+
interaction_id: activationInteractionId,
|
|
567
|
+
scope: 'window',
|
|
568
|
+
window_id: requestedWindowId,
|
|
569
|
+
...(typeof input.args.label === 'string' && input.args.label.trim() ? { label: input.args.label.trim() } : {}),
|
|
570
|
+
},
|
|
571
|
+
input.timeoutMs,
|
|
572
|
+
input.signal,
|
|
573
|
+
dependencies,
|
|
574
|
+
);
|
|
575
|
+
const visualRevision = firstNumber(screenshot, 'visual_revision', 'visualRevision');
|
|
576
|
+
const capturedWindowId = firstNumber(screenshot, 'windowId', 'window_id') ?? requestedWindowId;
|
|
577
|
+
if (!visualRevision || !capturedWindowId) {
|
|
578
|
+
throw providerError('DESKTOP_FOREGROUND_CAPTURE_INVALID', 'Desktop Operator did not return a fresh visual revision for the foreground window.', true);
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
const click = await callProvider(
|
|
582
|
+
registration,
|
|
583
|
+
`${input.requestId}:click`,
|
|
584
|
+
'desktop_pointer_click',
|
|
585
|
+
{
|
|
586
|
+
interaction_id: activationInteractionId,
|
|
587
|
+
window_id: capturedWindowId,
|
|
588
|
+
visual_revision: visualRevision,
|
|
589
|
+
x,
|
|
590
|
+
y,
|
|
591
|
+
},
|
|
592
|
+
input.timeoutMs,
|
|
593
|
+
input.signal,
|
|
594
|
+
dependencies,
|
|
595
|
+
);
|
|
596
|
+
return {
|
|
597
|
+
interactionId: activationInteractionId,
|
|
598
|
+
activationVerified: true,
|
|
599
|
+
windowId: capturedWindowId,
|
|
600
|
+
visualRevision,
|
|
601
|
+
screenshot,
|
|
602
|
+
click,
|
|
603
|
+
};
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
if (registration.pluginId === 'desktop_operator' && input.actionId === 'desktop_key') {
|
|
607
|
+
const sourceInteractionId = typeof input.args.interaction_id === 'string' ? input.args.interaction_id.trim() : '';
|
|
608
|
+
const keys = Array.isArray(input.args.keys) ? input.args.keys : [];
|
|
609
|
+
if (!sourceInteractionId || keys.length === 0) {
|
|
610
|
+
throw providerError('DESKTOP_FOREGROUND_KEY_ARGUMENT_INVALID', 'desktop_key requires interaction_id and at least one key.');
|
|
611
|
+
}
|
|
612
|
+
const sourceStatus = await callProvider(
|
|
613
|
+
registration,
|
|
614
|
+
`${input.requestId}:source-status`,
|
|
615
|
+
'desktop_status',
|
|
616
|
+
{ limit: 500 },
|
|
617
|
+
input.timeoutMs,
|
|
618
|
+
input.signal,
|
|
619
|
+
dependencies,
|
|
620
|
+
);
|
|
621
|
+
const sourceSession = desktopSession(sourceStatus, sourceInteractionId);
|
|
622
|
+
if (!sourceSession) {
|
|
623
|
+
throw providerError('DESKTOP_FOREGROUND_KEY_SESSION_NOT_FOUND', `Desktop session ${sourceInteractionId} is no longer available.`, true);
|
|
624
|
+
}
|
|
625
|
+
const bundleId = firstString(sourceSession, 'bundleIdentifier', 'bundle_id');
|
|
626
|
+
const appName = firstString(sourceSession, 'appName', 'app_name');
|
|
627
|
+
if (!bundleId && !appName) {
|
|
628
|
+
throw providerError('DESKTOP_FOREGROUND_KEY_TARGET_UNAVAILABLE', `Desktop session ${sourceInteractionId} has no stable application identity.`);
|
|
629
|
+
}
|
|
630
|
+
const activation = await openVerifiedDesktopSession(
|
|
631
|
+
registration,
|
|
632
|
+
`${input.requestId}:activate`,
|
|
633
|
+
{ ...(bundleId ? { bundle_id: bundleId } : { app_name: appName }), launch: false, activate: true },
|
|
634
|
+
input.timeoutMs,
|
|
635
|
+
input.signal,
|
|
636
|
+
dependencies,
|
|
637
|
+
);
|
|
638
|
+
const activationInteractionId = firstString(activation, 'interactionId', 'interaction_id');
|
|
639
|
+
if (!activationInteractionId) {
|
|
640
|
+
throw providerError('DESKTOP_ACTIVATION_SESSION_MISSING', 'Desktop Operator activated the application without returning a bound interaction session.', true);
|
|
641
|
+
}
|
|
642
|
+
return await callProvider(
|
|
643
|
+
registration,
|
|
644
|
+
`${input.requestId}:key`,
|
|
645
|
+
'desktop_key',
|
|
646
|
+
{ interaction_id: activationInteractionId, keys },
|
|
647
|
+
input.timeoutMs,
|
|
648
|
+
input.signal,
|
|
649
|
+
dependencies,
|
|
650
|
+
);
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
if (registration.pluginId === 'desktop_operator' && input.actionId === 'desktop_session_open' && input.args.activate === true) {
|
|
654
|
+
return await openVerifiedDesktopSession(
|
|
655
|
+
registration,
|
|
656
|
+
input.requestId,
|
|
657
|
+
input.args,
|
|
658
|
+
input.timeoutMs,
|
|
659
|
+
input.signal,
|
|
660
|
+
dependencies,
|
|
661
|
+
);
|
|
662
|
+
}
|
|
308
663
|
return await callProvider(
|
|
309
664
|
registration,
|
|
310
665
|
input.requestId,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { spawnSync } from 'child_process';
|
|
2
2
|
import { existsSync } from 'fs';
|
|
3
3
|
import { createConnection, type Socket } from 'net';
|
|
4
|
-
import { dirname, isAbsolute, join } from 'path';
|
|
4
|
+
import { dirname, isAbsolute, join, resolve } from 'path';
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
6
6
|
import { resolveBunExecutable } from '../shared/process-environment';
|
|
7
7
|
import { AssistantPluginError } from './errors';
|
|
@@ -178,7 +178,13 @@ export async function callExternalUnixSocket(
|
|
|
178
178
|
export function resolveExternalPluginProbeSidecarPath(
|
|
179
179
|
execPath: string = process.execPath,
|
|
180
180
|
moduleUrl: string = import.meta.url,
|
|
181
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
181
182
|
): string {
|
|
183
|
+
const configuredReleaseRoot = env.FORGE_RELEASE_PATH?.trim();
|
|
184
|
+
if (configuredReleaseRoot) {
|
|
185
|
+
const releaseSidecar = join(resolve(configuredReleaseRoot), 'external-unix-socket-probe.cjs');
|
|
186
|
+
if (existsSync(releaseSidecar)) return releaseSidecar;
|
|
187
|
+
}
|
|
182
188
|
const releaseSibling = join(dirname(execPath), 'external-unix-socket-probe.cjs');
|
|
183
189
|
if (existsSync(releaseSibling)) return releaseSibling;
|
|
184
190
|
const moduleSibling = fileURLToPath(new URL('./external-unix-socket-probe.cjs', moduleUrl));
|
|
@@ -8,6 +8,7 @@ import { iosPluginAdapter } from './ios-adapter';
|
|
|
8
8
|
import { localSystemPluginAdapter } from './local-system-adapter';
|
|
9
9
|
import { pluginManagementAdapter } from './plugin-management-adapter';
|
|
10
10
|
import { resendPluginAdapter } from './resend-adapter';
|
|
11
|
+
import { xiaohongshuPluginAdapter } from './xiaohongshu-publish';
|
|
11
12
|
import type { AssistantPluginAdapter } from './types';
|
|
12
13
|
|
|
13
14
|
const FIRST_PARTY_PLUGIN_ADAPTERS: readonly AssistantPluginAdapter[] = [
|
|
@@ -19,6 +20,7 @@ const FIRST_PARTY_PLUGIN_ADAPTERS: readonly AssistantPluginAdapter[] = [
|
|
|
19
20
|
googleCalendarPluginAdapter,
|
|
20
21
|
googleTasksPluginAdapter,
|
|
21
22
|
resendPluginAdapter,
|
|
23
|
+
xiaohongshuPluginAdapter,
|
|
22
24
|
localSystemPluginAdapter,
|
|
23
25
|
pluginManagementAdapter,
|
|
24
26
|
];
|
|
@@ -7,6 +7,11 @@ import {
|
|
|
7
7
|
refreshIssueWithGitHubPlugin,
|
|
8
8
|
saveGitHubPluginConfig,
|
|
9
9
|
} from '../../cli/github/plugin';
|
|
10
|
+
import {
|
|
11
|
+
dispatchGitHubWorkflow,
|
|
12
|
+
listGitHubWorkflowRuns,
|
|
13
|
+
listGitHubWorkflows,
|
|
14
|
+
} from '../../cli/github/github';
|
|
10
15
|
import type {
|
|
11
16
|
AssistantPluginActionDescriptor,
|
|
12
17
|
AssistantPluginActionExecutionInput,
|
|
@@ -37,6 +42,20 @@ function githubPermissions(ready: boolean, projectConfigured: boolean): Assistan
|
|
|
37
42
|
granted: ready && projectConfigured,
|
|
38
43
|
required: projectConfigured,
|
|
39
44
|
},
|
|
45
|
+
{
|
|
46
|
+
scope: 'github:actions:read',
|
|
47
|
+
mode: 'read',
|
|
48
|
+
description: 'List GitHub Actions workflows and recent workflow runs.',
|
|
49
|
+
granted: ready,
|
|
50
|
+
required: false,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
scope: 'github:actions:write',
|
|
54
|
+
mode: 'write',
|
|
55
|
+
description: 'Dispatch an explicitly named workflow_dispatch workflow.',
|
|
56
|
+
granted: ready,
|
|
57
|
+
required: false,
|
|
58
|
+
},
|
|
40
59
|
{
|
|
41
60
|
scope: 'controller:issues:write',
|
|
42
61
|
mode: 'write',
|
|
@@ -63,6 +82,13 @@ function githubCapabilities(): AssistantPluginCapability[] {
|
|
|
63
82
|
scopes: ['github:projects:write'],
|
|
64
83
|
actions: ['configure', 'publish_issue'],
|
|
65
84
|
},
|
|
85
|
+
{
|
|
86
|
+
capabilityId: 'actions-ci',
|
|
87
|
+
title: 'GitHub Actions CI',
|
|
88
|
+
description: 'List workflow definitions and runs, and dispatch an explicitly named workflow_dispatch workflow.',
|
|
89
|
+
scopes: ['github:actions:read', 'github:actions:write'],
|
|
90
|
+
actions: ['list_workflows', 'list_workflow_runs', 'dispatch_workflow'],
|
|
91
|
+
},
|
|
66
92
|
];
|
|
67
93
|
}
|
|
68
94
|
|
|
@@ -144,6 +170,74 @@ function githubActions(): AssistantPluginActionDescriptor[] {
|
|
|
144
170
|
additionalProperties: false,
|
|
145
171
|
},
|
|
146
172
|
},
|
|
173
|
+
{
|
|
174
|
+
actionId: 'list_workflows',
|
|
175
|
+
title: 'List GitHub Actions workflows',
|
|
176
|
+
description: 'List workflow definitions for the configured GitHub repository.',
|
|
177
|
+
readOnly: true,
|
|
178
|
+
risk: 'readonly',
|
|
179
|
+
confirmation: 'none',
|
|
180
|
+
defaultTimeoutMs: 30_000,
|
|
181
|
+
cancellable: true,
|
|
182
|
+
idempotent: true,
|
|
183
|
+
scopes: ['github:actions:read'],
|
|
184
|
+
resourceClaims: [{ resource: 'remote', mode: 'read' }],
|
|
185
|
+
argumentsSchema: {
|
|
186
|
+
type: 'object',
|
|
187
|
+
properties: {
|
|
188
|
+
limit: { type: 'number', minimum: 1, maximum: 100 },
|
|
189
|
+
include_disabled: { type: 'boolean' },
|
|
190
|
+
},
|
|
191
|
+
additionalProperties: false,
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
actionId: 'list_workflow_runs',
|
|
196
|
+
title: 'List GitHub Actions runs',
|
|
197
|
+
description: 'List recent GitHub Actions workflow runs with optional workflow, branch, and status filters.',
|
|
198
|
+
readOnly: true,
|
|
199
|
+
risk: 'readonly',
|
|
200
|
+
confirmation: 'none',
|
|
201
|
+
defaultTimeoutMs: 30_000,
|
|
202
|
+
cancellable: true,
|
|
203
|
+
idempotent: true,
|
|
204
|
+
scopes: ['github:actions:read'],
|
|
205
|
+
resourceClaims: [{ resource: 'remote', mode: 'read' }],
|
|
206
|
+
argumentsSchema: {
|
|
207
|
+
type: 'object',
|
|
208
|
+
properties: {
|
|
209
|
+
workflow: { type: 'string' },
|
|
210
|
+
branch: { type: 'string' },
|
|
211
|
+
status: { type: 'string' },
|
|
212
|
+
limit: { type: 'number', minimum: 1, maximum: 100 },
|
|
213
|
+
include_disabled: { type: 'boolean' },
|
|
214
|
+
},
|
|
215
|
+
additionalProperties: false,
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
actionId: 'dispatch_workflow',
|
|
220
|
+
title: 'Dispatch GitHub Actions workflow',
|
|
221
|
+
description: 'Create a workflow_dispatch event for one explicitly named workflow.',
|
|
222
|
+
readOnly: false,
|
|
223
|
+
risk: 'remote_write',
|
|
224
|
+
confirmation: 'authorization',
|
|
225
|
+
defaultTimeoutMs: 60_000,
|
|
226
|
+
cancellable: true,
|
|
227
|
+
idempotent: false,
|
|
228
|
+
scopes: ['github:actions:write'],
|
|
229
|
+
resourceClaims: [{ resource: 'remote', mode: 'exclusive' }],
|
|
230
|
+
argumentsSchema: {
|
|
231
|
+
type: 'object',
|
|
232
|
+
properties: {
|
|
233
|
+
workflow: { type: 'string' },
|
|
234
|
+
ref: { type: 'string' },
|
|
235
|
+
inputs: { type: 'object', additionalProperties: { type: ['string', 'number', 'boolean'] } },
|
|
236
|
+
},
|
|
237
|
+
required: ['workflow'],
|
|
238
|
+
additionalProperties: false,
|
|
239
|
+
},
|
|
240
|
+
},
|
|
147
241
|
{
|
|
148
242
|
actionId: 'close_issue',
|
|
149
243
|
title: 'Close linked GitHub issue',
|
|
@@ -252,6 +346,37 @@ export async function executeGitHubPluginAction(input: AssistantPluginActionExec
|
|
|
252
346
|
return { issue: publishIssueWithGitHubPlugin(input.repoRoot, String(input.args.issue_id ?? '').trim()) };
|
|
253
347
|
case 'refresh_issue':
|
|
254
348
|
return refreshIssueWithGitHubPlugin(input.repoRoot, String(input.args.issue_id ?? '').trim()) as Record<string, unknown>;
|
|
349
|
+
case 'list_workflows': {
|
|
350
|
+
const config = loadGitHubPluginConfig(input.repoRoot);
|
|
351
|
+
return {
|
|
352
|
+
workflows: listGitHubWorkflows(input.repoRoot, config.repository, {
|
|
353
|
+
limit: typeof input.args.limit === 'number' ? input.args.limit : undefined,
|
|
354
|
+
includeDisabled: input.args.include_disabled === true,
|
|
355
|
+
}),
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
case 'list_workflow_runs': {
|
|
359
|
+
const config = loadGitHubPluginConfig(input.repoRoot);
|
|
360
|
+
return {
|
|
361
|
+
runs: listGitHubWorkflowRuns(input.repoRoot, config.repository, {
|
|
362
|
+
workflow: typeof input.args.workflow === 'string' ? input.args.workflow : undefined,
|
|
363
|
+
branch: typeof input.args.branch === 'string' ? input.args.branch : undefined,
|
|
364
|
+
status: typeof input.args.status === 'string' ? input.args.status : undefined,
|
|
365
|
+
limit: typeof input.args.limit === 'number' ? input.args.limit : undefined,
|
|
366
|
+
includeDisabled: input.args.include_disabled === true,
|
|
367
|
+
}),
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
case 'dispatch_workflow': {
|
|
371
|
+
const config = loadGitHubPluginConfig(input.repoRoot);
|
|
372
|
+
return dispatchGitHubWorkflow(input.repoRoot, config.repository, {
|
|
373
|
+
workflow: String(input.args.workflow ?? ''),
|
|
374
|
+
ref: typeof input.args.ref === 'string' ? input.args.ref : undefined,
|
|
375
|
+
inputs: input.args.inputs && typeof input.args.inputs === 'object' && !Array.isArray(input.args.inputs)
|
|
376
|
+
? input.args.inputs as Record<string, string | number | boolean>
|
|
377
|
+
: undefined,
|
|
378
|
+
});
|
|
379
|
+
}
|
|
255
380
|
case 'close_issue':
|
|
256
381
|
return { issue: closeIssueWithGitHubPlugin(input.repoRoot, String(input.args.issue_id ?? '').trim()) };
|
|
257
382
|
default:
|