@moretea-labs/forge 1.5.0-rc.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 +120 -0
- package/CHANGELOG.md +36 -0
- package/CLAUDE.md +120 -0
- package/CODE_OF_CONDUCT.md +23 -0
- package/CONTRIBUTING.md +77 -0
- package/LICENSE +22 -0
- package/NOTICE +9 -0
- package/README.en.md +5 -0
- package/README.es.md +12 -0
- package/README.fr.md +12 -0
- package/README.ja.md +12 -0
- package/README.md +132 -0
- package/README.zh-CN.md +84 -0
- package/SECURITY.md +50 -0
- package/SKILL.md +431 -0
- package/SUPPORT.md +31 -0
- package/THIRD_PARTY_NOTICES.md +18 -0
- package/agents/openai.yaml +4 -0
- package/assets/AGENTS.md +68 -0
- package/assets/CLAUDE.md +68 -0
- package/assets/branding/README.md +10 -0
- package/assets/branding/forge-controller-flow.mmd +8 -0
- package/assets/hooks/AGENTS.md +75 -0
- package/assets/hooks/CLAUDE.md +75 -0
- package/assets/hooks/anti-simplification.sh +12 -0
- package/assets/hooks/changelog-guard.sh +80 -0
- package/assets/hooks/codex.hooks.template.json +60 -0
- package/assets/hooks/first-principles-guard.sh +72 -0
- package/assets/hooks/hook-input.sh +618 -0
- package/assets/hooks/lib/session-state.sh +106 -0
- package/assets/hooks/lib/workflow-state.sh +1730 -0
- package/assets/hooks/post-bash.sh +215 -0
- package/assets/hooks/post-edit-guard.sh +256 -0
- package/assets/hooks/post-tool-observer.sh +99 -0
- package/assets/hooks/pre-edit-guard.sh +240 -0
- package/assets/hooks/prompt-guard.sh +1077 -0
- package/assets/hooks/run-hook.sh +67 -0
- package/assets/hooks/security-sentinel.sh +115 -0
- package/assets/hooks/session-start-context.sh +593 -0
- package/assets/hooks/settings.template.json +60 -0
- package/assets/hooks/stop-orchestrator.sh +171 -0
- package/assets/hooks/subagent-return-channel-guard.sh +107 -0
- package/assets/hooks/worktree-guard.sh +39 -0
- package/assets/initializer-question-pack.v1.json +132 -0
- package/assets/initializer-question-pack.v1.schema.json +46 -0
- package/assets/initializer-question-pack.v2.json +174 -0
- package/assets/initializer-question-pack.v3.json +206 -0
- package/assets/initializer-question-pack.v3.schema.json +92 -0
- package/assets/initializer-question-pack.v4.json +557 -0
- package/assets/initializer-question-pack.v4.schema.json +169 -0
- package/assets/partials/01-header.partial.md +10 -0
- package/assets/partials/02-iron-rules.partial.md +30 -0
- package/assets/partials/03-philosophy.partial.md +32 -0
- package/assets/partials/04-project-structure.partial.md +56 -0
- package/assets/partials/05-workflow.partial.md +79 -0
- package/assets/partials/06-cloudflare.partial.md +20 -0
- package/assets/partials/07-footer.partial.md +38 -0
- package/assets/partials/08-orchestration.partial.md +49 -0
- package/assets/partials/09-compact-instructions.partial.md +11 -0
- package/assets/partials/_assembly-order.md +40 -0
- package/assets/partials-agents/01-header.partial.md +8 -0
- package/assets/partials-agents/02-operating-mode.partial.md +44 -0
- package/assets/partials-agents/03-orchestration.partial.md +45 -0
- package/assets/partials-agents/04-task-protocol.partial.md +69 -0
- package/assets/partials-agents/05-coding-constraints.partial.md +20 -0
- package/assets/partials-agents/06-quality-safety.partial.md +23 -0
- package/assets/partials-agents/07-cloudflare.partial.md +9 -0
- package/assets/partials-agents/08-deep-docs.partial.md +32 -0
- package/assets/plan-map.json +301 -0
- package/assets/plugin-registry.v1.json +8 -0
- package/assets/project-structures/ai-native-collaborative-editor.txt +25 -0
- package/assets/project-structures/ai-native-product-copilot.txt +21 -0
- package/assets/project-structures/ai-native-runtime-console.txt +25 -0
- package/assets/project-structures/ai-native-sidecar-kernel.txt +19 -0
- package/assets/project-structures/astro-ssr.txt +25 -0
- package/assets/project-structures/expo-nativewind.txt +52 -0
- package/assets/project-structures/monorepo.txt +63 -0
- package/assets/project-structures/remix.txt +50 -0
- package/assets/project-structures/tanstack-start-workers.txt +51 -0
- package/assets/project-structures/vite-tanstack.txt +58 -0
- package/assets/reference-configs/AGENTS.md +13 -0
- package/assets/reference-configs/CLAUDE.md +13 -0
- package/assets/reference-configs/agentic-development-flow.md +94 -0
- package/assets/reference-configs/ai-workflows.md +14 -0
- package/assets/reference-configs/changelog-versioning.md +13 -0
- package/assets/reference-configs/coding-standards.md +14 -0
- package/assets/reference-configs/development-protocol.md +21 -0
- package/assets/reference-configs/document-generation.md +38 -0
- package/assets/reference-configs/evaluator-rubric.md +19 -0
- package/assets/reference-configs/external-tooling.md +374 -0
- package/assets/reference-configs/git-strategy.md +14 -0
- package/assets/reference-configs/global-working-rules.md +64 -0
- package/assets/reference-configs/handoff-protocol.md +38 -0
- package/assets/reference-configs/harness-overview.md +124 -0
- package/assets/reference-configs/heartbeat-triage.md +57 -0
- package/assets/reference-configs/hook-operations.md +96 -0
- package/assets/reference-configs/release-deploy.md +40 -0
- package/assets/reference-configs/spa-day-protocol.md +14 -0
- package/assets/reference-configs/sprint-contracts.md +89 -0
- package/assets/reference-configs/workflow-orchestration.md +14 -0
- package/assets/skill-hooks.json +41 -0
- package/assets/skill-version.json +189 -0
- package/assets/skills/claude-review/SKILL.md +231 -0
- package/assets/skills/codex-review/SKILL.md +103 -0
- package/assets/templates/AGENTS.md +13 -0
- package/assets/templates/CLAUDE.md +13 -0
- package/assets/templates/architecture.template.md +80 -0
- package/assets/templates/brief.template.md +38 -0
- package/assets/templates/contract.template.md +104 -0
- package/assets/templates/decisions.template.md +85 -0
- package/assets/templates/factor-factory/factor-backtest-report.template.md +36 -0
- package/assets/templates/factor-factory/factor-hypothesis.template.md +30 -0
- package/assets/templates/factor-factory/factor-registry.template.json +5 -0
- package/assets/templates/gitignore.template +53 -0
- package/assets/templates/guides/metro-esm-gotchas.template.md +46 -0
- package/assets/templates/helpers/architecture-event.ts +822 -0
- package/assets/templates/helpers/architecture-queue.sh +647 -0
- package/assets/templates/helpers/archive-architecture-request.sh +244 -0
- package/assets/templates/helpers/archive-workflow.sh +295 -0
- package/assets/templates/helpers/capability-config.ts +394 -0
- package/assets/templates/helpers/capability-resolver.ts +505 -0
- package/assets/templates/helpers/capture-plan.sh +335 -0
- package/assets/templates/helpers/check-agent-tooling.sh +1533 -0
- package/assets/templates/helpers/check-architecture-sync.sh +287 -0
- package/assets/templates/helpers/check-brain-manifest.sh +255 -0
- package/assets/templates/helpers/check-context-files.sh +49 -0
- package/assets/templates/helpers/check-deploy-sql-order.sh +117 -0
- package/assets/templates/helpers/check-skill-version.ts +193 -0
- package/assets/templates/helpers/check-task-sync.sh +65 -0
- package/assets/templates/helpers/check-task-workflow.sh +1002 -0
- package/assets/templates/helpers/codex-handoff-resume.sh +269 -0
- package/assets/templates/helpers/context-contract-sync.sh +516 -0
- package/assets/templates/helpers/contract-run.ts +465 -0
- package/assets/templates/helpers/contract-worktree.sh +725 -0
- package/assets/templates/helpers/ensure-task-workflow.sh +1218 -0
- package/assets/templates/helpers/harness-trace-grade.sh +150 -0
- package/assets/templates/helpers/heartbeat-triage.sh +361 -0
- package/assets/templates/helpers/inspect-project-state.ts +280 -0
- package/assets/templates/helpers/maintenance-triage.sh +167 -0
- package/assets/templates/helpers/migrate-project-template.sh +54 -0
- package/assets/templates/helpers/migrate-workflow-docs.ts +413 -0
- package/assets/templates/helpers/new-plan.sh +183 -0
- package/assets/templates/helpers/new-spec.sh +50 -0
- package/assets/templates/helpers/new-sprint.sh +49 -0
- package/assets/templates/helpers/plan-to-todo.sh +799 -0
- package/assets/templates/helpers/prepare-codex-handoff.sh +203 -0
- package/assets/templates/helpers/prepare-handoff.sh +81 -0
- package/assets/templates/helpers/refresh-current-status.sh +469 -0
- package/assets/templates/helpers/select-agent-context-blocks.sh +66 -0
- package/assets/templates/helpers/ship-worktrees.sh +561 -0
- package/assets/templates/helpers/sprint-backlog.sh +837 -0
- package/assets/templates/helpers/summarize-failures.sh +125 -0
- package/assets/templates/helpers/switch-plan.sh +153 -0
- package/assets/templates/helpers/sync-brain-docs.sh +381 -0
- package/assets/templates/helpers/verify-contract.sh +705 -0
- package/assets/templates/helpers/verify-sprint.sh +680 -0
- package/assets/templates/helpers/workflow-contract.ts +202 -0
- package/assets/templates/helpers/workstream-sync.sh +263 -0
- package/assets/templates/implementation-notes.template.md +37 -0
- package/assets/templates/packages.template.md +45 -0
- package/assets/templates/plan.template.md +77 -0
- package/assets/templates/prd.template.md +165 -0
- package/assets/templates/research.template.md +25 -0
- package/assets/templates/review.template.md +78 -0
- package/assets/templates/spec.template.md +31 -0
- package/assets/templates/sprint.template.md +69 -0
- package/assets/templates/tech-stack.template.md +57 -0
- package/assets/versions.json +77 -0
- package/assets/workflow-contract.v1.json +671 -0
- package/bin/forge-desktop-helper.mjs +204 -0
- package/bin/forge-hook.mjs +32 -0
- package/bin/forge-runtime-service.mjs +34 -0
- package/bin/forge-runtime.mjs +30 -0
- package/bin/forge.mjs +32 -0
- package/docs/CHANGELOG.md +978 -0
- package/docs/README.md +72 -0
- package/docs/README.zh-CN.md +58 -0
- package/docs/architecture/chatgpt-handoff-facade.md +393 -0
- package/docs/architecture/current/README.md +158 -0
- package/docs/architecture/current/approved-target-architecture.zh-CN.md +1501 -0
- package/docs/architecture/current/architecture-invariants.md +331 -0
- package/docs/architecture/current/automation-and-schedule-engine.md +453 -0
- package/docs/architecture/current/codegraph-context-provider.md +226 -0
- package/docs/architecture/current/control-plane-authority-inventory.md +82 -0
- package/docs/architecture/current/controller-repository-decoupling.md +148 -0
- package/docs/architecture/current/dispatch-and-agent-strategy.md +354 -0
- package/docs/architecture/current/entity-model.md +619 -0
- package/docs/architecture/current/external-plugin-governance.md +396 -0
- package/docs/architecture/current/failure-recovery.md +471 -0
- package/docs/architecture/current/governance.md +213 -0
- package/docs/architecture/current/human-interaction-plane.md +87 -0
- package/docs/architecture/current/implementation-status.md +128 -0
- package/docs/architecture/current/job-and-run-lifecycle.md +413 -0
- package/docs/architecture/current/local-workspace-target-grants.md +70 -0
- package/docs/architecture/current/migration-roadmap.md +105 -0
- package/docs/architecture/current/multi-repository-execution.md +371 -0
- package/docs/architecture/current/operations-runbook.md +45 -0
- package/docs/architecture/current/peer-supercontroller-runtime.md +32 -0
- package/docs/architecture/current/personal-assistant-plugin-baseline.md +207 -0
- package/docs/architecture/current/repository-access-modes.md +102 -0
- package/docs/architecture/current/route-policy.md +15 -0
- package/docs/architecture/current/route-session-concurrency.md +85 -0
- package/docs/architecture/current/runtime-architecture-simplification.md +214 -0
- package/docs/architecture/current/runtime-directory-map.md +49 -0
- package/docs/architecture/current/runtime-health-and-resource-lifecycle.md +85 -0
- package/docs/architecture/current/scheduler-and-resource-claims.md +432 -0
- package/docs/architecture/current/session-aware-execution-and-authorization.md +77 -0
- package/docs/architecture/current/system-overview.md +144 -0
- package/docs/architecture/current/target-requirements-traceability.md +202 -0
- package/docs/architecture/current/thin-harness-governance-policy.md +32 -0
- package/docs/architecture/current/thin-harness-v1.md +313 -0
- package/docs/architecture/current/verification-and-release-gates.md +391 -0
- package/docs/architecture/decisions/20260801-controller-home-sqlite-state.md +100 -0
- package/docs/architecture/decisions/20260803-canonical-skill-surface.md +40 -0
- package/docs/architecture/decisions/20260803-release-identity-binding-and-exit-policy.md +53 -0
- package/docs/architecture/diagrams/.gitkeep +1 -0
- package/docs/architecture/diagrams/agentic-dev-plugin-architecture.html +186 -0
- package/docs/architecture/domains/.gitkeep +0 -0
- package/docs/architecture/domains/public-surface.md +30 -0
- package/docs/architecture/domains/runtime-harness.md +33 -0
- package/docs/architecture/domains/verification.md +33 -0
- package/docs/architecture/domains/workflow-engine.md +30 -0
- package/docs/architecture/global-hook-runtime.md +162 -0
- package/docs/architecture/history.md +38 -0
- package/docs/architecture/index.md +114 -0
- package/docs/architecture/ios-semantic-automation-provider-v2.md +166 -0
- package/docs/architecture/modules/.gitkeep +0 -0
- package/docs/architecture/modules/controller-runtime/transport-lifecycle.md +24 -0
- package/docs/architecture/requests/.gitkeep +1 -0
- package/docs/architecture/requests/archive/2026/20260528-154740-ai-hooks-ai-hooks-hook-input-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-154816-assets-hooks-assets-hooks-hook-input-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-161851-ai-harness-workflow-contract-json-ai-harness-workflow-contract-json.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-161853-scripts-check-task-workflow-sh-scripts-check-task-workflow-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-161911-assets-workflow-contract-v1-json-assets-workflow-contract-v1-json.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-222416-ai-hooks-ai-hooks-hook-input-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-222444-ai-hooks-ai-hooks-pre-edit-guard-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-222457-ai-hooks-ai-hooks-pre-edit-guard-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-222648-ai-hooks-ai-hooks-pre-edit-guard-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-222705-ai-hooks-ai-hooks-worktree-guard-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-222726-ai-hooks-ai-hooks-prompt-guard-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-222727-ai-hooks-ai-hooks-prompt-guard-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-224736-ai-hooks-ai-hooks-hook-input-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-233259-ai-hooks-ai-hooks-prompt-guard-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-233335-assets-hooks-assets-hooks-prompt-guard-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-233456-ai-hooks-ai-hooks-prompt-guard-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-233457-assets-hooks-assets-hooks-prompt-guard-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-233637-ai-hooks-ai-hooks-prompt-guard-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260528-233638-assets-hooks-assets-hooks-prompt-guard-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260529-000322-root-package-json.md +59 -0
- package/docs/architecture/requests/archive/2026/20260529-004238-ai-hooks-ai-hooks-lib-workflow-state-sh.md +59 -0
- package/docs/architecture/requests/archive/2026/20260529-020654-ai-harness-policy-json-ai-harness-policy-json.md +63 -0
- package/docs/architecture/requests/archive/2026/20260529-094236-ai-hooks-ai-hooks-prompt-guard-sh.md +60 -0
- package/docs/architecture/requests/archive/2026/20260529-094323-assets-hooks-assets-hooks-prompt-guard-sh.md +60 -0
- package/docs/architecture/requests/archive/2026/20260529-094331-ai-hooks-ai-hooks-prompt-guard-sh.md +60 -0
- package/docs/architecture/requests/archive/2026/20260529-094339-assets-hooks-assets-hooks-prompt-guard-sh.md +60 -0
- package/docs/architecture/requests/archive/2026/20260529-094430-assets-hooks-assets-hooks-session-start-context-sh.md +60 -0
- package/docs/architecture/requests/archive/2026/20260529-094446-ai-hooks-ai-hooks-session-start-context-sh.md +60 -0
- package/docs/architecture/requests/archive/2026/20260613-002040-runtime-harness-hook-adapters.md +68 -0
- package/docs/architecture/requests/archive/2026/root.md +68 -0
- package/docs/architecture/requests/archive/2026/runtime-harness-hook-adapters.md +76 -0
- package/docs/architecture/requests/archive/2026/verification-evals-checks.md +68 -0
- package/docs/architecture/requests/archive/2026/workflow-engine-contract-assets.md +69 -0
- package/docs/architecture/reviews/2026-07-11-access-surface-review.md +99 -0
- package/docs/architecture/snapshots/.gitkeep +1 -0
- package/docs/forge-autonomous-goal-loop.md +7 -0
- package/docs/forge-chatgpt-browser-engine.md +11 -0
- package/docs/forge-chatgpt-mcp-setup.md +239 -0
- package/docs/forge-chatgpt-supervised-automation.md +11 -0
- package/docs/forge-github-issue-launcher.md +7 -0
- package/docs/forge-plugin-management.md +95 -0
- package/docs/forge-provider-configuration.md +7 -0
- package/docs/forge-runtime-self-healing-loop.md +7 -0
- package/docs/images/forge-banner-cn.svg +1 -0
- package/docs/images/forge-banner.svg +1 -0
- package/docs/images/forge-controller-flow.svg +1 -0
- package/docs/images/image.png +0 -0
- package/docs/images/repo-harness-gptpro-cn.png +0 -0
- package/docs/images/repo-harness-gptpro.png +0 -0
- package/docs/images/repo-harness-hook-carrot.png +0 -0
- package/docs/operations/chatgpt-personal-assistant-runtime.md +83 -0
- package/docs/operations/checkout-route-integrity.md +22 -0
- package/docs/operations/controller-browser-plugin.md +299 -0
- package/docs/operations/controller-desktop-plugin.md +112 -0
- package/docs/operations/controller-performance-and-502.md +126 -0
- package/docs/operations/controller-reliability-runbook.md +134 -0
- package/docs/operations/environment-hardening.md +50 -0
- package/docs/operations/features.md +45 -0
- package/docs/operations/features.zh-CN.md +45 -0
- package/docs/operations/github-repository.md +60 -0
- package/docs/operations/gmail-assistant-routines.md +186 -0
- package/docs/operations/homebrew.md +26 -0
- package/docs/operations/local-system-assistant.md +46 -0
- package/docs/operations/local-system-assistant.zh-CN.md +46 -0
- package/docs/operations/mcp-tool-exposure.md +58 -0
- package/docs/operations/mobile-intents-shortcuts.md +117 -0
- package/docs/operations/open-source-release-hygiene.md +31 -0
- package/docs/operations/personal-assistant-operator-guide.md +61 -0
- package/docs/operations/platform-support.md +62 -0
- package/docs/operations/platform-support.zh-CN.md +61 -0
- package/docs/operations/provider-configuration.md +31 -0
- package/docs/operations/releasing.md +86 -0
- package/docs/operations/releasing.zh-CN.md +86 -0
- package/docs/operations/route-session-concurrency-baseline.json +893 -0
- package/docs/operations/route-session-concurrency-baseline.md +94 -0
- package/docs/operations/runtime-performance-diagnostics.md +14 -0
- package/docs/operations/sqlite-control-plane-recovery.md +65 -0
- package/docs/operations/standalone-disaster-recovery.md +136 -0
- package/docs/operations/troubleshooting.md +72 -0
- package/docs/operations/troubleshooting.zh-CN.md +70 -0
- package/docs/public-usage-guide.md +33 -0
- package/docs/public-usage-guide.zh-CN.md +33 -0
- package/docs/tutorials/01-install-and-start.md +93 -0
- package/docs/tutorials/01-install-and-start.zh-CN.md +93 -0
- package/docs/tutorials/02-connect-chatgpt.md +82 -0
- package/docs/tutorials/02-connect-chatgpt.zh-CN.md +80 -0
- package/docs/tutorials/03-first-repository-task.md +57 -0
- package/docs/tutorials/03-first-repository-task.zh-CN.md +57 -0
- package/docs/tutorials/README.md +13 -0
- package/docs/tutorials/README.zh-CN.md +13 -0
- package/docs/wiki/Architecture.md +85 -0
- package/docs/wiki/Core-Concepts.md +27 -0
- package/docs/wiki/Home.md +36 -0
- package/docs/wiki/Implementation.md +172 -0
- package/docs/wiki/Installation.md +50 -0
- package/docs/wiki/Integrations.md +29 -0
- package/docs/wiki/Operations.md +26 -0
- package/docs/wiki/Quick-Start.md +46 -0
- package/docs/wiki/Releases-and-Upgrades.md +34 -0
- package/docs/wiki/Runtime-Architecture.md +50 -0
- package/docs/wiki/Security-Model.md +31 -0
- package/docs/wiki/Troubleshooting.md +38 -0
- package/docs/wiki/Work-Lifecycle.md +31 -0
- package/docs/wiki/_Sidebar.md +21 -0
- package/install.ps1 +48 -0
- package/install.sh +66 -0
- package/package.json +156 -0
- package/scripts/activate-source-baseline.ts +335 -0
- package/scripts/architecture-event.ts +822 -0
- package/scripts/architecture-queue.sh +647 -0
- package/scripts/archive-architecture-request.sh +244 -0
- package/scripts/archive-workflow.sh +295 -0
- package/scripts/assemble-template.ts +1172 -0
- package/scripts/benchmark-controller-hotpath.ts +212 -0
- package/scripts/benchmark-controller-round2.ts +139 -0
- package/scripts/benchmark-ios-agent-device.ts +514 -0
- package/scripts/benchmark-route-session-concurrency.ts +714 -0
- package/scripts/benchmark-thin-harness-gateway-ab.ts +632 -0
- package/scripts/benchmark-thin-harness-mcp-e2e.ts +479 -0
- package/scripts/benchmark-thin-harness.ts +251 -0
- package/scripts/bootstrap-runtime-maintenance-recovery.sh +183 -0
- package/scripts/canary-global-hook.sh +263 -0
- package/scripts/capability-config.ts +394 -0
- package/scripts/capability-resolver.ts +505 -0
- package/scripts/capture-plan.sh +335 -0
- package/scripts/check-agent-tooling.sh +1549 -0
- package/scripts/check-architecture-sync.sh +373 -0
- package/scripts/check-brain-manifest.sh +255 -0
- package/scripts/check-ci.sh +16 -0
- package/scripts/check-context-files.sh +49 -0
- package/scripts/check-deploy-sql-order.sh +117 -0
- package/scripts/check-mcp-compatibility.ts +93 -0
- package/scripts/check-npm-release.sh +32 -0
- package/scripts/check-open-source-tracked-surface.sh +146 -0
- package/scripts/check-package-identity.mjs +117 -0
- package/scripts/check-platform-support.mjs +79 -0
- package/scripts/check-public-docs.sh +105 -0
- package/scripts/check-public-release-surface.sh +19 -0
- package/scripts/check-release-published.sh +57 -0
- package/scripts/check-release-readiness.sh +43 -0
- package/scripts/check-release-version.mjs +74 -0
- package/scripts/check-runtime-architecture.mjs +593 -0
- package/scripts/check-runtime-env.mjs +89 -0
- package/scripts/check-skill-version.ts +193 -0
- package/scripts/check-tarball-install-smoke.sh +66 -0
- package/scripts/check-task-sync.sh +65 -0
- package/scripts/check-task-workflow.sh +1002 -0
- package/scripts/check-third-party-notices.mjs +36 -0
- package/scripts/codex-handoff-resume.sh +269 -0
- package/scripts/complete-control-plane-cutover.ts +126 -0
- package/scripts/context-contract-sync.sh +516 -0
- package/scripts/contract-run.ts +465 -0
- package/scripts/contract-worktree.sh +725 -0
- package/scripts/controller-ngrok-rotation.sh +678 -0
- package/scripts/create-project-dirs.sh +282 -0
- package/scripts/ensure-codegraph.sh +16 -0
- package/scripts/ensure-task-workflow.sh +1218 -0
- package/scripts/export-requirement-portfolio.ts +28 -0
- package/scripts/factor-lab-check.sh +73 -0
- package/scripts/factor-lab-new.sh +96 -0
- package/scripts/factor-lab-promote.sh +86 -0
- package/scripts/factor-lab-reject.sh +68 -0
- package/scripts/harness-trace-grade.sh +150 -0
- package/scripts/heartbeat-triage.sh +361 -0
- package/scripts/hook-dispatch-diet-report.ts +234 -0
- package/scripts/hook-shim.sh +93 -0
- package/scripts/init-project.sh +505 -0
- package/scripts/initializer-question-pack.ts +200 -0
- package/scripts/inspect-project-state.ts +280 -0
- package/scripts/install-desktop-operator-registration.ts +45 -0
- package/scripts/install-standalone-recovery.ts +74 -0
- package/scripts/lib/AGENTS.md +13 -0
- package/scripts/lib/CLAUDE.md +13 -0
- package/scripts/lib/controller-home-env.sh +69 -0
- package/scripts/lib/project-init-lib.sh +2759 -0
- package/scripts/load-standalone-recovery.sh +17 -0
- package/scripts/loop-engine-cutover-gate.ts +324 -0
- package/scripts/maintenance-triage.sh +167 -0
- package/scripts/migrate-project-template.sh +1189 -0
- package/scripts/migrate-requirement-portfolio.ts +86 -0
- package/scripts/migrate-workflow-docs.ts +413 -0
- package/scripts/new-plan.sh +183 -0
- package/scripts/new-spec.sh +50 -0
- package/scripts/new-sprint.sh +49 -0
- package/scripts/open-source-audit-allowlist.txt +46 -0
- package/scripts/package-source-archive.sh +147 -0
- package/scripts/plan-to-todo.sh +799 -0
- package/scripts/prepare-codex-handoff.sh +203 -0
- package/scripts/prepare-handoff.sh +81 -0
- package/scripts/public-release-files.txt +39 -0
- package/scripts/public-release.ts +174 -0
- package/scripts/publish-release-tarball.sh +27 -0
- package/scripts/refresh-current-status.sh +469 -0
- package/scripts/refresh-ios-physical-runtime.ts +196 -0
- package/scripts/repair-executable-modes.ts +8 -0
- package/scripts/rollout-all-registered-repos.sh +7 -0
- package/scripts/route-nl-vs-ts-eval.ts +679 -0
- package/scripts/run-bun-test-file.ts +182 -0
- package/scripts/run-governed-gate.ts +140 -0
- package/scripts/run-mobile-monitor-bridge.ts +71 -0
- package/scripts/run-skill-evals.ts +1022 -0
- package/scripts/run-skill-hook.ts +244 -0
- package/scripts/run-supervised-command.ts +24 -0
- package/scripts/run-tests-portable.sh +20 -0
- package/scripts/select-agent-context-blocks.sh +66 -0
- package/scripts/setup-plugins.sh +43 -0
- package/scripts/ship-worktrees.sh +561 -0
- package/scripts/smoke-browser-cdp-bridge.ts +93 -0
- package/scripts/smoke-chatgpt-supervised-automation.ts +208 -0
- package/scripts/smoke-ios-physical-device.ts +114 -0
- package/scripts/smoke-mcp-http-runtime.ts +216 -0
- package/scripts/smoke-mcp-tool-surface.ts +117 -0
- package/scripts/smoke-runtime-recovery.ts +220 -0
- package/scripts/smoke-schedule-engine.ts +283 -0
- package/scripts/sprint-backlog.sh +837 -0
- package/scripts/stage-runtime-release.ts +38 -0
- package/scripts/summarize-failures.sh +125 -0
- package/scripts/switch-plan.sh +153 -0
- package/scripts/sync-brain-docs.sh +381 -0
- package/scripts/sync-codex-installed-copies.sh +183 -0
- package/scripts/test-governance.ts +75 -0
- package/scripts/verify-contract.sh +705 -0
- package/scripts/verify-forge-runtime.sh +31 -0
- package/scripts/verify-sprint.sh +680 -0
- package/scripts/windows-paths.d.mts +7 -0
- package/scripts/windows-paths.mjs +28 -0
- package/scripts/workflow-contract.ts +206 -0
- package/scripts/workstream-sync.sh +263 -0
- package/src/cli/agent-jobs/executable-resolver.ts +289 -0
- package/src/cli/agent-jobs/executor-health.ts +252 -0
- package/src/cli/agent-jobs/integration.ts +963 -0
- package/src/cli/agent-jobs/job-manager.ts +2030 -0
- package/src/cli/agent-jobs/types.ts +219 -0
- package/src/cli/agent-jobs/worker-lifecycle.ts +288 -0
- package/src/cli/chatgpt-browser/bind-server.ts +504 -0
- package/src/cli/chatgpt-browser/binding.ts +140 -0
- package/src/cli/chatgpt-browser/bridge-extension.ts +221 -0
- package/src/cli/chatgpt-browser/bridge-provider.ts +268 -0
- package/src/cli/chatgpt-browser/engine.ts +569 -0
- package/src/cli/chatgpt-browser/file-policy.ts +158 -0
- package/src/cli/chatgpt-browser/native-provider.ts +553 -0
- package/src/cli/chatgpt-browser/oracle-provider.ts +437 -0
- package/src/cli/chatgpt-browser/prompt-assembler.ts +29 -0
- package/src/cli/chatgpt-browser/session-store.ts +301 -0
- package/src/cli/chatgpt-browser/types.ts +172 -0
- package/src/cli/commands/adopt-plan.ts +186 -0
- package/src/cli/commands/brain-root.ts +132 -0
- package/src/cli/commands/brain.ts +609 -0
- package/src/cli/commands/capability-context.ts +613 -0
- package/src/cli/commands/chatgpt.ts +424 -0
- package/src/cli/commands/controller.ts +680 -0
- package/src/cli/commands/docs.ts +103 -0
- package/src/cli/commands/doctor.ts +476 -0
- package/src/cli/commands/global-runtime.ts +323 -0
- package/src/cli/commands/hook.ts +34 -0
- package/src/cli/commands/init-hook.ts +870 -0
- package/src/cli/commands/init.ts +829 -0
- package/src/cli/commands/install.ts +86 -0
- package/src/cli/commands/mcp.ts +315 -0
- package/src/cli/commands/migrate.ts +154 -0
- package/src/cli/commands/plugin.ts +74 -0
- package/src/cli/commands/prompt-guard-decision.ts +238 -0
- package/src/cli/commands/recovery.ts +667 -0
- package/src/cli/commands/repository.ts +224 -0
- package/src/cli/commands/run.ts +23 -0
- package/src/cli/commands/runtime.ts +191 -0
- package/src/cli/commands/security.ts +440 -0
- package/src/cli/commands/status.ts +137 -0
- package/src/cli/commands/tools.ts +167 -0
- package/src/cli/controller/check-runner.ts +1022 -0
- package/src/cli/controller/codex-continuation.ts +153 -0
- package/src/cli/controller/completion-backlog.ts +380 -0
- package/src/cli/controller/completion-orchestrator.ts +1807 -0
- package/src/cli/controller/completion-target.ts +96 -0
- package/src/cli/controller/composite-operations.ts +196 -0
- package/src/cli/controller/composite-result.ts +130 -0
- package/src/cli/controller/context-pack.ts +652 -0
- package/src/cli/controller/execution-completion.ts +175 -0
- package/src/cli/controller/execution-policy.ts +392 -0
- package/src/cli/controller/governance.ts +594 -0
- package/src/cli/controller/issue-store.ts +1421 -0
- package/src/cli/controller/launch-agents.ts +410 -0
- package/src/cli/controller/legacy-issue-cutover.ts +415 -0
- package/src/cli/controller/lifecycle-authority.ts +16 -0
- package/src/cli/controller/migrated-issue-decision.ts +237 -0
- package/src/cli/controller/operational-plan.ts +226 -0
- package/src/cli/controller/postcondition.ts +134 -0
- package/src/cli/controller/progress.ts +656 -0
- package/src/cli/controller/project-state.ts +147 -0
- package/src/cli/controller/requirement-portfolio-export.ts +146 -0
- package/src/cli/controller/requirement-portfolio-migration.ts +613 -0
- package/src/cli/controller/run-evidence.ts +43 -0
- package/src/cli/controller/runtime-config.ts +92 -0
- package/src/cli/controller/stuck-state-migration.ts +396 -0
- package/src/cli/controller/task-ledger.ts +632 -0
- package/src/cli/controller/task-status-resolver.ts +403 -0
- package/src/cli/controller/types.ts +273 -0
- package/src/cli/controller/work-mode.ts +186 -0
- package/src/cli/controller/worklog.ts +201 -0
- package/src/cli/diagnostic-entry.ts +39 -0
- package/src/cli/editing/edit-session.ts +1606 -0
- package/src/cli/editing/executable-modes.ts +70 -0
- package/src/cli/github/github.ts +274 -0
- package/src/cli/github/plugin.ts +345 -0
- package/src/cli/github/session.ts +104 -0
- package/src/cli/hook/prompt-guard-decision.ts +238 -0
- package/src/cli/hook/prompt-intents.ts +534 -0
- package/src/cli/hook/route-registry.ts +107 -0
- package/src/cli/hook/runtime.ts +303 -0
- package/src/cli/hook/state-snapshot.ts +388 -0
- package/src/cli/hook-entry.ts +51 -0
- package/src/cli/index.ts +574 -0
- package/src/cli/installer/managed-entries.ts +78 -0
- package/src/cli/installer/shared.ts +65 -0
- package/src/cli/installer/targets/claude.ts +136 -0
- package/src/cli/installer/targets/codex.ts +174 -0
- package/src/cli/installer/targets/registry.ts +28 -0
- package/src/cli/installer/types.ts +72 -0
- package/src/cli/local-bridge/connector-freshness.ts +529 -0
- package/src/cli/local-bridge/console-view-models.ts +324 -0
- package/src/cli/local-bridge/dashboard.ts +1312 -0
- package/src/cli/local-bridge/facade-api.ts +1877 -0
- package/src/cli/local-bridge/job-store.ts +1451 -0
- package/src/cli/local-bridge/mobile-intents.ts +344 -0
- package/src/cli/local-bridge/mobile-monitor.ts +209 -0
- package/src/cli/local-bridge/server.ts +3183 -0
- package/src/cli/local-bridge/types.ts +176 -0
- package/src/cli/mcp/access-mode.ts +132 -0
- package/src/cli/mcp/access-tools.ts +387 -0
- package/src/cli/mcp/audit.ts +32 -0
- package/src/cli/mcp/auth.ts +402 -0
- package/src/cli/mcp/instructions.ts +33 -0
- package/src/cli/mcp/legacy-context.ts +16 -0
- package/src/cli/mcp/legacy-tool-service.ts +5516 -0
- package/src/cli/mcp/multi-repository.ts +423 -0
- package/src/cli/mcp/oauth.ts +226 -0
- package/src/cli/mcp/paths.ts +134 -0
- package/src/cli/mcp/policy.ts +230 -0
- package/src/cli/mcp/proxy-env.ts +62 -0
- package/src/cli/mcp/readiness-projection.ts +24 -0
- package/src/cli/mcp/redaction.ts +21 -0
- package/src/cli/mcp/repo.ts +24 -0
- package/src/cli/mcp/repository-tools.ts +1295 -0
- package/src/cli/mcp/server.ts +341 -0
- package/src/cli/mcp/setup.ts +793 -0
- package/src/cli/mcp/tool-capability-cache.ts +87 -0
- package/src/cli/mcp/tools.ts +9 -0
- package/src/cli/mcp/toolset-names.ts +70 -0
- package/src/cli/mcp/toolset-selection.ts +41 -0
- package/src/cli/mcp/toolset.ts +300 -0
- package/src/cli/mcp/transports/AGENTS.md +39 -0
- package/src/cli/mcp/transports/CLAUDE.md +39 -0
- package/src/cli/mcp/transports/http.ts +1234 -0
- package/src/cli/mcp/transports/session-registry.ts +428 -0
- package/src/cli/mcp/transports/stdio.ts +8 -0
- package/src/cli/mcp/types.ts +41 -0
- package/src/cli/mcp/umbrella-tools.ts +117 -0
- package/src/cli/repo-adoption/reclaim-runtime.ts +681 -0
- package/src/cli/repositories/branch-name-policy.ts +57 -0
- package/src/cli/repositories/command-classifier.ts +600 -0
- package/src/cli/repositories/command-executor.ts +1066 -0
- package/src/cli/repositories/command-normalization.ts +53 -0
- package/src/cli/repositories/command-scope.ts +264 -0
- package/src/cli/repositories/controller-home.ts +88 -0
- package/src/cli/repositories/entity-migration.ts +199 -0
- package/src/cli/repositories/ephemeral-workspace.ts +62 -0
- package/src/cli/repositories/git-command-executor.ts +301 -0
- package/src/cli/repositories/goal-registry.ts +239 -0
- package/src/cli/repositories/identity.ts +64 -0
- package/src/cli/repositories/local-project-onboarding.ts +539 -0
- package/src/cli/repositories/locks.ts +262 -0
- package/src/cli/repositories/registry.ts +1057 -0
- package/src/cli/repositories/runtime-storage.ts +411 -0
- package/src/cli/repositories/safe-patch.ts +421 -0
- package/src/cli/repositories/selected-path-actions.ts +341 -0
- package/src/cli/repositories/structured-git.ts +257 -0
- package/src/cli/repositories/types.ts +155 -0
- package/src/cli/repositories/umbrella.ts +134 -0
- package/src/cli/repositories/workbench.ts +140 -0
- package/src/cli/repositories/worktree-storage.ts +137 -0
- package/src/cli/repository/inspector.ts +637 -0
- package/src/cli/repository/session-cache.ts +453 -0
- package/src/cli/runtime/helper-runner.ts +172 -0
- package/src/cli/runtime-invocation.ts +318 -0
- package/src/cli/tools/codegraph.ts +676 -0
- package/src/cli/v81-entry.ts +29 -0
- package/src/core/adoption/gitignore-plan.ts +127 -0
- package/src/core/adoption/helper-wrapper-plan.ts +159 -0
- package/src/core/adoption/manifest-templates.ts +60 -0
- package/src/core/adoption/modes.ts +7 -0
- package/src/core/adoption/operations.ts +126 -0
- package/src/core/adoption/plan.ts +149 -0
- package/src/core/adoption/render.ts +70 -0
- package/src/core/adoption/rollback.ts +62 -0
- package/src/core/adoption/summary.ts +43 -0
- package/src/core/adoption/workflow-contract-asset.ts +14 -0
- package/src/core/adoption/workflow-contract-plan.ts +31 -0
- package/src/effects/fs-transaction.ts +540 -0
- package/src/effects/git-executable.ts +59 -0
- package/src/effects/managed-block.ts +86 -0
- package/src/effects/path-safety.ts +47 -0
- package/src/effects/process-runner.ts +192 -0
- package/src/runtime/assistant/action-proposals.ts +279 -0
- package/src/runtime/assistant/intent.ts +395 -0
- package/src/runtime/assistant/model-provider.ts +460 -0
- package/src/runtime/assistant/openapi.ts +223 -0
- package/src/runtime/assistant/policy.ts +89 -0
- package/src/runtime/assistant/readiness.ts +258 -0
- package/src/runtime/assistant/routine-runtime.ts +477 -0
- package/src/runtime/assistant/schedule-binding.ts +171 -0
- package/src/runtime/assistant/standing-grants.ts +375 -0
- package/src/runtime/assistant/store.ts +243 -0
- package/src/runtime/assistant/types.ts +135 -0
- package/src/runtime/context/codegraph-read-provider.ts +347 -0
- package/src/runtime/context/codegraph-sidecar.cjs +207 -0
- package/src/runtime/control-plane/dispatch-priority.ts +67 -0
- package/src/runtime/control-plane/execution/direct-edit-work-completion.ts +151 -0
- package/src/runtime/control-plane/execution/execution-identity.ts +456 -0
- package/src/runtime/control-plane/execution/session-store.ts +175 -0
- package/src/runtime/control-plane/execution/validation.ts +117 -0
- package/src/runtime/control-plane/execution/verification-evidence.ts +191 -0
- package/src/runtime/control-plane/execution/work-handle-store.ts +225 -0
- package/src/runtime/control-plane/execution/work-prepare-request-store.ts +159 -0
- package/src/runtime/control-plane/execution/work-task-receipt.ts +445 -0
- package/src/runtime/control-plane/execution/work-terminal-cleanup.ts +821 -0
- package/src/runtime/control-plane/facade/capability-registry.ts +279 -0
- package/src/runtime/control-plane/facade/check-normalization.ts +233 -0
- package/src/runtime/control-plane/facade/codex-delegation.ts +196 -0
- package/src/runtime/control-plane/facade/controller-session-store.ts +199 -0
- package/src/runtime/control-plane/facade/facade-result.ts +41 -0
- package/src/runtime/control-plane/facade/goal-workloop-access.ts +177 -0
- package/src/runtime/control-plane/facade/goal-workloop.ts +1216 -0
- package/src/runtime/control-plane/facade/handoff-inbox-store.ts +221 -0
- package/src/runtime/control-plane/facade/index.ts +16 -0
- package/src/runtime/control-plane/facade/operation-digest.ts +528 -0
- package/src/runtime/control-plane/facade/plan-contract-store.ts +403 -0
- package/src/runtime/control-plane/facade/policy-gate.ts +149 -0
- package/src/runtime/control-plane/facade/requirement-board.ts +280 -0
- package/src/runtime/control-plane/facade/self-healing-loop.ts +555 -0
- package/src/runtime/control-plane/facade/suggested-actions.ts +108 -0
- package/src/runtime/control-plane/facade/types.ts +729 -0
- package/src/runtime/control-plane/facade/work-admission-policy.ts +93 -0
- package/src/runtime/control-plane/facade/work-continuation.ts +104 -0
- package/src/runtime/control-plane/facade/work-contract-store.ts +1118 -0
- package/src/runtime/control-plane/facade/work-task-projection.ts +66 -0
- package/src/runtime/control-plane/global-scheduler/reconciliation.ts +365 -0
- package/src/runtime/control-plane/global-scheduler/scheduler.ts +920 -0
- package/src/runtime/control-plane/global-scheduler/wake-signal.ts +89 -0
- package/src/runtime/control-plane/goal-loop/config-facade.ts +700 -0
- package/src/runtime/control-plane/goal-loop/config-store.ts +570 -0
- package/src/runtime/control-plane/goal-loop/config-types.ts +213 -0
- package/src/runtime/control-plane/goal-loop/executor-router.ts +109 -0
- package/src/runtime/control-plane/goal-loop/failure-taxonomy.ts +149 -0
- package/src/runtime/control-plane/goal-loop/goal-contract-store.ts +304 -0
- package/src/runtime/control-plane/goal-loop/goal-loop-engine.ts +1001 -0
- package/src/runtime/control-plane/goal-loop/handoff-packet.ts +160 -0
- package/src/runtime/control-plane/goal-loop/index.ts +13 -0
- package/src/runtime/control-plane/goal-loop/local-tools.ts +290 -0
- package/src/runtime/control-plane/goal-loop/policy-gates.ts +203 -0
- package/src/runtime/control-plane/goal-loop/provider-dispatch.ts +93 -0
- package/src/runtime/control-plane/goal-loop/provider-registry.ts +545 -0
- package/src/runtime/control-plane/goal-loop/types.ts +378 -0
- package/src/runtime/control-plane/governance/access-policy.ts +147 -0
- package/src/runtime/control-plane/governance/authorization.ts +195 -0
- package/src/runtime/control-plane/governance/external-effects.ts +43 -0
- package/src/runtime/control-plane/launcher/thin-launcher.ts +97 -0
- package/src/runtime/control-plane/persistence/metadata-payload-policy.ts +53 -0
- package/src/runtime/control-plane/persistence/requirement-store.ts +241 -0
- package/src/runtime/control-plane/persistence/sqlite-store.ts +539 -0
- package/src/runtime/control-plane/release-retention.ts +447 -0
- package/src/runtime/control-plane/repo-actor/actor.ts +181 -0
- package/src/runtime/control-plane/repo-actor/registry.ts +20 -0
- package/src/runtime/control-plane/routing/index.ts +1 -0
- package/src/runtime/control-plane/routing/route-policy.ts +379 -0
- package/src/runtime/control-plane/runtime-cleanup.ts +727 -0
- package/src/runtime/control-plane/runtime-generation.ts +509 -0
- package/src/runtime/control-plane/runtime-pid-ownership.ts +11 -0
- package/src/runtime/control-plane/runtime-status-client.ts +90 -0
- package/src/runtime/control-plane/startup-recovery.ts +198 -0
- package/src/runtime/diagnostics/connectivity-observability.ts +475 -0
- package/src/runtime/diagnostics/mcp-timing.ts +64 -0
- package/src/runtime/diagnostics/performance.ts +379 -0
- package/src/runtime/diagnostics/process-facade.ts +350 -0
- package/src/runtime/diagnostics/read-only-tool.ts +226 -0
- package/src/runtime/evidence/artifact-store.ts +154 -0
- package/src/runtime/evidence/event-ledger.ts +80 -0
- package/src/runtime/evidence/evidence-store.ts +68 -0
- package/src/runtime/evidence/process-check-receipt.ts +43 -0
- package/src/runtime/evidence/result-store.ts +209 -0
- package/src/runtime/evidence/sensitive-output.ts +353 -0
- package/src/runtime/execution/jobs/child-reference.ts +124 -0
- package/src/runtime/execution/jobs/legacy-adapter.ts +22 -0
- package/src/runtime/execution/jobs/receipt-recovery.ts +119 -0
- package/src/runtime/execution/jobs/receipt-store.ts +243 -0
- package/src/runtime/execution/jobs/store.ts +737 -0
- package/src/runtime/execution/jobs/timeouts.ts +109 -0
- package/src/runtime/execution/jobs/types.ts +230 -0
- package/src/runtime/execution/jobs/wait.ts +45 -0
- package/src/runtime/execution/process-runtime/canary.ts +26 -0
- package/src/runtime/execution/process-runtime/check-facade.ts +272 -0
- package/src/runtime/execution/process-runtime/check-receipt.ts +185 -0
- package/src/runtime/execution/process-runtime/check-runner-sidecar.ts +60 -0
- package/src/runtime/execution/process-runtime/command-facade.ts +321 -0
- package/src/runtime/execution/process-runtime/gc.ts +171 -0
- package/src/runtime/execution/process-runtime/index.ts +9 -0
- package/src/runtime/execution/process-runtime/interactive-admission.ts +23 -0
- package/src/runtime/execution/process-runtime/process-runner-entry.ts +466 -0
- package/src/runtime/execution/process-runtime/resource-claims.ts +440 -0
- package/src/runtime/execution/process-runtime/runtime.ts +1816 -0
- package/src/runtime/execution/process-runtime/store.ts +687 -0
- package/src/runtime/execution/process-runtime/types.ts +352 -0
- package/src/runtime/execution/thin-harness/async-process.ts +181 -0
- package/src/runtime/execution/thin-harness/batch-executor.ts +671 -0
- package/src/runtime/execution/thin-harness/execution-router.ts +700 -0
- package/src/runtime/execution/thin-harness/fast-executor.ts +1263 -0
- package/src/runtime/execution/thin-harness/fast-receipt.ts +235 -0
- package/src/runtime/execution/thin-harness/fingerprint-worker.ts +191 -0
- package/src/runtime/execution/thin-harness/index.ts +13 -0
- package/src/runtime/execution/thin-harness/latency-trace.ts +107 -0
- package/src/runtime/execution/thin-harness/lightweight-lanes.ts +745 -0
- package/src/runtime/execution/thin-harness/mutation-gate.ts +578 -0
- package/src/runtime/execution/thin-harness/proposal-store.ts +409 -0
- package/src/runtime/execution/thin-harness/request-ledger.ts +595 -0
- package/src/runtime/execution/thin-harness/search-worker.ts +114 -0
- package/src/runtime/execution/thin-harness/types.ts +313 -0
- package/src/runtime/execution/thin-harness/workspace-savepoint.ts +333 -0
- package/src/runtime/execution/workers/executor.ts +687 -0
- package/src/runtime/execution/workers/ownership.ts +94 -0
- package/src/runtime/execution/workers/worker-entry.ts +277 -0
- package/src/runtime/gateway/mcp/execution-tools.ts +2009 -0
- package/src/runtime/gateway/mcp/persisted-check-process.ts +255 -0
- package/src/runtime/gateway/mcp/process-tools.ts +230 -0
- package/src/runtime/gateway/mcp/resource-policy.ts +195 -0
- package/src/runtime/gateway/mcp/router.ts +1088 -0
- package/src/runtime/gateway/mcp/runtime-tools.ts +5994 -0
- package/src/runtime/gateway/mcp/work-validation-reconciler.ts +219 -0
- package/src/runtime/health/evaluator.ts +474 -0
- package/src/runtime/health/index.ts +2 -0
- package/src/runtime/health/operational-view.ts +198 -0
- package/src/runtime/maintenance/cleanup.ts +419 -0
- package/src/runtime/model-clients/deepseek-adapter.ts +312 -0
- package/src/runtime/model-clients/index.ts +2 -0
- package/src/runtime/model-clients/types.ts +101 -0
- package/src/runtime/observability/gateway-contention-metrics.ts +129 -0
- package/src/runtime/observability/route-session-benchmark.ts +110 -0
- package/src/runtime/personal-assistant/gmail-triage-manager.ts +231 -0
- package/src/runtime/personal-assistant/reporting-runtime.ts +344 -0
- package/src/runtime/personal-assistant/triage-runtime.ts +748 -0
- package/src/runtime/plugins/app-store-connect-adapter.ts +868 -0
- package/src/runtime/plugins/browser-adapter.ts +2812 -0
- package/src/runtime/plugins/browser-automation-service.ts +46 -0
- package/src/runtime/plugins/browser-handoff-host.ts +304 -0
- package/src/runtime/plugins/browser-handoff.ts +371 -0
- package/src/runtime/plugins/browser-macos-bridge.ts +865 -0
- package/src/runtime/plugins/browser-node-bridge-host.ts +64 -0
- package/src/runtime/plugins/browser-node-bridge.ts +249 -0
- package/src/runtime/plugins/desktop-adapter.ts +374 -0
- package/src/runtime/plugins/desktop-operator-registration.ts +418 -0
- package/src/runtime/plugins/errors.ts +39 -0
- package/src/runtime/plugins/execution-origin.ts +26 -0
- package/src/runtime/plugins/external-adapter.ts +322 -0
- package/src/runtime/plugins/external-registration.ts +308 -0
- package/src/runtime/plugins/external-unix-socket-probe.cjs +79 -0
- package/src/runtime/plugins/external-unix-socket.ts +238 -0
- package/src/runtime/plugins/first-party-registry.ts +37 -0
- package/src/runtime/plugins/github-adapter.ts +266 -0
- package/src/runtime/plugins/gmail-adapter.ts +729 -0
- package/src/runtime/plugins/google-calendar-adapter.ts +468 -0
- package/src/runtime/plugins/google-shared.ts +578 -0
- package/src/runtime/plugins/google-tasks-adapter.ts +535 -0
- package/src/runtime/plugins/interaction-session.ts +252 -0
- package/src/runtime/plugins/ios/agent-device-capabilities.ts +258 -0
- package/src/runtime/plugins/ios/agent-device-failures.ts +95 -0
- package/src/runtime/plugins/ios/agent-device-provider.ts +63 -0
- package/src/runtime/plugins/ios/agent-device-typed-provider.ts +268 -0
- package/src/runtime/plugins/ios/app-adapters.ts +122 -0
- package/src/runtime/plugins/ios-adapter.ts +509 -0
- package/src/runtime/plugins/ios-agent-device.ts +2311 -0
- package/src/runtime/plugins/ios-physical-device.ts +955 -0
- package/src/runtime/plugins/local-system-adapter.ts +1016 -0
- package/src/runtime/plugins/macos-capability-broker.ts +73 -0
- package/src/runtime/plugins/managed-process-adapter.ts +366 -0
- package/src/runtime/plugins/resend-adapter.ts +506 -0
- package/src/runtime/plugins/store.ts +1025 -0
- package/src/runtime/plugins/types.ts +138 -0
- package/src/runtime/projections/controller-context.ts +596 -0
- package/src/runtime/projections/git-status-sampler.ts +84 -0
- package/src/runtime/projections/invalidation.ts +250 -0
- package/src/runtime/projections/materialized-view.ts +694 -0
- package/src/runtime/recovery/actions.ts +158 -0
- package/src/runtime/recovery/audit.ts +38 -0
- package/src/runtime/recovery/classifier.ts +163 -0
- package/src/runtime/recovery/index.ts +9 -0
- package/src/runtime/recovery/local-jobs-repair.ts +393 -0
- package/src/runtime/recovery/maintenance-executor.ts +822 -0
- package/src/runtime/recovery/patch-handoff.ts +50 -0
- package/src/runtime/recovery/probe.ts +308 -0
- package/src/runtime/recovery/store.ts +35 -0
- package/src/runtime/recovery/types.ts +175 -0
- package/src/runtime/release/identity.ts +101 -0
- package/src/runtime/release/release-gate.ts +137 -0
- package/src/runtime/resources/claims/conflicts.ts +205 -0
- package/src/runtime/resources/index.ts +1 -0
- package/src/runtime/resources/leases/store.ts +539 -0
- package/src/runtime/resources/leases/types.ts +50 -0
- package/src/runtime/resources/ownership.ts +72 -0
- package/src/runtime/root/controller-services.ts +42 -0
- package/src/runtime/root/entry.ts +70 -0
- package/src/runtime/root/gateway-adapter.ts +46 -0
- package/src/runtime/root/local-bridge.ts +72 -0
- package/src/runtime/root/mcp-transport.ts +198 -0
- package/src/runtime/root/ownership.ts +94 -0
- package/src/runtime/root/readiness.ts +69 -0
- package/src/runtime/root/release-manifest.ts +147 -0
- package/src/runtime/root/release-materialize.ts +509 -0
- package/src/runtime/root/release-store.ts +236 -0
- package/src/runtime/root/runtime.ts +318 -0
- package/src/runtime/root/scheduler.ts +58 -0
- package/src/runtime/root/service-runner-entry.ts +20 -0
- package/src/runtime/root/service-runner.ts +69 -0
- package/src/runtime/root/service.ts +291 -0
- package/src/runtime/root/status.ts +127 -0
- package/src/runtime/root/types.ts +112 -0
- package/src/runtime/root/write-fence.ts +309 -0
- package/src/runtime/safe-tooling/browser-safe.ts +133 -0
- package/src/runtime/safe-tooling/external-filesystem.ts +304 -0
- package/src/runtime/safe-tooling/google-credential-store.ts +95 -0
- package/src/runtime/safe-tooling/google-oauth-broker.ts +286 -0
- package/src/runtime/safe-tooling/index.ts +11 -0
- package/src/runtime/safe-tooling/ios-development.ts +1039 -0
- package/src/runtime/safe-tooling/job-summary.ts +361 -0
- package/src/runtime/safe-tooling/plugin-summary.ts +53 -0
- package/src/runtime/safe-tooling/resend-oauth.ts +387 -0
- package/src/runtime/safe-tooling/review-artifacts.ts +133 -0
- package/src/runtime/safe-tooling/types.ts +103 -0
- package/src/runtime/safe-tooling/workspace-auth.ts +116 -0
- package/src/runtime/shared/bounded-child-supervisor.ts +235 -0
- package/src/runtime/shared/idempotent-retry.ts +128 -0
- package/src/runtime/shared/json-files.ts +43 -0
- package/src/runtime/shared/local-bridge-surface.ts +231 -0
- package/src/runtime/shared/managed-env.ts +154 -0
- package/src/runtime/shared/node-ts-loader.mjs +50 -0
- package/src/runtime/shared/process-environment.ts +97 -0
- package/src/runtime/shared/process-identity.ts +72 -0
- package/src/runtime/shared/process-tree.ts +227 -0
- package/src/runtime/shared/response-budget.ts +246 -0
- package/src/runtime/standalone-recovery/core.ts +2275 -0
- package/src/runtime/standalone-recovery/entry.ts +686 -0
- package/src/runtime/standalone-recovery/http-transport.ts +317 -0
- package/src/runtime/standalone-recovery/installer.ts +747 -0
- package/src/runtime/standalone-recovery/release.ts +241 -0
- package/src/runtime/watchdog/workflow-watchdog.ts +118 -0
- package/src/runtime/workflow/campaigns/cleanup.ts +263 -0
- package/src/runtime/workflow/campaigns/engine.ts +112 -0
- package/src/runtime/workflow/campaigns/normalize.ts +100 -0
- package/src/runtime/workflow/campaigns/review.ts +315 -0
- package/src/runtime/workflow/campaigns/store.ts +526 -0
- package/src/runtime/workflow/campaigns/supervisor.ts +112 -0
- package/src/runtime/workflow/campaigns/types.ts +290 -0
- package/src/runtime/workflow/campaigns/workspace-agent.ts +155 -0
- package/src/runtime/workflow/campaigns/workspace.ts +200 -0
- package/src/runtime/workflow/findings/store.ts +165 -0
- package/src/runtime/workflow/findings/types.ts +36 -0
- package/src/runtime/workflow/portfolio/engine.ts +20 -0
- package/src/runtime/workflow/portfolio/store.ts +185 -0
- package/src/runtime/workflow/portfolio/types.ts +29 -0
- package/src/runtime/workflow/schedules/engine.ts +620 -0
- package/src/runtime/workflow/schedules/settlement.ts +144 -0
- package/src/runtime/workflow/schedules/store.ts +417 -0
- package/src/runtime/workflow/schedules/types.ts +124 -0
- package/src/runtime/workspace-targets/index.ts +24 -0
- package/src/runtime/workspace-targets/target-grant.ts +721 -0
- package/src/testing/test-governance.ts +626 -0
- package/src/version.ts +21 -0
|
@@ -0,0 +1,1312 @@
|
|
|
1
|
+
export function localBridgeDashboardHtml(): string {
|
|
2
|
+
return `<!doctype html>
|
|
3
|
+
<html lang="zh-CN">
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8" />
|
|
6
|
+
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
|
7
|
+
<title>forge · 执行助手控制台</title>
|
|
8
|
+
<style>
|
|
9
|
+
:root{color-scheme:dark;--bg:#070b10;--panel:#0f1620;--panel2:#131c28;--line:rgba(255,255,255,.08);--text:#f3f6f9;--muted:#95a0ab;--faint:#6d7784;--green:#34d399;--amber:#fbbf24;--red:#f87171;--blue:#60a5fa;--radius:16px}
|
|
10
|
+
*{box-sizing:border-box}html,body{height:100%;margin:0}body{background:radial-gradient(circle at 80% -10%,rgba(52,211,153,.14),transparent 32%),linear-gradient(160deg,#05080c,#0a1118 55%,#06090d);color:var(--text);font:14px/1.5 Inter,"PingFang SC","Hiragino Sans GB","Microsoft YaHei",system-ui,sans-serif}
|
|
11
|
+
button,input,textarea{font:inherit}button{cursor:pointer}.mono{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
|
|
12
|
+
.app{min-height:100vh;display:grid;grid-template-rows:64px 1fr}
|
|
13
|
+
.top{display:flex;align-items:center;gap:12px;padding:0 18px;border-bottom:1px solid var(--line);background:rgba(8,12,18,.88);backdrop-filter:blur(16px);position:sticky;top:0;z-index:20}
|
|
14
|
+
.brand{display:flex;align-items:center;gap:10px;font-weight:800;min-width:180px}
|
|
15
|
+
.logo{width:28px;height:28px;border-radius:9px;display:grid;place-items:center;background:rgba(52,211,153,.12);color:var(--green);border:1px solid rgba(52,211,153,.28)}
|
|
16
|
+
.top-actions{margin-left:auto;display:flex;gap:8px;align-items:center;flex-wrap:wrap}
|
|
17
|
+
.chip,.btn,.pill{border:1px solid var(--line);background:rgba(255,255,255,.04);color:var(--text);border-radius:12px;padding:8px 12px}
|
|
18
|
+
.chip{display:inline-flex;align-items:center;gap:8px;min-height:36px}.chip strong{font-weight:700}
|
|
19
|
+
.btn{min-height:38px}.btn.primary{background:linear-gradient(180deg,#2f9f6b,#1f7a51);border-color:rgba(52,211,153,.4)}.btn.danger{background:rgba(248,113,113,.12);border-color:rgba(248,113,113,.35);color:#fecaca}.btn.ghost{background:transparent}
|
|
20
|
+
.dot{width:8px;height:8px;border-radius:50%;background:var(--green);box-shadow:0 0 0 4px rgba(52,211,153,.12)}.dot.amber{background:var(--amber);box-shadow:0 0 0 4px rgba(251,191,36,.12)}.dot.red{background:var(--red);box-shadow:0 0 0 4px rgba(248,113,113,.12)}.dot.blue{background:var(--blue);box-shadow:0 0 0 4px rgba(96,165,250,.12)}.dot.gray{background:#7b8794}
|
|
21
|
+
.body{display:grid;grid-template-columns:220px 1fr;min-height:0}
|
|
22
|
+
.side{border-right:1px solid var(--line);padding:16px 12px;background:rgba(8,12,18,.55)}
|
|
23
|
+
.nav{display:grid;gap:6px}.nav button{text-align:left;width:100%;padding:11px 12px;border-radius:12px;border:1px solid transparent;background:transparent;color:var(--text)}.nav button.active,.nav button:hover{background:rgba(255,255,255,.05);border-color:var(--line)}
|
|
24
|
+
.nav .count{margin-left:6px;display:inline-grid;place-items:center;min-width:20px;height:20px;border-radius:999px;background:rgba(248,113,113,.18);color:#fecaca;font-size:12px;font-weight:700}
|
|
25
|
+
.main{padding:24px 28px 48px;overflow:auto}.main>.view{width:min(1240px,100%);margin:0 auto}
|
|
26
|
+
.view{display:none}.view.active{display:block}
|
|
27
|
+
.page-head{display:flex;justify-content:space-between;gap:12px;align-items:flex-start;margin-bottom:16px}.page-head h1{margin:0 0 4px;font-size:24px}.page-head p{margin:0;color:var(--muted)}
|
|
28
|
+
.grid{display:grid;gap:14px}.grid.two{grid-template-columns:1.4fr .9fr}.grid.cards{grid-template-columns:repeat(3,1fr)}.grid.stats{grid-template-columns:repeat(4,minmax(0,1fr))}
|
|
29
|
+
.panel{background:rgba(15,22,32,.92);border:1px solid var(--line);border-radius:var(--radius);padding:16px;box-shadow:0 18px 40px rgba(0,0,0,.22)}
|
|
30
|
+
.panel h2,.panel h3{margin:0 0 8px}.muted{color:var(--muted)}.faint{color:var(--faint)}
|
|
31
|
+
.stat strong{display:block;font-size:22px;margin-top:4px}.stat span{color:var(--muted);font-size:12px}
|
|
32
|
+
.plugin-card{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:12px;align-items:start}
|
|
33
|
+
.action-row{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:10px;align-items:center;padding:10px 0;border-top:1px solid var(--line)}
|
|
34
|
+
.action-row:first-child{border-top:0;padding-top:0}
|
|
35
|
+
.composer textarea,.composer input,.input,textarea,input[type=text],input[type=number]{width:100%;border:1px solid var(--line);background:rgba(0,0,0,.22);color:var(--text);border-radius:12px;padding:12px 14px}
|
|
36
|
+
.composer textarea{min-height:120px;resize:vertical}
|
|
37
|
+
.composer .row{display:flex;gap:10px;flex-wrap:wrap;margin-top:10px;align-items:center}
|
|
38
|
+
.mode-card{display:grid;gap:6px}.mode-card .label{font-weight:800;font-size:16px}
|
|
39
|
+
.pill{display:inline-flex;align-items:center;gap:6px;padding:5px 10px;font-size:12px;font-weight:700;border-radius:999px}
|
|
40
|
+
.pill.green{background:rgba(52,211,153,.12);color:#a7f3d0;border-color:rgba(52,211,153,.28)}
|
|
41
|
+
.pill.amber{background:rgba(251,191,36,.12);color:#fde68a;border-color:rgba(251,191,36,.28)}
|
|
42
|
+
.pill.red{background:rgba(248,113,113,.12);color:#fecaca;border-color:rgba(248,113,113,.28)}
|
|
43
|
+
.pill.blue{background:rgba(96,165,250,.12);color:#bfdbfe;border-color:rgba(96,165,250,.28)}
|
|
44
|
+
.pill.gray{background:rgba(255,255,255,.05);color:#cbd5e1}
|
|
45
|
+
.steps{display:flex;flex-wrap:wrap;gap:8px;margin:10px 0}
|
|
46
|
+
.step{padding:6px 10px;border-radius:999px;border:1px solid var(--line);color:var(--faint);font-size:12px}.step.done{color:#a7f3d0;border-color:rgba(52,211,153,.3)}.step.active{color:#bfdbfe;border-color:rgba(96,165,250,.35)}
|
|
47
|
+
.actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}
|
|
48
|
+
.list{display:grid;gap:10px}
|
|
49
|
+
.card-row{display:grid;grid-template-columns:1fr auto;gap:12px;align-items:start;padding:14px;border:1px solid var(--line);border-radius:14px;background:rgba(255,255,255,.02)}
|
|
50
|
+
.card-row h3{margin:0 0 6px;font-size:15px}.card-row p{margin:0 0 6px;color:var(--muted)}
|
|
51
|
+
.evidence{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px}.evidence span{font-size:12px;padding:4px 8px;border-radius:999px;background:rgba(255,255,255,.04);border:1px solid var(--line);color:var(--muted)}
|
|
52
|
+
details.advanced{margin-top:12px;border-top:1px dashed var(--line);padding-top:10px}.advanced summary{cursor:pointer;color:var(--muted)}
|
|
53
|
+
.toast{position:fixed;right:18px;bottom:18px;background:#111827;border:1px solid var(--line);padding:12px 14px;border-radius:12px;opacity:0;transform:translateY(8px);transition:.2s;z-index:50;max-width:360px}.toast.show{opacity:1;transform:none}
|
|
54
|
+
.empty{padding:22px;border:1px dashed var(--line);border-radius:14px;color:var(--muted);text-align:center}
|
|
55
|
+
.section-title{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px}
|
|
56
|
+
.warn{padding:10px 12px;border-radius:12px;background:rgba(251,191,36,.08);border:1px solid rgba(251,191,36,.25);color:#fde68a;margin-bottom:12px}
|
|
57
|
+
.errbox{padding:12px 14px;border-radius:12px;background:rgba(248,113,113,.08);border:1px solid rgba(248,113,113,.28);color:#fecaca;margin:10px 0}
|
|
58
|
+
.errbox h4{margin:0 0 6px;font-size:14px}.errbox .muted{color:#fca5a5}
|
|
59
|
+
.setup{padding:14px 16px;border-radius:14px;background:rgba(96,165,250,.08);border:1px solid rgba(96,165,250,.28);margin-bottom:14px}
|
|
60
|
+
.files{display:grid;gap:6px;margin-top:8px}.file-row{display:flex;justify-content:space-between;gap:10px;padding:6px 8px;border-radius:8px;background:rgba(255,255,255,.03);border:1px solid var(--line);font-size:12px}
|
|
61
|
+
.opbar{margin-bottom:12px;padding:10px 12px;border-radius:12px;border:1px solid var(--line);background:rgba(255,255,255,.03);display:flex;gap:10px;align-items:center;flex-wrap:wrap}
|
|
62
|
+
.opbar.running{border-color:rgba(96,165,250,.35);background:rgba(96,165,250,.08)}
|
|
63
|
+
.opbar.ok{border-color:rgba(52,211,153,.35);background:rgba(52,211,153,.08)}
|
|
64
|
+
.opbar.err{border-color:rgba(248,113,113,.35);background:rgba(248,113,113,.08)}
|
|
65
|
+
.btn:disabled{opacity:.55;cursor:not-allowed}
|
|
66
|
+
.busy-banner{font-size:12px;color:var(--muted)}
|
|
67
|
+
.refresh-meta{font-size:12px;color:var(--faint);margin-left:auto}
|
|
68
|
+
.composer h2{font-size:20px}.composer .hint{color:var(--muted);margin:0 0 10px;font-size:13px}
|
|
69
|
+
.decision-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin:12px 0}.decision-box{padding:12px;border:1px solid var(--line);border-radius:12px;background:rgba(255,255,255,.025)}.decision-box strong{display:block;margin-bottom:5px}.decision-box p{margin:0;color:var(--muted)}
|
|
70
|
+
.flow{display:flex;align-items:stretch;gap:6px;margin:12px 0;overflow:auto}.flow-step{min-width:130px;flex:1;padding:9px 10px;border-radius:10px;border:1px solid var(--line);background:rgba(255,255,255,.025);color:var(--muted);font-size:12px}.flow-arrow{display:grid;place-items:center;color:var(--faint)}
|
|
71
|
+
@media(max-width:980px){.body{grid-template-columns:1fr}.side{display:none}.grid.two,.grid.cards,.grid.stats,.decision-grid{grid-template-columns:1fr}.top{flex-wrap:wrap;height:auto;padding:10px 12px}}
|
|
72
|
+
</style>
|
|
73
|
+
</head>
|
|
74
|
+
<body>
|
|
75
|
+
<div class="app">
|
|
76
|
+
<header class="top">
|
|
77
|
+
<div class="brand"><span class="logo">∞</span><span>执行助手控制台</span></div>
|
|
78
|
+
<button class="chip" id="repoChip" onclick="switchView('repositories')">仓库 · <strong id="topRepo">—</strong></button>
|
|
79
|
+
<span class="chip"><span class="dot" id="readyDot"></span><strong id="topReady">检查中</strong></span>
|
|
80
|
+
<span class="chip"><span class="dot" id="connectorDot"></span><span id="topConnector">连接</span></span>
|
|
81
|
+
<button class="chip" onclick="switchView('capabilities')">插件 <strong id="topPlugins">—</strong></button>
|
|
82
|
+
<button class="chip" onclick="switchView('inbox')">需要处理 <span class="count" id="topHandoffs">0</span></button>
|
|
83
|
+
<div class="top-actions">
|
|
84
|
+
<button class="btn ghost" onclick="refreshAll()">刷新</button>
|
|
85
|
+
<button class="btn ghost" onclick="switchView('advanced')">高级</button>
|
|
86
|
+
</div>
|
|
87
|
+
</header>
|
|
88
|
+
<div class="body">
|
|
89
|
+
<aside class="side">
|
|
90
|
+
<nav class="nav">
|
|
91
|
+
<button class="active" data-view="home">⌂ 指挥中心</button>
|
|
92
|
+
<button data-view="inbox">△ 需要处理 <span class="count" id="sideHandoffs">0</span></button>
|
|
93
|
+
<button data-view="work">▷ 当前任务</button>
|
|
94
|
+
<button data-view="capabilities">◇ 能力 / 插件 <span class="count" id="sidePlugins" style="display:none">0</span></button>
|
|
95
|
+
<button data-view="automation">⚙ 模型与工具</button>
|
|
96
|
+
<button data-view="readiness">◎ 系统状态</button>
|
|
97
|
+
<button data-view="repositories">□ 仓库</button>
|
|
98
|
+
<button data-view="advanced">⌁ 高级诊断</button>
|
|
99
|
+
</nav>
|
|
100
|
+
</aside>
|
|
101
|
+
<main class="main">
|
|
102
|
+
<section class="view active" id="view-home"></section>
|
|
103
|
+
<section class="view" id="view-inbox"></section>
|
|
104
|
+
<section class="view" id="view-work"></section>
|
|
105
|
+
<section class="view" id="view-capabilities"></section>
|
|
106
|
+
<section class="view" id="view-automation"></section>
|
|
107
|
+
<section class="view" id="view-readiness"></section>
|
|
108
|
+
<section class="view" id="view-repositories"></section>
|
|
109
|
+
<section class="view" id="view-advanced"></section>
|
|
110
|
+
</main>
|
|
111
|
+
</div>
|
|
112
|
+
</div>
|
|
113
|
+
<div class="toast" id="toast"></div>
|
|
114
|
+
<script>
|
|
115
|
+
function safeGet(k){try{return sessionStorage.getItem(k)||''}catch(_e){return ''}}
|
|
116
|
+
function safeSet(k,v){try{if(v)sessionStorage.setItem(k,v);else sessionStorage.removeItem(k)}catch(_e){}}
|
|
117
|
+
function queryRepoId(){try{return new URLSearchParams(location.search).get('repoId')||''}catch(_e){return ''}}
|
|
118
|
+
function setQueryRepoId(id){try{var u=new URL(location.href);if(id)u.searchParams.set('repoId',id);else u.searchParams.delete('repoId');history.replaceState(null,'',u)}catch(_e){}}
|
|
119
|
+
function esc(v){return String(v==null?'':v).replace(/[&<>"']/g,function(c){return({'&':'&','<':'<','>':'>','"':'"',"'":'''})[c]})}
|
|
120
|
+
function arr(v){return Array.isArray(v)?v:[]}
|
|
121
|
+
function obj(v){return v&&typeof v==='object'&&!Array.isArray(v)?v:{}}
|
|
122
|
+
function toast(msg){var t=document.getElementById('toast');t.textContent=msg;t.classList.add('show');setTimeout(function(){t.classList.remove('show')},2800)}
|
|
123
|
+
function pill(tone,label){return '<span class="pill '+esc(tone||'gray')+'">'+esc(label||'')+'</span>'}
|
|
124
|
+
function setDot(id,tone){document.getElementById(id).className='dot '+(tone&&tone!=='green'?tone:'')}
|
|
125
|
+
|
|
126
|
+
var selectedRepoId=queryRepoId()||safeGet('forgeSelectedRepoId')||'';
|
|
127
|
+
var commandCenter=null;
|
|
128
|
+
var automationSettings=null;
|
|
129
|
+
var selectedWorkId=safeGet('forgeSelectedWorkId')||'';
|
|
130
|
+
var selectedHandoffId='';
|
|
131
|
+
var selectedPluginId=safeGet('forgeSelectedPluginId')||'';
|
|
132
|
+
var modePreview=null;
|
|
133
|
+
var advancedRaw=null;
|
|
134
|
+
var lastFacade=null;
|
|
135
|
+
var lastOperation=null; // {phase,statusLabel,summary,errorMessage,at}
|
|
136
|
+
var pluginActionResult=null;
|
|
137
|
+
var busy=false;
|
|
138
|
+
var pollTimer=null;
|
|
139
|
+
var refreshInFlight=false;
|
|
140
|
+
var lastRefreshedAt='';
|
|
141
|
+
var pageVisible=!document.hidden;
|
|
142
|
+
var workExtras={}; // workId -> {changedFiles, error, summary}
|
|
143
|
+
|
|
144
|
+
document.addEventListener('visibilitychange',function(){
|
|
145
|
+
pageVisible=!document.hidden;
|
|
146
|
+
if(!pageVisible){
|
|
147
|
+
if(pollTimer){clearInterval(pollTimer);pollTimer=null}
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
ensurePoll();
|
|
151
|
+
if(shouldPoll())refreshAll({silent:true});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
function repoQuery(){return selectedRepoId?'?repoId='+encodeURIComponent(selectedRepoId):''}
|
|
155
|
+
function rememberRepo(id){selectedRepoId=id||'';safeSet('forgeSelectedRepoId',selectedRepoId);setQueryRepoId(selectedRepoId)}
|
|
156
|
+
function rememberWork(id){selectedWorkId=id||'';safeSet('forgeSelectedWorkId',selectedWorkId)}
|
|
157
|
+
function api(path,opts){opts=opts||{};var headers=Object.assign({'content-type':'application/json'},opts.headers||{});return fetch(path,Object.assign({},opts,{credentials:'same-origin',headers:headers})).then(function(r){return r.json().catch(function(){return{}}).then(function(body){if(!r.ok){var msg=(body.error&&body.error.title)||body.summary||body.errorMessage||body.error||body.message||('请求失败 '+r.status);if(!msg||msg==='undefined')msg='请求失败,请查看高级诊断';var err=new Error(msg);err.payload=body;err.status=r.status;throw err}return body})})}
|
|
158
|
+
function setBusy(on,label){
|
|
159
|
+
busy=!!on;
|
|
160
|
+
document.querySelectorAll('button.btn').forEach(function(b){
|
|
161
|
+
if(on)b.setAttribute('disabled','disabled');else b.removeAttribute('disabled');
|
|
162
|
+
});
|
|
163
|
+
if(on){
|
|
164
|
+
lastOperation={phase:'running',statusLabel:label||'执行中',summary:label||'正在处理…',at:new Date().toISOString()};
|
|
165
|
+
renderOpBar();
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function setLastOp(res,fallback){
|
|
169
|
+
res=obj(res);
|
|
170
|
+
var feedback=obj(res.feedback);
|
|
171
|
+
var phase=feedback.phase||res.phase||(res.status==='ok'?'succeeded':(res.status==='failed'||res.status==='blocked'||res.status==='approval_required')?'failed':'succeeded');
|
|
172
|
+
var next='';
|
|
173
|
+
var actions=arr(feedback.suggestedNextActions||res.suggestedNextActions);
|
|
174
|
+
if(actions.length)next=actions[0].label||'';
|
|
175
|
+
if(feedback.error&&feedback.error.nextActions&&feedback.error.nextActions[0])next=next||feedback.error.nextActions[0];
|
|
176
|
+
lastOperation={
|
|
177
|
+
phase:phase,
|
|
178
|
+
statusLabel:feedback.statusLabel||res.statusLabel||fallback||'已更新',
|
|
179
|
+
summary:feedback.summary||res.summary||fallback||'操作已完成',
|
|
180
|
+
errorMessage:(feedback.error&&feedback.error.title)||res.errorMessage||'',
|
|
181
|
+
error:feedback.error||res.error||null,
|
|
182
|
+
next:next,
|
|
183
|
+
changedFiles:feedback.changedFiles||res.changedFiles||null,
|
|
184
|
+
at:new Date().toISOString()
|
|
185
|
+
};
|
|
186
|
+
// Remember changed files / errors against active work for card rendering.
|
|
187
|
+
var wid=selectedWorkId||(res.data&&(res.data.work&&(res.data.work.workId||res.data.work.id)||res.data.workId));
|
|
188
|
+
if(wid){
|
|
189
|
+
workExtras[wid]=workExtras[wid]||{};
|
|
190
|
+
if(lastOperation.changedFiles)workExtras[wid].changedFiles=lastOperation.changedFiles;
|
|
191
|
+
if(lastOperation.error)workExtras[wid].error=lastOperation.error;
|
|
192
|
+
if(lastOperation.summary)workExtras[wid].summary=lastOperation.summary;
|
|
193
|
+
}
|
|
194
|
+
lastFacade=res;
|
|
195
|
+
renderOpBar();
|
|
196
|
+
}
|
|
197
|
+
function renderOpBar(){
|
|
198
|
+
var nodes=document.querySelectorAll('#opBar');
|
|
199
|
+
if(!nodes.length)return;
|
|
200
|
+
var html='';
|
|
201
|
+
if(lastOperation){
|
|
202
|
+
var cls=lastOperation.phase==='running'||lastOperation.phase==='queued'||lastOperation.phase==='waiting'||lastOperation.phase==='submitting'?'running':(lastOperation.phase==='failed'||lastOperation.phase==='timed_out'||lastOperation.phase==='blocked'||lastOperation.phase==='needs_attention')?'err':'ok';
|
|
203
|
+
html='<div class="opbar '+cls+'">'+
|
|
204
|
+
'<span class="pill '+(cls==='ok'?'green':cls==='err'?'red':'blue')+'">'+esc(lastOperation.statusLabel)+'</span>'+
|
|
205
|
+
'<span>'+esc(lastOperation.summary||'')+'</span>'+
|
|
206
|
+
(lastOperation.errorMessage?'<span class="muted">'+esc(lastOperation.errorMessage)+'</span>':'')+
|
|
207
|
+
(lastOperation.next?'<span class="muted">下一步:'+esc(lastOperation.next)+'</span>':'')+
|
|
208
|
+
(busy?'<span class="busy-banner">请稍候,勿重复点击…</span>':'')+
|
|
209
|
+
(lastRefreshedAt?'<span class="refresh-meta">刷新于 '+esc(lastRefreshedAt)+'</span>':'')+
|
|
210
|
+
'</div>';
|
|
211
|
+
if(lastOperation.error&&lastOperation.error.title){
|
|
212
|
+
html+=renderErrorBox(lastOperation.error);
|
|
213
|
+
}
|
|
214
|
+
} else if(lastRefreshedAt){
|
|
215
|
+
html='<div class="opbar"><span class="refresh-meta">刷新于 '+esc(lastRefreshedAt)+'</span></div>';
|
|
216
|
+
}
|
|
217
|
+
nodes.forEach(function(n){n.innerHTML=html});
|
|
218
|
+
}
|
|
219
|
+
function renderErrorBox(err){
|
|
220
|
+
err=obj(err);
|
|
221
|
+
if(!err.title)return '';
|
|
222
|
+
var next=arr(err.nextActions).map(function(a){return '<span class="pill amber">'+esc(a)+'</span>'}).join(' ');
|
|
223
|
+
return '<div class="errbox"><h4>'+esc(err.title)+'</h4><div class="muted">'+esc(err.explanation||'')+'</div>'+(next?'<div class="actions" style="margin-top:8px">'+next+'</div>':'')+
|
|
224
|
+
'<details class="advanced"><summary>高级详情(仅调试)</summary><pre class="mono" style="white-space:pre-wrap;font-size:12px">'+esc(JSON.stringify(err,null,2))+'</pre></details></div>';
|
|
225
|
+
}
|
|
226
|
+
function renderChangedFiles(summary){
|
|
227
|
+
summary=obj(summary);
|
|
228
|
+
if(!summary.total&&!arr(summary.files).length)return '';
|
|
229
|
+
var files=arr(summary.files).slice(0,12);
|
|
230
|
+
return '<div style="margin-top:10px"><div class="section-title"><strong>改动文件</strong>'+pill('blue',summary.summaryLabel||((summary.total||files.length)+' 个文件'))+'</div>'+
|
|
231
|
+
'<div class="files">'+files.map(function(f){
|
|
232
|
+
return '<div class="file-row"><span class="mono">'+esc(f.path)+'</span><span class="pill gray">'+esc(f.statusLabel||f.status||'修改')+'</span></div>';
|
|
233
|
+
}).join('')+'</div>'+
|
|
234
|
+
(files.length<(summary.total||0)?'<div class="faint" style="margin-top:6px">仅显示前 '+files.length+' 项</div>':'')+
|
|
235
|
+
'</div>';
|
|
236
|
+
}
|
|
237
|
+
function shouldPoll(){
|
|
238
|
+
if(!pageVisible||refreshInFlight)return false;
|
|
239
|
+
var work=obj(commandCenter&&commandCenter.currentWork);
|
|
240
|
+
if(!work||!work.id)return false;
|
|
241
|
+
var phase=work.phase||'';
|
|
242
|
+
return phase==='running'||phase==='queued'||phase==='waiting'||phase==='submitting'||work.tone==='blue'||work.statusLabel==='进行中'||work.statusLabel==='待开始';
|
|
243
|
+
}
|
|
244
|
+
function ensurePoll(){
|
|
245
|
+
if(!pageVisible||pollTimer)return;
|
|
246
|
+
pollTimer=setInterval(function(){
|
|
247
|
+
if(!shouldPoll()){
|
|
248
|
+
if(pollTimer){clearInterval(pollTimer);pollTimer=null}
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
refreshAll({silent:true});
|
|
252
|
+
},3500);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function switchView(name){
|
|
256
|
+
document.querySelectorAll('.nav button').forEach(function(b){b.classList.toggle('active',b.dataset.view===name)});
|
|
257
|
+
document.querySelectorAll('.view').forEach(function(v){v.classList.toggle('active',v.id==='view-'+name)});
|
|
258
|
+
renderAll();
|
|
259
|
+
}
|
|
260
|
+
document.querySelectorAll('.nav button[data-view]').forEach(function(b){b.addEventListener('click',function(){switchView(b.dataset.view)})});
|
|
261
|
+
|
|
262
|
+
function btn(label, attrs, cls){
|
|
263
|
+
return '<button class="btn'+(cls?(' '+cls):'')+'" '+attrs+'>'+esc(label)+'</button>';
|
|
264
|
+
}
|
|
265
|
+
function stepsHtml(steps){
|
|
266
|
+
return '<div class="steps">'+arr(steps).map(function(s){return '<span class="step '+(s.done?'done':'')+(s.active?' active':'')+'">'+esc(s.label)+'</span>'}).join('')+'</div>';
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function evidenceHtml(labels){
|
|
270
|
+
if(!arr(labels).length)return '';
|
|
271
|
+
return '<div class="evidence">'+arr(labels).map(function(x){return '<span>'+esc(x)+'</span>'}).join('')+'</div>';
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function advancedBlock(data){
|
|
275
|
+
if(!data)return '';
|
|
276
|
+
return '<details class="advanced"><summary>高级详情</summary><pre class="mono" style="white-space:pre-wrap;color:var(--muted);font-size:12px">'+esc(JSON.stringify(data,null,2))+'</pre></details>';
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function renderChrome(){
|
|
280
|
+
var cc=obj(commandCenter), ready=obj(cc.readiness), repo=obj(cc.currentRepository);
|
|
281
|
+
var plug=obj(cc.pluginSummary);
|
|
282
|
+
document.getElementById('topRepo').textContent=repo.name||'未选择';
|
|
283
|
+
document.getElementById('topReady').textContent=ready.label||'未知';
|
|
284
|
+
setDot('readyDot', ready.state==='blocked'?'red':ready.state==='needs_setup'?'amber':'green');
|
|
285
|
+
document.getElementById('topConnector').textContent=ready.connectorLabel||'连接';
|
|
286
|
+
setDot('connectorDot', ready.connectorTone||'gray');
|
|
287
|
+
var n=ready.pendingHandoffCount||arr(cc.handoffs).length||0;
|
|
288
|
+
document.getElementById('topHandoffs').textContent=n;
|
|
289
|
+
document.getElementById('sideHandoffs').textContent=n;
|
|
290
|
+
var readyPlugins=plug.ready||0, totalPlugins=plug.total||arr(cc.plugins).length||0;
|
|
291
|
+
document.getElementById('topPlugins').textContent=totalPlugins?(readyPlugins+'/'+totalPlugins):'—';
|
|
292
|
+
var need=plug.needsAttention||0;
|
|
293
|
+
var sidePlugins=document.getElementById('sidePlugins');
|
|
294
|
+
if(sidePlugins){
|
|
295
|
+
if(need>0){sidePlugins.style.display='inline-grid';sidePlugins.textContent=String(need)}
|
|
296
|
+
else {sidePlugins.style.display='none'}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function renderHome(){
|
|
301
|
+
var cc=obj(commandCenter), ready=obj(cc.readiness), work=obj(cc.currentWork), handoffs=arr(cc.handoffs).slice(0,3);
|
|
302
|
+
var repo=obj(cc.currentRepository);
|
|
303
|
+
var setup=obj(cc.setupGuide);
|
|
304
|
+
var warnings=arr(cc.warnings).map(function(w){return '<div class="warn">'+esc(w)+'</div>'}).join('');
|
|
305
|
+
var mode=obj(modePreview||cc.modePreviewDefault);
|
|
306
|
+
var el=document.getElementById('view-home');
|
|
307
|
+
var setupHtml=setup.needed
|
|
308
|
+
? '<div class="setup"><strong>'+esc(setup.title||'需要先设置仓库')+'</strong><p class="muted" style="margin:6px 0 10px">'+esc(setup.body||'')+'</p>'+btn(setup.actionLabel||'去设置仓库','data-nav="repositories"','primary')+'</div>'
|
|
309
|
+
: '';
|
|
310
|
+
el.innerHTML=
|
|
311
|
+
'<div id="opBar"></div>'+
|
|
312
|
+
warnings+
|
|
313
|
+
setupHtml+
|
|
314
|
+
'<div class="page-head"><div><h1>指挥中心</h1><p>描述目标,开始执行,然后只关注当前进度和需要你决定的事项。</p></div>'+
|
|
315
|
+
'<div class="muted">当前仓库:<strong>'+esc(repo.name||'未选择')+'</strong>'+(repo.branchLabel?' · '+esc(repo.branchLabel):'')+(repo.dirtyLabel?' · '+esc(repo.dirtyLabel):'')+'</div></div>'+
|
|
316
|
+
'<div class="panel composer">'+
|
|
317
|
+
'<div class="section-title"><div><h2>你想让它完成什么?</h2><p class="hint">直接描述目标。路径、验收标准和执行模式由系统先判断,你仍可在开始前预览。</p></div>'+pill(ready.state==='ready'?'green':ready.state==='needs_setup'?'amber':'red',ready.label||'未知')+'</div>'+
|
|
318
|
+
'<textarea id="taskObjective" placeholder="例如:优化 Controller 首页的信息层级,让当前任务和待决定事项更容易找到,不改变后端行为。"></textarea>'+
|
|
319
|
+
'<details class="advanced" style="margin-top:10px"><summary>补充验收标准和允许修改的路径</summary>'+
|
|
320
|
+
'<div class="row" style="margin-top:10px"><input class="input" id="taskAcceptance" placeholder="验收标准(可选,用分号分隔)" style="flex:1"></div>'+
|
|
321
|
+
'<div class="row"><input class="input" id="taskPaths" placeholder="允许修改的路径(可选,逗号分隔)" style="flex:1"><input class="input" id="taskFiles" type="number" min="0" placeholder="预计文件数" style="width:140px"></div>'+
|
|
322
|
+
'</details>'+
|
|
323
|
+
'<div class="row" style="margin-top:14px">'+
|
|
324
|
+
'<button class="btn primary" id="btnStart" onclick="startTask()">开始执行</button>'+
|
|
325
|
+
'<button class="btn" id="btnPreview" onclick="previewMode()">预览执行方式</button>'+
|
|
326
|
+
'<button class="btn ghost" onclick="diagnoseFirst()">只做诊断</button>'+
|
|
327
|
+
'<span class="muted" style="margin-left:auto">建议:<strong>'+esc(mode.label||'直接执行')+'</strong></span>'+
|
|
328
|
+
'</div>'+
|
|
329
|
+
'</div>'+
|
|
330
|
+
'<div class="grid two" style="margin-top:16px">'+
|
|
331
|
+
renderWorkCard(work, '当前任务')+
|
|
332
|
+
'<div class="panel"><div class="section-title"><h2>需要处理</h2>'+btn('查看全部','data-nav="inbox"','ghost')+'</div>'+
|
|
333
|
+
(handoffs.length?handoffs.map(function(h){return handoffMini(h)}).join(''):'<div class="empty">目前没有需要你拍板的事项</div>')+
|
|
334
|
+
'</div>'+
|
|
335
|
+
'</div>'+
|
|
336
|
+
'<div class="panel" style="margin-top:16px">'+
|
|
337
|
+
'<div class="section-title"><div><h2>运行状态</h2><p class="muted" style="margin:0">'+esc(ready.headline||ready.description||'系统状态可用')+'</p></div>'+pill(ready.connectorTone||'gray',ready.connectorLabel||'连接')+'</div>'+
|
|
338
|
+
'<div class="actions">'+btn('系统状态','data-nav="readiness"')+btn('能力与插件','data-nav="capabilities"')+btn('模型与工具','data-nav="automation"')+btn('切换仓库','data-nav="repositories"')+'</div>'+
|
|
339
|
+
'</div>'+
|
|
340
|
+
renderGoalLoopPanel(cc.goalLoop);
|
|
341
|
+
bindNav(el);
|
|
342
|
+
renderOpBar();
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function renderGoalLoopPanel(gl){
|
|
346
|
+
gl=obj(gl);
|
|
347
|
+
var goals=arr(gl.goals);
|
|
348
|
+
var inv=arr(gl.invokableProviders);
|
|
349
|
+
var handoff=arr(gl.handoffOnlyProviders);
|
|
350
|
+
var active=gl.activeCount||goals.length||0;
|
|
351
|
+
return '<details class="panel advanced" style="margin-top:16px">'+
|
|
352
|
+
'<summary style="display:flex;align-items:center;gap:10px;list-style:none">'+
|
|
353
|
+
'<strong>自动化目标</strong>'+pill(active?'blue':'gray',active+' 个活跃目标')+
|
|
354
|
+
'<span class="muted">'+inv.length+' 个提供方可直接调用 · '+handoff.length+' 个仅支持 Handoff</span>'+
|
|
355
|
+
'<span class="muted" style="margin-left:auto">展开查看</span>'+
|
|
356
|
+
'</summary>'+
|
|
357
|
+
'<div style="margin-top:14px">'+
|
|
358
|
+
(gl.automationSummary?'<p class="muted">'+esc(gl.automationSummary)+'</p>':'')+
|
|
359
|
+
(goals.length?goals.slice(0,3).map(function(g){
|
|
360
|
+
return '<div class="card-row" style="margin-top:10px"><div>'+
|
|
361
|
+
'<h3>'+esc(g.title||'目标')+'</h3>'+
|
|
362
|
+
'<p class="muted">阶段:'+esc(g.stage)+' · 提供方:'+esc(g.providerSelected||'—')+'</p>'+
|
|
363
|
+
(g.whatIsBlocked?'<p class="muted">阻塞:'+esc(g.whatIsBlocked)+'</p>':'')+
|
|
364
|
+
(g.whatHappensNext?'<p class="faint">下一步:'+esc(g.whatHappensNext)+'</p>':'')+
|
|
365
|
+
'</div>'+pill(g.approvalRequired?'amber':g.handoffPacketAvailable?'blue':'green',g.handoffPacketAvailable?'有 Handoff 包':g.stage)+'</div>';
|
|
366
|
+
}).join(''):'<div class="empty">暂无活跃自动化目标</div>')+
|
|
367
|
+
'<div class="actions">'+btn('打开模型与工具','data-nav="automation"')+'</div>'+
|
|
368
|
+
'</div>'+
|
|
369
|
+
'</details>';
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function mergeWorkExtras(work){
|
|
373
|
+
work=obj(work);
|
|
374
|
+
var extra=obj(workExtras[work.id]);
|
|
375
|
+
if(extra.changedFiles&&!work.changedFiles)work.changedFiles=extra.changedFiles;
|
|
376
|
+
if(extra.error&&!work.error)work.error=extra.error;
|
|
377
|
+
if(extra.summary&&!work.latestSummary)work.latestSummary=extra.summary;
|
|
378
|
+
return work;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
function renderWorkCard(work, title){
|
|
382
|
+
work=mergeWorkExtras(obj(work));
|
|
383
|
+
if(!work.id){
|
|
384
|
+
return '<div class="panel"><div class="section-title"><h2>'+esc(title||'当前任务')+'</h2></div><div class="empty">还没有任务。在左侧描述目标并点击“开始”。</div></div>';
|
|
385
|
+
}
|
|
386
|
+
var v=obj(work.latestVerification);
|
|
387
|
+
var id=esc(work.id);
|
|
388
|
+
var primary=work.primaryActionLabel||work.nextAction||'继续';
|
|
389
|
+
var primaryKind='continue';
|
|
390
|
+
var suggested=arr(work.suggestedActions);
|
|
391
|
+
if(suggested.length&&suggested[0].kind)primaryKind=suggested[0].kind;
|
|
392
|
+
return '<div class="panel work-card" data-work-id="'+id+'">'+
|
|
393
|
+
'<div class="section-title"><h2>'+esc(title||'当前任务')+'</h2>'+pill(work.tone, work.statusLabel||work.phaseLabel||'状态')+'</div>'+
|
|
394
|
+
'<h3 style="margin:0 0 6px">'+esc(work.title||work.objective||'未命名任务')+'</h3>'+
|
|
395
|
+
'<div class="muted">模式:'+esc(work.modeLabel||'—')+' · 阶段:'+esc(work.phaseLabel||work.statusLabel||'—')+'</div>'+
|
|
396
|
+
'<div class="muted" style="margin-top:4px">最近动作:'+esc(work.latestAction||primary)+'</div>'+
|
|
397
|
+
(work.latestSummary?'<p class="muted" style="margin:8px 0 0">'+esc(work.latestSummary)+'</p>':'')+
|
|
398
|
+
stepsHtml(work.progressSteps)+
|
|
399
|
+
(v.summary?'<div style="margin-top:8px">'+pill(v.tone,v.label)+' <span class="muted">'+esc(v.summary)+'</span></div>':'')+
|
|
400
|
+
(work.error?renderErrorBox(work.error):'')+
|
|
401
|
+
renderChangedFiles(work.changedFiles)+
|
|
402
|
+
(work.delegateSummary?'<p class="muted" style="margin-top:8px">'+esc(work.delegateSummary)+'</p>':'')+
|
|
403
|
+
evidenceHtml(work.evidenceLabels)+
|
|
404
|
+
(arr(work.acceptanceCriteria).length?'<p class="faint" style="margin-top:8px">验收:'+esc(arr(work.acceptanceCriteria).join(' · '))+'</p>':'')+
|
|
405
|
+
'<div class="actions">'+
|
|
406
|
+
btn(primary,'data-work-act="'+(primaryKind==='verify'?'verify':primaryKind==='finalize'?'finalize':primaryKind==='repair'?'repair':'continue')+'" data-work-id="'+id+'"','primary')+
|
|
407
|
+
btn('验证','data-work-act="verify" data-work-id="'+id+'"')+
|
|
408
|
+
btn('委派 Codex','data-work-act="delegate-codex" data-work-id="'+id+'"')+
|
|
409
|
+
btn('请 Grok 审阅','data-work-act="delegate-grok" data-work-id="'+id+'"')+
|
|
410
|
+
btn('修复诊断','data-work-act="repair" data-work-id="'+id+'"')+
|
|
411
|
+
btn('收尾','data-work-act="finalize" data-work-id="'+id+'"')+
|
|
412
|
+
btn('停止','data-work-act="stop" data-work-id="'+id+'"','danger')+
|
|
413
|
+
btn('打开详情','data-open-work="'+id+'"','ghost')+
|
|
414
|
+
'</div>'+
|
|
415
|
+
advancedBlock(work.advanced)+
|
|
416
|
+
'</div>';
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
function handoffMini(h){
|
|
420
|
+
var id=esc(h.id);
|
|
421
|
+
var d=obj(h.decision);
|
|
422
|
+
return '<div class="card-row" style="margin-bottom:8px">'+
|
|
423
|
+
'<div><div style="margin-bottom:6px">'+pill(h.tone,d.typeLabel||h.severityLabel||'需要决定')+'</div><h3>'+esc(h.title)+'</h3>'+
|
|
424
|
+
'<p><strong>需要你决定:</strong>'+esc(d.requestedAction||h.reason||'请打开查看详情')+'</p>'+
|
|
425
|
+
'<div class="faint">'+esc(d.afterApproval||h.recommendedDecision||'请先阅读详情')+'</div></div>'+
|
|
426
|
+
'<div class="actions" style="flex-direction:column">'+
|
|
427
|
+
btn(d.canApproveAndContinue?'查看审批详情':'查看并决定','data-open-handoff="'+id+'"','primary')+
|
|
428
|
+
'</div></div>';
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
function renderInbox(){
|
|
432
|
+
var items=arr(obj(commandCenter).handoffs);
|
|
433
|
+
var detail=selectedHandoffId?items.find(function(x){return x.id===selectedHandoffId}):null;
|
|
434
|
+
if(!detail&&items.length){selectedHandoffId=items[0].id;detail=items[0]}
|
|
435
|
+
var root=document.getElementById('view-inbox');
|
|
436
|
+
root.innerHTML=
|
|
437
|
+
'<div class="page-head"><div><h1>需要处理</h1><p>这里只展示真正阻塞执行的业务决定、不可逆操作和无法自动恢复的问题。</p></div><button class="btn" onclick="refreshAll()">刷新</button></div>'+
|
|
438
|
+
'<div class="grid two">'+
|
|
439
|
+
'<div class="list">'+(items.length?items.map(function(h){
|
|
440
|
+
var id=esc(h.id);var d=obj(h.decision);
|
|
441
|
+
return '<div class="panel" style="padding:14px;cursor:pointer;border-color:'+(selectedHandoffId===h.id?'rgba(96,165,250,.45)':'')+'" data-open-handoff="'+id+'">'+
|
|
442
|
+
'<div class="section-title"><h3 style="margin:0">'+esc(h.title)+'</h3>'+pill(h.tone,d.typeLabel||h.severityLabel)+'</div>'+
|
|
443
|
+
'<p class="muted"><strong>需要决定:</strong>'+esc(d.requestedAction||h.reason)+'</p>'+
|
|
444
|
+
'<p class="faint"><strong>处理后:</strong>'+esc(d.afterApproval||h.recommendedDecision||'—')+'</p></div>';
|
|
445
|
+
}).join(''):'<div class="empty">没有待审批或待决定事项。你可以回到指挥中心开始新任务。</div>')+'</div>'+
|
|
446
|
+
'<div class="panel" id="handoffDetail">'+(detail?renderHandoffDetail(detail):'<div class="empty">选择左侧事项查看详情</div>')+'</div>'+
|
|
447
|
+
'</div>';
|
|
448
|
+
bindActions(root);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
function renderHandoffDetail(h){
|
|
452
|
+
var id=esc(h.id);var d=obj(h.decision);
|
|
453
|
+
var primary=d.canApproveAndContinue
|
|
454
|
+
? btn(d.primaryActionLabel||'批准并继续执行','data-handoff-act="approve" data-handoff-id="'+id+'"','primary')
|
|
455
|
+
: btn(d.primaryActionLabel||'记录决定','data-handoff-act="resolve" data-handoff-id="'+id+'"','primary');
|
|
456
|
+
return '<div class="section-title"><div><h2>'+esc(h.title)+'</h2><div>'+pill(h.tone,d.typeLabel||h.severityLabel)+' '+pill(d.necessityLabel==='必须确认'?'amber':'gray',d.necessityLabel||'需要判断')+'</div></div>'+pill(h.tone,h.statusLabel)+'</div>'+
|
|
457
|
+
'<div class="setup" style="margin:12px 0"><strong>你正在批准 / 决定什么</strong><p class="muted" style="margin:6px 0 0">'+esc(d.requestedAction||h.reason||'—')+'</p></div>'+
|
|
458
|
+
'<div class="decision-grid">'+
|
|
459
|
+
'<div class="decision-box"><strong>是否有必要</strong><p>'+esc(d.necessityExplanation||h.reason||'—')+'</p></div>'+
|
|
460
|
+
'<div class="decision-box"><strong>会产生什么影响</strong><p>'+esc(d.impact||'—')+'</p></div>'+
|
|
461
|
+
'<div class="decision-box"><strong>批准 / 记录后</strong><p>'+esc(d.afterApproval||'—')+'</p></div>'+
|
|
462
|
+
'<div class="decision-box"><strong>不批准会怎样</strong><p>'+esc(d.ifRejected||'—')+'</p></div>'+
|
|
463
|
+
'</div>'+
|
|
464
|
+
'<div class="flow"><div class="flow-step">1. 当前停在安全点</div><div class="flow-arrow">→</div><div class="flow-step">2. 阅读对象、必要性和影响</div><div class="flow-arrow">→</div><div class="flow-step">3. '+esc(d.canApproveAndContinue?'批准后创建任务':'记录决定或补充信息')+'</div><div class="flow-arrow">→</div><div class="flow-step">4. 打开任务详情并显示下一步</div></div>'+
|
|
465
|
+
'<p><strong>为什么停下来</strong><br><span class="muted">'+esc(h.reason)+'</span></p>'+
|
|
466
|
+
'<p><strong>相关任务</strong><br><span class="muted">'+esc(h.workTitle||'尚未创建任务')+'</span></p>'+
|
|
467
|
+
'<div class="setup" style="margin:10px 0"><strong>系统建议</strong><p class="muted" style="margin:6px 0 0">'+esc(h.recommendedDecision||'请阅读后自行判断')+'</p></div>'+
|
|
468
|
+
(arr(h.attemptedActions).length?'<p><strong>已尝试</strong><br><span class="muted">'+esc(h.attemptedActions.join(' · '))+'</span></p>':'')+
|
|
469
|
+
evidenceHtml(h.evidenceLabels)+
|
|
470
|
+
'<div class="actions">'+primary+
|
|
471
|
+
(d.canApproveAndContinue?btn('仅记录其他决定','data-handoff-act="resolve" data-handoff-id="'+id+'"'):'')+
|
|
472
|
+
btn('确认已知晓','data-handoff-act="ack" data-handoff-id="'+id+'"')+
|
|
473
|
+
btn('暂不处理','data-handoff-act="dismiss" data-handoff-id="'+id+'"')+
|
|
474
|
+
(h.continuationPrompt?btn('复制人工继续提示','data-copy="1" data-copy-text="'+esc(h.continuationPrompt)+'"'):'')+
|
|
475
|
+
(h.advanced&&h.advanced.workId?btn('查看相关任务','data-open-work="'+esc(h.advanced.workId)+'"'):'')+
|
|
476
|
+
'</div>'+
|
|
477
|
+
advancedBlock(h.advanced);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
function renderWork(){
|
|
481
|
+
var work=null;
|
|
482
|
+
if(selectedWorkId){
|
|
483
|
+
var all=[obj(commandCenter).currentWork].concat(arr(obj(commandCenter).recentWork));
|
|
484
|
+
work=all.find(function(w){return w&&w.id===selectedWorkId})||obj(commandCenter).currentWork;
|
|
485
|
+
} else {
|
|
486
|
+
work=obj(commandCenter).currentWork;
|
|
487
|
+
}
|
|
488
|
+
var recent=arr(obj(commandCenter).recentWork);
|
|
489
|
+
var root=document.getElementById('view-work');
|
|
490
|
+
root.innerHTML=
|
|
491
|
+
'<div class="page-head"><div><h1>任务详情</h1><p>用自然语言理解进度,不必关心内部 ID。</p></div></div>'+
|
|
492
|
+
renderWorkCard(work,'任务')+
|
|
493
|
+
'<div class="panel" style="margin-top:14px"><div class="section-title"><h2>最近任务</h2></div>'+
|
|
494
|
+
(recent.length?recent.map(function(w){
|
|
495
|
+
return '<div class="card-row" style="margin-bottom:8px"><div><h3>'+esc(w.title)+'</h3><div class="muted">'+esc(w.modeLabel)+' · '+esc(w.statusLabel)+'</div></div>'+
|
|
496
|
+
btn('打开','data-open-work="'+esc(w.id)+'"')+'</div>';
|
|
497
|
+
}).join(''):'<div class="empty">暂无任务记录</div>')+
|
|
498
|
+
'</div>';
|
|
499
|
+
bindActions(root);
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
function renderConnectorHowToFix(fresh){
|
|
503
|
+
fresh=obj(fresh);
|
|
504
|
+
var steps=arr(fresh.howToFix);
|
|
505
|
+
if(!steps.length && !fresh.summary) return '';
|
|
506
|
+
var actions=arr(fresh.suggestedActions);
|
|
507
|
+
return '<div class="panel" style="margin-top:14px">'+
|
|
508
|
+
'<div class="section-title"><h2 style="margin:0">连接器诊断</h2>'+pill(fresh.severity==='error'?'red':fresh.severity==='warning'?'amber':fresh.severity==='ok'?'green':'blue', fresh.severity||'info')+'</div>'+
|
|
509
|
+
'<p class="muted">'+esc(fresh.summary||'')+'</p>'+
|
|
510
|
+
(arr(fresh.expectedFacadeTools).length?'<p class="faint">期望 facade:'+esc(arr(fresh.expectedFacadeTools).join(' · '))+'</p>':'')+
|
|
511
|
+
(arr(fresh.missingLocalTools).length?'<p class="muted">本地缺失:'+esc(arr(fresh.missingLocalTools).join(', '))+'</p>':'')+
|
|
512
|
+
(arr(fresh.missingConnectorTools).length?'<p class="muted">连接器快照缺失:'+esc(arr(fresh.missingConnectorTools).join(', '))+'</p>':'')+
|
|
513
|
+
(steps.length
|
|
514
|
+
? '<details class="advanced" style="margin-top:10px"><summary>如何修复</summary><ol style="margin:10px 0 0 18px;color:var(--muted);font-size:13px;line-height:1.55">'+
|
|
515
|
+
steps.map(function(s){return '<li>'+esc(s)+'</li>';}).join('')+
|
|
516
|
+
'</ol>'+
|
|
517
|
+
(actions.length?'<p class="faint" style="margin-top:10px">建议:'+esc(actions.join(' · '))+'</p>':'')+
|
|
518
|
+
'</details>'
|
|
519
|
+
: '')+
|
|
520
|
+
'</div>';
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
function renderReadiness(){
|
|
524
|
+
var ready=obj(obj(commandCenter).readiness);
|
|
525
|
+
var fresh=obj(ready.connectorFreshness);
|
|
526
|
+
document.getElementById('view-readiness').innerHTML=
|
|
527
|
+
'<div class="page-head"><div><h1>系统状态</h1><p>用白话告诉你 forge 是否可用。</p></div>'+
|
|
528
|
+
'<div class="actions"><button class="btn primary" onclick="diagnoseFirst()">诊断</button><button class="btn" onclick="repairDryRun()">预览修复</button></div></div>'+
|
|
529
|
+
'<div class="panel" style="margin-bottom:14px"><h2>'+esc(ready.headline||'')+'</h2><p class="muted">'+esc(ready.description||'')+'</p></div>'+
|
|
530
|
+
'<div class="grid cards">'+arr(ready.sections).map(function(s){
|
|
531
|
+
return '<div class="panel"><div class="section-title"><h3 style="margin:0">'+esc(s.title)+'</h3>'+pill(s.tone,s.statusLabel)+'</div><p class="muted">'+esc(s.detail)+'</p></div>';
|
|
532
|
+
}).join('')+'</div>'+
|
|
533
|
+
renderConnectorHowToFix(fresh);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
function renderRepositories(){
|
|
537
|
+
var repos=arr(obj(commandCenter).repositories);
|
|
538
|
+
var root=document.getElementById('view-repositories');
|
|
539
|
+
root.innerHTML=
|
|
540
|
+
'<div class="page-head"><div><h1>仓库</h1><p>选择当前工作仓库。显示名称、分支和是否干净会直接影响你是否能开始任务。</p></div>'+
|
|
541
|
+
'<button class="btn primary" onclick="toggleAddRepo()">添加本地仓库</button></div>'+
|
|
542
|
+
'<div class="panel" id="repoAdd" style="display:none;margin-bottom:14px">'+
|
|
543
|
+
'<div class="row" style="display:grid;grid-template-columns:1.4fr .8fr auto;gap:10px">'+
|
|
544
|
+
'<input class="input" id="repoPath" placeholder="./YourRepo">'+
|
|
545
|
+
'<input class="input" id="repoName" placeholder="显示名称(可选)">'+
|
|
546
|
+
'<button class="btn primary" onclick="registerRepo()">注册</button>'+
|
|
547
|
+
'</div></div>'+
|
|
548
|
+
(repos.length?'':'<div class="setup"><strong>还没有仓库</strong><p class="muted" style="margin:6px 0 0">添加一个本地 Git 仓库后,指挥中心才能启动任务。</p></div>')+
|
|
549
|
+
'<div class="list">'+repos.map(function(r){
|
|
550
|
+
return '<div class="panel card-row"><div><h3>'+esc(r.name)+'</h3><div class="muted mono">'+esc(r.path)+'</div>'+
|
|
551
|
+
'<div class="muted" style="margin-top:6px">'+(r.branchLabel?('分支 '+esc(r.branchLabel)):'')+(r.dirtyLabel?' · '+esc(r.dirtyLabel):'')+(r.readinessLabel?' · '+esc(r.readinessLabel):'')+'</div></div>'+
|
|
552
|
+
'<div class="actions">'+
|
|
553
|
+
btn(r.current?'当前仓库':'设为当前','data-select-repo="'+esc(r.id)+'"',r.current?'primary':'')+
|
|
554
|
+
btn('删除注册','data-remove-repo="'+esc(r.id)+'" data-remove-repo-name="'+esc(r.name||r.id)+'"','danger')+
|
|
555
|
+
'</div>'+
|
|
556
|
+
advancedBlock(r.advanced)+
|
|
557
|
+
'</div>';
|
|
558
|
+
}).join('')+'</div>';
|
|
559
|
+
bindActions(root);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
function rememberPlugin(id){
|
|
563
|
+
selectedPluginId=id||'';
|
|
564
|
+
safeSet('forgeSelectedPluginId', selectedPluginId);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
function pluginById(id){
|
|
568
|
+
return arr(obj(commandCenter).plugins).find(function(p){return p.id===id})||null;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
function renderCapabilities(){
|
|
572
|
+
var cc=obj(commandCenter);
|
|
573
|
+
var plugins=arr(cc.plugins);
|
|
574
|
+
var summary=obj(cc.pluginSummary);
|
|
575
|
+
var selected=selectedPluginId?pluginById(selectedPluginId):null;
|
|
576
|
+
if(selectedPluginId&&!selected&&plugins.length){
|
|
577
|
+
selected=plugins[0];
|
|
578
|
+
rememberPlugin(selected.id);
|
|
579
|
+
}
|
|
580
|
+
var ready=summary.ready||plugins.filter(function(p){return p.status==='ready'}).length;
|
|
581
|
+
var need=summary.needsAttention||plugins.filter(function(p){return p.status!=='ready'&&p.status!=='disabled'}).length;
|
|
582
|
+
var failed=plugins.filter(function(p){return p.status==='failed'||p.status==='disabled'}).length;
|
|
583
|
+
var root=document.getElementById('view-capabilities');
|
|
584
|
+
root.innerHTML=
|
|
585
|
+
'<div class="page-head"><div><h1>能力 / 插件</h1><p>预览并管理 forge 可调用的助手插件;普通动作直接执行,不可逆操作需要强确认。</p></div>'+
|
|
586
|
+
'<div class="actions"><button class="btn" onclick="refreshPlugins()">检查连接</button></div></div>'+
|
|
587
|
+
'<div class="grid stats" style="margin-bottom:14px">'+
|
|
588
|
+
'<div class="panel stat"><span>能力总数</span><strong>'+plugins.length+'</strong></div>'+
|
|
589
|
+
'<div class="panel stat"><span>可用</span><strong>'+ready+'</strong></div>'+
|
|
590
|
+
'<div class="panel stat"><span>需要配置</span><strong>'+need+'</strong></div>'+
|
|
591
|
+
'<div class="panel stat"><span>不可用</span><strong>'+failed+'</strong></div>'+
|
|
592
|
+
'</div>'+
|
|
593
|
+
'<div class="grid two">'+
|
|
594
|
+
'<div class="list">'+
|
|
595
|
+
(plugins.length?plugins.map(function(p){
|
|
596
|
+
var active=selected&&selected.id===p.id;
|
|
597
|
+
return '<div class="panel plugin-card" style="cursor:pointer;border-color:'+(active?'rgba(96,165,250,.45)':'')+'" data-open-plugin="'+esc(p.id)+'">'+
|
|
598
|
+
'<div><h3 style="margin:0 0 6px">'+esc(p.name)+'</h3>'+
|
|
599
|
+
'<div class="muted">'+esc(p.description||'')+'</div>'+
|
|
600
|
+
'<div class="muted" style="margin-top:6px">'+esc(p.nextStep||'')+'</div>'+
|
|
601
|
+
(arr(p.capabilityLabels).length?'<div class="evidence" style="margin-top:8px">'+arr(p.capabilityLabels).map(function(c){return '<span>'+esc(c)+'</span>'}).join('')+'</div>':'')+
|
|
602
|
+
'</div>'+
|
|
603
|
+
'<div style="text-align:right">'+pill(p.tone,p.statusLabel)+
|
|
604
|
+
'<div class="actions" style="margin-top:8px;justify-content:flex-end">'+btn(active?'已选中':'查看', 'data-open-plugin="'+esc(p.id)+'"', active?'primary':'')+'</div>'+
|
|
605
|
+
'</div></div>';
|
|
606
|
+
}).join(''):'<div class="empty">当前仓库没有发现插件</div>')+
|
|
607
|
+
'</div>'+
|
|
608
|
+
'<div class="panel" id="pluginDetail">'+renderPluginDetail(selected)+'</div>'+
|
|
609
|
+
'</div>'+
|
|
610
|
+
(pluginActionResult?'<div class="panel" style="margin-top:14px"><div class="section-title"><h2>最近动作结果</h2></div><pre class="mono" style="white-space:pre-wrap;font-size:12px;color:var(--muted)">'+esc(JSON.stringify(pluginActionResult,null,2))+'</pre></div>':'');
|
|
611
|
+
bindActions(root);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
function renderPluginDetail(p){
|
|
615
|
+
if(!p||!p.id){
|
|
616
|
+
return '<div class="empty">选择左侧插件查看能力、健康状态与可执行动作</div>';
|
|
617
|
+
}
|
|
618
|
+
var actions=arr(p.actions);
|
|
619
|
+
var previewActions=actions.filter(function(a){return a.canPreview});
|
|
620
|
+
var otherActions=actions.filter(function(a){return !a.canPreview});
|
|
621
|
+
return '<div class="section-title"><h2 style="margin:0">'+esc(p.name)+'</h2>'+pill(p.tone,p.statusLabel)+'</div>'+
|
|
622
|
+
'<p class="muted">'+esc(p.nextStep||'')+'</p>'+
|
|
623
|
+
'<div class="meta muted" style="display:flex;gap:10px;flex-wrap:wrap;margin:8px 0 12px">'+
|
|
624
|
+
'<span>提供方:'+esc(p.provider||'—')+'</span>'+
|
|
625
|
+
'<span>健康:'+esc(p.healthLabel||'—')+'</span>'+
|
|
626
|
+
'<span>生命周期:'+esc(p.lifecycleLabel||'—')+'</span>'+
|
|
627
|
+
'<span>动作:'+esc(String(p.actionCount||actions.length))+'</span>'+
|
|
628
|
+
'</div>'+
|
|
629
|
+
(arr(p.warnings).length?'<div class="warn">'+esc(arr(p.warnings).join(' · '))+'</div>':'')+
|
|
630
|
+
(arr(p.capabilityLabels).length?'<p><strong>能力域</strong></p><div class="evidence">'+arr(p.capabilityLabels).map(function(c){return '<span>'+esc(c)+'</span>'}).join('')+'</div>':'')+
|
|
631
|
+
'<div style="margin-top:14px"><div class="section-title"><h3 style="margin:0">预览 / 状态动作</h3><span class="muted">只读或配置检查,优先使用</span></div>'+
|
|
632
|
+
(previewActions.length?previewActions.map(function(a){return pluginActionRow(p.id,a,true)}).join(''):'<div class="empty">没有可预览动作</div>')+
|
|
633
|
+
'</div>'+
|
|
634
|
+
'<div style="margin-top:14px"><div class="section-title"><h3 style="margin:0">写入动作</h3><span class="muted">只有不可逆操作需要强确认</span></div>'+
|
|
635
|
+
(otherActions.length?otherActions.map(function(a){return pluginActionRow(p.id,a,false)}).join(''):'<div class="empty">没有写入动作</div>')+
|
|
636
|
+
'</div>'+
|
|
637
|
+
advancedBlock(p.advanced);
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
function pluginActionRow(pluginId, action, isPreview){
|
|
641
|
+
var id=esc(pluginId), aid=esc(action.id);
|
|
642
|
+
return '<div class="action-row">'+
|
|
643
|
+
'<div><div><strong>'+esc(action.title||action.id)+'</strong> '+pill(action.readOnly?'green':action.risk==='destructive'?'red':'amber', action.riskLabel)+'</div>'+
|
|
644
|
+
'<div class="muted">'+esc(action.description||'')+'</div>'+
|
|
645
|
+
'<div class="faint">'+esc(action.confirmationLabel||'')+'</div></div>'+
|
|
646
|
+
'<div class="actions">'+
|
|
647
|
+
btn(isPreview?'运行预览':'执行', 'data-plugin-act="run" data-plugin-id="'+id+'" data-action-id="'+aid+'"', isPreview?'primary':'')+
|
|
648
|
+
'</div></div>';
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
function fmtDuration(ms){
|
|
652
|
+
if(typeof ms!=='number'||!isFinite(ms)||ms<0)return '—';
|
|
653
|
+
if(ms<1000)return Math.round(ms)+' ms';
|
|
654
|
+
var sec=ms/1000;
|
|
655
|
+
if(sec<60)return (sec<10?sec.toFixed(1):Math.round(sec))+' s';
|
|
656
|
+
var min=Math.floor(sec/60), rem=Math.round(sec%60);
|
|
657
|
+
return min+'m '+rem+'s';
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
function renderConnectivitySection(payload){
|
|
661
|
+
payload=obj(payload);
|
|
662
|
+
var conn=obj(payload.connectivity);
|
|
663
|
+
var summary=obj(conn.summary);
|
|
664
|
+
if(!summary.headline)return '';
|
|
665
|
+
var latest=obj(conn.latestEvent);
|
|
666
|
+
var attr=obj(latest.attribution||summary.latestAttribution);
|
|
667
|
+
var observations=arr(latest.observations);
|
|
668
|
+
var jobs=arr(latest.jobTimings);
|
|
669
|
+
var counts=obj(summary.attributionCounts);
|
|
670
|
+
var evidence=arr(attr.evidence);
|
|
671
|
+
return '<div class="panel" style="margin-bottom:14px">'+
|
|
672
|
+
'<div class="section-title"><h2 style="margin:0">连接稳定性</h2>'+pill(summary.tone||attr.tone||'gray', summary.statusLabel||attr.overallStatusLabel||'观察中')+'</div>'+
|
|
673
|
+
'<p class="muted">'+esc(summary.headline||'')+'</p>'+
|
|
674
|
+
'<div class="muted" style="display:flex;gap:10px;flex-wrap:wrap;margin-top:8px">'+
|
|
675
|
+
'<span>归因:'+esc(attr.categoryLabel||'—')+'</span>'+
|
|
676
|
+
'<span>置信度:'+esc(attr.confidenceLabel||'—')+'</span>'+
|
|
677
|
+
'<span>最近探测:'+esc(summary.latestObservedAt||'—')+'</span>'+
|
|
678
|
+
'<span>样本:'+esc(String(summary.eventsStored||0))+'</span>'+
|
|
679
|
+
'</div>'+
|
|
680
|
+
'<div class="evidence" style="margin-top:10px">'+
|
|
681
|
+
'<span>公网路径 '+esc(String(counts.public_path||0))+'</span>'+
|
|
682
|
+
'<span>Gateway '+esc(String(counts.gateway||0))+'</span>'+
|
|
683
|
+
'<span>Local Bridge '+esc(String(counts.local_bridge||0))+'</span>'+
|
|
684
|
+
'<span>Controller '+esc(String(counts.controller||0))+'</span>'+
|
|
685
|
+
'<span>连接器/未知 '+esc(String(counts.connector_or_unknown||0))+'</span>'+
|
|
686
|
+
'</div>'+
|
|
687
|
+
(observations.length?'<div class="grid cards" style="margin-top:14px">'+observations.map(function(item){
|
|
688
|
+
item=obj(item);
|
|
689
|
+
return '<div class="panel" style="padding:12px;background:rgba(255,255,255,.02)">'+
|
|
690
|
+
'<div class="section-title"><strong>'+esc(item.label||item.component||'组件')+'</strong>'+pill(item.tone||'gray', item.stateLabel||item.state||'未知')+'</div>'+
|
|
691
|
+
'<p class="muted" style="margin:0">'+esc(item.detail||'')+'</p>'+
|
|
692
|
+
'</div>';
|
|
693
|
+
}).join('')+'</div>':'')+
|
|
694
|
+
(jobs.length?'<div style="margin-top:14px"><div class="section-title"><h3 style="margin:0">最近 durable Job 时序</h3><span class="muted">基于 queued/dispatched/started/finished 持久时间戳</span></div><div class="list">'+jobs.map(function(job){
|
|
695
|
+
job=obj(job);
|
|
696
|
+
return '<div class="card-row" style="padding:12px"><div><h3 style="margin:0 0 6px">'+esc(job.operation||job.jobId||'job')+'</h3>'+
|
|
697
|
+
'<p class="muted">Job '+esc(job.jobId||'—')+' · '+esc(job.statusLabel||job.status||'未知')+' · '+esc(job.stageLabel||'—')+'</p>'+
|
|
698
|
+
'<div class="evidence">'+
|
|
699
|
+
'<span>排队 '+esc(fmtDuration(job.queuedDelayMs))+'</span>'+
|
|
700
|
+
'<span>派发到启动 '+esc(fmtDuration(job.dispatchToStartMs))+'</span>'+
|
|
701
|
+
'<span>执行 '+esc(fmtDuration(job.executionDurationMs))+'</span>'+
|
|
702
|
+
'<span>总计 '+esc(fmtDuration(job.totalMs))+'</span>'+
|
|
703
|
+
'</div></div>'+pill((job.status==='failed'||job.status==='timed_out'||job.status==='orphaned'||job.status==='stale')?'red':(job.status==='running'||job.status==='dispatched')?'blue':'gray', job.statusLabel||job.status||'')+'</div>';
|
|
704
|
+
}).join('')+'</div></div>':'')+
|
|
705
|
+
(evidence.length?'<details class="advanced" style="margin-top:14px"><summary>归因证据</summary><ul style="margin:10px 0 0 18px;color:var(--muted);font-size:13px;line-height:1.55">'+evidence.map(function(line){return '<li>'+esc(line)+'</li>';}).join('')+'</ul></details>':'')+
|
|
706
|
+
'</div>';
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
function renderAdvanced(){
|
|
710
|
+
var root=document.getElementById('view-advanced');
|
|
711
|
+
var payload=advancedRaw||lastFacade||{note:'点击“读取原始快照”加载调试数据。日常任务请使用指挥中心。'};
|
|
712
|
+
root.innerHTML=
|
|
713
|
+
'<div class="page-head"><div><h1>高级诊断</h1><p>仅用于排错。默认任务流请回到指挥中心,不要从这里开始日常开发。</p></div>'+
|
|
714
|
+
'<div class="actions"><button class="btn" onclick="loadAdvanced()">读取原始快照</button>'+
|
|
715
|
+
'<button class="btn" onclick="copyText(JSON.stringify(advancedRaw||lastFacade||{},null,2))">复制 JSON</button>'+
|
|
716
|
+
btn('返回指挥中心','data-nav="home"','primary')+'</div></div>'+
|
|
717
|
+
renderConnectivitySection(payload)+
|
|
718
|
+
'<div class="panel"><div class="warn">调试信息默认折叠,避免干扰主流程。</div>'+
|
|
719
|
+
'<details class="advanced" open><summary>原始 JSON(调试)</summary>'+
|
|
720
|
+
'<pre class="mono" style="white-space:pre-wrap;font-size:12px;color:var(--muted);max-height:60vh;overflow:auto">'+esc(JSON.stringify(payload,null,2))+'</pre></details></div>';
|
|
721
|
+
bindNav(root);
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
function renderAutomation(){
|
|
725
|
+
var root=document.getElementById('view-automation');
|
|
726
|
+
if(!root)return;
|
|
727
|
+
var s=obj(automationSettings);
|
|
728
|
+
if(!s.schemaVersion){
|
|
729
|
+
root.innerHTML='<div class="page-head"><div><h1>模型与工具提供方</h1><p>配置 LLM、本地工具与路由偏好。</p></div>'+
|
|
730
|
+
'<button class="btn primary" onclick="loadAutomationSettings()">加载配置</button></div>'+
|
|
731
|
+
'<div class="empty">正在读取 Automation Settings…</div>';
|
|
732
|
+
loadAutomationSettings();
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
var ov=obj(s.overview);
|
|
736
|
+
var providers=arr(s.providers);
|
|
737
|
+
var tools=arr(s.localTools);
|
|
738
|
+
var creds=arr(s.credentials);
|
|
739
|
+
var routing=obj(s.routing);
|
|
740
|
+
var warnings=arr(s.warnings).map(function(w){return '<div class="warn">'+esc(w)+'</div>'}).join('');
|
|
741
|
+
root.innerHTML=
|
|
742
|
+
'<div class="page-head"><div><h1>模型与工具提供方</h1><p>控制 goal loop 可用哪些 LLM / 本地工具、优先级与安全策略。密钥只读状态,永不展示值。</p></div>'+
|
|
743
|
+
'<div class="actions"><button class="btn" onclick="loadAutomationSettings()">刷新</button>'+
|
|
744
|
+
'<button class="btn" onclick="previewRoute()">预览路由</button>'+
|
|
745
|
+
'<button class="btn danger" onclick="resetProviders()">恢复默认</button></div></div>'+
|
|
746
|
+
warnings+
|
|
747
|
+
'<div class="panel" style="margin-bottom:14px"><h2>总览</h2>'+
|
|
748
|
+
'<p class="muted">'+esc(ov.plainLanguageSummary||'')+'</p>'+
|
|
749
|
+
'<div class="grid stats" style="margin-top:10px">'+
|
|
750
|
+
'<div class="stat"><span>Goal loop</span><strong>'+(ov.goalLoopEnabled?'开':'关')+'</strong></div>'+
|
|
751
|
+
'<div class="stat"><span>Live API(有效)</span><strong>'+(ov.liveModelProvidersEffective?'开':'关')+'</strong></div>'+
|
|
752
|
+
'<div class="stat"><span>直接可用</span><strong>'+esc(String(ov.directProvidersReady||0))+'</strong></div>'+
|
|
753
|
+
'<div class="stat"><span>需配置</span><strong>'+esc(String(ov.providersNeedingConfig||0))+'</strong></div>'+
|
|
754
|
+
'</div>'+
|
|
755
|
+
'<p class="faint" style="margin-top:10px">环境 Live 标志:'+(ov.liveModelProvidersEnv?'已设置':'未设置')+' · GUI 偏好:'+(ov.liveModelProvidersPreference?'已开启':'未开启')+' · 两者同时满足才允许远程 API 直接调度。</p>'+
|
|
756
|
+
'<div class="actions" style="margin-top:10px">'+
|
|
757
|
+
'<button class="btn" onclick="toggleLivePref('+(ov.liveModelProvidersPreference?'false':'true')+')">'+(ov.liveModelProvidersPreference?'关闭 GUI Live 偏好':'开启 GUI Live 偏好')+'</button>'+
|
|
758
|
+
'<button class="btn" onclick="toggleGoalLoop('+(ov.goalLoopEnabled?'false':'true')+')">'+(ov.goalLoopEnabled?'暂停 Goal Loop':'启用 Goal Loop')+'</button>'+
|
|
759
|
+
'</div>'+
|
|
760
|
+
'<p class="muted" style="margin-top:10px">默认路由:小改动 <strong>'+esc(obj(ov.defaultRoutes).small_edit||'—')+'</strong> · 实现 <strong>'+esc(obj(ov.defaultRoutes).normal_code_task||'—')+'</strong> · 修复 <strong>'+esc(obj(ov.defaultRoutes).repair||'—')+'</strong> · 规划 <strong>'+esc(obj(ov.defaultRoutes).planning||'—')+'</strong></p>'+
|
|
761
|
+
'</div>'+
|
|
762
|
+
'<div class="panel" style="margin-bottom:14px"><div class="section-title"><h2>LLM 提供方</h2></div><div class="list">'+
|
|
763
|
+
providers.map(function(p){return providerCardHtml(p)}).join('')+
|
|
764
|
+
'</div></div>'+
|
|
765
|
+
'<div class="panel" style="margin-bottom:14px"><div class="section-title"><h2>API 凭证状态</h2><span class="muted">env 或页面存储 · 永不显示明文</span></div>'+
|
|
766
|
+
(creds.length?creds.map(function(c){
|
|
767
|
+
return '<div class="card-row" style="margin-bottom:8px"><div>'+
|
|
768
|
+
'<h3>'+esc(c.displayName)+'</h3>'+
|
|
769
|
+
'<p class="muted">URL:'+esc(c.baseUrl||'—')+' · model:'+esc(c.model||'—')+'</p>'+
|
|
770
|
+
'<p class="muted">env:'+(arr(c.presentEnvVars).length?esc(arr(c.presentEnvVars).join(', ')):'未设置')+
|
|
771
|
+
' · 页面密钥:'+(c.storedAuthPresent?esc(c.storedKeyHint||'已保存'):'未保存')+'</p>'+
|
|
772
|
+
'<p class="faint">模式:'+esc(c.storageMode)+'</p>'+
|
|
773
|
+
'<details class="advanced"><summary>Shell 示例</summary><pre class="mono" style="white-space:pre-wrap;font-size:12px;color:var(--muted)">'+esc(c.setupExample||'')+'</pre></details>'+
|
|
774
|
+
'</div>'+pill(c.authPresent?'green':'amber', c.authPresent?'已配置':'缺失')+'</div>';
|
|
775
|
+
}).join(''):'<div class="empty">无 API 凭证条目</div>')+
|
|
776
|
+
'</div>'+
|
|
777
|
+
'<div class="panel" style="margin-bottom:14px"><div class="section-title"><h2>本地执行工具</h2></div><div class="list">'+
|
|
778
|
+
tools.map(function(t){
|
|
779
|
+
return '<div class="card-row" style="margin-bottom:8px"><div>'+
|
|
780
|
+
'<h3>'+esc(t.displayName)+'</h3>'+
|
|
781
|
+
'<p class="muted">'+esc(t.summary||'')+'</p>'+
|
|
782
|
+
(t.executablePath?'<p class="faint mono">'+esc(t.executablePath)+(t.version?(' · '+esc(t.version)):'')+'</p>':'')+
|
|
783
|
+
'<div class="evidence">'+(arr(t.usedByWorkflows).map(function(w){return '<span>'+esc(w)+'</span>'}).join(''))+'</div>'+
|
|
784
|
+
'</div><div class="actions" style="flex-direction:column">'+
|
|
785
|
+
pill(t.status==='detected'?'green':t.status==='disabled'?'gray':'amber', t.status)+
|
|
786
|
+
(t.enabled
|
|
787
|
+
? '<button class="btn" onclick="setToolEnabled(\\''+esc(t.toolId)+'\\',false)">禁用</button>'
|
|
788
|
+
: '<button class="btn primary" onclick="setToolEnabled(\\''+esc(t.toolId)+'\\',true)">启用</button>')+
|
|
789
|
+
'<button class="btn ghost" onclick="healthTool(\\''+esc(t.toolId)+'\\')">健康检查</button>'+
|
|
790
|
+
'</div></div>';
|
|
791
|
+
}).join('')+
|
|
792
|
+
'</div></div>'+
|
|
793
|
+
'<div class="panel" style="margin-bottom:14px"><div class="section-title"><h2>路由偏好</h2><button class="btn" onclick="resetRouting()">使用自动路由</button></div>'+
|
|
794
|
+
'<p class="muted">自动路由会按提供方优先级、能力和健康状态选择;显式路由会覆盖通用优先级。Handoff-only(ChatGPT)只能作为回退。</p>'+
|
|
795
|
+
['implementation','repair','planning','review','browser_planning','ios_analysis'].map(function(key){
|
|
796
|
+
var order=arr(obj(routing.orders)[key]);
|
|
797
|
+
return '<div style="margin:10px 0;padding:10px;border:1px solid var(--line);border-radius:12px">'+
|
|
798
|
+
'<strong>'+esc(key)+'</strong><div class="muted mono" style="margin-top:6px">'+esc(order.join(' → ')||'—')+'</div></div>';
|
|
799
|
+
}).join('')+
|
|
800
|
+
'<p class="faint">若无可直接调用提供方:forge 会创建 continuation packet,而不是假装调用 ChatGPT 会话。</p>'+
|
|
801
|
+
'</div>';
|
|
802
|
+
bindNav(root);
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
function providerCardHtml(p){
|
|
806
|
+
p=obj(p);
|
|
807
|
+
var id=esc(p.providerId);
|
|
808
|
+
var handoff=!!p.handoffOnly;
|
|
809
|
+
var api=obj(p.apiSettings);
|
|
810
|
+
var apiForm='';
|
|
811
|
+
if(api.configurable){
|
|
812
|
+
var keyHint=api.hasStoredApiKey?('已保存密钥 '+(api.storedKeyHint||'••••')):(p.credential&&p.credential.envAuthPresent?'使用环境变量':'未配置密钥');
|
|
813
|
+
apiForm=
|
|
814
|
+
'<div class="setup" style="margin-top:10px">'+
|
|
815
|
+
'<strong>API 配置</strong>'+
|
|
816
|
+
'<p class="faint" style="margin:4px 0 8px">密钥仅存 controllerHome,不进 git;列表接口永不回显明文。</p>'+
|
|
817
|
+
'<label class="faint">Base URL</label>'+
|
|
818
|
+
'<input class="input" id="api-url-'+id+'" value="'+esc(api.baseUrl||api.defaultBaseUrl||'')+'" placeholder="'+esc(api.defaultBaseUrl||'https://…')+'">'+
|
|
819
|
+
'<label class="faint" style="display:block;margin-top:8px">Model</label>'+
|
|
820
|
+
'<input class="input" id="api-model-'+id+'" value="'+esc(api.model||api.defaultModel||'')+'" placeholder="'+esc(api.defaultModel||'model-id')+'">'+
|
|
821
|
+
'<label class="faint" style="display:block;margin-top:8px">API Key(留空则保留原密钥)</label>'+
|
|
822
|
+
'<input class="input" id="api-key-'+id+'" type="password" autocomplete="off" placeholder="'+esc(keyHint)+'">'+
|
|
823
|
+
'<div class="actions" style="margin-top:8px">'+
|
|
824
|
+
'<button class="btn primary" onclick="saveProviderApi(\\''+id+'\\')">保存 API 配置</button>'+
|
|
825
|
+
(api.hasStoredApiKey?'<button class="btn danger" onclick="clearProviderApiKey(\\''+id+'\\')">清除已存密钥</button>':'')+
|
|
826
|
+
'</div>'+
|
|
827
|
+
'<p class="faint" style="margin-top:6px">状态:'+esc(keyHint)+
|
|
828
|
+
(p.credential&&p.credential.envAuthPresent?' · 环境变量已就绪':'')+
|
|
829
|
+
'</p>'+
|
|
830
|
+
'</div>';
|
|
831
|
+
}
|
|
832
|
+
return '<div class="card-row" style="margin-bottom:10px;grid-template-columns:1fr"><div>'+
|
|
833
|
+
'<div style="display:grid;grid-template-columns:minmax(0,1fr) auto;gap:12px;align-items:start">'+
|
|
834
|
+
'<div>'+
|
|
835
|
+
'<div class="section-title" style="margin:0"><h3 style="margin:0">'+esc(p.displayName)+'</h3>'+pill(p.directDispatch?'green':handoff?'blue':p.status==='disabled'?'gray':'amber', p.statusLabel)+'</div>'+
|
|
836
|
+
'<p class="muted">'+esc(p.kindLabel)+' · 优先级 '+esc(String(p.priority))+'</p>'+
|
|
837
|
+
'<p class="muted">'+esc(p.explanation||p.summary||'')+'</p>'+
|
|
838
|
+
'<div class="evidence">'+(arr(p.capabilities).slice(0,8).map(function(c){return '<span>'+esc(c)+'</span>'}).join(''))+'</div>'+
|
|
839
|
+
'<p class="faint" style="margin-top:6px">文件直接改动:'+(p.safety&&p.safety.canMutateFilesDirectly?'是':'否')+
|
|
840
|
+
' · harness apply:'+(p.safety&&p.safety.requiresForgeApply?'是':'否')+
|
|
841
|
+
' · 外部副作用:'+esc((p.safety&&p.safety.externalSideEffects)||'approval_required')+'</p>'+
|
|
842
|
+
(p.lastErrorSummary?'<p class="faint">最近错误码:'+esc(p.lastErrorSummary)+'</p>':'')+
|
|
843
|
+
(handoff?'<div class="setup" style="margin-top:8px"><strong>Direct dispatch:不支持</strong><p class="muted" style="margin:6px 0 0">'+esc(p.explanation||'')+'</p></div>':'')+
|
|
844
|
+
apiForm+
|
|
845
|
+
'</div>'+
|
|
846
|
+
'<div class="actions" style="flex-direction:column">'+
|
|
847
|
+
(!handoff?(p.enabled
|
|
848
|
+
? '<button class="btn" onclick="setProviderEnabled(\\''+id+'\\',false)">禁用</button>'
|
|
849
|
+
: '<button class="btn primary" onclick="setProviderEnabled(\\''+id+'\\',true)">启用</button>'):'<span class="pill blue">Handoff-only</span>')+
|
|
850
|
+
(!handoff?'<button class="btn ghost" onclick="moveProvider(\\''+id+'\\',\\'up\\')">优先级↑</button><button class="btn ghost" onclick="moveProvider(\\''+id+'\\',\\'down\\')">优先级↓</button>':'')+
|
|
851
|
+
'<button class="btn ghost" onclick="healthProvider(\\''+id+'\\')">健康检查</button>'+
|
|
852
|
+
'</div>'+
|
|
853
|
+
'</div>'+
|
|
854
|
+
'</div></div>';
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
function loadAutomationSettings(){
|
|
858
|
+
return api('/api/console/automation-settings'+repoQuery()).then(function(res){
|
|
859
|
+
automationSettings=res;
|
|
860
|
+
renderAutomation();
|
|
861
|
+
}).catch(function(e){toast(e.message||'加载配置失败')});
|
|
862
|
+
}
|
|
863
|
+
function setProviderEnabled(id,on){
|
|
864
|
+
setBusy(true,on?'启用提供方':'禁用提供方');
|
|
865
|
+
api('/api/console/providers/'+encodeURIComponent(id)+'/'+(on?'enable':'disable')+repoQuery(),{method:'POST',body:'{}'}).then(function(){
|
|
866
|
+
toast(on?'已启用':'已禁用');return loadAutomationSettings();
|
|
867
|
+
}).catch(function(e){toast(e.message)}).finally(function(){setBusy(false)});
|
|
868
|
+
}
|
|
869
|
+
function moveProvider(id,dir){
|
|
870
|
+
setBusy(true,'调整优先级');
|
|
871
|
+
api('/api/console/providers/'+encodeURIComponent(id)+'/priority'+repoQuery(),{method:'POST',body:JSON.stringify({direction:dir})}).then(function(){
|
|
872
|
+
toast('优先级已更新');return loadAutomationSettings();
|
|
873
|
+
}).catch(function(e){toast(e.message)}).finally(function(){setBusy(false)});
|
|
874
|
+
}
|
|
875
|
+
function healthProvider(id){
|
|
876
|
+
api('/api/console/providers/health'+repoQuery(),{method:'POST',body:JSON.stringify({providerId:id})}).then(function(res){
|
|
877
|
+
toast((res.health&&res.health.summary)||'健康检查完成');
|
|
878
|
+
advancedRaw=res;
|
|
879
|
+
}).catch(function(e){toast(e.message)});
|
|
880
|
+
}
|
|
881
|
+
function saveProviderApi(id){
|
|
882
|
+
var urlEl=document.getElementById('api-url-'+id);
|
|
883
|
+
var modelEl=document.getElementById('api-model-'+id);
|
|
884
|
+
var keyEl=document.getElementById('api-key-'+id);
|
|
885
|
+
var body={
|
|
886
|
+
baseUrl:urlEl?String(urlEl.value||'').trim():undefined,
|
|
887
|
+
model:modelEl?String(modelEl.value||'').trim():undefined
|
|
888
|
+
};
|
|
889
|
+
if(keyEl&&String(keyEl.value||'').trim())body.apiKey=String(keyEl.value).trim();
|
|
890
|
+
setBusy(true,'保存 API 配置');
|
|
891
|
+
api('/api/console/providers/'+encodeURIComponent(id)+'/api-settings'+repoQuery(),{method:'POST',body:JSON.stringify(body)}).then(function(res){
|
|
892
|
+
toast('已保存 '+id+(res.storedKeyHint?(' · 密钥 '+res.storedKeyHint):''));
|
|
893
|
+
if(keyEl)keyEl.value='';
|
|
894
|
+
return loadAutomationSettings();
|
|
895
|
+
}).catch(function(e){toast(e.message)}).finally(function(){setBusy(false)});
|
|
896
|
+
}
|
|
897
|
+
function clearProviderApiKey(id){
|
|
898
|
+
if(!confirm('清除页面保存的 API Key?(环境变量密钥不受影响)'))return;
|
|
899
|
+
setBusy(true,'清除密钥');
|
|
900
|
+
api('/api/console/providers/'+encodeURIComponent(id)+'/api-settings'+repoQuery(),{method:'POST',body:JSON.stringify({clearApiKey:true})}).then(function(){
|
|
901
|
+
toast('已清除存储密钥');return loadAutomationSettings();
|
|
902
|
+
}).catch(function(e){toast(e.message)}).finally(function(){setBusy(false)});
|
|
903
|
+
}
|
|
904
|
+
function setToolEnabled(id,on){
|
|
905
|
+
setBusy(true,on?'启用工具':'禁用工具');
|
|
906
|
+
api('/api/console/local-tools/'+encodeURIComponent(id)+'/'+(on?'enable':'disable')+repoQuery(),{method:'POST',body:'{}'}).then(function(){
|
|
907
|
+
toast(on?'工具已启用':'工具已禁用');return loadAutomationSettings();
|
|
908
|
+
}).catch(function(e){toast(e.message)}).finally(function(){setBusy(false)});
|
|
909
|
+
}
|
|
910
|
+
function healthTool(id){
|
|
911
|
+
api('/api/console/local-tools/health'+repoQuery(),{method:'POST',body:JSON.stringify({toolId:id})}).then(function(res){
|
|
912
|
+
toast((res.tool&&res.tool.summary)||'工具检查完成');
|
|
913
|
+
}).catch(function(e){toast(e.message)});
|
|
914
|
+
}
|
|
915
|
+
function toggleLivePref(on){
|
|
916
|
+
setBusy(true,'更新 Live 偏好');
|
|
917
|
+
api('/api/console/provider-config'+repoQuery(),{method:'POST',body:JSON.stringify({preferLiveModelProviders:!!on})}).then(function(){
|
|
918
|
+
toast(on?'已开启 GUI Live 偏好(仍需环境变量)':'已关闭 GUI Live 偏好');return loadAutomationSettings();
|
|
919
|
+
}).catch(function(e){toast(e.message)}).finally(function(){setBusy(false)});
|
|
920
|
+
}
|
|
921
|
+
function toggleGoalLoop(on){
|
|
922
|
+
setBusy(true,'更新 Goal Loop');
|
|
923
|
+
api('/api/console/provider-config'+repoQuery(),{method:'POST',body:JSON.stringify({goalLoopEnabled:!!on})}).then(function(){
|
|
924
|
+
toast(on?'Goal Loop 已启用':'Goal Loop 已暂停');return loadAutomationSettings();
|
|
925
|
+
}).catch(function(e){toast(e.message)}).finally(function(){setBusy(false)});
|
|
926
|
+
}
|
|
927
|
+
function previewRoute(){
|
|
928
|
+
api('/api/console/executor-route-preview'+repoQuery(),{method:'POST',body:JSON.stringify({task_intent:'code_implementation'})}).then(function(res){
|
|
929
|
+
toast(res.explanation||res.whyThisProvider||'路由预览完成');
|
|
930
|
+
advancedRaw=res;
|
|
931
|
+
}).catch(function(e){toast(e.message)});
|
|
932
|
+
}
|
|
933
|
+
function resetProviders(){
|
|
934
|
+
if(!confirm('恢复提供方默认配置?(不会删除环境变量)'))return;
|
|
935
|
+
setBusy(true,'恢复默认');
|
|
936
|
+
api('/api/console/providers/reset'+repoQuery(),{method:'POST',body:'{}'}).then(function(){
|
|
937
|
+
toast('已恢复默认');return loadAutomationSettings();
|
|
938
|
+
}).catch(function(e){toast(e.message)}).finally(function(){setBusy(false)});
|
|
939
|
+
}
|
|
940
|
+
function resetRouting(){
|
|
941
|
+
if(!confirm('移除显式路由并恢复按提供方优先级、能力与健康状态自动选择?'))return;
|
|
942
|
+
setBusy(true,'恢复自动路由');
|
|
943
|
+
api('/api/console/executor-routing/reset'+repoQuery(),{method:'POST',body:'{}'}).then(function(){
|
|
944
|
+
toast('已恢复自动路由');return loadAutomationSettings();
|
|
945
|
+
}).catch(function(e){toast(e.message)}).finally(function(){setBusy(false)});
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
function bindNav(root){
|
|
949
|
+
if(!root)return;
|
|
950
|
+
root.querySelectorAll('[data-nav]').forEach(function(el){
|
|
951
|
+
el.addEventListener('click',function(){switchView(el.getAttribute('data-nav'))});
|
|
952
|
+
});
|
|
953
|
+
bindActions(root);
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
function bindActions(root){
|
|
957
|
+
if(!root)return;
|
|
958
|
+
root.querySelectorAll('[data-work-act]').forEach(function(el){
|
|
959
|
+
el.addEventListener('click',function(ev){ev.stopPropagation();workAction(el.getAttribute('data-work-act'),el.getAttribute('data-work-id'))});
|
|
960
|
+
});
|
|
961
|
+
root.querySelectorAll('[data-open-work]').forEach(function(el){
|
|
962
|
+
el.addEventListener('click',function(ev){ev.stopPropagation();openWork(el.getAttribute('data-open-work'))});
|
|
963
|
+
});
|
|
964
|
+
root.querySelectorAll('[data-open-handoff]').forEach(function(el){
|
|
965
|
+
el.addEventListener('click',function(ev){ev.stopPropagation();openHandoff(el.getAttribute('data-open-handoff'))});
|
|
966
|
+
});
|
|
967
|
+
root.querySelectorAll('[data-handoff-act]').forEach(function(el){
|
|
968
|
+
el.addEventListener('click',function(ev){ev.stopPropagation();handoffAction(el.getAttribute('data-handoff-act'),el.getAttribute('data-handoff-id'))});
|
|
969
|
+
});
|
|
970
|
+
root.querySelectorAll('[data-select-repo]').forEach(function(el){
|
|
971
|
+
el.addEventListener('click',function(ev){ev.stopPropagation();selectRepo(el.getAttribute('data-select-repo'))});
|
|
972
|
+
});
|
|
973
|
+
root.querySelectorAll('[data-remove-repo]').forEach(function(el){
|
|
974
|
+
el.addEventListener('click',function(ev){
|
|
975
|
+
ev.stopPropagation();
|
|
976
|
+
removeRepo(el.getAttribute('data-remove-repo'), el.getAttribute('data-remove-repo-name'));
|
|
977
|
+
});
|
|
978
|
+
});
|
|
979
|
+
root.querySelectorAll('[data-open-plugin]').forEach(function(el){
|
|
980
|
+
el.addEventListener('click',function(ev){ev.stopPropagation();openPlugin(el.getAttribute('data-open-plugin'))});
|
|
981
|
+
});
|
|
982
|
+
root.querySelectorAll('[data-plugin-act]').forEach(function(el){
|
|
983
|
+
el.addEventListener('click',function(ev){
|
|
984
|
+
ev.stopPropagation();
|
|
985
|
+
runPluginAction(el.getAttribute('data-plugin-id'), el.getAttribute('data-action-id'));
|
|
986
|
+
});
|
|
987
|
+
});
|
|
988
|
+
root.querySelectorAll('[data-copy]').forEach(function(el){
|
|
989
|
+
el.addEventListener('click',function(ev){ev.stopPropagation();copyText(el.getAttribute('data-copy-text')||'')});
|
|
990
|
+
});
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
function renderAll(){
|
|
994
|
+
if(!commandCenter){
|
|
995
|
+
document.getElementById('view-home').innerHTML='<div class="panel"><h2>正在读取控制台状态</h2><p class="muted">如果长时间无响应,请刷新或打开高级诊断。</p><button class="btn" onclick="refreshAll()">重新载入</button></div>';
|
|
996
|
+
return;
|
|
997
|
+
}
|
|
998
|
+
try{
|
|
999
|
+
renderChrome();
|
|
1000
|
+
renderHome();
|
|
1001
|
+
renderInbox();
|
|
1002
|
+
renderWork();
|
|
1003
|
+
renderCapabilities();
|
|
1004
|
+
renderAutomation();
|
|
1005
|
+
renderReadiness();
|
|
1006
|
+
renderRepositories();
|
|
1007
|
+
renderAdvanced();
|
|
1008
|
+
}catch(e){
|
|
1009
|
+
toast(e.message||String(e));
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
function openWork(id){rememberWork(id);switchView('work');refreshWorkDetail(id)}
|
|
1014
|
+
function openHandoff(id){selectedHandoffId=id;switchView('inbox');renderInbox()}
|
|
1015
|
+
function openPlugin(id){
|
|
1016
|
+
rememberPlugin(id);
|
|
1017
|
+
switchView('capabilities');
|
|
1018
|
+
renderCapabilities();
|
|
1019
|
+
// Refresh detail from console API for latest health/actions.
|
|
1020
|
+
api('/api/console/plugins/'+encodeURIComponent(id)+repoQuery()).then(function(res){
|
|
1021
|
+
if(res&&res.plugin){
|
|
1022
|
+
commandCenter=commandCenter||{};
|
|
1023
|
+
var list=arr(commandCenter.plugins);
|
|
1024
|
+
var idx=list.findIndex(function(p){return p.id===id});
|
|
1025
|
+
if(idx>=0)list[idx]=res.plugin; else list.push(res.plugin);
|
|
1026
|
+
commandCenter.plugins=list;
|
|
1027
|
+
commandCenter.pluginSummary=obj(commandCenter.pluginSummary);
|
|
1028
|
+
renderCapabilities();
|
|
1029
|
+
}
|
|
1030
|
+
}).catch(function(){});
|
|
1031
|
+
}
|
|
1032
|
+
function refreshPlugins(){
|
|
1033
|
+
api('/api/console/plugins'+repoQuery()).then(function(res){
|
|
1034
|
+
commandCenter=commandCenter||{};
|
|
1035
|
+
commandCenter.plugins=arr(res.plugins);
|
|
1036
|
+
commandCenter.pluginSummary=obj(res.summary);
|
|
1037
|
+
renderChrome();
|
|
1038
|
+
renderCapabilities();
|
|
1039
|
+
toast('插件状态已刷新');
|
|
1040
|
+
}).catch(function(e){toast(e.message)});
|
|
1041
|
+
}
|
|
1042
|
+
function runPluginAction(pluginId, actionId){
|
|
1043
|
+
if(busy){toast('上一步仍在处理,请稍候');return}
|
|
1044
|
+
var plugin=pluginById(pluginId)||{};
|
|
1045
|
+
var action=arr(plugin.actions).find(function(a){return a.id===actionId})||{id:actionId,title:actionId};
|
|
1046
|
+
var confirmAuth=false;
|
|
1047
|
+
var confirmationText=undefined;
|
|
1048
|
+
if(action.requiredConfirmationText||action.confirmation==='strong_confirmation'){
|
|
1049
|
+
var required=action.requiredConfirmationText||('CONFIRM '+actionId);
|
|
1050
|
+
var typed=prompt('该动作不可逆,请输入强确认文本:'+required,'');
|
|
1051
|
+
if(typed==null)return;
|
|
1052
|
+
if(typed!==required){toast('确认文本不匹配');return}
|
|
1053
|
+
confirmationText=typed;
|
|
1054
|
+
confirmAuth=true;
|
|
1055
|
+
}
|
|
1056
|
+
var requestId='gui-'+Date.now().toString(36)+'-'+Math.random().toString(36).slice(2,8);
|
|
1057
|
+
setBusy(true,'运行插件动作…');
|
|
1058
|
+
api('/api/plugins/'+encodeURIComponent(pluginId)+'/actions/'+encodeURIComponent(actionId)+repoQuery(),{
|
|
1059
|
+
method:'POST',
|
|
1060
|
+
body:JSON.stringify({
|
|
1061
|
+
requestId:requestId,
|
|
1062
|
+
arguments:{},
|
|
1063
|
+
confirmAuthorization:confirmAuth,
|
|
1064
|
+
confirmationText:confirmationText
|
|
1065
|
+
})
|
|
1066
|
+
}).then(function(res){
|
|
1067
|
+
pluginActionResult={
|
|
1068
|
+
at:new Date().toISOString(),
|
|
1069
|
+
pluginId:pluginId,
|
|
1070
|
+
actionId:actionId,
|
|
1071
|
+
accepted:res.accepted,
|
|
1072
|
+
deduplicated:res.deduplicated,
|
|
1073
|
+
job:res.job,
|
|
1074
|
+
action:res.action
|
|
1075
|
+
};
|
|
1076
|
+
setLastOp({phase:'succeeded',statusLabel:'动作已提交',summary:'插件动作 '+(action.title||actionId)+' 已提交'},'插件动作已提交');
|
|
1077
|
+
toast(res.deduplicated?'动作已去重复用':'插件动作已提交');
|
|
1078
|
+
return refreshAll({silent:true}).then(function(){renderCapabilities()});
|
|
1079
|
+
}).catch(function(e){
|
|
1080
|
+
pluginActionResult={at:new Date().toISOString(),pluginId:pluginId,actionId:actionId,error:e.message,payload:e.payload||null};
|
|
1081
|
+
setLastOp(e.payload||{phase:'failed',summary:e.message},e.message);
|
|
1082
|
+
toast(e.message);
|
|
1083
|
+
renderCapabilities();
|
|
1084
|
+
}).finally(function(){setBusy(false)});
|
|
1085
|
+
}
|
|
1086
|
+
function copyText(text){if(!text){toast('没有可复制内容');return}navigator.clipboard.writeText(text).then(function(){toast('已复制')}).catch(function(){toast('复制失败')})}
|
|
1087
|
+
function toggleAddRepo(){var el=document.getElementById('repoAdd');if(el)el.style.display=el.style.display==='none'?'block':'none'}
|
|
1088
|
+
|
|
1089
|
+
function taskPayload(){
|
|
1090
|
+
var objective=(document.getElementById('taskObjective')||{}).value||'';
|
|
1091
|
+
var acceptance=((document.getElementById('taskAcceptance')||{}).value||'').split(/[;;\\n]/).map(function(s){return s.trim()}).filter(Boolean);
|
|
1092
|
+
var paths=((document.getElementById('taskPaths')||{}).value||'').split(',').map(function(s){return s.trim()}).filter(Boolean);
|
|
1093
|
+
var files=Number((document.getElementById('taskFiles')||{}).value||0)||undefined;
|
|
1094
|
+
return {
|
|
1095
|
+
objective:objective.trim(),
|
|
1096
|
+
acceptanceCriteria:acceptance,
|
|
1097
|
+
allowedPaths:paths,
|
|
1098
|
+
expectedFiles:files,
|
|
1099
|
+
scopeClear:true
|
|
1100
|
+
};
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
function previewMode(){
|
|
1104
|
+
if(busy){toast('上一步仍在处理,请稍候');return}
|
|
1105
|
+
var body=taskPayload();
|
|
1106
|
+
if(!body.objective){toast('请先输入任务目标');return}
|
|
1107
|
+
setBusy(true,'预览模式…');
|
|
1108
|
+
api('/api/console/mode-preview'+repoQuery(),{method:'POST',body:JSON.stringify(body)}).then(function(res){
|
|
1109
|
+
modePreview=res.modePreview||res;
|
|
1110
|
+
setLastOp({phase:'succeeded',statusLabel:'模式已预览',summary:'建议:'+(modePreview.label||'直接执行')+'。'+(modePreview.explanation||'')},'模式已预览');
|
|
1111
|
+
renderHome();
|
|
1112
|
+
toast('建议模式:'+(modePreview.label||''));
|
|
1113
|
+
}).catch(function(e){setLastOp(e.payload||{phase:'failed',summary:e.message},e.message);toast(e.message||'预览失败')}).finally(function(){setBusy(false)});
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
function startTask(){
|
|
1117
|
+
if(busy){toast('上一步仍在处理,请勿重复提交');return}
|
|
1118
|
+
var body=taskPayload();
|
|
1119
|
+
if(!body.objective){toast('请先输入任务目标');return}
|
|
1120
|
+
setBusy(true,'正在提交任务…');
|
|
1121
|
+
api('/api/console/work/start'+repoQuery(),{method:'POST',body:JSON.stringify(body)}).then(function(res){
|
|
1122
|
+
setLastOp(res,'任务已提交');
|
|
1123
|
+
var data=obj(res.data);
|
|
1124
|
+
if(data.work&&data.work.workId){rememberWork(data.work.workId)}
|
|
1125
|
+
else if(data.work&&data.work.id){rememberWork(data.work.id)}
|
|
1126
|
+
else if(data.workId){rememberWork(data.workId)}
|
|
1127
|
+
toast(res.summary||(res.status==='blocked'?'已创建待决定事项':'任务已提交'));
|
|
1128
|
+
return refreshAll();
|
|
1129
|
+
}).then(function(){
|
|
1130
|
+
if(arr(obj(commandCenter).handoffs).length&&!selectedWorkId)switchView('inbox');
|
|
1131
|
+
else if(selectedWorkId)switchView('work');
|
|
1132
|
+
else switchView('home');
|
|
1133
|
+
}).catch(function(e){
|
|
1134
|
+
setLastOp(e.payload||{phase:'failed',summary:e.message||'启动失败'},e.message||'启动失败');
|
|
1135
|
+
toast(e.message||'启动失败');
|
|
1136
|
+
}).finally(function(){setBusy(false)});
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
function diagnoseFirst(){
|
|
1140
|
+
if(busy){toast('上一步仍在处理,请稍候');return}
|
|
1141
|
+
setBusy(true,'正在诊断…');
|
|
1142
|
+
api('/api/console/repair'+repoQuery(),{method:'POST',body:JSON.stringify({operation:'diagnose',dryRun:true})}).then(function(res){
|
|
1143
|
+
setLastOp(res,'诊断完成');toast(res.summary||'诊断完成');switchView('readiness');
|
|
1144
|
+
}).catch(function(e){setLastOp(e.payload||{phase:'failed',summary:e.message},e.message);toast(e.message)}).finally(function(){setBusy(false)});
|
|
1145
|
+
}
|
|
1146
|
+
function repairDryRun(){
|
|
1147
|
+
if(busy){toast('上一步仍在处理,请稍候');return}
|
|
1148
|
+
setBusy(true,'正在预览修复…');
|
|
1149
|
+
api('/api/console/repair'+repoQuery(),{method:'POST',body:JSON.stringify({operation:'repair',dryRun:true})}).then(function(res){
|
|
1150
|
+
setLastOp(res,'已生成修复预览');advancedRaw=res;toast(res.summary||'已生成修复预览');switchView('advanced');
|
|
1151
|
+
}).catch(function(e){setLastOp(e.payload||{phase:'failed',summary:e.message},e.message);toast(e.message)}).finally(function(){setBusy(false)});
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
function workAction(kind,workId){
|
|
1155
|
+
if(busy){toast('上一步仍在处理,请稍候');return}
|
|
1156
|
+
rememberWork(workId);
|
|
1157
|
+
if(kind==='continue')return postWork('/api/console/work/continue',{workId:workId},'继续任务');
|
|
1158
|
+
if(kind==='verify')return postWork('/api/console/work/verify',{workId:workId},'运行验证');
|
|
1159
|
+
if(kind==='finalize')return postWork('/api/console/work/finalize',{workId:workId},'收尾任务');
|
|
1160
|
+
if(kind==='stop')return postWork('/api/console/work/stop',{workId:workId,reason:'stopped from console'},'停止任务');
|
|
1161
|
+
if(kind==='repair'){
|
|
1162
|
+
setBusy(true,'正在诊断…');
|
|
1163
|
+
return api('/api/console/repair'+repoQuery(),{method:'POST',body:JSON.stringify({operation:'diagnose',dryRun:true,workId:workId})}).then(function(res){setLastOp(res,'诊断完成');toast(res.summary||'诊断完成')}).catch(function(e){setLastOp(e.payload||{phase:'failed',summary:e.message},e.message);toast(e.message)}).finally(function(){setBusy(false)});
|
|
1164
|
+
}
|
|
1165
|
+
if(kind==='delegate-codex')return postWork('/api/console/work/delegate',{workId:workId,target:'codex',available:true},'委派 Codex');
|
|
1166
|
+
if(kind==='delegate-grok')return postWork('/api/console/work/delegate',{workId:workId,target:'grok'},'准备 Grok 审阅包');
|
|
1167
|
+
}
|
|
1168
|
+
function postWork(path,body,label){
|
|
1169
|
+
setBusy(true,label||'处理中…');
|
|
1170
|
+
return api(path+repoQuery(),{method:'POST',body:JSON.stringify(body)}).then(function(res){
|
|
1171
|
+
setLastOp(res,label||'已更新');
|
|
1172
|
+
// Clarify handoff-only / request-packet outcomes for small-brain delegation.
|
|
1173
|
+
if(res&&res.data&&res.data.directExecutionAvailable===false){
|
|
1174
|
+
toast((res.summary||'已准备外部审阅请求')+'(非自动执行)');
|
|
1175
|
+
} else {
|
|
1176
|
+
toast(res.summary||'已更新');
|
|
1177
|
+
}
|
|
1178
|
+
return refreshAll();
|
|
1179
|
+
}).catch(function(e){setLastOp(e.payload||{phase:'failed',summary:e.message},e.message);toast(e.message)}).finally(function(){setBusy(false)});
|
|
1180
|
+
}
|
|
1181
|
+
function refreshWorkDetail(id){
|
|
1182
|
+
api('/api/console/work/'+encodeURIComponent(id)+repoQuery()).then(function(res){
|
|
1183
|
+
if(res.work){
|
|
1184
|
+
// merge into command center recent
|
|
1185
|
+
commandCenter=commandCenter||{};
|
|
1186
|
+
commandCenter.currentWork=res.work;
|
|
1187
|
+
renderWork();
|
|
1188
|
+
}
|
|
1189
|
+
}).catch(function(){});
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
function handoffAction(kind,id){
|
|
1193
|
+
if(busy){toast('上一步仍在处理,请稍候');return}
|
|
1194
|
+
var item=arr(obj(commandCenter).handoffs).find(function(h){return h.id===id})||{};
|
|
1195
|
+
var d=obj(item.decision);var body={};
|
|
1196
|
+
if(kind==='approve'){
|
|
1197
|
+
var approvalText='确认'+(d.primaryActionLabel||'批准并创建任务')+'?\\n\\n批准对象:'+(d.requestedAction||item.title||'当前操作')+'\\n影响:'+(d.impact||'按当前任务范围执行')+'\\n后续:'+(d.afterApproval||'打开任务详情');
|
|
1198
|
+
if(!confirm(approvalText))return;
|
|
1199
|
+
}
|
|
1200
|
+
if(kind==='resolve'){
|
|
1201
|
+
var decision=prompt('记录你的决定。注意:此操作只保存决定并移出待处理,不会自动继续任务。',item.recommendedDecision||'');
|
|
1202
|
+
if(decision==null)return;
|
|
1203
|
+
if(!String(decision).trim()){toast('请填写决定内容');return}
|
|
1204
|
+
body={decision:decision,resolver:'user'};
|
|
1205
|
+
}
|
|
1206
|
+
if(kind==='dismiss'){
|
|
1207
|
+
if(!confirm('确认暂不处理此事项?它会从待处理列表移除,相关操作不会执行。'))return;
|
|
1208
|
+
body={decision:'dismissed',resolver:'user'};
|
|
1209
|
+
}
|
|
1210
|
+
setBusy(true,kind==='approve'?'正在批准并创建任务…':kind==='resolve'?'仅记录决定…':kind==='dismiss'?'暂不处理…':'更新中…');
|
|
1211
|
+
api('/api/console/inbox/'+encodeURIComponent(id)+'/'+kind+repoQuery(),{method:'POST',body:JSON.stringify(body)}).then(function(res){
|
|
1212
|
+
if(kind==='approve'){
|
|
1213
|
+
setLastOp(res,'已批准并创建任务');
|
|
1214
|
+
var data=obj(obj(res.actionResult).data);var work=obj(data.work);
|
|
1215
|
+
if(work.workId)rememberWork(work.workId);else if(work.id)rememberWork(work.id);
|
|
1216
|
+
toast(res.summary||'已批准并创建任务');
|
|
1217
|
+
} else {
|
|
1218
|
+
setLastOp({phase:'succeeded',statusLabel:kind==='resolve'?'已记录决定':kind==='dismiss'?'已暂不处理':'已确认',summary:kind==='resolve'?'决定已保存;未触发任何后续执行':kind==='dismiss'?'事项已移出列表,相关操作未执行':'已确认已知晓'}, '已更新');
|
|
1219
|
+
toast(kind==='resolve'?'已记录决定(未自动继续)':kind==='dismiss'?'已暂不处理':'已确认');
|
|
1220
|
+
}
|
|
1221
|
+
selectedHandoffId='';
|
|
1222
|
+
return refreshAll().then(function(){if(kind==='approve'&&selectedWorkId)switchView('work')});
|
|
1223
|
+
}).catch(function(e){setLastOp(e.payload||{phase:'failed',summary:e.message||'更新失败'},e.message||'更新失败');toast(e.message||'更新失败')}).finally(function(){setBusy(false)});
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
function selectRepo(id){
|
|
1227
|
+
rememberRepo(id);
|
|
1228
|
+
toast('已切换仓库');
|
|
1229
|
+
refreshAll().then(function(){switchView('home')});
|
|
1230
|
+
}
|
|
1231
|
+
function registerRepo(){
|
|
1232
|
+
var path=(document.getElementById('repoPath')||{}).value||'';
|
|
1233
|
+
var name=(document.getElementById('repoName')||{}).value||'';
|
|
1234
|
+
if(!path.trim()){toast('请输入仓库路径');return}
|
|
1235
|
+
api('/api/repositories/register',{method:'POST',body:JSON.stringify({path:path.trim(),displayName:name.trim()||undefined})}).then(function(res){
|
|
1236
|
+
var repo=obj(res.repository);if(repo.repoId)rememberRepo(repo.repoId);
|
|
1237
|
+
toast('仓库已注册');return refreshAll();
|
|
1238
|
+
}).catch(function(e){toast(e.message)});
|
|
1239
|
+
}
|
|
1240
|
+
function removeRepo(id, name){
|
|
1241
|
+
if(!id)return;
|
|
1242
|
+
var label=name||id;
|
|
1243
|
+
if(!confirm('从控制台删除「'+label+'」的注册?\\n不会删除磁盘上的仓库文件,仅从 Controller 注册表中移除(可重新注册)。'))return;
|
|
1244
|
+
if(busy)return;
|
|
1245
|
+
setBusy(true,'删除注册中');
|
|
1246
|
+
api('/api/repositories/'+encodeURIComponent(id)+'/remove',{method:'POST',body:JSON.stringify({})}).then(function(res){
|
|
1247
|
+
if(selectedRepoId===id){
|
|
1248
|
+
var remaining=arr(res.repositories);
|
|
1249
|
+
var next=remaining.find(function(r){return r.id&&r.id!==id})||remaining[0];
|
|
1250
|
+
rememberRepo(next&&next.id?next.id:'');
|
|
1251
|
+
}
|
|
1252
|
+
toast(res.summary||'已删除仓库注册');
|
|
1253
|
+
return refreshAll();
|
|
1254
|
+
}).catch(function(e){
|
|
1255
|
+
var msg=e.message||'删除失败';
|
|
1256
|
+
if(String(msg).indexOf('REPOSITORY_SELF_PROTECTED')===0||(e.payload&&e.payload.errorMessage)){
|
|
1257
|
+
msg=(e.payload&&e.payload.errorMessage)||'不能删除当前进程所在仓库的注册(自我保护)';
|
|
1258
|
+
}
|
|
1259
|
+
toast(msg);
|
|
1260
|
+
}).finally(function(){setBusy(false)});
|
|
1261
|
+
}
|
|
1262
|
+
function loadAdvanced(){
|
|
1263
|
+
api('/api/console/advanced'+repoQuery()).then(function(res){advancedRaw=res;renderAdvanced();toast('原始快照已刷新')}).catch(function(e){toast(e.message)});
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
function refreshAll(opts){
|
|
1267
|
+
opts=opts||{};
|
|
1268
|
+
if(refreshInFlight)return Promise.resolve();
|
|
1269
|
+
refreshInFlight=true;
|
|
1270
|
+
return api('/api/console/command-center'+repoQuery()).then(function(res){
|
|
1271
|
+
commandCenter=res;
|
|
1272
|
+
lastRefreshedAt=new Date().toLocaleTimeString();
|
|
1273
|
+
var repo=obj(res.currentRepository);
|
|
1274
|
+
if(repo.id)rememberRepo(repo.id);
|
|
1275
|
+
if(!selectedWorkId&&res.currentWork&&res.currentWork.id)rememberWork(res.currentWork.id);
|
|
1276
|
+
// Merge extras into current work for card display after silent polls.
|
|
1277
|
+
if(res.currentWork&&res.currentWork.id)res.currentWork=mergeWorkExtras(res.currentWork);
|
|
1278
|
+
var loadSettings=(!opts.silent||!automationSettings)
|
|
1279
|
+
? api('/api/console/automation-settings'+repoQuery()).then(function(s){automationSettings=s}).catch(function(){/* optional */})
|
|
1280
|
+
: Promise.resolve();
|
|
1281
|
+
return loadSettings.then(function(){
|
|
1282
|
+
if(!opts.silent)renderAll();
|
|
1283
|
+
else {
|
|
1284
|
+
renderChrome();
|
|
1285
|
+
renderOpBar();
|
|
1286
|
+
try{renderHome();renderWork();renderInbox()}catch(_e){renderAll()}
|
|
1287
|
+
}
|
|
1288
|
+
ensurePoll();
|
|
1289
|
+
});
|
|
1290
|
+
}).catch(function(e){
|
|
1291
|
+
if(opts.silent){
|
|
1292
|
+
lastOperation={phase:'failed',statusLabel:'重连中',summary:e.message||'控制台暂时不可用,正在重试…',at:new Date().toISOString()};
|
|
1293
|
+
renderOpBar();
|
|
1294
|
+
return;
|
|
1295
|
+
}
|
|
1296
|
+
commandCenter={
|
|
1297
|
+
readiness:{state:'blocked',label:'读取失败',headline:'控制台不可用',description:e.message||'本地 API 暂时不可用',connectorLabel:'未知',connectorTone:'red',pendingHandoffCount:0,sections:[]},
|
|
1298
|
+
handoffs:[],recentWork:[],repositories:[],warnings:[e.message||'读取失败'],modePreviewDefault:{label:'—',explanation:''},
|
|
1299
|
+
setupGuide:{needed:true,title:'控制台暂不可用',body:e.message||'请确认 controller 已启动。',actionLabel:'重试'}
|
|
1300
|
+
};
|
|
1301
|
+
setLastOp({phase:'failed',statusLabel:'读取失败',summary:e.message||'本地 API 暂时不可用',error:{title:'控制器暂不可用',explanation:e.message||'本地 API 暂时不可用',nextActions:['刷新页面','重启 controller']}},e.message);
|
|
1302
|
+
renderAll();
|
|
1303
|
+
toast(e.message||'读取失败');
|
|
1304
|
+
}).finally(function(){refreshInFlight=false});
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
window.onerror=function(message){toast(String(message));return false};
|
|
1308
|
+
refreshAll();
|
|
1309
|
+
</script>
|
|
1310
|
+
</body>
|
|
1311
|
+
</html>`;
|
|
1312
|
+
}
|