@zaip-ai/cli 1.3.8 → 1.4.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/README.md +58 -3
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +17 -6
- package/dist/commands/init.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/services/adapters.js +4 -4
- package/dist/services/adapters.js.map +1 -1
- package/dist/services/codex-config-template.d.ts +2 -2
- package/dist/services/codex-config-template.d.ts.map +1 -1
- package/dist/services/codex-config-template.js +3 -3
- package/dist/services/codex-config-template.js.map +1 -1
- package/dist/services/codex-rules.d.ts +1 -1
- package/dist/services/codex-rules.d.ts.map +1 -1
- package/dist/services/codex-rules.js +9 -24
- package/dist/services/codex-rules.js.map +1 -1
- package/dist/services/delivery-git-preflight.d.ts +23 -0
- package/dist/services/delivery-git-preflight.d.ts.map +1 -0
- package/dist/services/delivery-git-preflight.js +69 -0
- package/dist/services/delivery-git-preflight.js.map +1 -0
- package/dist/services/doctor.d.ts.map +1 -1
- package/dist/services/doctor.js +13 -1
- package/dist/services/doctor.js.map +1 -1
- package/dist/services/install-agents-template.d.ts.map +1 -1
- package/dist/services/install-agents-template.js +22 -28
- package/dist/services/install-agents-template.js.map +1 -1
- package/dist/services/install-profile.d.ts +8 -0
- package/dist/services/install-profile.d.ts.map +1 -0
- package/dist/services/install-profile.js +56 -0
- package/dist/services/install-profile.js.map +1 -0
- package/dist/services/logger.d.ts.map +1 -1
- package/dist/services/logger.js +6 -5
- package/dist/services/logger.js.map +1 -1
- package/dist/services/stack-git.d.ts +9 -0
- package/dist/services/stack-git.d.ts.map +1 -0
- package/dist/services/stack-git.js +188 -0
- package/dist/services/stack-git.js.map +1 -0
- package/dist/services/stack-plan.d.ts +3 -1
- package/dist/services/stack-plan.d.ts.map +1 -1
- package/dist/services/stack-plan.js +15 -1
- package/dist/services/stack-plan.js.map +1 -1
- package/dist/services/stack-terraform.d.ts +13 -0
- package/dist/services/stack-terraform.d.ts.map +1 -0
- package/dist/services/stack-terraform.js +274 -0
- package/dist/services/stack-terraform.js.map +1 -0
- package/dist/services/template-manifest.d.ts.map +1 -1
- package/dist/services/template-manifest.js +14 -1
- package/dist/services/template-manifest.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/templates/.agents/.env.example +34 -0
- package/templates/{README.md → .agents/README.md} +124 -60
- package/templates/.agents/config/agents/catalog.yaml +23 -23
- package/templates/.agents/config/clients/codex/agents/zaip-agent-analyst.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-auditor.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-backend.toml +5 -4
- package/templates/.agents/config/clients/codex/agents/zaip-agent-brand-strategist.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-builder.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-cloud-engineer.toml +10 -7
- package/templates/.agents/config/clients/codex/agents/zaip-agent-data-analyst.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-designer.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-finalizer.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-frontend.toml +5 -4
- package/templates/.agents/config/clients/codex/agents/zaip-agent-general-operations.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-governance-compliance.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-growth-strategist.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-integrator.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-marketing-analyst.toml +5 -4
- package/templates/.agents/config/clients/codex/agents/zaip-agent-orchestrator.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-refactoring-specialist.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-reviewer.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-sales-specialist.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-security-auditor.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-task-executor.toml +1 -0
- package/templates/.agents/config/clients/codex/agents/zaip-agent-website-developer.toml +5 -4
- package/templates/.agents/config/clients/codex/agents/zaip-agent-writer.toml +1 -0
- package/templates/.agents/config/pricing/models.json +25 -1
- package/templates/.agents/config/project.yaml +2 -0
- package/templates/.agents/dashboard/.zaip-managed.json +200 -88
- package/templates/.agents/dashboard/DATA-DICTIONARY.md +1 -1
- package/templates/.agents/dashboard/README.md +58 -19
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{CostCalculationGuidePage-DwVZOmMV.js → CostCalculationGuidePage-snUCQYTC.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-VcLx9iOO.js → DashboardHelpDialog-oZVlf-l5.js} +72 -8
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{PricingSettingsDialog-CyjMXkm8.js → PricingSettingsDialog-BPtVUGgs.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-3Awyaovx.js +3 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{TraceabilityWorkspace-DFZwIXSC.js → TraceabilityWorkspace-BYjVOHI_.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-DbaLbU2q.js +68 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{icons-vendor-DXBOtWNI.js → icons-vendor-TPUT2IUt.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-Cmlx8OYH.css +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-ZJFXmK7m.js +2 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{react-vendor-DaNXQPyk.js → react-vendor-Ct48XHGL.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{traceability-I4AKqVDX.js → traceability-BDe4_Ubl.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/index.html +6 -6
- package/templates/.agents/dashboard/apps/frontend/src/App.tsx +73 -67
- package/templates/.agents/dashboard/apps/frontend/src/AppLoadingBoundary.tsx +35 -7
- package/templates/.agents/dashboard/apps/frontend/src/AppWorkBoard.ts +55 -0
- package/templates/.agents/dashboard/apps/frontend/src/ProjectStackEditor.tsx +11 -0
- package/templates/.agents/dashboard/apps/frontend/src/app-loading-boundary.css +98 -0
- package/templates/.agents/dashboard/apps/frontend/src/cost-period-refresh.test.ts +5 -5
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api-reconciliation.ts +33 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.test.ts +75 -0
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.ts +7 -8
- package/templates/.agents/dashboard/apps/frontend/src/project-settings-model.ts +14 -2
- package/templates/.agents/dashboard/apps/frontend/src/project-settings.test.ts +35 -0
- package/templates/.agents/dashboard/apps/frontend/src/snapshot-coherence.test.ts +78 -2
- package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.test.ts +28 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.ts +8 -5
- package/templates/.agents/dashboard/apps/frontend/src/use-app-effects.ts +180 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/contracts.ts +7 -4
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorContent.tsx +13 -7
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +14 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTableDisplay.ts +211 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.test.ts +152 -157
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.tsx +155 -142
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/InvocationManifestQuery.test.ts +145 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/period-cost-groups.ts +7 -5
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-compact-cost-page.ts +4 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-group-page.ts +4 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-run-page.ts +4 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-projection.ts +4 -4
- package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.test.ts +79 -1
- package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.tsx +105 -11
- package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +482 -332
- package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +430 -285
- package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-runtime.mjs +14 -2
- package/templates/.agents/dashboard/packages/local-runtime/scripts/rebuild-sqlite-read-model.mjs +6 -26
- package/templates/.agents/dashboard/packages/local-runtime/scripts/validate-sqlite-read-model.mjs +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/scripts/verify-persistent-launch.mjs +268 -0
- package/templates/.agents/dashboard/packages/local-runtime/server.mjs +482 -332
- package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.test.ts +90 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.ts +112 -22
- package/templates/.agents/dashboard/packages/local-runtime/src/server-agent-assets.ts +39 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-browser-lease.ts +33 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-reconciliation-refresh.test.ts +148 -11
- package/templates/.agents/dashboard/packages/local-runtime/src/server-reconciliation-result.test.ts +68 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-refresh.test.ts +19 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-refresh.ts +39 -43
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-revision.test.ts +42 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-revision.ts +26 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.ts +34 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-startup.ts +30 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-work-reconciliation.test.ts +89 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-work-reconciliation.ts +88 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-workspace.ts +68 -7
- package/templates/.agents/dashboard/packages/local-runtime/src/server.test.ts +11 -5
- package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +129 -99
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-agent-productivity.test.ts +111 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-agent-productivity.ts +140 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-agent-page.test.ts +127 -4
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-agent-page.ts +145 -5
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-aggregates.ts +156 -23
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-group-projection.ts +18 -9
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-invocation-projection.ts +52 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-first-fold-persistence.ts +35 -13
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-force-canonical.test.ts +56 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-incremental-cache.test.ts +29 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-incremental-cache.ts +136 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-incremental-refresh.test.ts +251 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-operations-projection.ts +22 -7
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-cache.test-support.ts +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-canonical-parsing.ts +42 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-canonical.ts +793 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-multi-provider-duration.test.ts +270 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-multi-provider-fixture.ts +3 -2
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-multi-provider.test.ts +18 -4
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-source-fingerprint.test.ts +87 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-source-fingerprint.ts +105 -16
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.test.ts +131 -59
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.ts +1000 -1115
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-snapshot-cache.ts +13 -92
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-launch-claims.test.mjs +79 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-launch-page.mjs +27 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-lifecycle.mjs +6 -6
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-prerequisites.mjs +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-refresh.mjs +2 -10
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-server.mjs +142 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.mjs +231 -239
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.test.mjs +18 -29
- package/templates/.agents/dashboard/packages/windows-launcher/Program.cs +6 -0
- package/templates/.agents/dashboard/zaip-dashboard-windows.exe +0 -0
- package/templates/.agents/requirements/autonomous-assurance.md +1 -1
- package/templates/.agents/requirements/cloud-hostinger-autonomy.md +47 -0
- package/templates/.agents/requirements/comparative-audit.md +1 -1
- package/templates/.agents/requirements/context-engine.md +1 -1
- package/templates/.agents/requirements/cost-observability.md +1 -1
- package/templates/.agents/requirements/dashboard-launch.md +2 -2
- package/templates/.agents/requirements/data-export.md +1 -1
- package/templates/.agents/requirements/design-system.md +1 -1
- package/templates/.agents/requirements/execution-engine.md +1 -1
- package/templates/.agents/requirements/kanban-dashboard.md +1 -1
- package/templates/.agents/requirements/model-orchestration.md +1 -1
- package/templates/.agents/requirements/public-distribution.md +1 -1
- package/templates/.agents/requirements/software-architecture.md +1 -1
- package/templates/.agents/requirements/strategic-improvements.md +1 -1
- package/templates/.agents/requirements/work-lifecycle.md +1 -1
- package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
- package/templates/.agents/rules/autonomy-decision.md +1 -1
- package/templates/.agents/rules/cloud-hostinger-autonomy.md +21 -0
- package/templates/.agents/rules/core.md +5 -4
- package/templates/.agents/rules/local-sqlite-storage.md +18 -0
- package/templates/.agents/rules/meta-mcp.md +21 -0
- package/templates/.agents/rules/workflow.md +1 -0
- package/templates/.agents/runtime/bin/zaip.mjs +305 -137
- package/templates/.agents/runtime/checksums.sha256 +2 -2
- package/templates/.agents/runtime/provenance.json +2 -2
- package/templates/.agents/skills/zaip-skill-api-to-mcp/SKILL.md +4 -0
- package/templates/.agents/skills/zaip-skill-brand-governance/SKILL.md +25 -9
- package/templates/.agents/skills/zaip-skill-brand-governance/references/brandbook-framework.md +2 -2
- package/templates/.agents/skills/zaip-skill-brand-governance/references/brandbook-standards.md +2 -2
- package/templates/.agents/skills/zaip-skill-change/references/observable-evidence.md +15 -0
- package/templates/.agents/skills/zaip-skill-dashboard-sqlite/SKILL.md +13 -5
- package/templates/.agents/skills/zaip-skill-data-analyst/SKILL.md +10 -5
- package/templates/.agents/skills/zaip-skill-execution/SKILL.md +5 -4
- package/templates/.agents/skills/zaip-skill-frontend-launcher/SKILL.md +4 -3
- package/templates/.agents/skills/zaip-skill-frontend-launcher/references/launcher-contract.md +5 -3
- package/templates/.agents/skills/zaip-skill-github-deploy/SKILL.md +5 -5
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/preflight.mjs +78 -13
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/preflight.test.mjs +59 -0
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/yaml-parser.mjs +157 -0
- package/templates/.agents/skills/zaip-skill-growth-strategy-revops/SKILL.md +11 -6
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/SKILL.md +17 -0
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/agents/openai.yaml +7 -0
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/references/autonomous-cloud-inputs.example.json +41 -0
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/references/autonomous-runner.md +84 -0
- package/templates/.agents/skills/zaip-skill-hostinger-cloudflare-terraform/references/operational-contract.md +19 -0
- package/templates/.agents/skills/zaip-skill-local-credentials/SKILL.md +43 -0
- package/templates/.agents/skills/zaip-skill-local-credentials/agents/openai.yaml +6 -0
- package/templates/.agents/skills/zaip-skill-local-credentials/references/dotenv-resolution.md +47 -0
- package/templates/.agents/skills/zaip-skill-marketing/SKILL.md +8 -3
- package/templates/.agents/skills/zaip-skill-meta-ads/SKILL.md +16 -0
- package/templates/.agents/skills/zaip-skill-meta-ads/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-meta-ads/references/setup.md +3 -0
- package/templates/.agents/skills/zaip-skill-meta-ads-setup/SKILL.md +24 -0
- package/templates/.agents/skills/zaip-skill-meta-ads-setup/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-meta-ads-setup/references/diagnostics.md +13 -0
- package/templates/.agents/skills/zaip-skill-meta-ads-setup/references/official-sources.md +10 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-api-health/SKILL.md +12 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-api-health/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-api-health/references/LICENSE +21 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-api-health/references/upstream.md +77 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-api-integration/SKILL.md +12 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-api-integration/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-api-integration/references/LICENSE +21 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-api-integration/references/upstream.md +126 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-app-health-check/SKILL.md +12 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-app-health-check/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-app-health-check/references/LICENSE +21 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-app-health-check/references/upstream.md +67 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-app-review-prep/SKILL.md +12 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-app-review-prep/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-app-review-prep/references/LICENSE +21 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-app-review-prep/references/upstream.md +69 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-compliance-check/SKILL.md +12 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-compliance-check/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-compliance-check/references/LICENSE +21 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-compliance-check/references/upstream.md +79 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-debug-access-token/SKILL.md +14 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-debug-access-token/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-debug-access-token/references/LICENSE +21 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-debug-access-token/references/upstream.md +144 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-debug-webhooks/SKILL.md +12 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-debug-webhooks/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-debug-webhooks/references/LICENSE +21 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-debug-webhooks/references/upstream.md +83 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-search-docs/SKILL.md +10 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-search-docs/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-search-docs/references/LICENSE +21 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-search-docs/references/setup.md +11 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-search-docs/references/upstream.md +55 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-webhook-setup/SKILL.md +12 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-webhook-setup/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-webhook-setup/references/LICENSE +21 -0
- package/templates/.agents/skills/zaip-skill-meta-devtools-webhook-setup/references/upstream.md +56 -0
- package/templates/.agents/skills/zaip-skill-sales-methodology/SKILL.md +12 -7
- package/templates/.agents/skills/zaip-skill-sqlite-read-model/SKILL.md +11 -4
- package/templates/.agents/skills/zaip-skill-tool-setup/SKILL.md +6 -4
- package/templates/.agents/skills/zaip-skill-tool-setup/references/codex-config.md +4 -2
- package/templates/.agents/skills/zaip-skill-tool-setup/references/secrets.md +1 -0
- package/templates/.agents/tools/catalog.yaml +6 -0
- package/templates/.agents/tools/cloud-runner-dns.mjs +28 -0
- package/templates/.agents/tools/cloud-runner-terraform.mjs +212 -0
- package/templates/.agents/tools/cloud-runner.integration.test.mjs +239 -0
- package/templates/.agents/tools/cloud-runner.mjs +786 -0
- package/templates/.agents/tools/cloud-runner.test.mjs +534 -0
- package/templates/.agents/tools/cloud-terraform-plan-policy.mjs +262 -0
- package/templates/.agents/tools/mcp/development/meta-devtools/README.md +14 -0
- package/templates/.agents/tools/mcp/development/meta-devtools/manifest.yaml +28 -0
- package/templates/.agents/tools/mcp/infra/cloudflare/manifest.yaml +2 -3
- package/templates/.agents/tools/mcp/infra/hostinger/manifest.yaml +1 -3
- package/templates/.agents/tools/mcp/marketing/meta-ads/README.md +15 -13
- package/templates/.agents/tools/mcp/marketing/meta-ads/manifest.yaml +15 -10
- package/templates/.agents/tools/profiles/development.yaml +3 -0
- package/templates/infra/terraform/.terraform.lock.hcl +42 -0
- package/templates/infra/terraform/README.md +31 -0
- package/templates/infra/terraform/backend.tf.json +13 -0
- package/templates/infra/terraform/deployment-inputs.example.yaml +22 -0
- package/templates/infra/terraform/fixtures/approved-targets.json +32 -0
- package/templates/infra/terraform/fixtures/plan-approved.json +67 -0
- package/templates/infra/terraform/main.tf +77 -0
- package/templates/infra/terraform/outputs.tf +20 -0
- package/templates/infra/terraform/terraform.tfvars.example +26 -0
- package/templates/infra/terraform/variables.tf +91 -0
- package/templates/infra/terraform/versions.tf +18 -0
- package/templates/scripts/validate-cloud-hostinger-contract.mjs +89 -0
- package/templates/scripts/validate-cloud-terraform-plan.mjs +1 -0
- package/templates/template-manifest.json +599 -167
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-BwnJpl02.js +0 -3
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-C09KmlSw.js +0 -68
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-Dyo_wpL4.js +0 -2
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-hPPfVGQv.css +0 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-stale-seed.ts +0 -50
|
@@ -9,7 +9,8 @@ export const stackComponentDefinitions = [
|
|
|
9
9
|
{ id: "auth_storage", defaultName: "Supabase Auth + Storage", scope: "backend" },
|
|
10
10
|
{ id: "cache_messaging", defaultName: "Redis", scope: "backend" },
|
|
11
11
|
{ id: "async_queue", defaultName: "BullMQ", scope: "backend" },
|
|
12
|
-
{ id: "backend_infrastructure", defaultName: "
|
|
12
|
+
{ id: "backend_infrastructure", defaultName: "Terraform", scope: "backend" },
|
|
13
|
+
{ id: "backend_hosting", defaultName: "Hostinger VPS", scope: "backend" },
|
|
13
14
|
{ id: "web_framework", defaultName: "React", scope: "frontend" },
|
|
14
15
|
{ id: "web_language", defaultName: "TypeScript", scope: "frontend" },
|
|
15
16
|
{ id: "web_build", defaultName: "Vite", scope: "frontend" },
|
|
@@ -19,6 +20,14 @@ export const stackComponentDefinitions = [
|
|
|
19
20
|
{ id: "site_islands", defaultName: "React Islands", scope: "site" },
|
|
20
21
|
{ id: "site_build", defaultName: "Vite", scope: "site" },
|
|
21
22
|
{ id: "site_hosting", defaultName: "Cloudflare Pages", scope: "site" },
|
|
23
|
+
{ id: "prometheus", defaultName: "Prometheus", scope: "observability" },
|
|
24
|
+
{ id: "grafana", defaultName: "Grafana", scope: "observability" },
|
|
25
|
+
{ id: "uptime_kuma", defaultName: "Uptime Kuma", scope: "observability" },
|
|
26
|
+
{ id: "cadvisor", defaultName: "cAdvisor", scope: "observability" },
|
|
27
|
+
{ id: "node_exporter", defaultName: "node-exporter", scope: "observability" },
|
|
28
|
+
{ id: "redis_exporter", defaultName: "Redis Exporter", scope: "observability" },
|
|
29
|
+
{ id: "k6", defaultName: "k6", scope: "testing" },
|
|
30
|
+
{ id: "autocannon", defaultName: "autocannon", scope: "testing" },
|
|
22
31
|
] as const;
|
|
23
32
|
|
|
24
33
|
export type StackComponentId = (typeof stackComponentDefinitions)[number]["id"];
|
|
@@ -107,13 +116,16 @@ export function buildProjectSettingsPayload(
|
|
|
107
116
|
},
|
|
108
117
|
]),
|
|
109
118
|
) as StackComponentsDraft;
|
|
119
|
+
const existingComponents = isRecord(config.stack.overrides.components)
|
|
120
|
+
? config.stack.overrides.components
|
|
121
|
+
: {};
|
|
110
122
|
return {
|
|
111
123
|
...config,
|
|
112
124
|
stack: {
|
|
113
125
|
...config.stack,
|
|
114
126
|
overrides: {
|
|
115
127
|
...otherOverrides,
|
|
116
|
-
components: normalized,
|
|
128
|
+
components: { ...existingComponents, ...normalized },
|
|
117
129
|
languages: {
|
|
118
130
|
frontend: componentNames(normalized, "frontend"),
|
|
119
131
|
backend: componentNames(normalized, "backend"),
|
|
@@ -70,6 +70,7 @@ describe("project settings form mapping", () => {
|
|
|
70
70
|
"Supabase Auth + Storage",
|
|
71
71
|
"Redis",
|
|
72
72
|
"BullMQ",
|
|
73
|
+
"Terraform",
|
|
73
74
|
"Hostinger VPS",
|
|
74
75
|
],
|
|
75
76
|
site: ["Astro", "TypeScript", "React Islands", "Vite", "Cloudflare Pages"],
|
|
@@ -98,6 +99,40 @@ describe("project settings form mapping", () => {
|
|
|
98
99
|
).toThrow("deve ser exata");
|
|
99
100
|
});
|
|
100
101
|
|
|
102
|
+
it("keeps observability and on-demand testing tools editable with pinned-or-empty versions", () => {
|
|
103
|
+
const configured = {
|
|
104
|
+
...config,
|
|
105
|
+
stack: {
|
|
106
|
+
...config.stack,
|
|
107
|
+
overrides: {
|
|
108
|
+
...config.stack.overrides,
|
|
109
|
+
components: { future_tool: { enabled: true } },
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
} satisfies ProjectConfigSettings;
|
|
113
|
+
const draft = projectSettingsDraft(configured);
|
|
114
|
+
const components = {
|
|
115
|
+
...draft.components,
|
|
116
|
+
prometheus: { name: "Prometheus", version: "3.6.0", reference: "docker:prom/prometheus" },
|
|
117
|
+
grafana: { name: "Grafana", version: "", reference: "docker:grafana/grafana" },
|
|
118
|
+
k6: { name: "k6", version: "1.1.0", reference: "docker:grafana/k6" },
|
|
119
|
+
autocannon: { name: "autocannon", version: "", reference: "npm:autocannon" },
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const payload = buildProjectSettingsPayload(configured, components, draft.otherOverrides);
|
|
123
|
+
|
|
124
|
+
expect(payload.stack.overrides).toMatchObject({
|
|
125
|
+
components: {
|
|
126
|
+
prometheus: components.prometheus,
|
|
127
|
+
grafana: components.grafana,
|
|
128
|
+
uptime_kuma: { name: "Uptime Kuma", version: "", reference: "" },
|
|
129
|
+
k6: components.k6,
|
|
130
|
+
autocannon: components.autocannon,
|
|
131
|
+
future_tool: { enabled: true },
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
101
136
|
it("keeps execution and assurance settings in the save payload", () => {
|
|
102
137
|
const configured: ProjectConfigSettings = {
|
|
103
138
|
...config,
|
|
@@ -2,7 +2,20 @@ import { readFileSync } from "node:fs";
|
|
|
2
2
|
import { describe, expect, it } from "vitest";
|
|
3
3
|
import { isCurrentDashboardRequest, mergeBoardPages, needsAtomicCostSnapshot } from "./App.js";
|
|
4
4
|
import { loadAtomicCostSnapshot } from "./snapshot-coherence.js";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
isCommittedSnapshotRevision,
|
|
7
|
+
projectionRefreshDebounceMs,
|
|
8
|
+
settleSnapshotRevisionRefresh,
|
|
9
|
+
shouldPollSnapshotReady,
|
|
10
|
+
shouldRefreshForSnapshotRevision,
|
|
11
|
+
shouldRefreshVisibleProjection,
|
|
12
|
+
snapshotReadyPollAttempts,
|
|
13
|
+
snapshotReadyPollExhaustedMessage,
|
|
14
|
+
snapshotRevisionHiddenFailurePollMs,
|
|
15
|
+
snapshotRevisionHiddenPollMs,
|
|
16
|
+
snapshotRevisionPollDelay,
|
|
17
|
+
snapshotRevisionVisiblePollMs,
|
|
18
|
+
} from "./use-app-effects.js";
|
|
6
19
|
|
|
7
20
|
describe("atomic Cost snapshot loading", () => {
|
|
8
21
|
it("keeps Operations, Cost, and cards on one source generation while the source moves", async () => {
|
|
@@ -82,7 +95,7 @@ describe("atomic Cost snapshot loading", () => {
|
|
|
82
95
|
expect(retry).not.toContain("loadCosts");
|
|
83
96
|
});
|
|
84
97
|
|
|
85
|
-
it("does not prefetch
|
|
98
|
+
it("does not prefetch a newer Operations snapshot in the background", () => {
|
|
86
99
|
const app = readFileSync(new URL("./App.tsx", import.meta.url), "utf8");
|
|
87
100
|
const effects = readFileSync(new URL("./use-app-effects.ts", import.meta.url), "utf8");
|
|
88
101
|
const costLoaders = readFileSync(new URL("./use-app-cost-loaders.ts", import.meta.url), "utf8");
|
|
@@ -135,6 +148,69 @@ describe("atomic Cost snapshot loading", () => {
|
|
|
135
148
|
expect(effects).toContain("void refresh(false, false, true)");
|
|
136
149
|
});
|
|
137
150
|
|
|
151
|
+
it("polls ready only while a startup snapshot reports updating", () => {
|
|
152
|
+
expect(shouldPollSnapshotReady(true, 0)).toBe(true);
|
|
153
|
+
expect(shouldPollSnapshotReady(true, snapshotReadyPollAttempts - 1)).toBe(true);
|
|
154
|
+
expect(shouldPollSnapshotReady(true, snapshotReadyPollAttempts)).toBe(false);
|
|
155
|
+
expect(shouldPollSnapshotReady(false, 0)).toBe(false);
|
|
156
|
+
expect(snapshotReadyPollExhaustedMessage).toContain("desatualizados");
|
|
157
|
+
const effects = readFileSync(new URL("./use-app-effects.ts", import.meta.url), "utf8");
|
|
158
|
+
expect(effects).toContain("const ready = await api.ready()");
|
|
159
|
+
expect(effects).toContain("await refresh(false, false, false, true)");
|
|
160
|
+
expect(effects).not.toContain("refresh(false, true");
|
|
161
|
+
expect(effects).toContain("setSnapshotUpdating(false);");
|
|
162
|
+
expect(effects).toContain("setError(snapshotReadyPollExhaustedMessage)");
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it("observes committed snapshot revisions from an open tab with GET-only refreshes", () => {
|
|
166
|
+
expect(snapshotRevisionPollDelay("visible", 0)).toBe(snapshotRevisionVisiblePollMs);
|
|
167
|
+
expect(snapshotRevisionPollDelay("hidden", 0)).toBe(snapshotRevisionHiddenPollMs);
|
|
168
|
+
expect(snapshotRevisionPollDelay("hidden", 1)).toBe(snapshotRevisionHiddenFailurePollMs);
|
|
169
|
+
const committedHash = "40fb07a77e3f";
|
|
170
|
+
const nextCommittedHash = "1c83d5ea7142";
|
|
171
|
+
expect(shouldRefreshForSnapshotRevision(null, committedHash)).toBe(false);
|
|
172
|
+
expect(shouldRefreshForSnapshotRevision(committedHash, undefined)).toBe(false);
|
|
173
|
+
expect(shouldRefreshForSnapshotRevision(committedHash, committedHash)).toBe(false);
|
|
174
|
+
// `updating` only means a later generation is being prepared. The hash
|
|
175
|
+
// still identifies the already committed SQLite generation and can make
|
|
176
|
+
// an open tab reload when it differs from the last applied one.
|
|
177
|
+
expect(isCommittedSnapshotRevision("updating", nextCommittedHash)).toBe(true);
|
|
178
|
+
expect(shouldRefreshForSnapshotRevision(committedHash, nextCommittedHash)).toBe(true);
|
|
179
|
+
expect(isCommittedSnapshotRevision("current", undefined)).toBe(false);
|
|
180
|
+
expect(isCommittedSnapshotRevision("current", nextCommittedHash)).toBe(true);
|
|
181
|
+
|
|
182
|
+
const afterFailedReload = settleSnapshotRevisionRefresh({
|
|
183
|
+
observedRevision: "revision-1",
|
|
184
|
+
pendingRevision: "revision-2",
|
|
185
|
+
requestedRevision: "revision-2",
|
|
186
|
+
succeeded: false,
|
|
187
|
+
});
|
|
188
|
+
expect(afterFailedReload).toEqual({
|
|
189
|
+
observedRevision: "revision-1",
|
|
190
|
+
pendingRevision: "revision-2",
|
|
191
|
+
});
|
|
192
|
+
expect(
|
|
193
|
+
settleSnapshotRevisionRefresh({
|
|
194
|
+
...afterFailedReload,
|
|
195
|
+
requestedRevision: "revision-2",
|
|
196
|
+
succeeded: true,
|
|
197
|
+
}),
|
|
198
|
+
).toEqual({ observedRevision: "revision-2", pendingRevision: null });
|
|
199
|
+
|
|
200
|
+
const effects = readFileSync(new URL("./use-app-effects.ts", import.meta.url), "utf8");
|
|
201
|
+
expect(effects).toContain("const observedSnapshotRevision = useRef<string | null>(null)");
|
|
202
|
+
expect(effects).toContain("pendingSnapshotRevisionRefresh");
|
|
203
|
+
expect(effects).toContain(
|
|
204
|
+
"isCommittedSnapshotRevision(ready.snapshot_state, ready.snapshot_revision)",
|
|
205
|
+
);
|
|
206
|
+
expect(effects).toContain("settleSnapshotRevisionRefresh({");
|
|
207
|
+
expect(effects).toContain(
|
|
208
|
+
"snapshotRevisionPollDelay(document.visibilityState, consecutiveFailures)",
|
|
209
|
+
);
|
|
210
|
+
expect(effects).toContain("void refresh(false, false, false, true)");
|
|
211
|
+
expect(effects).not.toContain("refresh(false, false, true, true)");
|
|
212
|
+
});
|
|
213
|
+
|
|
138
214
|
it("does not reconcile open work automatically", () => {
|
|
139
215
|
const app = readFileSync(new URL("./App.tsx", import.meta.url), "utf8");
|
|
140
216
|
expect(app).not.toContain("startupReconciliation");
|
|
@@ -119,6 +119,34 @@ describe("daily Cost Monitor continuous pagination", () => {
|
|
|
119
119
|
});
|
|
120
120
|
});
|
|
121
121
|
|
|
122
|
+
describe("SQLite Cost group duration adapter", () => {
|
|
123
|
+
it("prefers total_duration over a synthesized duration_known zero and uses zero only when absent", async () => {
|
|
124
|
+
const api = {
|
|
125
|
+
sqliteViewPage: async () => ({
|
|
126
|
+
offset: 0,
|
|
127
|
+
limit: 10,
|
|
128
|
+
total_count: 2,
|
|
129
|
+
has_more: false,
|
|
130
|
+
rows: [
|
|
131
|
+
{ key: "gpt-5.6-sol", total_duration: 285_480_000, duration_known: 0 },
|
|
132
|
+
{ key: "unavailable", total_duration: null, duration_known: undefined },
|
|
133
|
+
],
|
|
134
|
+
}),
|
|
135
|
+
};
|
|
136
|
+
const page = await loadSqliteCostGroupPage(api as never, {
|
|
137
|
+
view: "models",
|
|
138
|
+
offset: 0,
|
|
139
|
+
limit: 10,
|
|
140
|
+
filters: {} as never,
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
expect(page.rows).toMatchObject([
|
|
144
|
+
{ key: "gpt-5.6-sol", duration_ms: 285_480_000, duration: { known_sum: 285_480_000 } },
|
|
145
|
+
{ key: "unavailable", duration_ms: null, duration: { known_sum: 0 } },
|
|
146
|
+
]);
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
|
|
122
150
|
describe("adaptSqliteCostRun", () => {
|
|
123
151
|
it("renders a sparse API invocation row without throwing and marks missing multipliers unavailable", () => {
|
|
124
152
|
const run = adaptSqliteCostRun({
|
|
@@ -40,7 +40,9 @@ function costGroupQueryOptions(request: CostGroupLoadRequest, offset: number, li
|
|
|
40
40
|
function adaptSqliteCostGroup(row: Record<string, unknown>) {
|
|
41
41
|
const duration = costGroupDuration(row);
|
|
42
42
|
const durationUnknown = Number(row.duration_unknown ?? (duration === null ? 1 : 0));
|
|
43
|
-
|
|
43
|
+
// Model rows may expose only `total_duration`. Prefer it over a legacy
|
|
44
|
+
// synthesized zero in `duration_known` so the table and export agree.
|
|
45
|
+
const durationKnown = duration ?? nullableSqlNumber(row.duration_known) ?? 0;
|
|
44
46
|
return {
|
|
45
47
|
key: String(row.key ?? row.period_key ?? "total"),
|
|
46
48
|
label: String(row.label ?? row.key ?? row.period_key ?? ""),
|
|
@@ -49,10 +51,11 @@ function adaptSqliteCostGroup(row: Record<string, unknown>) {
|
|
|
49
51
|
job: typeof row.job === "string" ? row.job : null,
|
|
50
52
|
run_count: Number(row.total_run_count ?? row.invocation_count ?? 0),
|
|
51
53
|
task_count: nullableSqlNumber(row.task_count),
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
conversation_count: Number(row.conversation_count ?? 0),
|
|
55
|
+
prd_count: nullableSqlNumber(row.prd_count),
|
|
56
|
+
spec_count: nullableSqlNumber(row.spec_count),
|
|
57
|
+
evidence_count: nullableSqlNumber(row.evidence_count),
|
|
58
|
+
test_count: nullableSqlNumber(row.validation_count),
|
|
56
59
|
event_count: Number(row.source_event_count ?? 0),
|
|
57
60
|
total_tokens: nullableSqlNumber(row.total_tokens),
|
|
58
61
|
estimated_usd: nullableSqlNumber(row.total_cost_usd),
|
|
@@ -17,6 +17,68 @@ import {
|
|
|
17
17
|
} from "./operations-detail-hydration.js";
|
|
18
18
|
|
|
19
19
|
export const projectionRefreshDebounceMs = 5_000;
|
|
20
|
+
export const snapshotReadyPollMs = 2_000;
|
|
21
|
+
export const snapshotReadyPollAttempts = 90;
|
|
22
|
+
export const snapshotRevisionVisiblePollMs = 5_000;
|
|
23
|
+
export const snapshotRevisionHiddenPollMs = 10_000;
|
|
24
|
+
export const snapshotRevisionHiddenFailurePollMs = 30_000;
|
|
25
|
+
export const snapshotReadyPollExhaustedMessage =
|
|
26
|
+
"A atualização do snapshot não foi concluída. Os dados exibidos podem estar desatualizados.";
|
|
27
|
+
|
|
28
|
+
export function shouldPollSnapshotReady(snapshotUpdating: boolean, attempts: number): boolean {
|
|
29
|
+
return snapshotUpdating && attempts < snapshotReadyPollAttempts;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function snapshotRevisionPollDelay(
|
|
33
|
+
visibilityState: DocumentVisibilityState,
|
|
34
|
+
consecutiveFailures: number,
|
|
35
|
+
): number {
|
|
36
|
+
if (visibilityState === "visible") return snapshotRevisionVisiblePollMs;
|
|
37
|
+
return consecutiveFailures > 0
|
|
38
|
+
? snapshotRevisionHiddenFailurePollMs
|
|
39
|
+
: snapshotRevisionHiddenPollMs;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function shouldRefreshForSnapshotRevision(
|
|
43
|
+
previousRevision: string | null,
|
|
44
|
+
nextRevision: string | undefined,
|
|
45
|
+
): boolean {
|
|
46
|
+
return (
|
|
47
|
+
previousRevision !== null &&
|
|
48
|
+
typeof nextRevision === "string" &&
|
|
49
|
+
nextRevision.length > 0 &&
|
|
50
|
+
previousRevision !== nextRevision
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function isCommittedSnapshotRevision(
|
|
55
|
+
snapshotState: "current" | "updating" | undefined,
|
|
56
|
+
snapshotRevision: string | undefined,
|
|
57
|
+
): snapshotRevision is string {
|
|
58
|
+
return (
|
|
59
|
+
(snapshotState === "current" || snapshotState === "updating") &&
|
|
60
|
+
typeof snapshotRevision === "string" &&
|
|
61
|
+
snapshotRevision.length > 0
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function settleSnapshotRevisionRefresh({
|
|
66
|
+
observedRevision,
|
|
67
|
+
pendingRevision,
|
|
68
|
+
requestedRevision,
|
|
69
|
+
succeeded,
|
|
70
|
+
}: {
|
|
71
|
+
observedRevision: string | null;
|
|
72
|
+
pendingRevision: string | null;
|
|
73
|
+
requestedRevision: string;
|
|
74
|
+
succeeded: boolean;
|
|
75
|
+
}): { observedRevision: string | null; pendingRevision: string | null } {
|
|
76
|
+
if (!succeeded) return { observedRevision, pendingRevision };
|
|
77
|
+
return {
|
|
78
|
+
observedRevision: requestedRevision,
|
|
79
|
+
pendingRevision: pendingRevision === requestedRevision ? null : pendingRevision,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
20
82
|
|
|
21
83
|
export function shouldRefreshVisibleProjection({
|
|
22
84
|
inFlight,
|
|
@@ -48,6 +110,8 @@ export function useAppEffects({
|
|
|
48
110
|
pricing,
|
|
49
111
|
refresh,
|
|
50
112
|
refreshVersion,
|
|
113
|
+
snapshotUpdating,
|
|
114
|
+
setSnapshotUpdating,
|
|
51
115
|
setError,
|
|
52
116
|
setFxRate,
|
|
53
117
|
setPathname,
|
|
@@ -68,8 +132,11 @@ export function useAppEffects({
|
|
|
68
132
|
visible?: boolean,
|
|
69
133
|
reconcileOpenWork?: boolean,
|
|
70
134
|
refreshProjection?: boolean,
|
|
71
|
-
|
|
135
|
+
reloadCostSummary?: boolean,
|
|
136
|
+
) => Promise<boolean>;
|
|
72
137
|
refreshVersion: MutableRefObject<number>;
|
|
138
|
+
snapshotUpdating: boolean;
|
|
139
|
+
setSnapshotUpdating: Dispatch<SetStateAction<boolean>>;
|
|
73
140
|
setError: Dispatch<SetStateAction<string | null>>;
|
|
74
141
|
setFxRate: Dispatch<SetStateAction<Awaited<ReturnType<DashboardApiClient["fxRate"]>> | null>>;
|
|
75
142
|
setPathname: Dispatch<SetStateAction<string>>;
|
|
@@ -77,6 +144,9 @@ export function useAppEffects({
|
|
|
77
144
|
}) {
|
|
78
145
|
const projectionRefreshInFlight = useRef(false);
|
|
79
146
|
const lastProjectionRefreshAt = useRef(0);
|
|
147
|
+
const observedSnapshotRevision = useRef<string | null>(null);
|
|
148
|
+
const snapshotRevisionRefreshInFlight = useRef(false);
|
|
149
|
+
const pendingSnapshotRevisionRefresh = useRef<string | null>(null);
|
|
80
150
|
useEffect(() => {
|
|
81
151
|
void refresh();
|
|
82
152
|
return () => {
|
|
@@ -124,6 +194,115 @@ export function useAppEffects({
|
|
|
124
194
|
};
|
|
125
195
|
}, [refresh]);
|
|
126
196
|
|
|
197
|
+
useEffect(() => {
|
|
198
|
+
if (!snapshotUpdating) return;
|
|
199
|
+
let cancelled = false;
|
|
200
|
+
let attempts = 0;
|
|
201
|
+
let timeout: number | null = null;
|
|
202
|
+
const pollReady = async () => {
|
|
203
|
+
if (cancelled || !shouldPollSnapshotReady(true, attempts)) return;
|
|
204
|
+
attempts += 1;
|
|
205
|
+
try {
|
|
206
|
+
const ready = await api.ready();
|
|
207
|
+
if (cancelled) return;
|
|
208
|
+
if (ready.snapshot_state === "current") {
|
|
209
|
+
setSnapshotUpdating(false);
|
|
210
|
+
// Promotion produced a new immutable SQLite generation. Reload its
|
|
211
|
+
// Operations and Cost Monitor summaries by GET; never rebuild or
|
|
212
|
+
// reconcile as part of the readiness poll.
|
|
213
|
+
await refresh(false, false, false, true);
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
} catch {
|
|
217
|
+
// Keep the validated stale seed visible within the bounded poll window.
|
|
218
|
+
}
|
|
219
|
+
if (cancelled) return;
|
|
220
|
+
if (shouldPollSnapshotReady(true, attempts)) {
|
|
221
|
+
timeout = window.setTimeout(() => void pollReady(), snapshotReadyPollMs);
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
// Stop the progress indicator after the bounded window, while retaining
|
|
225
|
+
// an explicit visible warning that the stale snapshot remains on screen.
|
|
226
|
+
setSnapshotUpdating(false);
|
|
227
|
+
setError(snapshotReadyPollExhaustedMessage);
|
|
228
|
+
};
|
|
229
|
+
void pollReady();
|
|
230
|
+
return () => {
|
|
231
|
+
cancelled = true;
|
|
232
|
+
if (timeout !== null) window.clearTimeout(timeout);
|
|
233
|
+
};
|
|
234
|
+
}, [api, refresh, setError, setSnapshotUpdating, snapshotUpdating]);
|
|
235
|
+
|
|
236
|
+
useEffect(() => {
|
|
237
|
+
let cancelled = false;
|
|
238
|
+
let consecutiveFailures = 0;
|
|
239
|
+
let timeout: number | null = null;
|
|
240
|
+
|
|
241
|
+
const refreshChangedRevision = () => {
|
|
242
|
+
if (cancelled || snapshotRevisionRefreshInFlight.current) return;
|
|
243
|
+
const requestedRevision = pendingSnapshotRevisionRefresh.current;
|
|
244
|
+
if (requestedRevision === null) return;
|
|
245
|
+
snapshotRevisionRefreshInFlight.current = true;
|
|
246
|
+
// A committed revision is discovered by GET /ready. Its data reload
|
|
247
|
+
// remains GET-only: it must never start a projection rebuild or
|
|
248
|
+
// lifecycle reconciliation from a tab that happened to stay open.
|
|
249
|
+
void refresh(false, false, false, true)
|
|
250
|
+
.then((succeeded) => {
|
|
251
|
+
const settled = settleSnapshotRevisionRefresh({
|
|
252
|
+
observedRevision: observedSnapshotRevision.current,
|
|
253
|
+
pendingRevision: pendingSnapshotRevisionRefresh.current,
|
|
254
|
+
requestedRevision,
|
|
255
|
+
succeeded,
|
|
256
|
+
});
|
|
257
|
+
// A failed GET leaves the exact revision pending. The following
|
|
258
|
+
// passive readiness poll retries it without changing the UI state.
|
|
259
|
+
observedSnapshotRevision.current = settled.observedRevision;
|
|
260
|
+
pendingSnapshotRevisionRefresh.current = settled.pendingRevision;
|
|
261
|
+
})
|
|
262
|
+
.finally(() => {
|
|
263
|
+
snapshotRevisionRefreshInFlight.current = false;
|
|
264
|
+
// A newer committed revision that arrived while this GET was in
|
|
265
|
+
// flight can run immediately; retrying the same rejected revision
|
|
266
|
+
// waits for the normal passive polling cadence.
|
|
267
|
+
if (pendingSnapshotRevisionRefresh.current !== requestedRevision) {
|
|
268
|
+
refreshChangedRevision();
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
const pollRevision = async () => {
|
|
274
|
+
try {
|
|
275
|
+
const ready = await api.ready();
|
|
276
|
+
if (cancelled) return;
|
|
277
|
+
consecutiveFailures = 0;
|
|
278
|
+
const previousRevision = observedSnapshotRevision.current;
|
|
279
|
+
if (isCommittedSnapshotRevision(ready.snapshot_state, ready.snapshot_revision)) {
|
|
280
|
+
if (previousRevision === null) {
|
|
281
|
+
observedSnapshotRevision.current = ready.snapshot_revision;
|
|
282
|
+
}
|
|
283
|
+
if (shouldRefreshForSnapshotRevision(previousRevision, ready.snapshot_revision)) {
|
|
284
|
+
pendingSnapshotRevisionRefresh.current = ready.snapshot_revision;
|
|
285
|
+
refreshChangedRevision();
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
} catch {
|
|
289
|
+
consecutiveFailures += 1;
|
|
290
|
+
}
|
|
291
|
+
if (!cancelled) {
|
|
292
|
+
timeout = window.setTimeout(
|
|
293
|
+
() => void pollRevision(),
|
|
294
|
+
snapshotRevisionPollDelay(document.visibilityState, consecutiveFailures),
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
void pollRevision();
|
|
300
|
+
return () => {
|
|
301
|
+
cancelled = true;
|
|
302
|
+
if (timeout !== null) window.clearTimeout(timeout);
|
|
303
|
+
};
|
|
304
|
+
}, [api, refresh]);
|
|
305
|
+
|
|
127
306
|
useEffect(() => {
|
|
128
307
|
if (
|
|
129
308
|
!shouldHydrateOperationsDetails(
|
|
@@ -135,6 +135,8 @@ export interface CostGroupRow {
|
|
|
135
135
|
run_count: number;
|
|
136
136
|
/** Null when a paged source does not provide a factual task attribution. */
|
|
137
137
|
task_count: number | null;
|
|
138
|
+
/** Distinct factual conversation memberships for the displayed model. */
|
|
139
|
+
conversation_count?: number | null;
|
|
138
140
|
/** Canonical export fields; task_count remains the active-task alias. */
|
|
139
141
|
tasksCreated?: number;
|
|
140
142
|
tasksActive?: number | null;
|
|
@@ -143,10 +145,11 @@ export interface CostGroupRow {
|
|
|
143
145
|
/** Stable ZAIP identity details for the Agent aggregation only. */
|
|
144
146
|
persona?: string | null;
|
|
145
147
|
job?: string | null;
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
148
|
+
/** Creation-run attribution is unavailable when canonical linkage is absent. */
|
|
149
|
+
prd_count: number | null;
|
|
150
|
+
spec_count: number | null;
|
|
151
|
+
evidence_count: number | null;
|
|
152
|
+
test_count: number | null;
|
|
150
153
|
event_count: number;
|
|
151
154
|
total_tokens: number | null;
|
|
152
155
|
estimated_usd: number | null;
|
|
@@ -290,16 +290,22 @@ export function CostMonitorContent({
|
|
|
290
290
|
locale={locale}
|
|
291
291
|
loading={groupPageLoading}
|
|
292
292
|
rows={groups[key]}
|
|
293
|
-
{...(key === "models"
|
|
294
|
-
?
|
|
295
|
-
: groupPage?.totals === undefined
|
|
293
|
+
{...(key === "models"
|
|
294
|
+
? groupPage?.totals === undefined
|
|
296
295
|
? {}
|
|
297
|
-
: { totals: groupPage.totals }
|
|
296
|
+
: { totals: groupPage.totals }
|
|
297
|
+
: key === "providers"
|
|
298
|
+
? { totals: summaryTotals }
|
|
299
|
+
: groupPage?.totals === undefined
|
|
300
|
+
? {}
|
|
301
|
+
: { totals: groupPage.totals })}
|
|
298
302
|
{...(key === "agents"
|
|
299
303
|
? { showDateTime: false, showAgentIdentity: true }
|
|
300
|
-
: key === "models"
|
|
301
|
-
? { showDateTime: false,
|
|
302
|
-
:
|
|
304
|
+
: key === "models"
|
|
305
|
+
? { showDateTime: false, showModelLifecycleDetails: true }
|
|
306
|
+
: key === "providers"
|
|
307
|
+
? { showDateTime: false, showInvocationTasks: true }
|
|
308
|
+
: {})}
|
|
303
309
|
/>
|
|
304
310
|
{groupPager}
|
|
305
311
|
</>
|
|
@@ -204,6 +204,17 @@ export function CostMonitorPage({
|
|
|
204
204
|
const [detailLoading, setDetailLoading] = useState(false);
|
|
205
205
|
const [detailError, setDetailError] = useState<string | null>(null);
|
|
206
206
|
const [detailAttempt, setDetailAttempt] = useState(0);
|
|
207
|
+
// The summary object is replaced only when the host receives a newer
|
|
208
|
+
// snapshot. Keep this revision separate from tabs and filters so the active
|
|
209
|
+
// remote table is reloaded without remounting the Cost Monitor surface.
|
|
210
|
+
const dataRevisionRef = useRef({ data, revision: 0 });
|
|
211
|
+
if (dataRevisionRef.current.data !== data) {
|
|
212
|
+
dataRevisionRef.current = {
|
|
213
|
+
data,
|
|
214
|
+
revision: dataRevisionRef.current.revision + 1,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
const dataRevision = dataRevisionRef.current.revision;
|
|
207
218
|
const loadDetailRef = useRef(loadDetail);
|
|
208
219
|
loadDetailRef.current = loadDetail;
|
|
209
220
|
const text = costCopy[locale];
|
|
@@ -267,6 +278,7 @@ export function CostMonitorPage({
|
|
|
267
278
|
globalQuery: globalFilters?.query ?? "",
|
|
268
279
|
filters,
|
|
269
280
|
limit: groupPageLimit,
|
|
281
|
+
revision: dataRevision,
|
|
270
282
|
...(groupView === null ? {} : { load: loadGroupPage }),
|
|
271
283
|
});
|
|
272
284
|
const displayedGroupPage = groupPageState.page ?? groupPageState.stalePage;
|
|
@@ -285,6 +297,7 @@ export function CostMonitorPage({
|
|
|
285
297
|
range: compactPageRange,
|
|
286
298
|
query: globalFilters?.query,
|
|
287
299
|
filters,
|
|
300
|
+
revision: dataRevision,
|
|
288
301
|
});
|
|
289
302
|
// Server pagination is safe only when every active Run filter is part of the
|
|
290
303
|
// endpoint contract. Unsupported local text/metadata filters retain the
|
|
@@ -309,6 +322,7 @@ export function CostMonitorPage({
|
|
|
309
322
|
// must not silently add a date range and bypass the fast all-time page.
|
|
310
323
|
range: groupPageRange,
|
|
311
324
|
refresh: lastUpdatedAt,
|
|
325
|
+
revision: dataRevision,
|
|
312
326
|
load: loadRunPage,
|
|
313
327
|
});
|
|
314
328
|
useEffect(
|