@zaip-ai/cli 1.3.0 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/services/agent-adapters.js +1 -1
- package/dist/services/agent-adapters.js.map +1 -1
- package/dist/services/agent-adapters.test.js +2 -1
- package/dist/services/agent-adapters.test.js.map +1 -1
- package/dist/services/codex-pre-tool-hook-template.d.ts.map +1 -1
- package/dist/services/codex-pre-tool-hook-template.js +89 -7
- package/dist/services/codex-pre-tool-hook-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 +7 -0
- package/dist/services/codex-rules.js.map +1 -1
- package/dist/services/install-agents-template.d.ts.map +1 -1
- package/dist/services/install-agents-template.js +1 -0
- package/dist/services/install-agents-template.js.map +1 -1
- package/dist/services/runtime-template.test.js +31 -7
- package/dist/services/runtime-template.test.js.map +1 -1
- package/dist/services/template-manifest.d.ts.map +1 -1
- package/dist/services/template-manifest.js +7 -3
- package/dist/services/template-manifest.js.map +1 -1
- package/package.json +1 -1
- package/templates/.agents/config/agents/catalog.yaml +7 -7
- package/templates/.agents/config/clients/codex/agents/zaip-agent-backend.toml +2 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-designer.toml +2 -2
- package/templates/.agents/config/clients/codex/agents/zaip-agent-frontend.toml +8 -8
- package/templates/.agents/dashboard/.zaip-managed.json +373 -205
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{CostCalculationGuidePage-DxR_pgSV.js → CostCalculationGuidePage-ovxurkIk.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-4jZLTWE_.js → DashboardHelpDialog-BXy6nti1.js} +268 -86
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{PricingSettingsDialog-CKcsqb-r.js → PricingSettingsDialog-vSvvOHQp.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{ProjectSettingsPage-DmmJD2Th.js → ProjectSettingsPage-zH758vfs.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-CTH2wDs5.js +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{TraceabilityWorkspace-CaKwQP43.css → TraceabilityWorkspace-DvvavDLY.css} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-DKwP1stV.js +68 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-PoJA2PI1.css +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{icons-vendor-C0fj2uU9.js → icons-vendor-B_lDDHn1.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-B31GMG5O.css +1 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-CuMcoUni.js +2 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{react-vendor-BEsJ-FYH.js → react-vendor-B3TJrD4O.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{traceability-B6y6Gw12.js → traceability-7f1j5wx3.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/index.html +7 -7
- package/templates/.agents/dashboard/apps/frontend/playwright.dom.config.ts +32 -0
- package/templates/.agents/dashboard/apps/frontend/src/App.tsx +132 -245
- package/templates/.agents/dashboard/apps/frontend/src/AppOverlays.tsx +0 -21
- package/templates/.agents/dashboard/apps/frontend/src/DashboardAlternateContent.tsx +9 -0
- package/templates/.agents/dashboard/apps/frontend/src/TraceabilityWorkspace.dom.e2e.ts +56 -0
- package/templates/.agents/dashboard/apps/frontend/src/TraceabilityWorkspace.test.ts +18 -1
- package/templates/.agents/dashboard/apps/frontend/src/TraceabilityWorkspace.tsx +75 -8
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.test.ts +25 -1
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.ts +7 -9
- package/templates/.agents/dashboard/apps/frontend/src/operations-period-render.test.ts +4 -4
- package/templates/.agents/dashboard/apps/frontend/src/overview-status-page.test.ts +1 -1
- package/templates/.agents/dashboard/apps/frontend/src/snapshot-banner-semantics.test.ts +7 -0
- package/templates/.agents/dashboard/apps/frontend/src/snapshot-coherence.test.ts +20 -8
- package/templates/.agents/dashboard/apps/frontend/src/sqlite-page-export.test.ts +32 -0
- package/templates/.agents/dashboard/apps/frontend/src/sqlite-page-export.ts +21 -0
- package/templates/.agents/dashboard/apps/frontend/src/styles.css +19 -0
- package/templates/.agents/dashboard/apps/frontend/src/traceability-task-pagination.test.ts +32 -0
- package/templates/.agents/dashboard/apps/frontend/src/traceability-task-pagination.ts +36 -0
- package/templates/.agents/dashboard/apps/frontend/src/traceability-workspace.css +6 -2
- package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.test.ts +48 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.ts +31 -27
- package/templates/.agents/dashboard/apps/frontend/src/use-app-trace-documents.ts +7 -1
- package/templates/.agents/dashboard/apps/frontend/src/use-app-work-list-page.test.ts +163 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-app-work-list-page.ts +136 -0
- package/templates/.agents/dashboard/apps/frontend/src/use-operations-detail-export.ts +76 -0
- package/templates/.agents/dashboard/apps/frontend/src/work-list-load-dedup.test.ts +23 -0
- package/templates/.agents/dashboard/apps/frontend/src/work-list-load-dedup.ts +27 -0
- package/templates/.agents/dashboard/apps/frontend/src/work-list-pagination.test.ts +38 -14
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostDeveloperAttributionPanel.tsx +60 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostDeveloperAttributionTable.tsx +191 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostFilters.loading.test.ts +14 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostFilters.run-page.test.ts +18 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostFilters.tsx +18 -3
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorContent.tsx +8 -2
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorLoadErrors.tsx +35 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.test.ts +47 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +50 -58
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTableLoading.test.ts +132 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTableLoading.tsx +70 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.test.ts +128 -138
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.tsx +17 -67
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-copy.ts +2 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-views.ts +3 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-page-range.ts +35 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-compact-cost-page.ts +16 -4
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-group-page.test.ts +37 -2
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-group-page.ts +44 -8
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-run-page.ts +6 -1
- package/templates/.agents/dashboard/modules/operations/src/contracts.ts +20 -3
- package/templates/.agents/dashboard/modules/operations/src/react/DeveloperAttributionPanel.test.ts +54 -0
- package/templates/.agents/dashboard/modules/operations/src/react/DeveloperAttributionPanel.tsx +247 -0
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsMainContent.tsx +39 -13
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.helpers.tsx +107 -2
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.macro-metrics.test.ts +55 -0
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.test.ts +20 -28
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.tsx +162 -165
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverviewTopPanel.tsx +127 -0
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsPage.tsx +13 -46
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsPageOverview.tsx +3 -0
- package/templates/.agents/dashboard/modules/operations/src/react/PagedWorkList.test.tsx +43 -0
- package/templates/.agents/dashboard/modules/operations/src/react/PagedWorkList.tsx +181 -0
- package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.test.ts +4 -2
- package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.tsx +13 -0
- package/templates/.agents/dashboard/modules/operations/src/react/developer-identities.test.ts +18 -0
- package/templates/.agents/dashboard/modules/operations/src/react/developer-identities.ts +30 -0
- package/templates/.agents/dashboard/modules/operations/src/react/execution-metrics.ts +1 -0
- package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.test.ts +8 -0
- package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.tsx +3 -0
- package/templates/.agents/dashboard/modules/operations/src/react/export/export-layout.test.ts +14 -5
- package/templates/.agents/dashboard/modules/operations/src/react/index.ts +1 -0
- package/templates/.agents/dashboard/modules/operations/src/react/operations-coverage-toast.test.ts +4 -3
- package/templates/.agents/dashboard/modules/operations/src/react/operations-date-filters.css +1 -1
- package/templates/.agents/dashboard/modules/operations/src/react/operations-overview-period-filter.test.ts +21 -11
- package/templates/.agents/dashboard/modules/operations/src/react/operations-overview.css +4 -0
- package/templates/.agents/dashboard/modules/operations/src/react/operations-page-contract.ts +8 -1
- package/templates/.agents/dashboard/modules/operations/src/react/operations-view-order.test.ts +1 -0
- package/templates/.agents/dashboard/modules/operations/src/react/period-summary.ts +1 -0
- package/templates/.agents/dashboard/modules/operations/src/server/metric-coverage.ts +1 -0
- package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +527 -335
- package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +501 -309
- package/templates/.agents/dashboard/packages/local-runtime/gitignore.template +2 -0
- package/templates/.agents/dashboard/packages/local-runtime/scripts/rebuild-sqlite-read-model.mjs +3 -1
- package/templates/.agents/dashboard/packages/local-runtime/scripts/test-sqlite-read-model.mjs +3 -3
- package/templates/.agents/dashboard/packages/local-runtime/scripts/validate-sqlite-read-model.mjs +25 -15
- package/templates/.agents/dashboard/packages/local-runtime/server.mjs +527 -335
- package/templates/.agents/dashboard/packages/local-runtime/src/server-board.test.ts +34 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-board.ts +15 -8
- package/templates/.agents/dashboard/packages/local-runtime/src/server-classification-page.test.ts +87 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-period-macro-metric.test.ts +44 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-period-macro-metric.ts +125 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-reconciliation-refresh.test.ts +66 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-request-authority.test.ts +61 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-request-authority.ts +18 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-run-projections.test.ts +42 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-refresh.ts +97 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot.test.ts +3 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/server-sqlite-task-trace.ts +91 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server.test-fixtures.ts +36 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server.test.ts +98 -123
- package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +111 -135
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-artifact-counts.ts +28 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-agent-page.test.ts +63 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-agent-page.ts +109 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-aggregates.ts +497 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-fast-page-parity.test-support.ts +65 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-group-page.test.ts +176 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-group-page.ts +119 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-group-projection.ts +41 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-invocation-page.test.ts +16 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-cost-invocation-page.ts +29 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-first-fold-cache.ts +355 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-first-fold-persistence.ts +121 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-first-fold-timing.ts +27 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-operations-projection.ts +15 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-operations-work-list.test.ts +293 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-operations-work-list.ts +371 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-cache.test-support.ts +23 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-first-fold-types.ts +89 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-multi-provider-fixture.ts +227 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-multi-provider.test.ts +691 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-source-fingerprint.ts +81 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.test.ts +440 -863
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.ts +1120 -1086
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-snapshot-cache.ts +129 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-snapshot-install.test.ts +26 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-snapshot-install.ts +28 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-snapshot-seed.test.ts +116 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-launch-page.mjs +146 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-launch-page.test.mjs +165 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-refresh.mjs +140 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.mjs +188 -299
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.test.mjs +51 -70
- package/templates/.agents/dashboard/packages/windows-launcher/Program.cs +5 -2
- package/templates/.agents/dashboard/tests/e2e/playwright.config.ts +4 -1
- package/templates/.agents/dashboard/tests/e2e/specs/cost-monitor-loading.spec.ts +142 -0
- package/templates/.agents/dashboard/tests/e2e/specs/cost-monitor-pagination.spec.ts +232 -0
- package/templates/.agents/dashboard/tests/e2e/specs/dashboard-performance-matrix.spec.ts +743 -0
- package/templates/.agents/dashboard/tests/e2e/specs/dashboard.spec.ts +183 -210
- package/templates/.agents/dashboard/zaip-dashboard-windows.exe +0 -0
- package/templates/.agents/requirements/autonomous-assurance.md +6 -6
- 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 +1 -1
- 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 +3 -3
- package/templates/.agents/requirements/kanban-dashboard.md +10 -2
- 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 +4 -4
- package/templates/.agents/requirements/zaip-strategic-95.md +1 -1
- package/templates/.agents/rules/dashboard-ui-consistency.md +14 -0
- package/templates/.agents/rules/frontend-lite.md +4 -4
- package/templates/.agents/rules/run-lifecycle-closure.md +4 -4
- package/templates/.agents/runtime/bin/zaip.mjs +1137 -1037
- package/templates/.agents/runtime/checksums.sha256 +2 -2
- package/templates/.agents/runtime/provenance.json +2 -2
- package/templates/.agents/skills/criar-pasta-obsidian/scripts/generate-obsidian-vault.test.mjs +20 -16
- package/templates/.agents/skills/zaip-skill-agent-catalog/SKILL.md +22 -0
- package/templates/.agents/skills/zaip-skill-agent-catalog/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-author-skills/SKILL.md +3 -2
- package/templates/.agents/skills/zaip-skill-author-skills/scripts/audit-skill-catalog.mjs +49 -0
- package/templates/.agents/skills/zaip-skill-author-skills/scripts/author-skill-scripts.test.mjs +27 -0
- package/templates/.agents/skills/zaip-skill-author-skills/scripts/run-skill-tests.mjs +37 -0
- package/templates/.agents/skills/zaip-skill-backend/SKILL.md +1 -0
- package/templates/.agents/skills/zaip-skill-change/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-change/references/observable-evidence.md +83 -0
- package/templates/.agents/skills/zaip-skill-dashboard-diagnostics/SKILL.md +22 -0
- package/templates/.agents/skills/zaip-skill-dashboard-diagnostics/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-execution/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-frontend/SKILL.md +4 -3
- package/templates/.agents/skills/zaip-skill-frontend/agents/openai.yaml +2 -2
- package/templates/.agents/skills/zaip-skill-github-deploy/SKILL.md +10 -10
- package/templates/.agents/skills/zaip-skill-lifecycle-closure/SKILL.md +27 -0
- package/templates/.agents/skills/zaip-skill-lifecycle-closure/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-prd/SKILL.md +4 -0
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-local-telemetry.mjs +72 -22
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-explicit-recovery.mjs +223 -0
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.mjs +42 -1
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.test.mjs +101 -0
- package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-remeasurement.test.mjs +53 -0
- package/templates/.agents/skills/zaip-skill-release-qualification/SKILL.md +20 -0
- package/templates/.agents/skills/zaip-skill-release-qualification/agents/openai.yaml +4 -0
- package/templates/.agents/skills/zaip-skill-review/SKILL.md +5 -0
- package/templates/.agents/skills/zaip-skill-rules/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-spec/SKILL.md +4 -0
- package/templates/.agents/skills/zaip-skill-sqlite-read-model/SKILL.md +22 -90
- package/templates/.agents/zaip-aios/INDEX.md +57 -32
- package/templates/.agents/zaip-aios/README.md +22 -12
- package/templates/.agents/zaip-aios/guides/02-requirements.md +5 -0
- package/templates/.agents/zaip-aios/guides/06-execucao.md +13 -4
- package/templates/.agents/zaip-aios/guides/07-revisao-e-validacao.md +7 -0
- package/templates/.agents/zaip-aios/guides/10-seguranca.md +23 -0
- package/templates/.agents/zaip-aios/guides/11-observabilidade-e-custos.md +6 -6
- package/templates/.agents/zaip-aios/guides/13-boas-praticas.md +3 -0
- package/templates/.agents/zaip-aios/guides/16-lifecycle-e-reconciliacao.md +12 -3
- package/templates/.agents/zaip-aios/guides/17-como-o-custo-e-calculado.md +5 -5
- package/templates/.agents/zaip-aios/guides/19-assurance-e-autonomia.md +23 -0
- package/templates/.agents/zaip-aios/guides/20-instalacao-detalhada.md +44 -8
- package/templates/.agents/zaip-aios/guides/21-telemetria-monitor-custos.md +8 -14
- package/templates/.agents/zaip-aios/guides/22-fluxos-e-roteamento.md +5 -0
- package/templates/.agents/zaip-aios/guides/23-orquestracao-de-modelos.md +6 -6
- package/templates/.agents/zaip-aios/guides/24-calculo-de-custos-openai.md +8 -8
- package/templates/.agents/zaip-aios/guides/25-fontes-de-precos-openai.md +3 -2
- package/templates/.agents/zaip-aios/guides/26-qualidade-e-release.md +92 -10
- package/templates/.agents/zaip-aios/guides/27-telemetria-git-native.md +8 -3
- package/templates/.agents/zaip-aios/guides/28-lifecycle-completo.md +5 -0
- package/templates/template-manifest.json +555 -170
- package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-BwtitWa_.js +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-BZ5WdaMN.css +0 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-N5Csr0RP.js +0 -68
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-C4aIB1PV.js +0 -2
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-DK_enB5Z.css +0 -1
- package/templates/.agents/dashboard/apps/frontend/src/use-idle-cost-prefetch.ts +0 -45
- package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs.metafile.json +0 -7333
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { OperationsPageFilters } from "./dashboard-api.js";
|
|
2
|
+
|
|
3
|
+
export type WorkListLoadIntent = "explicit" | "filter-hydration";
|
|
4
|
+
|
|
5
|
+
export function workListLoadKey(
|
|
6
|
+
filters: OperationsPageFilters,
|
|
7
|
+
period: { from: string | null; to: string | null },
|
|
8
|
+
): string {
|
|
9
|
+
return JSON.stringify([
|
|
10
|
+
filters.query,
|
|
11
|
+
filters.status,
|
|
12
|
+
filters.risk,
|
|
13
|
+
filters.origin ?? "",
|
|
14
|
+
filters.kind ?? "",
|
|
15
|
+
period.from ?? "",
|
|
16
|
+
period.to ?? "",
|
|
17
|
+
]);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Explicit type/reentry/page loads must remain actionable; delayed hydration is idempotent. */
|
|
21
|
+
export function shouldStartWorkListLoad(
|
|
22
|
+
intent: WorkListLoadIntent,
|
|
23
|
+
key: string,
|
|
24
|
+
knownKey: string | null,
|
|
25
|
+
): boolean {
|
|
26
|
+
return intent === "explicit" || key !== knownKey;
|
|
27
|
+
}
|
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import { describe, expect, it
|
|
2
|
-
import {
|
|
3
|
-
collectWorkListPages,
|
|
4
|
-
normalizeWorkListFilters,
|
|
5
|
-
selectedWorkListKinds,
|
|
6
|
-
} from "./work-list-pagination.js";
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { normalizeWorkListFilters, selectedWorkListKinds } from "./work-list-pagination.js";
|
|
7
3
|
|
|
8
4
|
describe("Trabalho (Lista) canonical pagination", () => {
|
|
9
5
|
it("keeps a server-selected PRD/SPEC kind instead of refetching every kind", () => {
|
|
@@ -33,14 +29,42 @@ describe("Trabalho (Lista) canonical pagination", () => {
|
|
|
33
29
|
expect(kanban).toEqual({ query: "kanban", status: "ready", risk: "", kind: "" });
|
|
34
30
|
});
|
|
35
31
|
|
|
36
|
-
it("
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
32
|
+
it("retains the active origin for the paginated List request and export", async () => {
|
|
33
|
+
const selected = normalizeWorkListFilters(
|
|
34
|
+
{ query: "", status: "", risk: "", origin: "standalone", kind: "standalone-task" },
|
|
35
|
+
{ query: "", status: "", risk: "", origin: "", kind: "" },
|
|
36
|
+
);
|
|
37
|
+
const loader = await import("node:fs/promises").then(({ readFile }) =>
|
|
38
|
+
readFile(new URL("./use-app-work-list-page.ts", import.meta.url), "utf8"),
|
|
39
|
+
);
|
|
40
|
+
const exportSource = await import("node:fs/promises").then(({ readFile }) =>
|
|
41
|
+
readFile(new URL("./use-operations-detail-export.ts", import.meta.url), "utf8"),
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
expect(selected.origin).toBe("standalone");
|
|
45
|
+
expect(loader).toContain(
|
|
46
|
+
"...(normalizedFilters.origin ? { origin: normalizedFilters.origin } : {})",
|
|
47
|
+
);
|
|
48
|
+
expect(loader).toContain("{ status: normalizedFilters.status }");
|
|
49
|
+
expect(exportSource).toContain("...(filters.origin ? { origin: filters.origin } : {})");
|
|
50
|
+
expect(exportSource).toContain("...(filters.status ? { status: filters.status } : {})");
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("uses one bounded SQLite page for visual List loading", async () => {
|
|
54
|
+
const loader = await import("node:fs/promises").then(({ readFile }) =>
|
|
55
|
+
readFile(new URL("./use-app-work-list-page.ts", import.meta.url), "utf8"),
|
|
56
|
+
);
|
|
57
|
+
const list = await import("node:fs/promises").then(({ readFile }) =>
|
|
58
|
+
readFile(
|
|
59
|
+
new URL("../../../modules/operations/src/react/PagedWorkList.tsx", import.meta.url),
|
|
60
|
+
"utf8",
|
|
61
|
+
),
|
|
62
|
+
);
|
|
41
63
|
|
|
42
|
-
|
|
43
|
-
expect(
|
|
44
|
-
expect(
|
|
64
|
+
expect(loader).toContain('"operations_work_list"');
|
|
65
|
+
expect(loader).toContain("limit: 10");
|
|
66
|
+
expect(loader).not.toContain("collectWorkListPages");
|
|
67
|
+
expect(loader).not.toContain("Promise.all(");
|
|
68
|
+
expect(list).toContain("row.kind ?? row.entity_kind");
|
|
45
69
|
});
|
|
46
70
|
});
|
package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostDeveloperAttributionPanel.tsx
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import { type CostDeveloperAttributionRow, CostDeveloperAttributionTable } from "./CostTables.js";
|
|
3
|
+
import type { CostLocale } from "./cost-monitor-copy.js";
|
|
4
|
+
|
|
5
|
+
/** Cost-specific rendering of the factual developer aggregate endpoint. */
|
|
6
|
+
export function CostDeveloperAttributionPanel({
|
|
7
|
+
from,
|
|
8
|
+
to,
|
|
9
|
+
locale,
|
|
10
|
+
}: {
|
|
11
|
+
from?: string;
|
|
12
|
+
to?: string;
|
|
13
|
+
locale: CostLocale;
|
|
14
|
+
}) {
|
|
15
|
+
const [state, setState] = useState<{
|
|
16
|
+
loading: boolean;
|
|
17
|
+
error: string | null;
|
|
18
|
+
rows: readonly CostDeveloperAttributionRow[];
|
|
19
|
+
}>({ loading: true, error: null, rows: [] });
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
const controller = new AbortController();
|
|
22
|
+
const params = new URLSearchParams();
|
|
23
|
+
if (from) params.set("from", from);
|
|
24
|
+
if (to) params.set("to", to);
|
|
25
|
+
setState((previous) => ({ ...previous, loading: true, error: null }));
|
|
26
|
+
fetch(`/api/v2/developers${params.size === 0 ? "" : `?${params}`}`, {
|
|
27
|
+
signal: controller.signal,
|
|
28
|
+
})
|
|
29
|
+
.then(async (response) => {
|
|
30
|
+
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
31
|
+
return response.json() as Promise<{ rows?: CostDeveloperAttributionRow[] }>;
|
|
32
|
+
})
|
|
33
|
+
.then((payload) => setState({ loading: false, error: null, rows: payload.rows ?? [] }))
|
|
34
|
+
.catch((error: unknown) => {
|
|
35
|
+
if ((error as { name?: string }).name !== "AbortError")
|
|
36
|
+
setState({
|
|
37
|
+
loading: false,
|
|
38
|
+
error: error instanceof Error ? error.message : "unknown",
|
|
39
|
+
rows: [],
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
return () => controller.abort();
|
|
43
|
+
}, [from, to]);
|
|
44
|
+
if (state.loading)
|
|
45
|
+
return (
|
|
46
|
+
<p className="operations-empty" role="status">
|
|
47
|
+
{locale === "pt-BR" ? "Carregando desenvolvedores…" : "Loading developers…"}
|
|
48
|
+
</p>
|
|
49
|
+
);
|
|
50
|
+
if (state.error)
|
|
51
|
+
return (
|
|
52
|
+
<p className="operations-empty" role="alert">
|
|
53
|
+
{locale === "pt-BR"
|
|
54
|
+
? "Não foi possível carregar desenvolvedores."
|
|
55
|
+
: "Could not load developers."}{" "}
|
|
56
|
+
{state.error}
|
|
57
|
+
</p>
|
|
58
|
+
);
|
|
59
|
+
return <CostDeveloperAttributionTable locale={locale} rows={state.rows} />;
|
|
60
|
+
}
|
package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostDeveloperAttributionTable.tsx
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DataTable,
|
|
3
|
+
formatCompactNumber,
|
|
4
|
+
formatCurrency as formatDashboardCurrency,
|
|
5
|
+
formatDurationMs,
|
|
6
|
+
} from "@zaip-ai/dashboard-ui";
|
|
7
|
+
import type { CostLocale } from "./cost-monitor-copy.js";
|
|
8
|
+
|
|
9
|
+
export type CostDeveloperAttributionRow = {
|
|
10
|
+
account_id: string;
|
|
11
|
+
login_snapshot: string | null;
|
|
12
|
+
prd_count: number;
|
|
13
|
+
spec_count: number;
|
|
14
|
+
task_count: number;
|
|
15
|
+
run_count: number;
|
|
16
|
+
test_count: number | null;
|
|
17
|
+
evidence_count: number | null;
|
|
18
|
+
total_duration_ms: number | null;
|
|
19
|
+
total_tokens: number | null;
|
|
20
|
+
total_cost_brl: number | null;
|
|
21
|
+
duration_covered_runs: number;
|
|
22
|
+
token_covered_runs: number;
|
|
23
|
+
brl_covered_runs: number;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const visuallyHiddenStyle = {
|
|
27
|
+
clip: "rect(0, 0, 0, 0)",
|
|
28
|
+
height: 1,
|
|
29
|
+
margin: -1,
|
|
30
|
+
overflow: "hidden",
|
|
31
|
+
position: "absolute",
|
|
32
|
+
whiteSpace: "nowrap",
|
|
33
|
+
width: 1,
|
|
34
|
+
} as const;
|
|
35
|
+
|
|
36
|
+
function formatCount(value: number | null, locale: CostLocale): string {
|
|
37
|
+
return value === null
|
|
38
|
+
? "—"
|
|
39
|
+
: new Intl.NumberFormat(locale, { maximumFractionDigits: 0 }).format(value);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function formatDuration(value: number | null, locale: CostLocale): string {
|
|
43
|
+
if (value === null) return locale === "pt-BR" ? "Indisponível" : "Unavailable";
|
|
44
|
+
return value === 0 ? "0" : formatDurationMs(value, locale);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function formatBrlCurrency(value: number | null, locale: CostLocale): string {
|
|
48
|
+
return value === null ? "—" : formatDashboardCurrency(value, "BRL", locale);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function formatTokens(value: number | null, locale: CostLocale): string {
|
|
52
|
+
return value === null
|
|
53
|
+
? locale === "pt-BR"
|
|
54
|
+
? "Indisponível"
|
|
55
|
+
: "Unavailable"
|
|
56
|
+
: formatCompactNumber(value, locale);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function partialMetric(
|
|
60
|
+
formatted: string,
|
|
61
|
+
coveredRuns: number,
|
|
62
|
+
runCount: number,
|
|
63
|
+
locale: CostLocale,
|
|
64
|
+
) {
|
|
65
|
+
if (coveredRuns >= runCount) return formatted;
|
|
66
|
+
const label =
|
|
67
|
+
locale === "pt-BR"
|
|
68
|
+
? `Valor parcial: telemetria conhecida em ${coveredRuns} de ${runCount} runs.`
|
|
69
|
+
: `Partial value: telemetry is known for ${coveredRuns} of ${runCount} runs.`;
|
|
70
|
+
return (
|
|
71
|
+
<span title={label}>
|
|
72
|
+
<span aria-hidden="true">{formatted}</span>
|
|
73
|
+
<span style={visuallyHiddenStyle}>{`${label} ${formatted}`}</span>
|
|
74
|
+
</span>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Developer facts are intentionally separate from the Operations table. The
|
|
80
|
+
* Cost Monitor reports only structural and financial facts tied to an
|
|
81
|
+
* attributed developer Run.
|
|
82
|
+
*/
|
|
83
|
+
export function CostDeveloperAttributionTable({
|
|
84
|
+
locale,
|
|
85
|
+
rows,
|
|
86
|
+
}: {
|
|
87
|
+
locale: CostLocale;
|
|
88
|
+
rows: readonly CostDeveloperAttributionRow[];
|
|
89
|
+
}) {
|
|
90
|
+
return (
|
|
91
|
+
<DataTable
|
|
92
|
+
columns={[
|
|
93
|
+
{
|
|
94
|
+
key: "developer",
|
|
95
|
+
label: locale === "pt-BR" ? "Desenvolvedor" : "Developer",
|
|
96
|
+
render: (row) => (
|
|
97
|
+
<>
|
|
98
|
+
<strong>{row.login_snapshot ?? row.account_id}</strong>
|
|
99
|
+
<small>#{row.account_id}</small>
|
|
100
|
+
</>
|
|
101
|
+
),
|
|
102
|
+
sortValue: (row) => row.login_snapshot ?? row.account_id,
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
key: "prds",
|
|
106
|
+
label: "PRDs",
|
|
107
|
+
render: (row) => formatCount(row.prd_count, locale),
|
|
108
|
+
align: "right",
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
key: "specs",
|
|
112
|
+
label: "SPECs",
|
|
113
|
+
render: (row) => formatCount(row.spec_count, locale),
|
|
114
|
+
align: "right",
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
key: "tasks",
|
|
118
|
+
label: locale === "pt-BR" ? "Tarefas" : "Tasks",
|
|
119
|
+
render: (row) => formatCount(row.task_count, locale),
|
|
120
|
+
align: "right",
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
key: "runs",
|
|
124
|
+
label: "Runs",
|
|
125
|
+
render: (row) => formatCount(row.run_count, locale),
|
|
126
|
+
align: "right",
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
key: "tests",
|
|
130
|
+
label: locale === "pt-BR" ? "Testes" : "Tests",
|
|
131
|
+
render: (row) => formatCount(row.test_count, locale),
|
|
132
|
+
align: "right",
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
key: "evidences",
|
|
136
|
+
label: locale === "pt-BR" ? "Evidências" : "Evidence",
|
|
137
|
+
render: (row) => formatCount(row.evidence_count, locale),
|
|
138
|
+
align: "right",
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
key: "duration",
|
|
142
|
+
label: locale === "pt-BR" ? "Tempo" : "Time",
|
|
143
|
+
render: (row) =>
|
|
144
|
+
partialMetric(
|
|
145
|
+
formatDuration(row.total_duration_ms, locale),
|
|
146
|
+
row.duration_covered_runs,
|
|
147
|
+
row.run_count,
|
|
148
|
+
locale,
|
|
149
|
+
),
|
|
150
|
+
sortValue: (row) => row.total_duration_ms,
|
|
151
|
+
align: "right",
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
key: "tokens",
|
|
155
|
+
label: "Tokens",
|
|
156
|
+
render: (row) =>
|
|
157
|
+
partialMetric(
|
|
158
|
+
formatTokens(row.total_tokens, locale),
|
|
159
|
+
row.token_covered_runs,
|
|
160
|
+
row.run_count,
|
|
161
|
+
locale,
|
|
162
|
+
),
|
|
163
|
+
sortValue: (row) => row.total_tokens,
|
|
164
|
+
align: "right",
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
key: "cost",
|
|
168
|
+
label: locale === "pt-BR" ? "Custos" : "Costs",
|
|
169
|
+
render: (row) =>
|
|
170
|
+
partialMetric(
|
|
171
|
+
formatBrlCurrency(row.total_cost_brl, locale),
|
|
172
|
+
row.brl_covered_runs,
|
|
173
|
+
row.run_count,
|
|
174
|
+
locale,
|
|
175
|
+
),
|
|
176
|
+
sortValue: (row) => row.total_cost_brl,
|
|
177
|
+
align: "right",
|
|
178
|
+
},
|
|
179
|
+
]}
|
|
180
|
+
defaultSort={{ key: "cost", direction: "desc" }}
|
|
181
|
+
emptyMessage={locale === "pt-BR" ? "Nenhum dado disponível." : "No data available."}
|
|
182
|
+
locale={locale}
|
|
183
|
+
pageSize={10}
|
|
184
|
+
rowKey={(row) => row.account_id}
|
|
185
|
+
rows={rows}
|
|
186
|
+
scrollLabel={locale === "pt-BR" ? "Métricas por desenvolvedor" : "Developer metrics"}
|
|
187
|
+
showColumnInfo
|
|
188
|
+
sortable
|
|
189
|
+
/>
|
|
190
|
+
);
|
|
191
|
+
}
|
package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostFilters.loading.test.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
|
|
4
|
+
describe("Cost period loading lifecycle", () => {
|
|
5
|
+
it("clears a filtered request when the embedded snapshot becomes sufficient", () => {
|
|
6
|
+
const source = readFileSync(new URL("./CostFilters.tsx", import.meta.url), "utf8");
|
|
7
|
+
|
|
8
|
+
expect(source).toContain("const generation = ++generationRef.current;");
|
|
9
|
+
expect(source).toContain("if (!shouldFetch)");
|
|
10
|
+
expect(source).toContain("setPeriodLoading(false);");
|
|
11
|
+
expect(source).toContain("setPeriodData(null);");
|
|
12
|
+
expect(source).toContain("generation === generationRef.current");
|
|
13
|
+
});
|
|
14
|
+
});
|
package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostFilters.run-page.test.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { loadCostMonitorRunPage } from "./CostFilters.js";
|
|
3
|
+
|
|
4
|
+
describe("Cost Monitor invocation page loading", () => {
|
|
5
|
+
it("uses a ten-row default for the remote invocation page", async () => {
|
|
6
|
+
const calls: string[] = [];
|
|
7
|
+
await loadCostMonitorRunPage({
|
|
8
|
+
currency: "BRL",
|
|
9
|
+
offset: 0,
|
|
10
|
+
fetcher: async (url) => {
|
|
11
|
+
calls.push(String(url));
|
|
12
|
+
return new Response(JSON.stringify({ runs: [] }), { status: 200 });
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
expect(new URL(calls[0]!, "http://dashboard.local").searchParams.get("limit")).toBe("10");
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -107,6 +107,7 @@ export async function loadCostMonitorRunPage({
|
|
|
107
107
|
currency,
|
|
108
108
|
filters,
|
|
109
109
|
from,
|
|
110
|
+
limit = 10,
|
|
110
111
|
offset,
|
|
111
112
|
refresh,
|
|
112
113
|
to,
|
|
@@ -116,6 +117,7 @@ export async function loadCostMonitorRunPage({
|
|
|
116
117
|
currency: CostCurrency;
|
|
117
118
|
filters?: CostFilterState;
|
|
118
119
|
from?: string;
|
|
120
|
+
limit?: number;
|
|
119
121
|
offset: number;
|
|
120
122
|
refresh?: string | null;
|
|
121
123
|
to?: string;
|
|
@@ -131,7 +133,7 @@ export async function loadCostMonitorRunPage({
|
|
|
131
133
|
});
|
|
132
134
|
query.set("scope", "runs");
|
|
133
135
|
query.set("offset", String(Math.max(0, offset)));
|
|
134
|
-
query.set("limit",
|
|
136
|
+
query.set("limit", String(Math.max(1, limit)));
|
|
135
137
|
const response = await fetcher(`/api/v2/cost-monitor?${query.toString()}`, {
|
|
136
138
|
...(signal === undefined ? {} : { signal }),
|
|
137
139
|
});
|
|
@@ -143,7 +145,7 @@ export async function loadCostMonitorRunPage({
|
|
|
143
145
|
return {
|
|
144
146
|
page_only: true,
|
|
145
147
|
runs: payload.runs,
|
|
146
|
-
run_page: payload.run_page ?? { offset, limit
|
|
148
|
+
run_page: payload.run_page ?? { offset, limit, total: null, has_more: false },
|
|
147
149
|
};
|
|
148
150
|
}
|
|
149
151
|
|
|
@@ -212,6 +214,7 @@ export function useCostMonitorPeriod({
|
|
|
212
214
|
const [periodLoading, setPeriodLoading] = useState(false);
|
|
213
215
|
const [periodError, setPeriodError] = useState<string | null>(null);
|
|
214
216
|
const initialDataRef = useRef(true);
|
|
217
|
+
const generationRef = useRef(0);
|
|
215
218
|
const loadPeriodRef = useRef(loadPeriod);
|
|
216
219
|
loadPeriodRef.current = loadPeriod;
|
|
217
220
|
const requestedRange =
|
|
@@ -222,8 +225,16 @@ export function useCostMonitorPeriod({
|
|
|
222
225
|
const requestedTo = requestedRange?.to;
|
|
223
226
|
const shouldFetch = shouldFetchCostPeriod({ filters, period, snapshotBacked });
|
|
224
227
|
useEffect(() => {
|
|
228
|
+
const generation = ++generationRef.current;
|
|
225
229
|
if (!shouldFetch) {
|
|
226
230
|
initialDataRef.current = false;
|
|
231
|
+
// A filtered request can be aborted immediately before this embedded
|
|
232
|
+
// default snapshot becomes sufficient again. There is no successor
|
|
233
|
+
// request in that branch to release the loading gate.
|
|
234
|
+
setPeriodLoading(false);
|
|
235
|
+
setPeriodError(null);
|
|
236
|
+
setPeriodData(null);
|
|
237
|
+
setPeriodDataBase(null);
|
|
227
238
|
return;
|
|
228
239
|
}
|
|
229
240
|
if (initialDataRef.current && Object.values(filters).every((value) => value === "")) {
|
|
@@ -255,7 +266,11 @@ export function useCostMonitorPeriod({
|
|
|
255
266
|
}
|
|
256
267
|
})
|
|
257
268
|
.finally(() => {
|
|
258
|
-
|
|
269
|
+
// An aborted predecessor must not clear a newer request. Conversely,
|
|
270
|
+
// an active request always releases its own loading gate, including an
|
|
271
|
+
// HTTP failure handled above.
|
|
272
|
+
if (!controller.signal.aborted && generation === generationRef.current)
|
|
273
|
+
setPeriodLoading(false);
|
|
259
274
|
});
|
|
260
275
|
return () => controller.abort();
|
|
261
276
|
}, [currency, data, filters, lastUpdatedAt, requestedFrom, requestedTo, shouldFetch]);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ExecutionTable } from "@zaip-ai/dashboard-operations/react";
|
|
2
|
-
import type { ComponentProps } from "react";
|
|
2
|
+
import type { ComponentProps, ReactNode } from "react";
|
|
3
3
|
import {
|
|
4
4
|
type CompactLifecycleCostSubtotal,
|
|
5
5
|
CompactLifecycleCostTable,
|
|
@@ -29,6 +29,7 @@ export function CostMonitorContent({
|
|
|
29
29
|
currency,
|
|
30
30
|
detailError,
|
|
31
31
|
detailLoading,
|
|
32
|
+
developerPanel,
|
|
32
33
|
dimensionalDetailPending,
|
|
33
34
|
dimensionalRows,
|
|
34
35
|
groups,
|
|
@@ -76,6 +77,7 @@ export function CostMonitorContent({
|
|
|
76
77
|
currency: CostCurrency;
|
|
77
78
|
detailError: string | null;
|
|
78
79
|
detailLoading: boolean;
|
|
80
|
+
developerPanel: ReactNode;
|
|
79
81
|
dimensionalDetailPending: boolean;
|
|
80
82
|
dimensionalRows: CostRunRows;
|
|
81
83
|
groups: {
|
|
@@ -152,6 +154,7 @@ export function CostMonitorContent({
|
|
|
152
154
|
) : null;
|
|
153
155
|
return (
|
|
154
156
|
<section
|
|
157
|
+
aria-busy={groupPageLoading || compactPageLoading || runPageLoading || undefined}
|
|
155
158
|
className={`cost-content cost-content-${view} ${view === "overview" ? "cost-content-overview" : ""}`}
|
|
156
159
|
>
|
|
157
160
|
{detailLoading || dimensionalDetailPending ? (
|
|
@@ -178,6 +181,7 @@ export function CostMonitorContent({
|
|
|
178
181
|
{...(useAggregateGroups ? { summaryUsage } : {})}
|
|
179
182
|
/>
|
|
180
183
|
) : null}
|
|
184
|
+
{view === "developers" ? developerPanel : null}
|
|
181
185
|
{view === "agentCalls" ? (
|
|
182
186
|
<>
|
|
183
187
|
<CostRunsTable
|
|
@@ -191,7 +195,7 @@ export function CostMonitorContent({
|
|
|
191
195
|
pagination: {
|
|
192
196
|
...(runPageData?.run_page ?? {
|
|
193
197
|
offset: runPageOffset,
|
|
194
|
-
limit:
|
|
198
|
+
limit: 10,
|
|
195
199
|
total: null,
|
|
196
200
|
has_more: false,
|
|
197
201
|
}),
|
|
@@ -284,6 +288,7 @@ export function CostMonitorContent({
|
|
|
284
288
|
: "Providers"
|
|
285
289
|
}
|
|
286
290
|
locale={locale}
|
|
291
|
+
loading={groupPageLoading}
|
|
287
292
|
rows={groups[key]}
|
|
288
293
|
{...(key === "models" || key === "providers"
|
|
289
294
|
? { totals: summaryTotals }
|
|
@@ -311,6 +316,7 @@ export function CostMonitorContent({
|
|
|
311
316
|
<CostGroupsTable
|
|
312
317
|
currency={currency}
|
|
313
318
|
locale={locale}
|
|
319
|
+
loading={groupPageLoading}
|
|
314
320
|
period={view}
|
|
315
321
|
rows={groups[view]}
|
|
316
322
|
showDateTime={false}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { CostLocale } from "./cost-monitor-copy.js";
|
|
2
|
+
|
|
3
|
+
export function CostMonitorLoadErrors({
|
|
4
|
+
groupError,
|
|
5
|
+
locale,
|
|
6
|
+
periodError,
|
|
7
|
+
retryGroup,
|
|
8
|
+
}: {
|
|
9
|
+
groupError: string | null;
|
|
10
|
+
locale: CostLocale;
|
|
11
|
+
periodError: string | null;
|
|
12
|
+
retryGroup: () => void;
|
|
13
|
+
}) {
|
|
14
|
+
return (
|
|
15
|
+
<>
|
|
16
|
+
{periodError ? (
|
|
17
|
+
<p className="cost-period-error" role="status">
|
|
18
|
+
{locale === "pt-BR"
|
|
19
|
+
? `Não foi possível carregar o período selecionado: ${periodError}`
|
|
20
|
+
: `Could not load the selected period: ${periodError}`}
|
|
21
|
+
</p>
|
|
22
|
+
) : null}
|
|
23
|
+
{groupError ? (
|
|
24
|
+
<p className="cost-period-error" role="status">
|
|
25
|
+
{locale === "pt-BR"
|
|
26
|
+
? `Não foi possível carregar esta aba: ${groupError}`
|
|
27
|
+
: `Could not load this tab: ${groupError}`}
|
|
28
|
+
<button onClick={retryGroup} type="button">
|
|
29
|
+
{locale === "pt-BR" ? "Tentar novamente" : "Try again"}
|
|
30
|
+
</button>
|
|
31
|
+
</p>
|
|
32
|
+
) : null}
|
|
33
|
+
</>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
@@ -111,6 +111,22 @@ describe("cost monitor navigation", () => {
|
|
|
111
111
|
expect(page).toContain("() => () => onLoadingChange?.(false)");
|
|
112
112
|
});
|
|
113
113
|
|
|
114
|
+
it("does not fetch group pages for a non-group Cost Monitor tab and exposes a retryable error", () => {
|
|
115
|
+
const page = readFileSync(new URL("./CostMonitorPage.tsx", import.meta.url), "utf8");
|
|
116
|
+
|
|
117
|
+
expect(page).toContain("active: groupView !== null");
|
|
118
|
+
expect(page).toContain("groupPageState.retry");
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("requests exactly ten remote rows for the slow Cost Monitor tabs", () => {
|
|
122
|
+
const page = readFileSync(new URL("./CostMonitorPage.tsx", import.meta.url), "utf8");
|
|
123
|
+
|
|
124
|
+
expect(page).toContain("const compactPageLimit = 10;");
|
|
125
|
+
expect(page).toContain("const groupPageLimit = 10;");
|
|
126
|
+
expect(page).toContain("limit: 10,");
|
|
127
|
+
expect(page).toContain("range: groupPageRange");
|
|
128
|
+
});
|
|
129
|
+
|
|
114
130
|
it("labels daily pagination by its continuous result range", () => {
|
|
115
131
|
expect(
|
|
116
132
|
costGroupPageLabel({
|
|
@@ -267,9 +283,19 @@ describe("cost monitor navigation", () => {
|
|
|
267
283
|
expect(runHook).toContain("query: filters.query || globalQuery");
|
|
268
284
|
expect(groupHook).toContain("export type CostGroupFilters = CostFilterState");
|
|
269
285
|
expect(groupHook).toContain("filters,");
|
|
270
|
-
expect(page).toContain(
|
|
286
|
+
expect(page).toContain(
|
|
287
|
+
"const displayedGroupPage = groupPageState.page ?? groupPageState.stalePage",
|
|
288
|
+
);
|
|
271
289
|
expect(page).toContain("? []");
|
|
272
290
|
});
|
|
291
|
+
|
|
292
|
+
it("keeps the Agents visual page bounded when the server page loader is available", () => {
|
|
293
|
+
const page = readFileSync(new URL("./CostMonitorPage.tsx", import.meta.url), "utf8");
|
|
294
|
+
|
|
295
|
+
expect(page).toContain('groupView === "agents" && loadGroupPage === undefined');
|
|
296
|
+
expect(page).toContain(": [...displayedGroupPage.rows]");
|
|
297
|
+
expect(page).toContain("const groupPageLimit = 10;");
|
|
298
|
+
});
|
|
273
299
|
it("uses the Sao Paulo calendar for global daily filtering on both sides of 03:00Z", () => {
|
|
274
300
|
const base = costRun("RUN-CALENDAR");
|
|
275
301
|
expect(
|
|
@@ -314,6 +340,7 @@ describe("cost monitor navigation", () => {
|
|
|
314
340
|
"daily",
|
|
315
341
|
"monthly",
|
|
316
342
|
"annual",
|
|
343
|
+
"developers",
|
|
317
344
|
"overview",
|
|
318
345
|
"executions",
|
|
319
346
|
"agentCalls",
|
|
@@ -327,14 +354,33 @@ describe("cost monitor navigation", () => {
|
|
|
327
354
|
]);
|
|
328
355
|
});
|
|
329
356
|
|
|
357
|
+
it("places the shared developer table inside the Cost Monitor content section", () => {
|
|
358
|
+
const page = readFileSync(new URL("./CostMonitorPage.tsx", import.meta.url), "utf8");
|
|
359
|
+
const content = readFileSync(new URL("./CostMonitorContent.tsx", import.meta.url), "utf8");
|
|
360
|
+
|
|
361
|
+
expect(page).toMatch(
|
|
362
|
+
/developerPanel=\{\s*view === "developers" \? \(\s*<CostDeveloperAttributionPanel\b/,
|
|
363
|
+
);
|
|
364
|
+
expect(page).not.toMatch(/<\/CostMonitorContent>\s*\{view === "developers"/);
|
|
365
|
+
expect(content).toContain('{view === "developers" ? developerPanel : null}');
|
|
366
|
+
});
|
|
367
|
+
|
|
330
368
|
it("prepares Agent Invocations from every server page for export", () => {
|
|
331
369
|
const page = readFileSync(new URL("./CostMonitorPage.tsx", import.meta.url), "utf8");
|
|
370
|
+
const exportSection = page.slice(
|
|
371
|
+
page.indexOf("const agentInvocationExportSource"),
|
|
372
|
+
page.indexOf("const costGroupExportSource"),
|
|
373
|
+
);
|
|
332
374
|
expect(page).toContain('view === "agentCalls" && serverPagingEligible');
|
|
333
375
|
expect(page).toContain("agentInvocationExportSource");
|
|
334
376
|
expect(page).toMatch(
|
|
335
377
|
/pageSource=\{\s*compactExportSource \?\? agentInvocationExportSource \?\? costGroupExportSource\s*\}/,
|
|
336
378
|
);
|
|
337
379
|
expect(page).toContain("if (page.runs.length === 0) return");
|
|
380
|
+
expect(exportSection.match(/limit: 100/g)).toHaveLength(2);
|
|
381
|
+
expect(exportSection).toContain("nextOffset >= page.run_page.total");
|
|
382
|
+
expect(exportSection).toContain("...(groupPageRange === undefined ? {} : groupPageRange)");
|
|
383
|
+
expect(exportSection).not.toContain("...(runPageRange === undefined ? {} : runPageRange)");
|
|
338
384
|
});
|
|
339
385
|
|
|
340
386
|
it("prepares every paginated period row for daily, monthly, and annual exports", () => {
|