@zaip-ai/cli 3.8.0 → 4.1.0
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 +5 -5
- package/dist/services/adapters.d.ts +1 -1
- package/dist/services/adapters.d.ts.map +1 -1
- package/dist/services/adapters.js +11 -6
- package/dist/services/adapters.js.map +1 -1
- package/dist/services/agent-adapters.js +1 -1
- package/dist/services/agent-adapters.js.map +1 -1
- package/dist/services/backup-gitignore.d.ts +9 -0
- package/dist/services/backup-gitignore.d.ts.map +1 -0
- package/dist/services/backup-gitignore.js +66 -0
- package/dist/services/backup-gitignore.js.map +1 -0
- package/dist/services/backup-gitignore.test.d.ts +2 -0
- package/dist/services/backup-gitignore.test.d.ts.map +1 -0
- package/dist/services/backup-gitignore.test.js +27 -0
- package/dist/services/backup-gitignore.test.js.map +1 -0
- 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 +4 -3
- package/dist/services/codex-config-template.js.map +1 -1
- package/dist/services/codex-conversation-lifecycle-hook.d.ts.map +1 -1
- package/dist/services/codex-conversation-lifecycle-hook.js +15 -7
- package/dist/services/codex-conversation-lifecycle-hook.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 +10 -11
- package/dist/services/codex-pre-tool-hook-template.js.map +1 -1
- package/dist/services/codex-pre-tool-hook-template.test.d.ts +2 -0
- package/dist/services/codex-pre-tool-hook-template.test.d.ts.map +1 -0
- package/dist/services/codex-pre-tool-hook-template.test.js +33 -0
- package/dist/services/codex-pre-tool-hook-template.test.js.map +1 -0
- package/dist/services/codex-subagent-hook-template.d.ts +1 -1
- package/dist/services/codex-subagent-hook-template.d.ts.map +1 -1
- package/dist/services/codex-subagent-hook-template.js +3 -0
- package/dist/services/codex-subagent-hook-template.js.map +1 -1
- package/dist/services/codex-windows-hook-command.d.ts +3 -0
- package/dist/services/codex-windows-hook-command.d.ts.map +1 -0
- package/dist/services/codex-windows-hook-command.js +10 -0
- package/dist/services/codex-windows-hook-command.js.map +1 -0
- package/dist/services/codex-windows-hook-command.test.d.ts +2 -0
- package/dist/services/codex-windows-hook-command.test.d.ts.map +1 -0
- package/dist/services/codex-windows-hook-command.test.js +44 -0
- package/dist/services/codex-windows-hook-command.test.js.map +1 -0
- package/dist/services/global-codex-config.d.ts.map +1 -1
- package/dist/services/global-codex-config.js +27 -13
- package/dist/services/global-codex-config.js.map +1 -1
- package/dist/services/global-codex-config.test.js +27 -2
- package/dist/services/global-codex-config.test.js.map +1 -1
- package/dist/services/install-agents-template.d.ts.map +1 -1
- package/dist/services/install-agents-template.js +43 -127
- package/dist/services/install-agents-template.js.map +1 -1
- package/dist/services/install-template-policy.d.ts.map +1 -1
- package/dist/services/install-template-policy.js +2 -0
- package/dist/services/install-template-policy.js.map +1 -1
- package/dist/services/legacy-records-migration.d.ts +15 -0
- package/dist/services/legacy-records-migration.d.ts.map +1 -0
- package/dist/services/legacy-records-migration.js +109 -0
- package/dist/services/legacy-records-migration.js.map +1 -0
- package/dist/services/local-state-migration.d.ts +8 -1
- package/dist/services/local-state-migration.d.ts.map +1 -1
- package/dist/services/local-state-migration.js +67 -32
- package/dist/services/local-state-migration.js.map +1 -1
- package/dist/services/logger.d.ts.map +1 -1
- package/dist/services/logger.js +2 -0
- package/dist/services/logger.js.map +1 -1
- package/dist/services/project-model-migration.d.ts +3 -0
- package/dist/services/project-model-migration.d.ts.map +1 -0
- package/dist/services/project-model-migration.js +163 -0
- package/dist/services/project-model-migration.js.map +1 -0
- package/dist/services/project-model-migration.test.d.ts +2 -0
- package/dist/services/project-model-migration.test.d.ts.map +1 -0
- package/dist/services/project-model-migration.test.js +62 -0
- package/dist/services/project-model-migration.test.js.map +1 -0
- package/dist/services/template-manifest.d.ts.map +1 -1
- package/dist/services/template-manifest.js +2 -0
- package/dist/services/template-manifest.js.map +1 -1
- package/dist/services/transactional-files.d.ts +1 -0
- package/dist/services/transactional-files.d.ts.map +1 -1
- package/dist/services/transactional-files.js +3 -0
- package/dist/services/transactional-files.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/README-ENG.md +88 -32
- package/templates/.agents/README.md +57 -30
- package/templates/.agents/config/agents/discovery.json +1 -1
- package/templates/.agents/config/clients/codex/agents/zaip-agent-orchestrator.toml +1 -1
- package/templates/.agents/config/project.yaml +21 -7
- package/templates/.agents/dashboard/.zaip-managed.json +184 -112
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{CostCalculationGuidePage-D2PL4UOu.js → CostCalculationGuidePage-f4ZGJRg3.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-CocoP9CA.js → DashboardHelpDialog-DlN5EMmD.js} +238 -124
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{PricingSettingsDialog-D255_hNf.js → PricingSettingsDialog-v9zGRTlk.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-BRdoeTWk.js +3 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{TraceabilityWorkspace-BTFSLQ69.js → TraceabilityWorkspace-B_5u4Xnp.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{cost-monitor-BsMfGfQi.css → cost-monitor-C2AFYBu_.css} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-D7PrDZy9.js +68 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{dashboard-localization-058lag33.js → dashboard-localization-CF7B1Hjn.js} +88 -32
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{icons-vendor-DeFPiN32.js → icons-vendor-Cv3WBFIF.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-C4rLXrz_.js +2 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{react-vendor-BIWcbEAc.js → react-vendor-mHgsmxb6.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/assets/{traceability-fZZL0ohD.js → traceability-B0CPyEVq.js} +1 -1
- package/templates/.agents/dashboard/apps/frontend/dist/index.html +6 -6
- package/templates/.agents/dashboard/apps/frontend/package.json +1 -1
- package/templates/.agents/dashboard/apps/frontend/src/AppDashboardContent.tsx +11 -1
- package/templates/.agents/dashboard/apps/frontend/src/AppLoadingBoundary.tsx +3 -2
- package/templates/.agents/dashboard/apps/frontend/src/AppLoadingPanels.tsx +1 -1
- package/templates/.agents/dashboard/apps/frontend/src/AppOverlays.tsx +1 -1
- package/templates/.agents/dashboard/apps/frontend/src/ProjectSettingsPage.tsx +9 -13
- package/templates/.agents/dashboard/apps/frontend/src/cost-monitor-population.test.tsx +4 -2
- package/templates/.agents/dashboard/apps/frontend/src/cost-period-refresh.test.ts +9 -5
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api-settings.ts +3 -2
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.test.ts +2 -2
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-identity.test.ts +3 -3
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-identity.ts +1 -1
- package/templates/.agents/dashboard/apps/frontend/src/dashboard-localization.test.ts +2 -1
- package/templates/.agents/dashboard/apps/frontend/src/operations-period-render.test.ts +40 -3
- package/templates/.agents/dashboard/apps/frontend/src/project-settings-model.ts +12 -1
- package/templates/.agents/dashboard/apps/frontend/src/project-settings.test.ts +19 -0
- package/templates/.agents/dashboard/apps/frontend/src/snapshot-coherence.test.ts +1 -1
- package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.test.ts +3 -1
- package/templates/.agents/dashboard/apps/frontend/src/use-dashboard-app-model.tsx +14 -23
- package/templates/.agents/dashboard/modules/cost-monitor/package.json +1 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CompactLifecycleCostTable.test.ts +3 -3
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CompactLifecycleCostTable.tsx +2 -3
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostDeveloperAttributionTable.tsx +2 -6
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostGroupsTable.period-values.test.tsx +66 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostGroupsTable.tsx +29 -34
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.embedded.test.ts +11 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +1 -13
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostPeriodAverageCards.test.tsx +23 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostPeriodAverageCards.tsx +2 -1
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTableDisplay.ts +6 -11
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables-keeps-legacy-codex-identity-fields-blank.test.ts +6 -6
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.test.ts +10 -12
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-group-page-totals.ts +23 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-group-period-values.tsx +34 -0
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-embedded.css +0 -7
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-table-formatters.ts +4 -9
- package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-table-presentation.ts +2 -3
- package/templates/.agents/dashboard/modules/operations/package.json +1 -1
- package/templates/.agents/dashboard/modules/operations/src/react/DeveloperAttributionPanel.tsx +2 -12
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.helpers.tsx +2 -2
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.test.ts +1 -6
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.tsx +34 -36
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverviewCharts.tsx +12 -3
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverviewTopPanel.tsx +12 -14
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsPage.tsx +4 -4
- package/templates/.agents/dashboard/modules/operations/src/react/OperationsPageOverview.tsx +23 -4
- package/templates/.agents/dashboard/modules/operations/src/react/OverviewCostKpi.tsx +30 -2
- package/templates/.agents/dashboard/modules/operations/src/react/TaskDetailsDialog.tsx +2 -13
- package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkBoard.priority.test.ts +8 -1
- package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkBoard.tsx +8 -16
- package/templates/.agents/dashboard/modules/operations/src/react/WorkColumnState.tsx +34 -0
- package/templates/.agents/dashboard/modules/operations/src/react/operation-duration.test.ts +1 -1
- package/templates/.agents/dashboard/modules/operations/src/react/operation-duration.ts +1 -1
- package/templates/.agents/dashboard/modules/operations/src/react/operations-average-unmeasured.test.ts +10 -0
- package/templates/.agents/dashboard/modules/operations/src/react/operations-content-visibility.ts +3 -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-overview-period-filter.test.ts +12 -1
- package/templates/.agents/dashboard/modules/operations/src/react/operations-page-contract.ts +1 -0
- package/templates/.agents/dashboard/modules/operations/src/react/operations-skeleton.css +80 -0
- package/templates/.agents/dashboard/modules/operations/src/react/operations.css +2 -11
- package/templates/.agents/dashboard/modules/operations/src/react/overview-cost-card.test.tsx +36 -0
- package/templates/.agents/dashboard/modules/operations/src/react/overview-metric-format.test.ts +11 -0
- package/templates/.agents/dashboard/modules/operations/src/react/overview-metric-format.ts +28 -3
- package/templates/.agents/dashboard/modules/operations/src/react/overview-metric-stats.ts +44 -0
- package/templates/.agents/dashboard/modules/operations/src/react/work-card-label.ts +5 -0
- package/templates/.agents/dashboard/modules/operations/src/react/work-column-state.ts +11 -0
- package/templates/.agents/dashboard/modules/operations/src/react/work-item-filter.ts +13 -0
- package/templates/.agents/dashboard/modules/traceability/package.json +1 -1
- package/templates/.agents/dashboard/packages/branding/package.json +1 -1
- package/templates/.agents/dashboard/packages/contracts/package.json +1 -1
- package/templates/.agents/dashboard/packages/data-export/package.json +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +157 -157
- package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +153 -153
- package/templates/.agents/dashboard/packages/local-runtime/package.json +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/server.mjs +159 -159
- package/templates/.agents/dashboard/packages/local-runtime/src/active-codex-telemetry.test.ts +31 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/active-codex-telemetry.ts +74 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.ts +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/server-identity.test.ts +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.test.ts +25 -3
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot-synchronization.ts +51 -16
- package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot.test.ts +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/server-ui-security.ts +37 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/server-workspace.ts +1 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +11 -33
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-rebuild.ts +12 -13
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-source-fingerprint.test.ts +71 -1
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-source-fingerprint.ts +141 -25
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model-worktree-sources.test.ts +60 -0
- package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-rebuild-fingerprint-options.ts +13 -0
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-launch-page.mjs +26 -2
- package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-launch-page.test.mjs +5 -0
- package/templates/.agents/dashboard/packages/ui/package.json +1 -1
- package/templates/.agents/dashboard/packages/ui/src/DashboardHeader.test.mjs +5 -0
- package/templates/.agents/dashboard/packages/ui/src/DashboardHeader.tsx +4 -4
- package/templates/.agents/dashboard/tests/e2e/package.json +1 -1
- package/templates/.agents/dashboard/tests/e2e/playwright.config.ts +4 -0
- package/templates/.agents/dashboard/tests/e2e/specs/dashboard-performance-matrix.spec.ts +4 -4
- package/templates/.agents/dashboard/tests/e2e/specs/dashboard.spec.ts +1 -1
- package/templates/.agents/dashboard/tests/e2e/specs/performance-work-row-identity.ts +6 -0
- package/templates/.agents/design/.zaip-managed.json +13 -9
- package/templates/.agents/design/apps/catalog/dist/assets/index-DkpQYoyC.js +72 -0
- package/templates/.agents/design/apps/catalog/dist/index.html +1 -1
- package/templates/.agents/design/apps/catalog/package.json +1 -1
- package/templates/.agents/design/apps/catalog/src/components/CostPopulationSpecimen.test.tsx +8 -4
- package/templates/.agents/design/apps/catalog/src/components/CostPopulationSpecimen.tsx +10 -3
- package/templates/.agents/design/apps/catalog/src/components/DashboardFiltersSpecimen.tsx +0 -15
- package/templates/.agents/design/apps/catalog/src/pages/ComponentsPage.tsx +3 -3
- package/templates/.agents/design/apps/catalog/src/stories/DashboardFilters.stories.tsx +0 -1
- package/templates/.agents/design/packages/local-runtime/package.json +1 -1
- package/templates/.agents/requirements/autonomous-assurance.md +1 -1
- package/templates/.agents/requirements/cloud-hostinger-autonomy.md +1 -1
- 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 +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 +2 -2
- package/templates/.agents/rules/workflow.md +1 -1
- package/templates/.agents/runtime/VERSION +1 -1
- package/templates/.agents/runtime/bin/zaip.mjs +65 -54
- package/templates/.agents/runtime/checksums.sha256 +5 -5
- package/templates/.agents/runtime/manifest.json +1 -1
- package/templates/.agents/runtime/provenance.json +4 -4
- package/templates/.agents/runtime/sbom.cdx.json +1 -1
- package/templates/.agents/skills/zaip-skill-executar-fila-pronta/SKILL.md +7 -7
- package/templates/.agents/skills/zaip-skill-executar-fila-pronta/scripts/ready-queue-fence.mjs +32 -7
- package/templates/.agents/skills/zaip-skill-executar-fila-pronta/scripts/ready-queue-fence.test.mjs +134 -1
- package/templates/.agents/skills/zaip-skill-executar-fila-pronta/scripts/ready-queue-lease.mjs +57 -0
- package/templates/.agents/skills/zaip-skill-executar-fila-pronta/scripts/scheduled-ready-queue-contract.test.mjs +9 -6
- package/templates/.agents/skills/zaip-skill-execution/SKILL.md +1 -1
- package/templates/.agents/skills/zaip-skill-execution/references/runtime-governance.md +2 -2
- package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-deploy-contract.test.mjs +18 -6
- package/templates/.agents/skills/zaip-skill-instalar-agendamento/SKILL.md +2 -2
- package/templates/.agents/skills/zaip-skill-release-qualification/SKILL.md +6 -0
- package/templates/.agents/skills/zaip-skill-release-qualification/references/local-preparation.md +47 -5
- package/templates/.agents/zaip-aios/README.md +4 -4
- package/templates/.agents/zaip-aios/VERSION +1 -1
- package/templates/.agents/zaip-aios/guides/01-primeiros-passos.md +4 -3
- package/templates/.agents/zaip-aios/guides/03-tasks.md +5 -4
- package/templates/.agents/zaip-aios/guides/04-specs.md +4 -1
- package/templates/.agents/zaip-aios/guides/05-prds.md +7 -3
- package/templates/.agents/zaip-aios/guides/06-execucao.md +9 -4
- package/templates/.agents/zaip-aios/guides/09-agentes-e-squads.md +9 -5
- package/templates/.agents/zaip-aios/guides/11-observabilidade-e-custos.md +10 -2
- package/templates/.agents/zaip-aios/guides/12-instalacao-e-upgrade.md +10 -5
- package/templates/.agents/zaip-aios/guides/13-boas-praticas.md +12 -1
- package/templates/.agents/zaip-aios/guides/14-troubleshooting.md +3 -1
- package/templates/.agents/zaip-aios/guides/16-lifecycle-e-reconciliacao.md +12 -7
- package/templates/.agents/zaip-aios/guides/17-como-o-custo-e-calculado.md +1 -1
- package/templates/.agents/zaip-aios/guides/18-catalogo-de-agentes.md +4 -0
- package/templates/.agents/zaip-aios/guides/19-assurance-e-autonomia.md +19 -15
- package/templates/.agents/zaip-aios/guides/20-instalacao-detalhada.md +12 -8
- package/templates/.agents/zaip-aios/guides/21-telemetria-monitor-custos.md +4 -3
- package/templates/.agents/zaip-aios/guides/22-fluxos-e-roteamento.md +9 -7
- package/templates/.agents/zaip-aios/guides/23-orquestracao-de-modelos.md +38 -22
- package/templates/.agents/zaip-aios/guides/24-calculo-de-custos-openai.md +1 -1
- package/templates/.agents/zaip-aios/guides/26-qualidade-e-release.md +14 -5
- package/templates/.agents/zaip-aios/guides/27-telemetria-git-native.md +6 -0
- package/templates/.agents/zaip-aios/guides/28-lifecycle-completo.md +129 -11
- package/templates/template-manifest.json +270 -186
- package/templates/tsconfig.base.json +22 -0
- package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-0f_x2TzJ.js +0 -3
- package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-zhY2JoLc.js +0 -68
- package/templates/.agents/dashboard/apps/frontend/dist/assets/index-Dh95Yodm.js +0 -2
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { ReactElement } from "react";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { CostGroupsTable, formatAuditableCurrency } from "./CostTables.js";
|
|
4
|
+
|
|
5
|
+
const unavailableGroup = {
|
|
6
|
+
key: "unknown",
|
|
7
|
+
label: "Sem telemetria",
|
|
8
|
+
latest_started_at: "2026-07-24T20:00:00.000Z",
|
|
9
|
+
run_count: 2,
|
|
10
|
+
task_count: 1,
|
|
11
|
+
prd_count: 0,
|
|
12
|
+
spec_count: 0,
|
|
13
|
+
evidence_count: 0,
|
|
14
|
+
test_count: 0,
|
|
15
|
+
event_count: 2,
|
|
16
|
+
total_tokens: null,
|
|
17
|
+
estimated_usd: null,
|
|
18
|
+
estimated_brl: null,
|
|
19
|
+
duration_ms: null,
|
|
20
|
+
duration: { known_sum: 0, unknown: 2, complete: false, coverage_ratio: 0 },
|
|
21
|
+
coverage: { events: 2, tokens: 0, usd: 0, brl: 0 },
|
|
22
|
+
} as const;
|
|
23
|
+
|
|
24
|
+
describe("period group values", () => {
|
|
25
|
+
it("discloses presentation zero without changing null sorting", () => {
|
|
26
|
+
const table = CostGroupsTable({
|
|
27
|
+
rows: [unavailableGroup],
|
|
28
|
+
currency: "BRL",
|
|
29
|
+
locale: "pt-BR",
|
|
30
|
+
period: "daily",
|
|
31
|
+
});
|
|
32
|
+
const columns = table.props.columns as Array<{
|
|
33
|
+
key: string;
|
|
34
|
+
render: (row: typeof unavailableGroup) => string | ReactElement;
|
|
35
|
+
sortValue?: (row: typeof unavailableGroup) => unknown;
|
|
36
|
+
footer?: ReactElement<{ "aria-label"?: string }>;
|
|
37
|
+
}>;
|
|
38
|
+
const column = (key: string) => columns.find((candidate) => candidate.key === key)!;
|
|
39
|
+
const duration = column("duration").render(unavailableGroup) as ReactElement<{
|
|
40
|
+
title: string;
|
|
41
|
+
children: string;
|
|
42
|
+
}>;
|
|
43
|
+
const tokens = column("tokens").render(unavailableGroup) as ReactElement<{
|
|
44
|
+
title: string;
|
|
45
|
+
children: string;
|
|
46
|
+
}>;
|
|
47
|
+
const cost = column("cost").render(unavailableGroup) as ReactElement<{
|
|
48
|
+
title: string;
|
|
49
|
+
children: string;
|
|
50
|
+
}>;
|
|
51
|
+
expect(duration.props.title).toBe(
|
|
52
|
+
"Zero exibido por falta de medição; não é um valor observado.",
|
|
53
|
+
);
|
|
54
|
+
expect([duration.props.children, tokens.props.children, cost.props.children]).toEqual([
|
|
55
|
+
"0",
|
|
56
|
+
"0",
|
|
57
|
+
formatAuditableCurrency(0, "BRL", "pt-BR"),
|
|
58
|
+
]);
|
|
59
|
+
expect(
|
|
60
|
+
[column("duration"), column("tokens"), column("cost")].map((entry) =>
|
|
61
|
+
entry.sortValue?.(unavailableGroup),
|
|
62
|
+
),
|
|
63
|
+
).toEqual([null, null, null]);
|
|
64
|
+
expect(column("duration").footer?.props["aria-label"]).not.toContain("Indisponível");
|
|
65
|
+
});
|
|
66
|
+
});
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { DataTable } from "@zaip-ai/dashboard-ui";
|
|
2
|
-
import type { CostGroupRow
|
|
2
|
+
import type { CostGroupRow } from "../contracts.js";
|
|
3
3
|
import { MoreVerticalIcon } from "./CostTableIcons.js";
|
|
4
4
|
import { costPeriodHeading } from "./CostTables.js";
|
|
5
|
+
import { costGroupConversationCount, costGroupPageTotals } from "./cost-group-page-totals.js";
|
|
6
|
+
import { createCostGroupPeriodValues } from "./cost-group-period-values.js";
|
|
5
7
|
import type { CostCurrency, CostLocale } from "./cost-monitor-copy.js";
|
|
6
|
-
import { localizedDescription
|
|
8
|
+
import { localizedDescription } from "./cost-table-metrics.js";
|
|
7
9
|
import {
|
|
8
10
|
costGroupsScrollLabel,
|
|
9
11
|
costPeriodTotalAriaLabel,
|
|
@@ -47,8 +49,6 @@ export {
|
|
|
47
49
|
import {
|
|
48
50
|
displayCostGroupLabel,
|
|
49
51
|
formatAuditableCompactNumber,
|
|
50
|
-
formatAuditableCurrency,
|
|
51
|
-
formatDurationCoverage,
|
|
52
52
|
formatFactualCount,
|
|
53
53
|
hasKnownDuration,
|
|
54
54
|
sortCostValue,
|
|
@@ -102,25 +102,10 @@ export function CostGroupsTable({
|
|
|
102
102
|
showAgentIdentity || showModelLifecycleDetails ? (value ?? 0) : value,
|
|
103
103
|
locale,
|
|
104
104
|
);
|
|
105
|
-
const
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
const
|
|
109
|
-
(row as { conversation_count?: number | null }).conversation_count ?? null;
|
|
110
|
-
const pageTotals = {
|
|
111
|
-
runs: rows.reduce((sum, row) => sum + row.run_count, 0),
|
|
112
|
-
tasks: sumNumbers(rows.map((row) => row.task_count)),
|
|
113
|
-
prds: sumNumbers(rows.map((row) => row.prd_count)),
|
|
114
|
-
specs: sumNumbers(rows.map((row) => row.spec_count)),
|
|
115
|
-
evidences: sumNumbers(rows.map((row) => row.evidence_count)),
|
|
116
|
-
tests: sumNumbers(rows.map((row) => row.test_count)),
|
|
117
|
-
conversations: sumNumbers(rows.map(conversationCount)),
|
|
118
|
-
durationKnownMs: rows.reduce((sum, row) => sum + row.duration.known_sum, 0),
|
|
119
|
-
durationPartial: rows.some((row) => !row.duration.complete),
|
|
120
|
-
tokens: sumNumbers(rows.map((row) => row.total_tokens)),
|
|
121
|
-
usd: sumNumbers(rows.map((row) => row.estimated_usd)),
|
|
122
|
-
brl: sumNumbers(rows.map((row) => row.estimated_brl)),
|
|
123
|
-
};
|
|
105
|
+
const periodValues = createCostGroupPeriodValues(currency, locale, period);
|
|
106
|
+
const periodDescription =
|
|
107
|
+
periodValues.description === undefined ? {} : { description: periodValues.description };
|
|
108
|
+
const pageTotals = costGroupPageTotals(rows);
|
|
124
109
|
const totals =
|
|
125
110
|
suppliedTotals === undefined
|
|
126
111
|
? pageTotals
|
|
@@ -131,14 +116,14 @@ export function CostGroupsTable({
|
|
|
131
116
|
specs: suppliedTotals.spec_count,
|
|
132
117
|
evidences: suppliedTotals.evidence_count,
|
|
133
118
|
tests: suppliedTotals.test_count,
|
|
134
|
-
conversations:
|
|
119
|
+
conversations: costGroupConversationCount(suppliedTotals) ?? pageTotals.conversations,
|
|
135
120
|
durationKnownMs: suppliedTotals.duration.known_sum,
|
|
136
121
|
durationPartial: !suppliedTotals.duration.complete,
|
|
137
122
|
tokens: suppliedTotals.total_tokens,
|
|
138
123
|
usd: suppliedTotals.estimated_usd,
|
|
139
124
|
brl: suppliedTotals.estimated_brl,
|
|
140
125
|
};
|
|
141
|
-
const totalDurationDisplay =
|
|
126
|
+
const totalDurationDisplay = periodValues.duration(
|
|
142
127
|
suppliedTotals?.duration ?? {
|
|
143
128
|
known_sum: totals.durationKnownMs,
|
|
144
129
|
unknown: totals.durationPartial ? 1 : 0,
|
|
@@ -152,7 +137,7 @@ export function CostGroupsTable({
|
|
|
152
137
|
showModelLifecycleDetails ? (totals.tokens ?? 0) : totals.tokens,
|
|
153
138
|
locale,
|
|
154
139
|
);
|
|
155
|
-
const totalCostDisplay =
|
|
140
|
+
const totalCostDisplay = periodValues.currency(currency === "BRL" ? totals.brl : totals.usd);
|
|
156
141
|
const totalAriaLabel = costPeriodTotalAriaLabel({
|
|
157
142
|
locale,
|
|
158
143
|
duration: totalDurationDisplay,
|
|
@@ -294,8 +279,8 @@ export function CostGroupsTable({
|
|
|
294
279
|
{
|
|
295
280
|
key: "conversations",
|
|
296
281
|
label: "Conversations",
|
|
297
|
-
render: (row: CostGroupRow) => displayCount(
|
|
298
|
-
sortValue: (row: CostGroupRow) =>
|
|
282
|
+
render: (row: CostGroupRow) => displayCount(costGroupConversationCount(row)),
|
|
283
|
+
sortValue: (row: CostGroupRow) => costGroupConversationCount(row) ?? 0,
|
|
299
284
|
align: "right" as const,
|
|
300
285
|
footer: displayCount(totals.conversations),
|
|
301
286
|
description: localizedDescription(
|
|
@@ -355,7 +340,10 @@ export function CostGroupsTable({
|
|
|
355
340
|
{
|
|
356
341
|
key: "duration",
|
|
357
342
|
label: "Tempo",
|
|
358
|
-
render: (row) =>
|
|
343
|
+
render: (row) =>
|
|
344
|
+
period !== undefined && !hasKnownDuration(row.duration)
|
|
345
|
+
? periodValues.disclose("0", true)
|
|
346
|
+
: periodValues.duration(row.duration),
|
|
359
347
|
sortValue: (row) =>
|
|
360
348
|
hasKnownDuration(row.duration)
|
|
361
349
|
? row.duration.known_sum
|
|
@@ -364,19 +352,23 @@ export function CostGroupsTable({
|
|
|
364
352
|
: null,
|
|
365
353
|
align: "right",
|
|
366
354
|
footer: <output aria-label={totalAriaLabel}>{totalDurationDisplay}</output>,
|
|
355
|
+
...periodDescription,
|
|
367
356
|
},
|
|
368
357
|
{
|
|
369
358
|
key: "tokens",
|
|
370
359
|
label: "Tokens",
|
|
371
|
-
render: (row) =>
|
|
372
|
-
formatAuditableCompactNumber(
|
|
360
|
+
render: (row) => {
|
|
361
|
+
const displayed = formatAuditableCompactNumber(
|
|
373
362
|
showModelLifecycleDetails ? (row.total_tokens ?? 0) : row.total_tokens,
|
|
374
363
|
locale,
|
|
375
|
-
)
|
|
364
|
+
);
|
|
365
|
+
return periodValues.disclose(displayed, row.total_tokens === null);
|
|
366
|
+
},
|
|
376
367
|
sortValue: (row) =>
|
|
377
368
|
showModelLifecycleDetails ? (row.total_tokens ?? 0) : row.total_tokens,
|
|
378
369
|
align: "right",
|
|
379
370
|
footer: <output aria-label={totalAriaLabel}>{totalTokensDisplay}</output>,
|
|
371
|
+
...periodDescription,
|
|
380
372
|
},
|
|
381
373
|
{
|
|
382
374
|
key: "cost",
|
|
@@ -392,14 +384,17 @@ export function CostGroupsTable({
|
|
|
392
384
|
: locale === "pt-BR"
|
|
393
385
|
? "Custos"
|
|
394
386
|
: "Costs",
|
|
395
|
-
render: (row) =>
|
|
396
|
-
|
|
387
|
+
render: (row) => {
|
|
388
|
+
const observed = currency === "BRL" ? row.estimated_brl : row.estimated_usd;
|
|
389
|
+
return periodValues.disclose(periodValues.currency(observed), observed === null);
|
|
390
|
+
},
|
|
397
391
|
sortValue: (row) =>
|
|
398
392
|
showModelLifecycleDetails
|
|
399
393
|
? (sortCostValue(currency, row.estimated_brl, row.estimated_usd) ?? 0)
|
|
400
394
|
: sortCostValue(currency, row.estimated_brl, row.estimated_usd),
|
|
401
395
|
align: "right",
|
|
402
396
|
footer: <output aria-label={totalAriaLabel}>{totalCostDisplay}</output>,
|
|
397
|
+
...periodDescription,
|
|
403
398
|
},
|
|
404
399
|
...(onOpenTrace
|
|
405
400
|
? [
|
package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.embedded.test.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
|
|
4
|
+
describe("embedded Cost Monitor", () => {
|
|
5
|
+
it("keeps global filters as the sole embedded filter surface", () => {
|
|
6
|
+
const page = readFileSync(new URL("./CostMonitorPage.tsx", import.meta.url), "utf8");
|
|
7
|
+
expect(page).not.toContain('className="cost-embedded-filters"');
|
|
8
|
+
expect(page).toContain("<CostMonitorContent");
|
|
9
|
+
expect(page).toContain("<CostFilters");
|
|
10
|
+
});
|
|
11
|
+
});
|
|
@@ -83,7 +83,7 @@ export {
|
|
|
83
83
|
export function CostMonitorPage({
|
|
84
84
|
capabilityNavigation,
|
|
85
85
|
data,
|
|
86
|
-
dashboardTitle = "Dashboard
|
|
86
|
+
dashboardTitle = "Dashboard ZAIP AIOS",
|
|
87
87
|
embedded = false,
|
|
88
88
|
globalFilters,
|
|
89
89
|
lastUpdatedAt,
|
|
@@ -708,18 +708,6 @@ export function CostMonitorPage({
|
|
|
708
708
|
</div>
|
|
709
709
|
) : null}
|
|
710
710
|
</div>{" "}
|
|
711
|
-
{embedded && view !== "developers" ? (
|
|
712
|
-
<details className="cost-embedded-filters">
|
|
713
|
-
<summary>{locale === "pt-BR" ? "Filtros de custos" : "Cost filters"}</summary>
|
|
714
|
-
<CostFilters
|
|
715
|
-
available={data.filters_available}
|
|
716
|
-
hideQuery
|
|
717
|
-
locale={locale}
|
|
718
|
-
onChange={setFilters}
|
|
719
|
-
value={filters}
|
|
720
|
-
/>
|
|
721
|
-
</details>
|
|
722
|
-
) : null}
|
|
723
711
|
{/* CostMonitorContent owns `view === "models" && useAggregateGroups ? (` and `rows={groups.models}`. */}{" "}
|
|
724
712
|
<CostMonitorContent
|
|
725
713
|
canonicalDurationTotal={canonicalDurationTotal}
|
package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostPeriodAverageCards.test.tsx
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ReactElement } from "react";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { CostPeriodAverageCards } from "./CostPeriodAverageCards.js";
|
|
4
|
+
|
|
5
|
+
describe("CostPeriodAverageCards", () => {
|
|
6
|
+
const props = { currency: "BRL", locale: "pt-BR", period: "daily", rows: [] } as const;
|
|
7
|
+
|
|
8
|
+
it("shows zero for loaded missing numeric averages without changing the source", () => {
|
|
9
|
+
const element = CostPeriodAverageCards({ ...props, average: null }) as ReactElement<{
|
|
10
|
+
metrics: readonly { value: string }[];
|
|
11
|
+
}>;
|
|
12
|
+
expect(element.props.metrics.map((metric) => metric.value)).toEqual(Array(6).fill("0"));
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("keeps loading distinct from a loaded zero", () => {
|
|
16
|
+
const element = CostPeriodAverageCards({ ...props, loading: true }) as ReactElement<{
|
|
17
|
+
role: string;
|
|
18
|
+
children: string;
|
|
19
|
+
}>;
|
|
20
|
+
expect(element.props.role).toBe("status");
|
|
21
|
+
expect(element.props.children).toContain("Carregando médias");
|
|
22
|
+
});
|
|
23
|
+
});
|
package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostPeriodAverageCards.tsx
CHANGED
|
@@ -39,7 +39,8 @@ export function CostPeriodAverageCards({
|
|
|
39
39
|
tokens: null,
|
|
40
40
|
cost: null,
|
|
41
41
|
});
|
|
42
|
-
|
|
42
|
+
// A loaded missing metric is presented as zero; the API retains null/coverage.
|
|
43
|
+
const unavailable = "0";
|
|
43
44
|
return (
|
|
44
45
|
<PeriodAverageCards
|
|
45
46
|
ariaLabel={periodAverageAriaLabel(period, locale)}
|
|
@@ -22,11 +22,7 @@ export function formatAuditableNumber(value: number | null, locale: CostLocale):
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export function formatFactualCount(value: number | null, locale: CostLocale): string {
|
|
25
|
-
return value
|
|
26
|
-
? locale === "pt-BR"
|
|
27
|
-
? "Indisponível"
|
|
28
|
-
: "Unavailable"
|
|
29
|
-
: formatAuditableNumber(value, locale);
|
|
25
|
+
return formatAuditableNumber(value, locale);
|
|
30
26
|
}
|
|
31
27
|
|
|
32
28
|
export function formatAuditableCompactNumber(value: number | null, locale: CostLocale): string {
|
|
@@ -38,12 +34,12 @@ export function formatAuditableCurrency(
|
|
|
38
34
|
currency: CostCurrency,
|
|
39
35
|
locale: CostLocale,
|
|
40
36
|
): string {
|
|
41
|
-
if (value === null) return
|
|
37
|
+
if (value === null) return "0";
|
|
42
38
|
return formatCurrency(value, currency, locale);
|
|
43
39
|
}
|
|
44
40
|
|
|
45
41
|
export function formatAuditableDuration(value: number | null, locale: CostLocale): string {
|
|
46
|
-
if (value === null) return
|
|
42
|
+
if (value === null) return "0";
|
|
47
43
|
return value === 0 ? "0" : formatDurationMs(value, locale);
|
|
48
44
|
}
|
|
49
45
|
|
|
@@ -71,8 +67,8 @@ export const formatInvocationMultiplierPair = (
|
|
|
71
67
|
export function invocationMetricDescription(locale: CostLocale, metric: string): string {
|
|
72
68
|
const source =
|
|
73
69
|
locale === "pt-BR"
|
|
74
|
-
? "Valor da projeção SQLite/API desta Invocação de Agente.
|
|
75
|
-
: "Value from this Agent Invocation's SQLite/API projection. A
|
|
70
|
+
? "Valor da projeção SQLite/API desta Invocação de Agente. O zero exibido para um fato não medido não altera o valor canônico nulo."
|
|
71
|
+
: "Value from this Agent Invocation's SQLite/API projection. A displayed zero for an unmeasured fact does not change its canonical null value.";
|
|
76
72
|
const details: Record<string, readonly [string, string]> = {
|
|
77
73
|
duration: [
|
|
78
74
|
"Tempo factual da invocação, quando capturado ou reconciliado.",
|
|
@@ -171,8 +167,7 @@ export function invocationMetricDescription(locale: CostLocale, metric: string):
|
|
|
171
167
|
}
|
|
172
168
|
|
|
173
169
|
export function formatDurationCoverage(value: DurationCoverage, locale: CostLocale): string {
|
|
174
|
-
if (value.known_sum <= 0 && !value.complete)
|
|
175
|
-
return locale === "pt-BR" ? "Indisponível" : "Unavailable";
|
|
170
|
+
if (value.known_sum <= 0 && !value.complete) return "0";
|
|
176
171
|
return value.known_sum <= 0 ? "0" : formatDurationMs(value.known_sum, locale);
|
|
177
172
|
}
|
|
178
173
|
|
|
@@ -176,10 +176,10 @@ describe("grouped cost availability", () => {
|
|
|
176
176
|
...model,
|
|
177
177
|
duration: { known_sum: 0, unknown: 1, complete: false, coverage_ratio: 0 },
|
|
178
178
|
}),
|
|
179
|
-
).toBe("
|
|
179
|
+
).toBe("0");
|
|
180
180
|
expect(
|
|
181
181
|
columns.find((column) => column.key === "cost")?.render?.({ ...model, estimated_brl: null }),
|
|
182
|
-
).toBe("
|
|
182
|
+
).toBe("0");
|
|
183
183
|
expect(
|
|
184
184
|
columns
|
|
185
185
|
.find((column) => column.key === "tokens")
|
|
@@ -324,14 +324,14 @@ describe("grouped cost availability", () => {
|
|
|
324
324
|
expect(column(key)?.description).toContain("projeção SQLite/API");
|
|
325
325
|
expect(column(key)?.hidden).not.toBe(true);
|
|
326
326
|
}
|
|
327
|
-
expect(column("duration")?.render?.(unavailableRun)).toBe("
|
|
327
|
+
expect(column("duration")?.render?.(unavailableRun)).toBe("0");
|
|
328
328
|
expect(column("inputTokens")?.render?.(unavailableRun)).toBe("0");
|
|
329
329
|
expect(column("inputRate")?.render?.(unavailableRun)).toBe("0,00");
|
|
330
|
-
expect(column("contextMultiplier")?.render?.(unavailableRun)).toBe("
|
|
330
|
+
expect(column("contextMultiplier")?.render?.(unavailableRun)).toBe("0");
|
|
331
331
|
expect(column("inputCost")?.render?.(unavailableRun)).toContain("0,00");
|
|
332
332
|
expect(column("fxRate")?.render?.(unavailableRun)).toBe("R$ 0,00");
|
|
333
|
-
expect(column("recordedBrl")?.render?.(unavailableRun)).toBe("
|
|
334
|
-
expect(column("cost")?.render?.(unavailableRun)).toBe("
|
|
333
|
+
expect(column("recordedBrl")?.render?.(unavailableRun)).toBe("0");
|
|
334
|
+
expect(column("cost")?.render?.(unavailableRun)).toBe("0");
|
|
335
335
|
});
|
|
336
336
|
it("provides a clear scroll label for the detailed Runs table", () => {
|
|
337
337
|
expect(costRunsScrollLabel("pt-BR")).toBe(
|
|
@@ -107,11 +107,11 @@ describe("monetary formatting", () => {
|
|
|
107
107
|
expect(ratio(106.73, 19.583444)).toBeCloseTo(5.45, 2);
|
|
108
108
|
expect(ratio(100, 0)).toBeNull();
|
|
109
109
|
});
|
|
110
|
-
it("
|
|
110
|
+
it("shows zero for unmeasured metrics without changing their source values", () => {
|
|
111
111
|
expect(formatRate(null, "pt-BR")).toBe("0,00");
|
|
112
112
|
expect(formatUsd(null, "en-US")).toContain("0.00");
|
|
113
|
-
expect(formatAuditableCurrency(null, "BRL", "pt-BR")).toBe("
|
|
114
|
-
expect(formatAuditableDuration(null, "pt-BR")).toBe("
|
|
113
|
+
expect(formatAuditableCurrency(null, "BRL", "pt-BR")).toBe("0");
|
|
114
|
+
expect(formatAuditableDuration(null, "pt-BR")).toBe("0");
|
|
115
115
|
expect(formatAuditableCompactNumber(null, "pt-BR")).toBe("0");
|
|
116
116
|
});
|
|
117
117
|
});
|
|
@@ -134,7 +134,7 @@ describe("duration coverage", () => {
|
|
|
134
134
|
{ known_sum: 0, unknown: 2, complete: false, coverage_ratio: 0 },
|
|
135
135
|
"pt-BR",
|
|
136
136
|
),
|
|
137
|
-
).toBe("
|
|
137
|
+
).toBe("0");
|
|
138
138
|
});
|
|
139
139
|
it("does not treat financial tokens as elapsed-time evidence", () => {
|
|
140
140
|
expect(
|
|
@@ -242,9 +242,7 @@ describe("grouped cost availability", () => {
|
|
|
242
242
|
]);
|
|
243
243
|
expect(columns.find((column) => column.key === "tests")?.render(unavailable)).toBe("—");
|
|
244
244
|
expect(columns.find((column) => column.key === "evidences")?.render(unavailable)).toBe("—");
|
|
245
|
-
expect(columns.find((column) => column.key === "duration")?.render(unavailable)).toBe(
|
|
246
|
-
"Indisponível",
|
|
247
|
-
);
|
|
245
|
+
expect(columns.find((column) => column.key === "duration")?.render(unavailable)).toBe("0");
|
|
248
246
|
});
|
|
249
247
|
it("marks incomplete aggregates in place without adding source or coverage columns", () => {
|
|
250
248
|
const partial = {
|
|
@@ -349,13 +347,13 @@ describe("grouped cost availability", () => {
|
|
|
349
347
|
}>;
|
|
350
348
|
const column = (key: string) => columns.find((candidate) => candidate.key === key);
|
|
351
349
|
expect(table.props.scrollLabel).toBe(costGroupsScrollLabel("pt-BR"));
|
|
352
|
-
expect(column("duration")?.render(unavailableGroup)).toBe("
|
|
350
|
+
expect(column("duration")?.render(unavailableGroup)).toBe("0");
|
|
353
351
|
expect(column("tokens")?.render(unavailableGroup)).toBe("0");
|
|
354
|
-
expect(column("cost")?.render(unavailableGroup)).toBe("
|
|
352
|
+
expect(column("cost")?.render(unavailableGroup)).toBe("0");
|
|
355
353
|
expect(column("duration")?.sortValue?.(unavailableGroup)).toBeNull();
|
|
356
354
|
expect(column("tokens")?.sortValue?.(unavailableGroup)).toBeNull();
|
|
357
355
|
expect(column("cost")?.sortValue?.(unavailableGroup)).toBeNull();
|
|
358
|
-
const totalSummary = "Total geral — Tempo:
|
|
356
|
+
const totalSummary = "Total geral — Tempo: 0; Tokens: 0; BRL: 0";
|
|
359
357
|
const footerLabel = (key: string) => {
|
|
360
358
|
const footer = column(key)?.footer as { props?: { "aria-label"?: string } } | undefined;
|
|
361
359
|
return footer?.props?.["aria-label"];
|
|
@@ -455,7 +453,7 @@ describe("grouped cost availability", () => {
|
|
|
455
453
|
for (const key of ["tasks", "prds", "specs", "tests", "evidences", "tokens"]) {
|
|
456
454
|
expect(columns.find((c) => c.key === key)?.render?.(missing)).toBe("0");
|
|
457
455
|
}
|
|
458
|
-
expect(columns.find((c) => c.key === "duration")?.render?.(missing)).toBe("
|
|
459
|
-
expect(columns.find((c) => c.key === "cost")?.render?.(missing)).toBe("
|
|
456
|
+
expect(columns.find((c) => c.key === "duration")?.render?.(missing)).toBe("0");
|
|
457
|
+
expect(columns.find((c) => c.key === "cost")?.render?.(missing)).toBe("0");
|
|
460
458
|
});
|
|
461
459
|
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { CostGroupRow } from "../contracts.js";
|
|
2
|
+
import { sumNumbers } from "./cost-table-metrics.js";
|
|
3
|
+
|
|
4
|
+
export function costGroupConversationCount(row: unknown): number | null {
|
|
5
|
+
return (row as { conversation_count?: number | null }).conversation_count ?? null;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function costGroupPageTotals(rows: readonly CostGroupRow[]) {
|
|
9
|
+
return {
|
|
10
|
+
runs: rows.reduce((sum, row) => sum + row.run_count, 0),
|
|
11
|
+
tasks: sumNumbers(rows.map((row) => row.task_count)),
|
|
12
|
+
prds: sumNumbers(rows.map((row) => row.prd_count)),
|
|
13
|
+
specs: sumNumbers(rows.map((row) => row.spec_count)),
|
|
14
|
+
evidences: sumNumbers(rows.map((row) => row.evidence_count)),
|
|
15
|
+
tests: sumNumbers(rows.map((row) => row.test_count)),
|
|
16
|
+
conversations: sumNumbers(rows.map(costGroupConversationCount)),
|
|
17
|
+
durationKnownMs: rows.reduce((sum, row) => sum + row.duration.known_sum, 0),
|
|
18
|
+
durationPartial: rows.some((row) => !row.duration.complete),
|
|
19
|
+
tokens: sumNumbers(rows.map((row) => row.total_tokens)),
|
|
20
|
+
usd: sumNumbers(rows.map((row) => row.estimated_usd)),
|
|
21
|
+
brl: sumNumbers(rows.map((row) => row.estimated_brl)),
|
|
22
|
+
};
|
|
23
|
+
}
|
package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-group-period-values.tsx
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { DurationCoverage } from "../contracts.js";
|
|
2
|
+
import type { CostCurrency, CostLocale } from "./cost-monitor-copy.js";
|
|
3
|
+
import {
|
|
4
|
+
formatAuditableCurrency,
|
|
5
|
+
formatDurationCoverage,
|
|
6
|
+
hasKnownDuration,
|
|
7
|
+
} from "./cost-table-formatters.js";
|
|
8
|
+
|
|
9
|
+
export function createCostGroupPeriodValues(
|
|
10
|
+
currency: CostCurrency,
|
|
11
|
+
locale: CostLocale,
|
|
12
|
+
period: "daily" | "monthly" | "annual" | undefined,
|
|
13
|
+
) {
|
|
14
|
+
const unmeasuredLabel =
|
|
15
|
+
locale === "pt-BR"
|
|
16
|
+
? "Zero exibido por falta de medição; não é um valor observado."
|
|
17
|
+
: "Zero displayed because no measurement was recorded; this is not an observed value.";
|
|
18
|
+
const disclose = (value: string) => (
|
|
19
|
+
<output aria-label={`${value}. ${unmeasuredLabel}`} title={unmeasuredLabel}>
|
|
20
|
+
{value}
|
|
21
|
+
</output>
|
|
22
|
+
);
|
|
23
|
+
return {
|
|
24
|
+
description: period === undefined ? undefined : unmeasuredLabel,
|
|
25
|
+
duration: (value: DurationCoverage) =>
|
|
26
|
+
period !== undefined && !hasKnownDuration(value)
|
|
27
|
+
? "0"
|
|
28
|
+
: formatDurationCoverage(value, locale),
|
|
29
|
+
currency: (value: number | null) =>
|
|
30
|
+
formatAuditableCurrency(period === undefined ? value : (value ?? 0), currency, locale),
|
|
31
|
+
disclose: (value: string, unmeasured: boolean) =>
|
|
32
|
+
period !== undefined && unmeasured ? disclose(value) : value,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -22,11 +22,7 @@ export function formatAuditableNumber(value: number | null, locale: CostLocale):
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export function formatFactualCount(value: number | null, locale: CostLocale): string {
|
|
25
|
-
return value
|
|
26
|
-
? locale === "pt-BR"
|
|
27
|
-
? "Indisponível"
|
|
28
|
-
: "Unavailable"
|
|
29
|
-
: formatAuditableNumber(value, locale);
|
|
25
|
+
return formatAuditableNumber(value, locale);
|
|
30
26
|
}
|
|
31
27
|
|
|
32
28
|
export function formatAuditableCompactNumber(value: number | null, locale: CostLocale): string {
|
|
@@ -38,12 +34,12 @@ export function formatAuditableCurrency(
|
|
|
38
34
|
currency: CostCurrency,
|
|
39
35
|
locale: CostLocale,
|
|
40
36
|
): string {
|
|
41
|
-
if (value === null) return
|
|
37
|
+
if (value === null) return "0";
|
|
42
38
|
return formatCurrency(value, currency, locale);
|
|
43
39
|
}
|
|
44
40
|
|
|
45
41
|
export function formatAuditableDuration(value: number | null, locale: CostLocale): string {
|
|
46
|
-
if (value === null) return
|
|
42
|
+
if (value === null) return "0";
|
|
47
43
|
return value === 0 ? "0" : formatDurationMs(value, locale);
|
|
48
44
|
}
|
|
49
45
|
|
|
@@ -73,8 +69,7 @@ export function formatDurationCoverage(value: DurationCoverage, locale: CostLoca
|
|
|
73
69
|
// activity in the population is unavailable. Keep completeness and the
|
|
74
70
|
// unknown count as coverage metadata; hiding the known portion would turn a
|
|
75
71
|
// true observation into an indistinguishable absence.
|
|
76
|
-
if (value.known_sum <= 0 && !value.complete)
|
|
77
|
-
return locale === "pt-BR" ? "Indisponível" : "Unavailable";
|
|
72
|
+
if (value.known_sum <= 0 && !value.complete) return "0";
|
|
78
73
|
return value.known_sum <= 0 ? "0" : formatDurationMs(value.known_sum, locale);
|
|
79
74
|
}
|
|
80
75
|
|
package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-table-presentation.ts
CHANGED
|
@@ -49,10 +49,9 @@ const detail = (value: string, _kind: "effort" | "speed", locale: CostLocale) =>
|
|
|
49
49
|
export const formatMultiplierPair = (
|
|
50
50
|
input: number | null,
|
|
51
51
|
output: number | null,
|
|
52
|
-
|
|
52
|
+
_locale: CostLocale,
|
|
53
53
|
) => {
|
|
54
|
-
if (input === null || output === null)
|
|
55
|
-
return locale === "pt-BR" ? "Indispon\u00edvel" : "Unavailable";
|
|
54
|
+
if (input === null || output === null) return "0";
|
|
56
55
|
return `${input.toLocaleString("en-US", { maximumFractionDigits: 3 })}\u00d7 / ${output.toLocaleString("en-US", { maximumFractionDigits: 3 })}\u00d7`;
|
|
57
56
|
};
|
|
58
57
|
export const formatReasoningEffort = (
|
package/templates/.agents/dashboard/modules/operations/src/react/DeveloperAttributionPanel.tsx
CHANGED
|
@@ -157,24 +157,14 @@ export function DeveloperAttributionTable({
|
|
|
157
157
|
key: "tokens",
|
|
158
158
|
label: copy.tokens,
|
|
159
159
|
align: "right",
|
|
160
|
-
render: (row) =>
|
|
161
|
-
row.total_tokens === null
|
|
162
|
-
? locale === "pt-BR"
|
|
163
|
-
? "Indisponível"
|
|
164
|
-
: "Unavailable"
|
|
165
|
-
: formatCompactNumber(row.total_tokens, locale),
|
|
160
|
+
render: (row) => formatCompactNumber(row.total_tokens, locale),
|
|
166
161
|
sortValue: (row) => row.total_tokens,
|
|
167
162
|
},
|
|
168
163
|
{
|
|
169
164
|
key: "cost",
|
|
170
165
|
label: copy.cost,
|
|
171
166
|
align: "right",
|
|
172
|
-
render: (row) =>
|
|
173
|
-
row.total_cost_brl === null
|
|
174
|
-
? locale === "pt-BR"
|
|
175
|
-
? "Indisponível"
|
|
176
|
-
: "Unavailable"
|
|
177
|
-
: formatCurrency(row.total_cost_brl, "BRL", locale),
|
|
167
|
+
render: (row) => formatCurrency(row.total_cost_brl, "BRL", locale),
|
|
178
168
|
sortValue: (row) => row.total_cost_brl,
|
|
179
169
|
},
|
|
180
170
|
]}
|
package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.helpers.tsx
CHANGED
|
@@ -603,8 +603,8 @@ export function formatExecutionAverageHint(
|
|
|
603
603
|
if (totalTasks <= 0) return "0";
|
|
604
604
|
if (totalDurationMs <= 0) {
|
|
605
605
|
return locale === "pt-BR"
|
|
606
|
-
? "
|
|
607
|
-
: "
|
|
606
|
+
? "Sem tempo medido para calcular médias"
|
|
607
|
+
: "No measured time for averages";
|
|
608
608
|
}
|
|
609
609
|
const averagePerTask = formatRoundedDuration(totalDurationMs / totalTasks, locale);
|
|
610
610
|
// Macro aggregates can provide duration and population without individual
|
|
@@ -357,11 +357,6 @@ describe("execution average summary", () => {
|
|
|
357
357
|
"20 min / tarefa (6 h / dia) (6 dias)",
|
|
358
358
|
);
|
|
359
359
|
});
|
|
360
|
-
it("keeps the known macro average when execution days are unavailable", () => {
|
|
361
|
-
expect(formatExecutionAverageHint(3_600_000, 3, 0, "pt-BR")).toBe("20 min / item");
|
|
362
|
-
expect(formatExecutionAverageHint(3_600_000, 3, 0, "en-US")).toBe("20 min / item");
|
|
363
|
-
expect(formatExecutionAverageHint(0, 3, 0, "pt-BR")).toBe("Médias de execução indisponíveis");
|
|
364
|
-
});
|
|
365
360
|
it("localizes English and shows zero for an empty population", () => {
|
|
366
361
|
expect(formatExecutionAverageHint(3_600_000, 3, 1, "en-US")).toBe(
|
|
367
362
|
"20 min / task (1 h / day) (1 day)",
|
|
@@ -444,7 +439,7 @@ describe("overviewMetricAverages", () => {
|
|
|
444
439
|
"Indisponível",
|
|
445
440
|
);
|
|
446
441
|
expect(formatSummaryMetricValue(42, 0, (value) => String(value), "pt-BR")).toBe("42");
|
|
447
|
-
expect(source).toContain("
|
|
442
|
+
expect(source).toContain("const metricStats = overviewMetricStats(");
|
|
448
443
|
expect(source).not.toContain("executionMetrics.durationMs ?? 0");
|
|
449
444
|
});
|
|
450
445
|
});
|