@zaip-ai/cli 1.0.7 → 1.0.8

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.
Files changed (410) hide show
  1. package/README.md +6 -4
  2. package/dist/services/adapters.d.ts +1 -1
  3. package/dist/services/adapters.d.ts.map +1 -1
  4. package/dist/services/adapters.js +15 -5
  5. package/dist/services/adapters.js.map +1 -1
  6. package/dist/services/adapters.test.js +1 -1
  7. package/dist/services/agent-adapters.d.ts +9 -0
  8. package/dist/services/agent-adapters.d.ts.map +1 -1
  9. package/dist/services/agent-adapters.js +38 -3
  10. package/dist/services/agent-adapters.js.map +1 -1
  11. package/dist/services/agent-adapters.test.js +8 -1
  12. package/dist/services/agent-adapters.test.js.map +1 -1
  13. package/dist/services/codex-config-template.d.ts +2 -1
  14. package/dist/services/codex-config-template.d.ts.map +1 -1
  15. package/dist/services/codex-config-template.js +13 -2
  16. package/dist/services/codex-config-template.js.map +1 -1
  17. package/dist/services/codex-rules.d.ts +1 -1
  18. package/dist/services/codex-rules.d.ts.map +1 -1
  19. package/dist/services/codex-rules.js +31 -7
  20. package/dist/services/codex-rules.js.map +1 -1
  21. package/dist/services/codex-subagent-hook-template.d.ts +1 -1
  22. package/dist/services/codex-subagent-hook-template.d.ts.map +1 -1
  23. package/dist/services/codex-subagent-hook-template.js +4 -1
  24. package/dist/services/codex-subagent-hook-template.js.map +1 -1
  25. package/dist/services/doctor.d.ts.map +1 -1
  26. package/dist/services/doctor.js +3 -1
  27. package/dist/services/doctor.js.map +1 -1
  28. package/dist/services/global-codex-config.d.ts +6 -3
  29. package/dist/services/global-codex-config.d.ts.map +1 -1
  30. package/dist/services/global-codex-config.js +82 -13
  31. package/dist/services/global-codex-config.js.map +1 -1
  32. package/dist/services/global-codex-config.test.js +57 -10
  33. package/dist/services/global-codex-config.test.js.map +1 -1
  34. package/dist/services/install-agents-template.d.ts.map +1 -1
  35. package/dist/services/install-agents-template.js +15 -2
  36. package/dist/services/install-agents-template.js.map +1 -1
  37. package/dist/services/logger.js +1 -1
  38. package/dist/services/logger.js.map +1 -1
  39. package/dist/services/logger.test.js +3 -3
  40. package/dist/services/logger.test.js.map +1 -1
  41. package/dist/services/runtime-template.test.js +21 -5
  42. package/dist/services/runtime-template.test.js.map +1 -1
  43. package/dist/services/template-manifest.d.ts.map +1 -1
  44. package/dist/services/template-manifest.js +2 -0
  45. package/dist/services/template-manifest.js.map +1 -1
  46. package/package.json +1 -1
  47. package/templates/.agents/config/agents/catalog.yaml +310 -10
  48. package/templates/.agents/config/clients/codex/agents/zaip-agent-brand-strategist.toml +30 -0
  49. package/templates/.agents/config/clients/codex/agents/zaip-agent-designer.toml +5 -5
  50. package/templates/.agents/config/clients/codex/agents/zaip-agent-finalizer.toml +1 -1
  51. package/templates/.agents/config/clients/codex/agents/zaip-agent-general-operations.toml +30 -0
  52. package/templates/.agents/config/clients/codex/agents/zaip-agent-governance-compliance.toml +30 -0
  53. package/templates/.agents/config/clients/codex/agents/zaip-agent-growth-strategist.toml +30 -0
  54. package/templates/.agents/config/clients/codex/agents/zaip-agent-marketing-analyst.toml +8 -8
  55. package/templates/.agents/config/clients/codex/agents/zaip-agent-orchestrator.toml +5 -3
  56. package/templates/.agents/config/clients/codex/agents/zaip-agent-sales-specialist.toml +30 -0
  57. package/templates/.agents/config/project.yaml +1 -1
  58. package/templates/.agents/dashboard/.zaip-managed.json +659 -163
  59. package/templates/.agents/dashboard/DATA-DICTIONARY.md +2227 -0
  60. package/templates/.agents/dashboard/README.md +48 -97
  61. package/templates/.agents/dashboard/apps/frontend/dist/assets/CostCalculationGuidePage-Z60df2r-.js +1 -0
  62. package/templates/.agents/dashboard/apps/frontend/dist/assets/{DashboardHelpDialog-Cv-JcoxP.js → DashboardHelpDialog-Cs6dzDmW.js} +294 -109
  63. package/templates/.agents/dashboard/apps/frontend/dist/assets/PricingSettingsDialog-Coc6pA-1.js +1 -0
  64. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-QE1k9yZB.css +1 -0
  65. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-_Pf5DA_A.js +3 -0
  66. package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-BVlz3DLZ.js +1 -0
  67. package/templates/.agents/dashboard/apps/frontend/dist/assets/TraceabilityWorkspace-CaKwQP43.css +1 -0
  68. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-BZ5WdaMN.css +1 -0
  69. package/templates/.agents/dashboard/apps/frontend/dist/assets/cost-monitor-Cf9ctPVt.js +68 -0
  70. package/templates/.agents/dashboard/apps/frontend/dist/assets/{dashboard-localization-C98LGC-Q.js → dashboard-localization-CLJ0lT9v.js} +1 -1
  71. package/templates/.agents/dashboard/apps/frontend/dist/assets/icons-vendor-DFBuc_qp.js +1 -0
  72. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-8A4DcNXM.js +2 -0
  73. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-DK_enB5Z.css +1 -0
  74. package/templates/.agents/dashboard/apps/frontend/dist/assets/react-vendor-CCQOHdVI.js +9 -0
  75. package/templates/.agents/dashboard/apps/frontend/dist/assets/rolldown-runtime-D9-fqq9M.js +1 -0
  76. package/templates/.agents/dashboard/apps/frontend/dist/assets/traceability-DFY7ZDlu.css +1 -0
  77. package/templates/.agents/dashboard/apps/frontend/dist/assets/traceability-pC2_0J8x.js +1 -0
  78. package/templates/.agents/dashboard/apps/frontend/dist/index.html +9 -2
  79. package/templates/.agents/dashboard/apps/frontend/package.json +1 -1
  80. package/templates/.agents/dashboard/apps/frontend/src/App.tsx +952 -595
  81. package/templates/.agents/dashboard/apps/frontend/src/AppLoadingBoundary.tsx +48 -0
  82. package/templates/.agents/dashboard/apps/frontend/src/AppLoadingPanels.tsx +2 -0
  83. package/templates/.agents/dashboard/apps/frontend/src/AppOverlays.tsx +247 -0
  84. package/templates/.agents/dashboard/apps/frontend/src/AppRequestGuards.tsx +95 -0
  85. package/templates/.agents/dashboard/apps/frontend/src/AppSetupRoutes.tsx +87 -0
  86. package/templates/.agents/dashboard/apps/frontend/src/CostCalculationGuidePage.tsx +641 -0
  87. package/templates/.agents/dashboard/apps/frontend/src/DashboardAlternateContent.tsx +159 -0
  88. package/templates/.agents/dashboard/apps/frontend/src/DashboardCapabilityNav.tsx +13 -13
  89. package/templates/.agents/dashboard/apps/frontend/src/DashboardGlobalSettings.tsx +56 -0
  90. package/templates/.agents/dashboard/apps/frontend/src/ProjectSettingsPage.tsx +257 -313
  91. package/templates/.agents/dashboard/apps/frontend/src/ProjectStackEditor.tsx +149 -0
  92. package/templates/.agents/dashboard/apps/frontend/src/TraceabilityWorkspace.test.ts +35 -0
  93. package/templates/.agents/dashboard/apps/frontend/src/TraceabilityWorkspace.tsx +111 -12
  94. package/templates/.agents/dashboard/apps/frontend/src/app-preferences.ts +15 -0
  95. package/templates/.agents/dashboard/apps/frontend/src/app-session-token.ts +20 -0
  96. package/templates/.agents/dashboard/apps/frontend/src/cost-calculation-guide.css +267 -0
  97. package/templates/.agents/dashboard/apps/frontend/src/cost-calculation-guide.test.ts +69 -0
  98. package/templates/.agents/dashboard/apps/frontend/src/cost-period-refresh.test.ts +70 -0
  99. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.test.ts +111 -0
  100. package/templates/.agents/dashboard/apps/frontend/src/dashboard-api.ts +432 -13
  101. package/templates/.agents/dashboard/apps/frontend/src/dashboard-localization.ts +1 -1
  102. package/templates/.agents/dashboard/apps/frontend/src/main.tsx +1 -0
  103. package/templates/.agents/dashboard/apps/frontend/src/operations-detail-hydration.test.ts +55 -0
  104. package/templates/.agents/dashboard/apps/frontend/src/operations-detail-hydration.ts +36 -0
  105. package/templates/.agents/dashboard/apps/frontend/src/operations-entity-page-projection.test.ts +126 -0
  106. package/templates/.agents/dashboard/apps/frontend/src/operations-entity-page-projection.ts +181 -0
  107. package/templates/.agents/dashboard/apps/frontend/src/operations-period-contract.test.ts +138 -0
  108. package/templates/.agents/dashboard/apps/frontend/src/operations-period-render.test.ts +105 -0
  109. package/templates/.agents/dashboard/apps/frontend/src/operations-period.test.ts +6 -3
  110. package/templates/.agents/dashboard/apps/frontend/src/operations-period.ts +9 -5
  111. package/templates/.agents/dashboard/apps/frontend/src/overview-status-page.test.ts +24 -0
  112. package/templates/.agents/dashboard/apps/frontend/src/period-transition-overlay.css +44 -0
  113. package/templates/.agents/dashboard/apps/frontend/src/project-settings-model.ts +121 -62
  114. package/templates/.agents/dashboard/apps/frontend/src/project-settings-page.css +471 -2
  115. package/templates/.agents/dashboard/apps/frontend/src/project-settings.test.ts +84 -17
  116. package/templates/.agents/dashboard/apps/frontend/src/snapshot-banner-semantics.test.ts +44 -0
  117. package/templates/.agents/dashboard/apps/frontend/src/snapshot-coherence.test.ts +196 -39
  118. package/templates/.agents/dashboard/apps/frontend/src/snapshot-notice.ts +15 -0
  119. package/templates/.agents/dashboard/apps/frontend/src/sqlite-cost-adapters.ts +26 -0
  120. package/templates/.agents/dashboard/apps/frontend/src/styles.css +14 -2
  121. package/templates/.agents/dashboard/apps/frontend/src/traceability-workspace.css +38 -2
  122. package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.test.ts +187 -0
  123. package/templates/.agents/dashboard/apps/frontend/src/use-app-cost-loaders.ts +190 -0
  124. package/templates/.agents/dashboard/apps/frontend/src/use-app-effects.ts +121 -0
  125. package/templates/.agents/dashboard/apps/frontend/src/use-app-operations-pages.ts +398 -0
  126. package/templates/.agents/dashboard/apps/frontend/src/use-app-trace-documents.ts +141 -0
  127. package/templates/.agents/dashboard/apps/frontend/src/use-idle-cost-prefetch.ts +45 -0
  128. package/templates/.agents/dashboard/apps/frontend/src/work-list-pagination.test.ts +46 -0
  129. package/templates/.agents/dashboard/apps/frontend/src/work-list-pagination.ts +37 -0
  130. package/templates/.agents/dashboard/apps/frontend/vite.config.ts +55 -5
  131. package/templates/.agents/dashboard/modules/cost-monitor/package.json +1 -1
  132. package/templates/.agents/dashboard/modules/cost-monitor/src/contracts.ts +47 -6
  133. package/templates/.agents/dashboard/modules/cost-monitor/src/duration-estimate.ts +13 -0
  134. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CompactLifecycleCostTable.test.ts +64 -0
  135. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CompactLifecycleCostTable.tsx +275 -0
  136. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostCharts.test.ts +100 -15
  137. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostCharts.tsx +131 -40
  138. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostFilters.tsx +137 -19
  139. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostModelsAuditTable.test.ts +2 -0
  140. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostModelsAuditTable.tsx +13 -10
  141. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorContent.tsx +303 -0
  142. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.test.ts +226 -6
  143. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostMonitorPage.tsx +479 -402
  144. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostSummary.tsx +5 -13
  145. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.test.ts +312 -72
  146. package/templates/.agents/dashboard/modules/cost-monitor/src/react/CostTables.tsx +373 -321
  147. package/templates/.agents/dashboard/modules/cost-monitor/src/react/MacroCostTable.test.ts +17 -0
  148. package/templates/.agents/dashboard/modules/cost-monitor/src/react/MacroCostTable.tsx +25 -6
  149. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-copy.ts +0 -2
  150. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-page-helpers.ts +17 -0
  151. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-responsive.css +6 -3
  152. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-row-filters.ts +123 -0
  153. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-summary.ts +8 -3
  154. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor-views.ts +32 -0
  155. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-monitor.css +52 -14
  156. package/templates/.agents/dashboard/modules/cost-monitor/src/react/cost-table-presentation.ts +121 -0
  157. package/templates/.agents/dashboard/modules/cost-monitor/src/react/index.ts +3 -0
  158. package/templates/.agents/dashboard/modules/cost-monitor/src/react/period-cost-groups.test.ts +68 -0
  159. package/templates/.agents/dashboard/modules/cost-monitor/src/react/period-cost-groups.ts +32 -5
  160. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-compact-cost-page.ts +108 -0
  161. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-group-page.test.ts +12 -0
  162. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-group-page.ts +60 -0
  163. package/templates/.agents/dashboard/modules/cost-monitor/src/react/use-cost-run-page.ts +106 -0
  164. package/templates/.agents/dashboard/modules/cost-monitor/src/server/aggregate.test.ts +2 -2
  165. package/templates/.agents/dashboard/modules/cost-monitor/src/server/aggregate.ts +5 -3
  166. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-pricing-fallback.test.ts +53 -0
  167. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-projection.basics.test.ts +34 -0
  168. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-projection.test.ts +168 -137
  169. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-monitor-projection.ts +188 -29
  170. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-projection.test.ts +956 -0
  171. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-projection.ts +775 -0
  172. package/templates/.agents/dashboard/modules/cost-monitor/src/server/build-cost-summary-terminal-day.test.ts +95 -0
  173. package/templates/.agents/dashboard/modules/cost-monitor/src/server/index.ts +1 -0
  174. package/templates/.agents/dashboard/modules/cost-monitor/src/server/refactor-map-xr9l.json +61 -0
  175. package/templates/.agents/dashboard/modules/cost-monitor/src/task-cost-groups.test.ts +41 -0
  176. package/templates/.agents/dashboard/modules/cost-monitor/src/task-cost-groups.ts +55 -11
  177. package/templates/.agents/dashboard/modules/operations/package.json +2 -1
  178. package/templates/.agents/dashboard/modules/operations/src/contracts.ts +182 -0
  179. package/templates/.agents/dashboard/modules/operations/src/duration-population.test.ts +63 -1
  180. package/templates/.agents/dashboard/modules/operations/src/duration-population.ts +60 -5
  181. package/templates/.agents/dashboard/modules/operations/src/react/EntityDetailsDialog.tsx +14 -3
  182. package/templates/.agents/dashboard/modules/operations/src/react/EntityTables.test.ts +44 -1
  183. package/templates/.agents/dashboard/modules/operations/src/react/EntityTables.tsx +325 -18
  184. package/templates/.agents/dashboard/modules/operations/src/react/MacroPlanningDialog.tsx +1 -0
  185. package/templates/.agents/dashboard/modules/operations/src/react/OperationDateFilters.test.ts +9 -5
  186. package/templates/.agents/dashboard/modules/operations/src/react/OperationDateFilters.tsx +2 -2
  187. package/templates/.agents/dashboard/modules/operations/src/react/OperationsMainContent.tsx +168 -0
  188. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.helpers.tsx +95 -6
  189. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.test.ts +365 -14
  190. package/templates/.agents/dashboard/modules/operations/src/react/OperationsOverview.tsx +532 -131
  191. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPage.tsx +314 -358
  192. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPageNavigation.tsx +68 -0
  193. package/templates/.agents/dashboard/modules/operations/src/react/OperationsPageOverview.tsx +169 -0
  194. package/templates/.agents/dashboard/modules/operations/src/react/PeriodSummaryTable.tsx +51 -8
  195. package/templates/.agents/dashboard/modules/operations/src/react/PrdDocumentDialog.test.tsx +32 -0
  196. package/templates/.agents/dashboard/modules/operations/src/react/PrdDocumentDialog.tsx +62 -6
  197. package/templates/.agents/dashboard/modules/operations/src/react/TaskBoard.test.ts +55 -0
  198. package/templates/.agents/dashboard/modules/operations/src/react/TaskBoard.tsx +27 -19
  199. package/templates/.agents/dashboard/modules/operations/src/react/TaskDetailsDialog.tsx +99 -42
  200. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkBoard.priority.test.ts +19 -0
  201. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkBoard.tsx +255 -34
  202. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.test.ts +163 -8
  203. package/templates/.agents/dashboard/modules/operations/src/react/UnifiedWorkList.tsx +101 -68
  204. package/templates/.agents/dashboard/modules/operations/src/react/conversation-rows.test.ts +72 -1
  205. package/templates/.agents/dashboard/modules/operations/src/react/conversation-rows.ts +78 -16
  206. package/templates/.agents/dashboard/modules/operations/src/react/execution-metrics.ts +6 -4
  207. package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.test.ts +50 -1
  208. package/templates/.agents/dashboard/modules/operations/src/react/export/ExcelExportAction.tsx +143 -9
  209. package/templates/.agents/dashboard/modules/operations/src/react/export/export-layout.test.ts +29 -4
  210. package/templates/.agents/dashboard/modules/operations/src/react/macro-planning-dialog-content.css +49 -0
  211. package/templates/.agents/dashboard/modules/operations/src/react/macro-planning-dialog.css +93 -50
  212. package/templates/.agents/dashboard/modules/operations/src/react/manual-work-priority.test.ts +82 -0
  213. package/templates/.agents/dashboard/modules/operations/src/react/operation-date-range.test.ts +29 -2
  214. package/templates/.agents/dashboard/modules/operations/src/react/operation-date-range.ts +22 -1
  215. package/templates/.agents/dashboard/modules/operations/src/react/operation-duration.test.ts +77 -4
  216. package/templates/.agents/dashboard/modules/operations/src/react/operation-duration.ts +65 -5
  217. package/templates/.agents/dashboard/modules/operations/src/react/operations-coverage-toast.test.ts +54 -0
  218. package/templates/.agents/dashboard/modules/operations/src/react/operations-global-filters.test.ts +19 -0
  219. package/templates/.agents/dashboard/modules/operations/src/react/operations-overview-period-filter.test.ts +149 -12
  220. package/templates/.agents/dashboard/modules/operations/src/react/operations-overview.status-cards.test.ts +27 -0
  221. package/templates/.agents/dashboard/modules/operations/src/react/operations-page-contract.ts +136 -0
  222. package/templates/.agents/dashboard/modules/operations/src/react/operations-period-scope.test.ts +160 -0
  223. package/templates/.agents/dashboard/modules/operations/src/react/operations-period-scope.ts +47 -0
  224. package/templates/.agents/dashboard/modules/operations/src/react/operations-query.ts +10 -0
  225. package/templates/.agents/dashboard/modules/operations/src/react/operations-responsive.css +3 -0
  226. package/templates/.agents/dashboard/modules/operations/src/react/operations-view-labels.ts +28 -0
  227. package/templates/.agents/dashboard/modules/operations/src/react/operations-view-order.test.ts +24 -7
  228. package/templates/.agents/dashboard/modules/operations/src/react/operations.css +42 -0
  229. package/templates/.agents/dashboard/modules/operations/src/react/period-summary-population.test.ts +54 -0
  230. package/templates/.agents/dashboard/modules/operations/src/react/period-summary-population.ts +32 -0
  231. package/templates/.agents/dashboard/modules/operations/src/react/period-summary.test.ts +165 -6
  232. package/templates/.agents/dashboard/modules/operations/src/react/period-summary.ts +148 -6
  233. package/templates/.agents/dashboard/modules/operations/src/react/popup-localization.test.ts +1 -1
  234. package/templates/.agents/dashboard/modules/operations/src/react/unified-work-board.css +132 -0
  235. package/templates/.agents/dashboard/modules/operations/src/react/unified-work-board.css.test.ts +13 -0
  236. package/templates/.agents/dashboard/modules/operations/src/react/unified-work-board.header.test.ts +16 -0
  237. package/templates/.agents/dashboard/modules/operations/src/react/use-infinite-column.ts +11 -5
  238. package/templates/.agents/dashboard/modules/operations/src/react/work-board-model.test.ts +5 -3
  239. package/templates/.agents/dashboard/modules/operations/src/react/work-board-model.ts +4 -83
  240. package/templates/.agents/dashboard/modules/operations/src/server/build-operations-projection.test.ts +291 -15
  241. package/templates/.agents/dashboard/modules/operations/src/server/build-operations-projection.ts +182 -472
  242. package/templates/.agents/dashboard/modules/operations/src/server/canonical-compat.test.ts +40 -0
  243. package/templates/.agents/dashboard/modules/operations/src/server/canonical-compat.ts +19 -6
  244. package/templates/.agents/dashboard/modules/operations/src/server/canonical-run-projection.ts +31 -6
  245. package/templates/.agents/dashboard/modules/operations/src/server/daily-duration-projection.ts +220 -0
  246. package/templates/.agents/dashboard/modules/operations/src/server/execution-duration-projection.ts +28 -0
  247. package/templates/.agents/dashboard/modules/operations/src/server/execution-relationship-counts.test.ts +27 -2
  248. package/templates/.agents/dashboard/modules/operations/src/server/execution-relationship-counts.ts +22 -13
  249. package/templates/.agents/dashboard/modules/operations/src/server/filter.test.ts +3 -3
  250. package/templates/.agents/dashboard/modules/operations/src/server/filter.ts +7 -2
  251. package/templates/.agents/dashboard/modules/operations/src/server/index.ts +3 -0
  252. package/templates/.agents/dashboard/modules/operations/src/server/macro.ts +3 -12
  253. package/templates/.agents/dashboard/modules/operations/src/server/manifest-usage.ts +65 -0
  254. package/templates/.agents/dashboard/modules/operations/src/server/operations-projection-aggregates.ts +297 -0
  255. package/templates/.agents/dashboard/modules/operations/src/server/quick-daily-operations-projection.ts +324 -0
  256. package/templates/.agents/dashboard/modules/operations/src/server/quick-operations-projection.test.ts +505 -0
  257. package/templates/.agents/dashboard/modules/operations/src/server/quick-operations-projection.ts +609 -0
  258. package/templates/.agents/dashboard/modules/operations/src/server/runs.ts +18 -19
  259. package/templates/.agents/dashboard/modules/operations/src/work-board-model.ts +76 -0
  260. package/templates/.agents/dashboard/modules/traceability/package.json +1 -1
  261. package/templates/.agents/dashboard/modules/traceability/src/server/build-task-trace.ts +3 -1
  262. package/templates/.agents/dashboard/packages/branding/package.json +1 -1
  263. package/templates/.agents/dashboard/packages/branding/src/index.ts +1 -1
  264. package/templates/.agents/dashboard/packages/contracts/package.json +1 -1
  265. package/templates/.agents/dashboard/packages/contracts/src/index.ts +1 -0
  266. package/templates/.agents/dashboard/packages/data-export/package.json +1 -1
  267. package/templates/.agents/dashboard/packages/local-runtime/dist/server.cjs +1756 -0
  268. package/templates/.agents/dashboard/packages/local-runtime/dist/sqlite-read-model.cjs +1608 -0
  269. package/templates/.agents/dashboard/packages/local-runtime/package.json +8 -3
  270. package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-dashboard.mjs +12 -0
  271. package/templates/.agents/dashboard/packages/local-runtime/scripts/build-sqlite-runtime.mjs +83 -0
  272. package/templates/.agents/dashboard/packages/local-runtime/scripts/rebuild-sqlite-read-model.mjs +28 -0
  273. package/templates/.agents/dashboard/packages/local-runtime/scripts/test-sqlite-read-model.mjs +262 -0
  274. package/templates/.agents/dashboard/packages/local-runtime/scripts/test-unix-launchers.mjs +41 -0
  275. package/templates/.agents/dashboard/packages/local-runtime/scripts/validate-sqlite-read-model.mjs +105 -0
  276. package/templates/.agents/dashboard/packages/local-runtime/server.mjs +1643 -107
  277. package/templates/.agents/dashboard/packages/local-runtime/src/agent-adapter-sync.ts +30 -0
  278. package/templates/.agents/dashboard/packages/local-runtime/src/agent-catalog-settings.test.ts +3 -2
  279. package/templates/.agents/dashboard/packages/local-runtime/src/agent-catalog-settings.ts +5 -0
  280. package/templates/.agents/dashboard/packages/local-runtime/src/manifest-runs.ts +72 -33
  281. package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.test.ts +335 -4
  282. package/templates/.agents/dashboard/packages/local-runtime/src/project-settings.ts +392 -1
  283. package/templates/.agents/dashboard/packages/local-runtime/src/runtime.mjs +5 -5
  284. package/templates/.agents/dashboard/packages/local-runtime/src/server-board.test.ts +71 -0
  285. package/templates/.agents/dashboard/packages/local-runtime/src/server-board.ts +179 -0
  286. package/templates/.agents/dashboard/packages/local-runtime/src/server-cross-layer-parity.test.ts +245 -0
  287. package/templates/.agents/dashboard/packages/local-runtime/src/server-daily-read-models-route.ts +64 -0
  288. package/templates/.agents/dashboard/packages/local-runtime/src/server-daily-read-models.test.ts +204 -0
  289. package/templates/.agents/dashboard/packages/local-runtime/src/server-daily-read-models.ts +194 -0
  290. package/templates/.agents/dashboard/packages/local-runtime/src/server-operations-pages.test.ts +163 -0
  291. package/templates/.agents/dashboard/packages/local-runtime/src/server-operations-pages.ts +354 -0
  292. package/templates/.agents/dashboard/packages/local-runtime/src/server-operations-runs-route.test.ts +74 -0
  293. package/templates/.agents/dashboard/packages/local-runtime/src/server-operations-runs-route.ts +113 -0
  294. package/templates/.agents/dashboard/packages/local-runtime/src/server-overview.test.ts +68 -0
  295. package/templates/.agents/dashboard/packages/local-runtime/src/server-period.ts +47 -0
  296. package/templates/.agents/dashboard/packages/local-runtime/src/server-projections.ts +483 -0
  297. package/templates/.agents/dashboard/packages/local-runtime/src/server-settings.test.ts +5 -2
  298. package/templates/.agents/dashboard/packages/local-runtime/src/server-snapshot.test.ts +163 -84
  299. package/templates/.agents/dashboard/packages/local-runtime/src/server-workspace.ts +145 -0
  300. package/templates/.agents/dashboard/packages/local-runtime/src/server.test.ts +551 -266
  301. package/templates/.agents/dashboard/packages/local-runtime/src/server.ts +1145 -308
  302. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-metric-contract.test.ts +53 -0
  303. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-metric-contract.ts +708 -0
  304. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.test.ts +2232 -0
  305. package/templates/.agents/dashboard/packages/local-runtime/src/sqlite-read-model.ts +6151 -0
  306. package/templates/.agents/dashboard/packages/local-runtime/src/work-priority-contract.test.ts +33 -0
  307. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-history.mjs +41 -0
  308. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard-processes.mjs +210 -0
  309. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.mjs +437 -190
  310. package/templates/.agents/dashboard/packages/local-runtime/start-dashboard.test.mjs +299 -24
  311. package/templates/.agents/dashboard/packages/ui/package.json +1 -1
  312. package/templates/.agents/dashboard/packages/windows-launcher/LauncherVerificationBehaviorTests.cs +206 -0
  313. package/templates/.agents/dashboard/packages/windows-launcher/Program.cs +95 -8
  314. package/templates/.agents/dashboard/packages/windows-launcher/build-dashboard-launcher.ps1 +2 -2
  315. package/templates/.agents/dashboard/packages/windows-launcher/run-launcher-verification-tests.ps1 +22 -0
  316. package/templates/.agents/dashboard/read-model.dbml +2201 -0
  317. package/templates/.agents/dashboard/tests/e2e/package.json +1 -1
  318. package/templates/.agents/dashboard/tests/e2e/playwright.config.ts +1 -1
  319. package/templates/.agents/dashboard/tests/e2e/specs/dashboard.spec.ts +214 -41
  320. package/templates/.agents/dashboard/work-priority.json +34 -0
  321. package/templates/.agents/dashboard/zaip-dashboard-linux.sh +45 -0
  322. package/templates/.agents/dashboard/zaip-dashboard-mac.command +3 -0
  323. package/templates/.agents/dashboard/zaip-dashboard-windows.exe +0 -0
  324. package/templates/.agents/design/.zaip-managed.json +3 -3
  325. package/templates/.agents/design/apps/catalog/package.json +1 -1
  326. package/templates/.agents/design/packages/local-runtime/package.json +1 -1
  327. package/templates/.agents/requirements/autonomous-assurance.md +1 -1
  328. package/templates/.agents/requirements/comparative-audit.md +1 -1
  329. package/templates/.agents/requirements/context-engine.md +1 -1
  330. package/templates/.agents/requirements/cost-observability.md +1 -1
  331. package/templates/.agents/requirements/dashboard-launch.md +24 -0
  332. package/templates/.agents/requirements/data-export.md +1 -1
  333. package/templates/.agents/requirements/design-system.md +1 -1
  334. package/templates/.agents/requirements/execution-engine.md +1 -1
  335. package/templates/.agents/requirements/kanban-dashboard.md +4 -3
  336. package/templates/.agents/requirements/model-orchestration.md +1 -1
  337. package/templates/.agents/requirements/public-distribution.md +9 -6
  338. package/templates/.agents/requirements/software-architecture.md +1 -1
  339. package/templates/.agents/requirements/strategic-improvements.md +1 -1
  340. package/templates/.agents/requirements/work-lifecycle.md +9 -3
  341. package/templates/.agents/requirements/zaip-strategic-95.md +4 -4
  342. package/templates/.agents/rules/autonomy-decision.md +15 -0
  343. package/templates/.agents/rules/core.md +1 -1
  344. package/templates/.agents/rules/run-lifecycle-closure.md +1 -1
  345. package/templates/.agents/rules/specialist-routing.md +19 -0
  346. package/templates/.agents/rules/workflow.md +1 -1
  347. package/templates/.agents/runtime/VERSION +1 -1
  348. package/templates/.agents/runtime/bin/zaip.mjs +114 -64
  349. package/templates/.agents/runtime/checksums.sha256 +6 -4
  350. package/templates/.agents/runtime/manifest.json +3 -1
  351. package/templates/.agents/runtime/pnpm-lock.sha256 +1 -0
  352. package/templates/.agents/runtime/provenance.json +11 -0
  353. package/templates/.agents/runtime/sbom.cdx.json +1929 -39
  354. package/templates/.agents/skills/zaip-aios/SKILL.md +1 -1
  355. package/templates/.agents/skills/zaip-skill-brand-governance/SKILL.md +15 -0
  356. package/templates/.agents/skills/zaip-skill-brand-governance/agents/openai.yaml +4 -0
  357. package/templates/.agents/skills/zaip-skill-brand-governance/references/brandbook-standards.md +30 -0
  358. package/templates/.agents/skills/zaip-skill-dashboard-sqlite/SKILL.md +25 -0
  359. package/templates/.agents/skills/zaip-skill-dashboard-sqlite/agents/openai.yaml +4 -0
  360. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/SKILL.md +18 -0
  361. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/agents/openai.yaml +6 -0
  362. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/scripts/ready-queue-fence.mjs +71 -0
  363. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/scripts/ready-queue-fence.test.mjs +60 -0
  364. package/templates/.agents/skills/zaip-skill-executar-fila-pronta/scripts/scheduled-ready-queue-contract.test.mjs +111 -0
  365. package/templates/.agents/skills/zaip-skill-execution/SKILL.md +2 -2
  366. package/templates/.agents/skills/zaip-skill-frontend-launcher/references/launcher-contract.md +3 -1
  367. package/templates/.agents/skills/zaip-skill-general-operations/SKILL.md +12 -0
  368. package/templates/.agents/skills/zaip-skill-general-operations/agents/openai.yaml +4 -0
  369. package/templates/.agents/skills/zaip-skill-github-deploy/SKILL.md +9 -7
  370. package/templates/.agents/skills/zaip-skill-github-deploy/agents/openai.yaml +2 -2
  371. package/templates/.agents/skills/zaip-skill-github-deploy/scripts/github-deploy-contract.test.mjs +11 -38
  372. package/templates/.agents/skills/zaip-skill-governance-compliance/SKILL.md +12 -0
  373. package/templates/.agents/skills/zaip-skill-governance-compliance/agents/openai.yaml +4 -0
  374. package/templates/.agents/skills/zaip-skill-growth-strategy-revops/SKILL.md +15 -0
  375. package/templates/.agents/skills/zaip-skill-growth-strategy-revops/agents/openai.yaml +4 -0
  376. package/templates/.agents/skills/zaip-skill-growth-strategy-revops/references/growth-revops-framework.md +25 -0
  377. package/templates/.agents/skills/zaip-skill-instalar-agendamento/SKILL.md +17 -0
  378. package/templates/.agents/skills/zaip-skill-instalar-agendamento/agents/openai.yaml +6 -0
  379. package/templates/.agents/skills/zaip-skill-marketing/SKILL.md +3 -3
  380. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-local-telemetry.mjs +76 -27
  381. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.mjs +128 -24
  382. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-lib.test.mjs +122 -4
  383. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-remeasurement.mjs +66 -19
  384. package/templates/.agents/skills/zaip-skill-reconcile-telemetry/scripts/reconcile-telemetry-remeasurement.test.mjs +193 -7
  385. package/templates/.agents/skills/zaip-skill-sales-methodology/SKILL.md +14 -0
  386. package/templates/.agents/skills/zaip-skill-sales-methodology/agents/openai.yaml +4 -0
  387. package/templates/.agents/skills/zaip-skill-sales-methodology/references/sales-process-framework.md +77 -0
  388. package/templates/.agents/skills/zaip-skill-setup/SKILL.md +5 -0
  389. package/templates/.agents/skills/zaip-skill-sqlite-read-model/SKILL.md +96 -0
  390. package/templates/.agents/skills/zaip-skill-sqlite-read-model/agents/openai.yaml +4 -0
  391. package/templates/.agents/skills/zaip-skill-sqlite-read-model/scripts/ensure-node.mjs +18 -0
  392. package/templates/.agents/zaip-aios/INDEX.md +1 -0
  393. package/templates/.agents/zaip-aios/README.md +37 -8
  394. package/templates/.agents/zaip-aios/VERSION +1 -1
  395. package/templates/.agents/zaip-aios/guides/09-agentes-e-squads.md +43 -6
  396. package/templates/.agents/zaip-aios/guides/10-seguranca.md +21 -7
  397. package/templates/.agents/zaip-aios/guides/17-como-o-custo-e-calculado.md +32 -0
  398. package/templates/template-manifest.json +945 -214
  399. package/templates/.agents/dashboard/apps/frontend/dist/assets/AgentCatalogSettingsPage-CLYIi7Vo.js +0 -1
  400. package/templates/.agents/dashboard/apps/frontend/dist/assets/AgentCatalogSettingsPage-DTDNVQGX.css +0 -1
  401. package/templates/.agents/dashboard/apps/frontend/dist/assets/PricingSettingsDialog-CzEggcRb.js +0 -1
  402. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-05YKn6Z4.js +0 -3
  403. package/templates/.agents/dashboard/apps/frontend/dist/assets/ProjectSettingsPage-YO3yqtgV.css +0 -1
  404. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-8AzCnl3a.js +0 -77
  405. package/templates/.agents/dashboard/apps/frontend/dist/assets/index-DdBYQ_8D.css +0 -1
  406. package/templates/.agents/dashboard/apps/frontend/src/AgentCatalogSettingsPage.tsx +0 -617
  407. package/templates/.agents/dashboard/apps/frontend/src/agent-catalog-settings-page.css +0 -660
  408. package/templates/.agents/dashboard/apps/frontend/src/agent-catalog-settings.test.ts +0 -249
  409. package/templates/.agents/dashboard/dashboard.config.json +0 -4
  410. package/templates/.agents/dashboard/zaip-dashboard.exe +0 -0
@@ -6,16 +6,32 @@ import {
6
6
  } from "@zaip-ai/dashboard-ui";
7
7
  import type { CostGroupRow, CostRunRow, DurationCoverage } from "../contracts.js";
8
8
  import { MoreVerticalIcon } from "./CostTableIcons.js";
9
- import { durationContributors } from "./cost-duration.js";
10
9
  import type { CostCurrency, CostLocale } from "./cost-monitor-copy.js";
10
+ import type { CostGroupTotals } from "./use-cost-group-page.js";
11
11
  import {
12
12
  agentRunModelPresentation,
13
13
  formatApiSpeedScenario,
14
14
  localizedDescription,
15
15
  sumNumbers,
16
16
  } from "./cost-table-metrics.js";
17
+ import {
18
+ costGroupsScrollLabel,
19
+ costPeriodTotalAriaLabel,
20
+ costRunsDurationTotal,
21
+ costRunsScrollLabel,
22
+ formatBrlRate,
23
+ formatCostPeriodLabel,
24
+ formatDateTime,
25
+ formatMultiplierPair,
26
+ formatRate,
27
+ formatReasoningEffort,
28
+ formatServiceTier,
29
+ formatUsd,
30
+ isCompactRunColumnVisible,
31
+ } from "./cost-table-presentation.js";
17
32
 
18
33
  export { CostModelsAuditTable } from "./CostModelsAuditTable.js";
34
+
19
35
  export {
20
36
  agentRunModelPresentation,
21
37
  contextUpliftUsd,
@@ -26,22 +42,35 @@ export {
26
42
  scenario,
27
43
  sumNumbers,
28
44
  } from "./cost-table-metrics.js";
45
+ export {
46
+ costGroupsScrollLabel,
47
+ costPeriodTotalAriaLabel,
48
+ costRunsDurationTotal,
49
+ costRunsScrollLabel,
50
+ formatBrlRate,
51
+ formatCostPeriodLabel,
52
+ formatDateTime,
53
+ formatMultiplierPair,
54
+ formatRate,
55
+ formatReasoningEffort,
56
+ formatServiceTier,
57
+ formatUsd,
58
+ isCompactRunColumnVisible,
59
+ } from "./cost-table-presentation.js";
29
60
 
30
- const unavailableMetricLabels: Readonly<Record<CostLocale, string>> = {
31
- "pt-BR": "Indisponível",
32
- "en-US": "Unavailable",
33
- };
34
- function unavailableMetricLabel(locale: CostLocale): string {
35
- return unavailableMetricLabels[locale];
61
+ export function displayCostGroupLabel(label: string, locale: CostLocale): string {
62
+ const normalized = label.trim().toLowerCase();
63
+ return normalized.length === 0 || normalized === "unknown"
64
+ ? (locale === "pt-BR" ? "Sem modelo/provedor atribuído" : "No model/provider assigned")
65
+ : label;
36
66
  }
37
67
 
38
68
  export function formatAuditableNumber(value: number | null, locale: CostLocale): string {
39
- if (value === null) return unavailableMetricLabel(locale);
40
- return new Intl.NumberFormat(locale, { maximumFractionDigits: 0 }).format(value);
69
+ return new Intl.NumberFormat(locale, { maximumFractionDigits: 0 }).format(value ?? 0);
41
70
  }
42
71
 
43
72
  export function formatAuditableCompactNumber(value: number | null, locale: CostLocale): string {
44
- return value === null ? unavailableMetricLabel(locale) : formatCompactNumber(value, locale);
73
+ return formatCompactNumber(value ?? 0, locale);
45
74
  }
46
75
 
47
76
  export function formatAuditableCurrency(
@@ -49,16 +78,94 @@ export function formatAuditableCurrency(
49
78
  currency: CostCurrency,
50
79
  locale: CostLocale,
51
80
  ): string {
52
- return value === null ? unavailableMetricLabel(locale) : formatCurrency(value, currency, locale);
81
+ return formatCurrency(value ?? 0, currency, locale);
53
82
  }
54
83
 
55
84
  export function formatAuditableDuration(value: number | null, locale: CostLocale): string {
56
- return value === null ? unavailableMetricLabel(locale) : formatDurationMs(value, locale);
85
+ if (value === null) return locale === "pt-BR" ? "Indisponível" : "Unavailable";
86
+ return value === 0 ? "0" : formatDurationMs(value, locale);
87
+ }
88
+
89
+ const formatInvocationNumber = (value: number | null, locale: CostLocale) =>
90
+ formatAuditableNumber(value, locale);
91
+ const formatInvocationCurrency = (
92
+ value: number | null,
93
+ currency: CostCurrency,
94
+ locale: CostLocale,
95
+ ) => formatAuditableCurrency(value, currency, locale);
96
+ const formatInvocationDuration = (value: number | null, locale: CostLocale) =>
97
+ formatAuditableDuration(value, locale);
98
+ const formatInvocationRate = (value: number | null, locale: CostLocale) =>
99
+ formatRate(value, locale);
100
+ const formatInvocationUsd = (value: number | null, locale: CostLocale) =>
101
+ formatUsd(value, locale);
102
+ const formatInvocationBrlRate = (value: number | null, locale: CostLocale) =>
103
+ formatBrlRate(value, locale);
104
+ const formatInvocationMultiplierPair = (
105
+ input: number | null,
106
+ output: number | null,
107
+ locale: CostLocale,
108
+ ) => formatMultiplierPair(input, output, locale);
109
+
110
+ function invocationMetricDescription(locale: CostLocale, metric: string): string {
111
+ const source =
112
+ locale === "pt-BR"
113
+ ? "Valor da projeção SQLite/API desta Invocação de Agente. Fato canônico nulo permanece indisponível e não é convertido em zero."
114
+ : "Value from this Agent Invocation's SQLite/API projection. A null canonical fact remains unavailable and is not converted to zero.";
115
+ const details: Record<string, readonly [string, string]> = {
116
+ duration: ["Tempo factual da invocação, quando capturado ou reconciliado.", "Factual invocation duration, when captured or reconciled."],
117
+ inputTokens: ["Input total informado pela fonte; inclui a parcela de cache.", "Source-reported total input; includes the cached portion."],
118
+ cachedInputTokens: ["Parcela de cache já incluída no input total.", "Cached portion already included in total input."],
119
+ outputTokens: ["Output total informado pela fonte; inclui a parcela de raciocínio.", "Source-reported total output; includes the reasoning portion."],
120
+ reasoningTokens: ["Parcela de raciocínio já incluída no output total.", "Reasoning portion already included in total output."],
121
+ totalTokens: ["Soma de entrada e saída quando ambas são conhecidas; caso contrário, total informado pela fonte.", "Input plus output when both are known; otherwise the source-reported total."],
122
+ inputRate: ["Tarifa efetiva de entrada em USD por milhão de tokens.", "Effective input rate in USD per million tokens."],
123
+ cacheRate: ["Tarifa efetiva de entrada em cache em USD por milhão de tokens.", "Effective cached-input rate in USD per million tokens."],
124
+ outputRate: ["Tarifa efetiva de saída em USD por milhão de tokens.", "Effective output rate in USD per million tokens."],
125
+ reasoningRate: ["Tarifa efetiva de raciocínio em USD por milhão de tokens.", "Effective reasoning rate in USD per million tokens."],
126
+ contextMultiplier: ["Multiplicadores de contexto de entrada/saída aplicados aos segmentos internos.", "Input/output context multipliers applied to internal segments."],
127
+ inputCost: ["Custo USD de entrada calculado com tokens e tarifa efetiva.", "Input USD cost calculated from tokens and the effective rate."],
128
+ cacheCost: ["Custo USD da entrada em cache calculado com tokens e tarifa efetiva.", "Cached-input USD cost calculated from tokens and the effective rate."],
129
+ outputCost: ["Custo USD de saída calculado com tokens e tarifa efetiva.", "Output USD cost calculated from tokens and the effective rate."],
130
+ reasoningCost: ["Custo USD de raciocínio calculado com tokens e tarifa efetiva.", "Reasoning USD cost calculated from tokens and the effective rate."],
131
+ standardCost: ["Custo USD no cenário Standard, antes do acréscimo de velocidade.", "USD cost in the Standard scenario, before the speed uplift."],
132
+ speedUplift: ["Acréscimo USD do cenário Priority/Fast, já incluído no custo efetivo.", "USD uplift from the Priority/Fast scenario, already included in the effective cost."],
133
+ finalUsd: ["Custo final estimado da API em USD, somando os componentes de custo desta invocação.", "Estimated final API cost in USD, summing this invocation's cost components."],
134
+ fxRate: ["Câmbio BRL/USD atual aplicado para converter o custo final atual.", "Current BRL/USD exchange rate used to convert the current final cost."],
135
+ recordedFxRate: ["Câmbio BRL/USD registrado no período da atividade.", "BRL/USD exchange rate recorded for the activity period."],
136
+ recordedBrl: ["Custo final BRL registrado no período, preservado para auditoria histórica.", "Final BRL cost recorded in the period, retained for historical audit."],
137
+ cost: ["Custo final atual: USD estimado ou sua conversão BRL pelo câmbio atual selecionado.", "Current final cost: estimated USD or its BRL conversion at the selected current exchange rate."],
138
+ };
139
+ const detail = details[metric] ?? ["Métrica numérica desta invocação.", "Numeric metric for this invocation."];
140
+ return `${detail[locale === "pt-BR" ? 0 : 1]} ${source}`;
57
141
  }
58
142
 
59
143
  export function formatDurationCoverage(value: DurationCoverage, locale: CostLocale): string {
60
- if (value.complete || value.coverage_ratio > 0) return formatDurationMs(value.known_sum, locale);
61
- return unavailableMetricLabel(locale);
144
+ // `known_sum` is a factual elapsed-time observation even when another
145
+ // activity in the population is unavailable. Keep completeness and the
146
+ // unknown count as coverage metadata; hiding the known portion would turn a
147
+ // true observation into an indistinguishable absence.
148
+ if (value.known_sum <= 0 && !value.complete)
149
+ return locale === "pt-BR" ? "Indisponível" : "Unavailable";
150
+ return value.known_sum <= 0 ? "0" : formatDurationMs(value.known_sum, locale);
151
+ }
152
+
153
+ export function hasKnownDuration(value: DurationCoverage): boolean {
154
+ return value.known_sum > 0 || value.coverage_ratio > 0;
155
+ }
156
+
157
+ export function formatTokenBackedDuration(
158
+ value: DurationCoverage,
159
+ _totalTokens: number | null,
160
+ locale: CostLocale,
161
+ ): string {
162
+ // Token presence is a financial observation, not evidence of elapsed time.
163
+ return formatDurationCoverage(value, locale);
164
+ }
165
+
166
+ export function costRunsFooterLabel(locale: CostLocale, pageOnly: boolean): string {
167
+ if (!pageOnly) return locale === "pt-BR" ? "Total" : "Total";
168
+ return locale === "pt-BR" ? "Subtotal da página" : "Page subtotal";
62
169
  }
63
170
 
64
171
  /** Keeps table ordering tied to the raw monetary value, not its localized label. */
@@ -85,25 +192,38 @@ export function CostRunsTable({
85
192
  currency,
86
193
  locale,
87
194
  compact = false,
195
+ pagination,
88
196
  }: {
89
197
  rows: readonly CostRunRow[];
90
198
  onOpenRun: (runId: string) => void;
91
199
  currency: CostCurrency;
92
200
  locale: CostLocale;
93
201
  compact?: boolean;
202
+ pagination?: {
203
+ offset: number;
204
+ limit: number;
205
+ total: number | null;
206
+ has_more: boolean;
207
+ loading: boolean;
208
+ error: string | null;
209
+ onChange: (offset: number) => void;
210
+ onRetry: () => void;
211
+ };
94
212
  }) {
213
+ const footerLabel = costRunsFooterLabel(locale, pagination !== undefined);
95
214
  const total = (key: keyof CostRunRow) => sumNumbers(rows.map((row) => row[key]));
215
+ const totalTokens = sumNumbers(rows.map(inclusiveTokenTotal));
96
216
  const durationTotal = costRunsDurationTotal(rows);
97
217
  const show = (select: (row: CostRunRow) => number | string | null) =>
98
218
  !compact || isCompactRunColumnVisible(rows, select);
99
- return (
219
+ const table = (
100
220
  <DataTable
101
221
  columns={[
102
222
  {
103
223
  key: "startedAt",
104
224
  label: locale === "pt-BR" ? "Data e hora" : "Date and time",
105
225
  render: (row) => formatDateTime(row.started_at, locale),
106
- footer: locale === "pt-BR" ? "Total" : "Total",
226
+ footer: footerLabel,
107
227
  },
108
228
  {
109
229
  key: "run",
@@ -129,20 +249,12 @@ export function CostRunsTable({
129
249
  },
130
250
  {
131
251
  key: "duration",
132
- label: locale === "pt-BR" ? "Tempo de execução" : "Execution time",
133
- render: (row) =>
134
- row.duration_provenance === "legacy_inferred" ? (
135
- <>
136
- <span>{formatAuditableDuration(row.duration_ms, locale)}</span>
137
- <small>{locale === "pt-BR" ? "Tempo inferido" : "Inferred time"}</small>
138
- </>
139
- ) : (
140
- formatAuditableDuration(row.duration_ms, locale)
141
- ),
252
+ label: locale === "pt-BR" ? "Tempo" : "Time",
253
+ description: invocationMetricDescription(locale, "duration"),
254
+ render: (row) => formatInvocationDuration(row.duration_ms, locale),
142
255
  sortValue: (row) => row.duration_ms,
143
256
  align: "right",
144
- footer: formatAuditableDuration(durationTotal, locale),
145
- hidden: !show((row) => row.duration_ms),
257
+ footer: formatInvocationDuration(durationTotal, locale),
146
258
  },
147
259
  {
148
260
  key: "agent",
@@ -182,120 +294,93 @@ export function CostRunsTable({
182
294
  },
183
295
  {
184
296
  key: "inputTokens",
185
- label: locale === "pt-BR" ? "Tokens entrada" : "Input tokens",
186
- render: (row) => formatAuditableNumber(row.input_tokens, locale),
297
+ label: locale === "pt-BR" ? "Input total" : "Total input",
298
+ description: invocationMetricDescription(locale, "inputTokens"),
299
+ render: (row) => formatInvocationNumber(row.input_tokens, locale),
187
300
  sortValue: (row) => row.input_tokens,
188
301
  align: "right",
189
- footer: formatAuditableNumber(total("input_tokens"), locale),
190
- hidden: !show((row) => row.input_tokens),
302
+ footer: formatInvocationNumber(total("input_tokens"), locale),
191
303
  },
192
304
  {
193
305
  key: "cachedInputTokens",
194
306
  label: locale === "pt-BR" ? "Tokens cache" : "Cached tokens",
195
- render: (row) => formatAuditableNumber(row.cached_input_tokens, locale),
307
+ description: invocationMetricDescription(locale, "cachedInputTokens"),
308
+ render: (row) => formatInvocationNumber(row.cached_input_tokens, locale),
196
309
  sortValue: (row) => row.cached_input_tokens,
197
310
  align: "right",
198
- footer: formatAuditableNumber(total("cached_input_tokens"), locale),
199
- hidden: !show((row) => row.cached_input_tokens),
200
- },
201
- {
202
- key: "uncachedInputTokens",
203
- label: locale === "pt-BR" ? "Entrada sem cache" : "Uncached input",
204
- render: (row) => formatAuditableNumber(row.uncached_input_tokens, locale),
205
- sortValue: (row) => row.uncached_input_tokens,
206
- align: "right",
207
- footer: formatAuditableNumber(total("uncached_input_tokens"), locale),
208
- hidden: !show((row) => row.uncached_input_tokens),
311
+ footer: formatInvocationNumber(total("cached_input_tokens"), locale),
209
312
  },
210
313
  {
211
314
  key: "outputTokens",
212
- label: locale === "pt-BR" ? "Tokens saída" : "Output tokens",
213
- render: (row) => formatAuditableNumber(row.output_tokens, locale),
315
+ label: locale === "pt-BR" ? "Output total" : "Total output",
316
+ description: invocationMetricDescription(locale, "outputTokens"),
317
+ render: (row) => formatInvocationNumber(row.output_tokens, locale),
214
318
  sortValue: (row) => row.output_tokens,
215
319
  align: "right",
216
- footer: formatAuditableNumber(total("output_tokens"), locale),
217
- hidden: !show((row) => row.output_tokens),
320
+ footer: formatInvocationNumber(total("output_tokens"), locale),
218
321
  },
219
322
  {
220
323
  key: "reasoningTokens",
221
324
  label: locale === "pt-BR" ? "Tokens raciocínio" : "Reasoning tokens",
222
- render: (row) => formatAuditableNumber(row.reasoning_tokens, locale),
325
+ description: invocationMetricDescription(locale, "reasoningTokens"),
326
+ render: (row) => formatInvocationNumber(row.reasoning_tokens, locale),
223
327
  sortValue: (row) => row.reasoning_tokens,
224
328
  align: "right",
225
- footer: formatAuditableNumber(total("reasoning_tokens"), locale),
226
- hidden: !show((row) => row.reasoning_tokens),
227
- },
228
- {
229
- key: "visibleOutputTokens",
230
- label: locale === "pt-BR" ? "Saída visível" : "Visible output",
231
- render: (row) => formatAuditableNumber(row.visible_output_tokens, locale),
232
- sortValue: (row) => row.visible_output_tokens,
233
- align: "right",
234
- footer: formatAuditableNumber(total("visible_output_tokens"), locale),
235
- hidden: !show((row) => row.visible_output_tokens),
329
+ footer: formatInvocationNumber(total("reasoning_tokens"), locale),
236
330
  },
237
331
  {
238
332
  key: "totalTokens",
239
333
  label: locale === "pt-BR" ? "Total tokens" : "Total tokens",
334
+ description: invocationMetricDescription(locale, "totalTokens"),
240
335
  render: (row) =>
241
- formatAuditableNumber(
242
- row.input_tokens !== null && row.output_tokens !== null
243
- ? row.input_tokens + row.output_tokens
244
- : row.total_tokens,
336
+ formatInvocationNumber(
337
+ inclusiveTokenTotal(row),
245
338
  locale,
246
339
  ),
247
340
  sortValue: (row) =>
248
- row.input_tokens !== null && row.output_tokens !== null
249
- ? row.input_tokens + row.output_tokens
250
- : row.total_tokens,
341
+ inclusiveTokenTotal(row),
251
342
  align: "right",
252
- footer: formatAuditableNumber(total("total_tokens"), locale),
253
- hidden: !show((row) => row.total_tokens),
343
+ footer: formatInvocationNumber(totalTokens, locale),
254
344
  },
255
345
  {
256
346
  key: "inputRate",
257
347
  label: "USD/M entrada",
258
- render: (row) => formatRate(row.input_rate_usd_per_million, locale),
348
+ description: invocationMetricDescription(locale, "inputRate"),
349
+ render: (row) => formatInvocationRate(row.input_rate_usd_per_million, locale),
259
350
  align: "right",
260
- hidden: !show((row) => row.input_rate_usd_per_million),
261
351
  },
262
352
  {
263
353
  key: "cacheRate",
264
354
  label: "USD/M cache",
265
- render: (row) => formatRate(row.cached_input_rate_usd_per_million, locale),
355
+ description: invocationMetricDescription(locale, "cacheRate"),
356
+ render: (row) => formatInvocationRate(row.cached_input_rate_usd_per_million, locale),
266
357
  align: "right",
267
- hidden: !show((row) => row.cached_input_rate_usd_per_million),
268
358
  },
269
359
  {
270
360
  key: "outputRate",
271
361
  label: "USD/M saída",
272
- render: (row) => formatRate(row.output_rate_usd_per_million, locale),
362
+ description: invocationMetricDescription(locale, "outputRate"),
363
+ render: (row) => formatInvocationRate(row.output_rate_usd_per_million, locale),
273
364
  align: "right",
274
- hidden: !show((row) => row.output_rate_usd_per_million),
275
365
  },
276
366
  {
277
367
  key: "reasoningRate",
278
368
  label: "USD/M raciocínio",
279
- render: (row) => formatRate(row.reasoning_rate_usd_per_million, locale),
369
+ description: invocationMetricDescription(locale, "reasoningRate"),
370
+ render: (row) => formatInvocationRate(row.reasoning_rate_usd_per_million, locale),
280
371
  align: "right",
281
- hidden: !show((row) => row.reasoning_rate_usd_per_million),
282
372
  },
283
373
  {
284
374
  key: "contextMultiplier",
285
375
  label: "Mult. contexto E/S",
286
- description: localizedDescription(
287
- locale,
288
- "Multiplicadores aplicados aos segmentos de uso desta Invocação de Agente quando o limite de contexto do modelo é ultrapassado. O total da invocação agrega os segmentos sem expor cada Chamada LLM.",
289
- "Multipliers applied to this Agent Invocation's usage segments when the model context limit is exceeded. The invocation total aggregates segments without exposing each LLM Call.",
290
- ),
376
+ description: invocationMetricDescription(locale, "contextMultiplier"),
291
377
  render: (row) =>
292
- formatMultiplierPair(
378
+ formatInvocationMultiplierPair(
293
379
  row.context_input_multiplier,
294
380
  row.context_output_multiplier,
295
381
  locale,
296
382
  ),
297
383
  align: "right",
298
- hidden: !show((row) => row.context_input_multiplier),
299
384
  },
300
385
  {
301
386
  key: "speedMultiplier",
@@ -312,101 +397,96 @@ export function CostRunsTable({
312
397
  {
313
398
  key: "inputCost",
314
399
  label: "USD entrada",
315
- render: (row) => formatUsd(row.input_cost_usd, locale),
400
+ description: invocationMetricDescription(locale, "inputCost"),
401
+ render: (row) => formatInvocationUsd(row.input_cost_usd, locale),
316
402
  align: "right",
317
- footer: formatUsd(total("input_cost_usd"), locale),
318
- hidden: !show((row) => row.input_cost_usd),
403
+ footer: formatInvocationUsd(total("input_cost_usd"), locale),
319
404
  },
320
405
  {
321
406
  key: "cacheCost",
322
407
  label: "USD cache",
323
- render: (row) => formatUsd(row.cached_input_cost_usd, locale),
408
+ description: invocationMetricDescription(locale, "cacheCost"),
409
+ render: (row) => formatInvocationUsd(row.cached_input_cost_usd, locale),
324
410
  align: "right",
325
- footer: formatUsd(total("cached_input_cost_usd"), locale),
326
- hidden: !show((row) => row.cached_input_cost_usd),
411
+ footer: formatInvocationUsd(total("cached_input_cost_usd"), locale),
327
412
  },
328
413
  {
329
414
  key: "outputCost",
330
415
  label: "USD saída",
331
- render: (row) => formatUsd(row.output_cost_usd, locale),
416
+ description: invocationMetricDescription(locale, "outputCost"),
417
+ render: (row) => formatInvocationUsd(row.output_cost_usd, locale),
332
418
  align: "right",
333
- footer: formatUsd(total("output_cost_usd"), locale),
334
- hidden: !show((row) => row.output_cost_usd),
419
+ footer: formatInvocationUsd(total("output_cost_usd"), locale),
335
420
  },
336
421
  {
337
422
  key: "reasoningCost",
338
423
  label: "USD raciocínio",
339
- render: (row) => formatUsd(row.reasoning_cost_usd, locale),
424
+ description: invocationMetricDescription(locale, "reasoningCost"),
425
+ render: (row) => formatInvocationUsd(row.reasoning_cost_usd, locale),
340
426
  align: "right",
341
- footer: formatUsd(total("reasoning_cost_usd"), locale),
342
- hidden: !show((row) => row.reasoning_cost_usd),
427
+ footer: formatInvocationUsd(total("reasoning_cost_usd"), locale),
343
428
  },
344
429
  {
345
430
  key: "standardCost",
346
431
  label: "USD padrão",
347
- render: (row) => formatUsd(row.standard_cost_usd, locale),
432
+ description: invocationMetricDescription(locale, "standardCost"),
433
+ render: (row) => formatInvocationUsd(row.standard_cost_usd, locale),
348
434
  align: "right",
349
- footer: formatUsd(total("standard_cost_usd"), locale),
350
- hidden: !show((row) => row.standard_cost_usd),
435
+ footer: formatInvocationUsd(total("standard_cost_usd"), locale),
351
436
  },
352
437
  {
353
438
  key: "speedUplift",
354
439
  label: "USD acréscimo rápido",
355
- description: localizedDescription(
356
- locale,
357
- "Parcela adicional causada pela velocidade Priority/Fast. Este valor já está incluído no custo efetivo e no total; é exibido separadamente apenas para auditoria.",
358
- "Additional amount caused by Priority/Fast speed. This value is already included in the effective cost and total; it is shown separately for auditing only.",
359
- ),
360
- render: (row) => formatUsd(row.speed_uplift_usd, locale),
440
+ description: invocationMetricDescription(locale, "speedUplift"),
441
+ render: (row) => formatInvocationUsd(row.speed_uplift_usd, locale),
361
442
  align: "right",
362
- footer: formatUsd(total("speed_uplift_usd"), locale),
363
- hidden: !show((row) => row.speed_uplift_usd),
443
+ footer: formatInvocationUsd(total("speed_uplift_usd"), locale),
364
444
  },
365
445
  {
366
446
  key: "finalUsd",
367
447
  label: locale === "pt-BR" ? "USD estimado API" : "Estimated API USD",
368
- render: (row) => formatUsd(row.estimated_usd, locale),
448
+ description: invocationMetricDescription(locale, "finalUsd"),
449
+ render: (row) => formatInvocationUsd(row.estimated_usd, locale),
369
450
  align: "right",
370
- footer: formatUsd(total("estimated_usd"), locale),
371
- hidden: !show((row) => row.estimated_usd),
451
+ footer: formatInvocationUsd(total("estimated_usd"), locale),
372
452
  },
373
453
  {
374
454
  key: "fxRate",
375
455
  label: locale === "pt-BR" ? "Cotação atual" : "Current exchange rate",
376
- render: (row) => formatBrlRate(row.fx_rate, locale),
456
+ description: invocationMetricDescription(locale, "fxRate"),
457
+ render: (row) => formatInvocationBrlRate(row.fx_rate, locale),
377
458
  align: "right",
378
- hidden: !show((row) => row.fx_rate),
379
459
  },
380
460
  {
381
461
  key: "recordedFxRate",
382
462
  label: locale === "pt-BR" ? "Cotação no período" : "Period exchange rate",
383
- render: (row) => formatBrlRate(row.recorded_fx_rate, locale),
463
+ description: invocationMetricDescription(locale, "recordedFxRate"),
464
+ render: (row) => formatInvocationBrlRate(row.recorded_fx_rate, locale),
384
465
  align: "right",
385
- hidden: !show((row) => row.recorded_fx_rate),
386
466
  },
387
467
  {
388
468
  key: "recordedBrl",
389
469
  label: locale === "pt-BR" ? "Custo Final no Período" : "Period final cost",
390
- render: (row) => formatAuditableCurrency(row.recorded_brl, "BRL", locale),
470
+ description: invocationMetricDescription(locale, "recordedBrl"),
471
+ render: (row) => formatInvocationCurrency(row.recorded_brl, "BRL", locale),
391
472
  align: "right",
392
- footer: formatAuditableCurrency(total("recorded_brl"), "BRL", locale),
393
- hidden: !show((row) => row.recorded_brl),
473
+ footer: formatInvocationCurrency(total("recorded_brl"), "BRL", locale),
394
474
  },
395
475
  {
396
476
  key: "cost",
397
477
  label: locale === "pt-BR" ? "Custo Final atual" : "Current final cost",
478
+ description: invocationMetricDescription(locale, "cost"),
398
479
  render: (row) => {
399
480
  const value = currency === "BRL" ? row.estimated_brl : row.estimated_usd;
400
- return formatAuditableCurrency(value, currency, locale);
481
+ return formatInvocationCurrency(value, currency, locale);
401
482
  },
402
483
  sortValue: (row) => sortCostValue(currency, row.estimated_brl, row.estimated_usd),
403
484
  align: "right",
404
- footer: formatAuditableCurrency(
485
+ footer: formatInvocationCurrency(
405
486
  total(currency === "BRL" ? "estimated_brl" : "estimated_usd"),
406
487
  currency,
407
488
  locale,
408
489
  ),
409
- hidden: !show((row) => (currency === "BRL" ? row.estimated_brl : row.estimated_usd)),
410
490
  },
411
491
  {
412
492
  key: "trace",
@@ -427,7 +507,7 @@ export function CostRunsTable({
427
507
  },
428
508
  ]}
429
509
  locale={locale}
430
- pageSize={100}
510
+ pageSize={pagination ? null : 100}
431
511
  rowKey={(row) => row.run_id}
432
512
  onRowClick={(row) => onOpenRun(row.run_id)}
433
513
  rows={rows}
@@ -436,156 +516,86 @@ export function CostRunsTable({
436
516
  sortable
437
517
  />
438
518
  );
519
+ return pagination ? (
520
+ <>
521
+ {table}
522
+ <CostRunServerPagination locale={locale} pagination={pagination} />
523
+ </>
524
+ ) : (
525
+ table
526
+ );
439
527
  }
440
528
 
441
- export function costRunsDurationTotal(rows: readonly CostRunRow[]): number | null {
442
- return sumNumbers(durationContributors(rows).map((row) => row.duration_ms));
443
- }
444
-
445
- export function isCompactRunColumnVisible(
446
- rows: readonly CostRunRow[],
447
- select: (row: CostRunRow) => number | string | null,
448
- ): boolean {
449
- return rows.some((row) => {
450
- const value = select(row);
451
- return value !== null && value !== 0 && value !== "";
452
- });
453
- }
454
-
455
- export function formatRate(value: number | null, locale: CostLocale): string {
456
- if (value === null) return unavailableMetricLabel(locale);
457
- return new Intl.NumberFormat(locale, {
458
- minimumFractionDigits: 2,
459
- maximumFractionDigits: 2,
460
- }).format(value);
461
- }
462
-
463
- export function formatBrlRate(value: number | null, locale: CostLocale): string {
464
- if (value === null) return unavailableMetricLabel(locale);
465
- return `R$ ${new Intl.NumberFormat(locale, {
466
- minimumFractionDigits: 2,
467
- maximumFractionDigits: 2,
468
- }).format(value)}`;
469
- }
470
-
471
- export function formatUsd(value: number | null, locale: CostLocale): string {
472
- if (value === null) return unavailableMetricLabel(locale);
473
- return new Intl.NumberFormat(locale, {
474
- style: "currency",
475
- currency: "USD",
476
- minimumFractionDigits: 2,
477
- maximumFractionDigits: 2,
478
- }).format(value);
479
- }
480
-
481
- function formatMultiplier(value: number | null, locale: CostLocale): string {
482
- return value === null
483
- ? unavailableMetricLabel(locale)
484
- : `${value.toLocaleString("en-US", { maximumFractionDigits: 3 })}×`;
485
- }
486
-
487
- export function formatMultiplierPair(
488
- input: number | null,
489
- output: number | null,
490
- locale: CostLocale,
491
- ): string {
492
- if (input === null || output === null) return unavailableMetricLabel(locale);
493
- return `${formatMultiplier(input, locale)} / ${formatMultiplier(output, locale)}`;
494
- }
495
-
496
- function formatRuntimeDetail(
497
- value: string | null,
498
- kind: "effort" | "speed",
499
- locale: CostLocale,
500
- ): string {
501
- if (value === null || value.trim() === "" || value.trim().toLowerCase() === "unknown") return "-";
502
- if (locale !== "pt-BR") return value;
503
- const labels: Record<string, string> = {
504
- low: "Leve",
505
- medium: "Médio",
506
- high: "Alto",
507
- xhigh: "Extra alto",
508
- max: "Ultra",
509
- default: kind === "speed" ? "Padrão" : "Padrão",
510
- priority: "Rápido",
511
- };
512
- return labels[value] ?? value;
513
- }
514
-
515
- export function formatReasoningEffort(
516
- effective: string | null,
517
- requested: string | null,
518
- locale: CostLocale,
519
- ): string {
520
- const effectiveValue = normalizedRuntimeValue(effective);
521
- if (effectiveValue !== null) return formatRuntimeDetail(effectiveValue, "effort", locale);
522
- const requestedValue = normalizedRuntimeValue(requested);
523
- if (requestedValue === null) return "-";
524
- const formatted = formatRuntimeDetail(requestedValue, "effort", locale);
525
- return locale === "pt-BR"
526
- ? `${formatted} (solicitado; efetivo -)`
527
- : `${formatted} (requested; effective -)`;
528
- }
529
-
530
- export function formatServiceTier(value: string | null, locale: CostLocale): string {
531
- const normalized = normalizedRuntimeValue(value);
532
- if (normalized === null) return locale === "pt-BR" ? "Padrão" : "Standard";
533
- return formatRuntimeDetail(normalized, "speed", locale);
534
- }
535
-
536
- function normalizedRuntimeValue(value: string | null): string | null {
537
- const normalized = value?.trim() ?? "";
538
- return normalized === "" || normalized.toLowerCase() === "unknown" ? null : normalized;
539
- }
540
-
541
- export function costRunsScrollLabel(locale: CostLocale): string {
542
- return locale === "pt-BR"
543
- ? "Tabela de custos por invocação com rolagem horizontal"
544
- : "Agent invocation costs table with horizontal scrolling";
545
- }
546
-
547
- export function costGroupsScrollLabel(locale: CostLocale): string {
548
- return locale === "pt-BR"
549
- ? "Tabela de custos agrupados com rolagem horizontal"
550
- : "Grouped costs table with horizontal scrolling";
551
- }
552
-
553
- export function formatDateTime(value: string, locale: CostLocale): string {
554
- if (!value || Number.isNaN(Date.parse(value))) return "—";
555
- return new Intl.DateTimeFormat(locale, {
556
- dateStyle: "short",
557
- timeStyle: "medium",
558
- }).format(new Date(value));
559
- }
560
-
561
- export function formatCostPeriodLabel(
562
- value: string,
563
- period: "daily" | "monthly" | "annual",
564
- locale: CostLocale,
565
- ): string {
566
- if (period === "annual") return value.slice(0, 4);
567
- if (period === "monthly") return value.slice(0, 7);
568
- const date = new Date(`${value}T12:00:00.000Z`);
569
- if (Number.isNaN(date.getTime())) return value;
570
- return new Intl.DateTimeFormat(locale, { dateStyle: "short", timeZone: "UTC" }).format(date);
529
+ function inclusiveTokenTotal(
530
+ row: Pick<CostRunRow, "input_tokens" | "output_tokens" | "total_tokens">,
531
+ ): number | null {
532
+ return row.input_tokens !== null && row.output_tokens !== null
533
+ ? row.input_tokens + row.output_tokens
534
+ : row.total_tokens;
571
535
  }
572
536
 
573
- export function costPeriodTotalAriaLabel({
537
+ function CostRunServerPagination({
574
538
  locale,
575
- duration,
576
- tokens,
577
- cost,
578
- currency,
539
+ pagination,
579
540
  }: {
580
541
  locale: CostLocale;
581
- duration: string;
582
- tokens: string;
583
- cost: string;
584
- currency: CostCurrency;
585
- }): string {
586
- return locale === "pt-BR"
587
- ? `Total geral — Tempo: ${duration}; Tokens: ${tokens}; ${currency}: ${cost}`
588
- : `Grand total — Time: ${duration}; Tokens: ${tokens}; Cost (${currency}): ${cost}`;
542
+ pagination: NonNullable<Parameters<typeof CostRunsTable>[0]["pagination"]>;
543
+ }) {
544
+ const first = pagination.total === 0 ? 0 : pagination.offset + 1;
545
+ const last =
546
+ pagination.total === null
547
+ ? pagination.offset + pagination.limit
548
+ : Math.min(pagination.offset + pagination.limit, pagination.total);
549
+ const previous = Math.max(0, pagination.offset - pagination.limit);
550
+ const next = pagination.offset + pagination.limit;
551
+ return (
552
+ <nav
553
+ aria-label={locale === "pt-BR" ? "Paginação das invocações" : "Invocation pagination"}
554
+ className="ui-table-pagination"
555
+ >
556
+ <button
557
+ disabled={pagination.loading || pagination.offset === 0}
558
+ onClick={() => pagination.onChange(previous)}
559
+ type="button"
560
+ >
561
+ {locale === "pt-BR" ? "Anterior" : "Previous"}
562
+ </button>
563
+ <span aria-live="polite">
564
+ {pagination.loading
565
+ ? locale === "pt-BR"
566
+ ? "Carregando invocações…"
567
+ : "Loading invocations…"
568
+ : pagination.total === null
569
+ ? `${first}–${last}${pagination.has_more ? "+" : ""}`
570
+ : `${first}–${last} ${locale === "pt-BR" ? "de" : "of"} ${pagination.total}`}
571
+ </span>
572
+ <button
573
+ disabled={
574
+ pagination.loading ||
575
+ (!pagination.has_more && (pagination.total === null || next >= pagination.total))
576
+ }
577
+ onClick={() => pagination.onChange(next)}
578
+ type="button"
579
+ >
580
+ {locale === "pt-BR" ? "Próxima" : "Next"}
581
+ </button>
582
+ {pagination.error ? (
583
+ <span role="status">
584
+ {pagination.error}{" "}
585
+ <button onClick={pagination.onRetry} type="button">
586
+ {locale === "pt-BR" ? "Tentar novamente" : "Retry"}
587
+ </button>
588
+ </span>
589
+ ) : null}
590
+ </nav>
591
+ );
592
+ }
593
+
594
+ function costPeriodHeading(period: "daily" | "monthly" | "annual", locale: CostLocale): string {
595
+ if (locale === "en-US") {
596
+ return period === "daily" ? "Day" : period === "monthly" ? "Month" : "Year";
597
+ }
598
+ return period === "daily" ? "Dia" : period === "monthly" ? "Mês" : "Ano";
589
599
  }
590
600
 
591
601
  export function CostGroupsTable({
@@ -595,8 +605,11 @@ export function CostGroupsTable({
595
605
  onOpenTrace,
596
606
  period,
597
607
  showDateTime = true,
608
+ showAgentIdentity = false,
609
+ showInvocationTasks = false,
598
610
  dateHeading,
599
611
  labelHeading,
612
+ totals: suppliedTotals,
600
613
  }: {
601
614
  rows: readonly CostGroupRow[];
602
615
  currency: CostCurrency;
@@ -604,19 +617,15 @@ export function CostGroupsTable({
604
617
  onOpenTrace?: (taskId: string) => void;
605
618
  period?: "daily" | "monthly" | "annual";
606
619
  showDateTime?: boolean;
620
+ showAgentIdentity?: boolean;
621
+ showInvocationTasks?: boolean;
607
622
  dateHeading?: string;
608
623
  labelHeading?: string;
624
+ totals?: CostGroupTotals;
609
625
  }) {
610
- const totals = {
626
+ const pageTotals = {
611
627
  runs: rows.reduce((sum, row) => sum + row.run_count, 0),
612
- tasks: rows.reduce(
613
- (sum, row) =>
614
- sum +
615
- (period === undefined
616
- ? row.task_count
617
- : (row.taskDaysActive ?? row.tasksActive ?? row.task_count)),
618
- 0,
619
- ),
628
+ tasks: rows.reduce((sum, row) => sum + (row.task_count ?? 0), 0),
620
629
  prds: rows.reduce((sum, row) => sum + row.prd_count, 0),
621
630
  specs: rows.reduce((sum, row) => sum + row.spec_count, 0),
622
631
  evidences: rows.reduce((sum, row) => sum + row.evidence_count, 0),
@@ -627,11 +636,30 @@ export function CostGroupsTable({
627
636
  usd: sumNumbers(rows.map((row) => row.estimated_usd)),
628
637
  brl: sumNumbers(rows.map((row) => row.estimated_brl)),
629
638
  };
630
- const totalDurationDisplay = !totals.durationPartial
631
- ? formatAuditableDuration(totals.durationKnownMs, locale)
632
- : totals.durationKnownMs === 0
633
- ? unavailableMetricLabel(locale)
634
- : formatDurationMs(totals.durationKnownMs, locale);
639
+ const totals = suppliedTotals === undefined ? pageTotals : {
640
+ runs: suppliedTotals.run_count,
641
+ tasks: suppliedTotals.task_count ?? 0,
642
+ prds: suppliedTotals.prd_count,
643
+ specs: suppliedTotals.spec_count,
644
+ evidences: suppliedTotals.evidence_count,
645
+ tests: suppliedTotals.test_count,
646
+ durationKnownMs: suppliedTotals.duration.known_sum,
647
+ durationPartial: !suppliedTotals.duration.complete,
648
+ tokens: suppliedTotals.total_tokens,
649
+ usd: suppliedTotals.estimated_usd,
650
+ brl: suppliedTotals.estimated_brl,
651
+ };
652
+ const totalDurationDisplay = formatDurationCoverage(
653
+ suppliedTotals?.duration ?? {
654
+ known_sum: totals.durationKnownMs,
655
+ unknown: totals.durationPartial ? 1 : 0,
656
+ complete: !totals.durationPartial,
657
+ // Group-level coverage is intentionally preserved separately from the
658
+ // factual known sum. Individual rows retain their original provenance.
659
+ coverage_ratio: totals.durationPartial ? 0 : 1,
660
+ },
661
+ locale,
662
+ );
635
663
  const totalTokensDisplay = formatAuditableCompactNumber(totals.tokens, locale);
636
664
  const totalCostDisplay = formatAuditableCurrency(
637
665
  currency === "BRL" ? totals.brl : totals.usd,
@@ -656,52 +684,55 @@ export function CostGroupsTable({
656
684
  hidden: !showDateTime,
657
685
  footer: showDateTime ? <output aria-label={totalLabel}>Total</output> : undefined,
658
686
  },
687
+ ...(showAgentIdentity
688
+ ? [
689
+ { key: "persona", label: locale === "pt-BR" ? "Persona" : "Persona", render: (row: CostGroupRow) => row.persona ?? "" },
690
+ { key: "job", label: locale === "pt-BR" ? "Cargo" : "Job", render: (row: CostGroupRow) => row.job ?? "" },
691
+ ]
692
+ : []),
659
693
  {
660
694
  key: "label",
661
695
  label:
662
696
  period === undefined
663
697
  ? (labelHeading ?? (locale === "pt-BR" ? "Grupo" : "Group"))
664
- : locale === "pt-BR"
665
- ? "Período"
666
- : "Period",
667
- render: (row) =>
668
- period === undefined ? (
698
+ : costPeriodHeading(period, locale),
699
+ render: (row) => {
700
+ if (period !== undefined) {
701
+ return <strong>{formatCostPeriodLabel(row.key, period, locale)}</strong>;
702
+ }
703
+ const displayLabel = displayCostGroupLabel(row.label, locale);
704
+ const unavailableLabel = displayLabel !== row.label;
705
+ return (
669
706
  <>
670
- <strong>{row.label}</strong>
671
- {row.key === row.label ? null : <small>{row.key}</small>}
707
+ <strong>{displayLabel}</strong>
708
+ {unavailableLabel || row.key === row.label ? null : <small>{row.key}</small>}
672
709
  </>
673
- ) : (
674
- <strong>{formatCostPeriodLabel(row.key, period, locale)}</strong>
675
- ),
710
+ );
711
+ },
676
712
  sortValue: (row) => row.key,
677
713
  footer: showDateTime ? undefined : <output aria-label={totalLabel}>Total</output>,
678
714
  },
679
- {
680
- key: "runs",
681
- label: locale === "pt-BR" ? "Invocações" : "Agent invocations",
682
- render: (row) => row.run_count,
683
- align: "right",
684
- footer: totals.runs,
685
- },
686
- {
687
- key: "tasks",
688
- label:
689
- period === undefined
690
- ? locale === "pt-BR"
691
- ? "Tarefas ativas"
692
- : "Active tasks"
693
- : locale === "pt-BR"
694
- ? "Dias-tarefa ativos"
695
- : "Active task-days",
696
- render: (row) =>
697
- period === undefined
698
- ? row.task_count
699
- : (row.taskDaysActive ?? row.tasksActive ?? row.task_count),
700
- align: "right",
701
- footer: totals.tasks,
702
- },
703
715
  ...(period === undefined
704
- ? []
716
+ ? [
717
+ {
718
+ key: "runs",
719
+ label: locale === "pt-BR" ? "Invocações" : "Agent invocations",
720
+ render: (row: CostGroupRow) => row.run_count,
721
+ align: "right" as const,
722
+ footer: totals.runs,
723
+ },
724
+ ...(showAgentIdentity
725
+ ? []
726
+ : [
727
+ {
728
+ key: "tasks",
729
+ label: showAgentIdentity || showInvocationTasks ? (locale === "pt-BR" ? "Tarefas com invocação" : "Tasks with invocations") : (locale === "pt-BR" ? "Tarefas criadas" : "Tasks created"),
730
+ render: (row: CostGroupRow) => row.task_count ?? 0,
731
+ align: "right" as const,
732
+ footer: totals.tasks,
733
+ },
734
+ ]),
735
+ ]
705
736
  : [
706
737
  {
707
738
  key: "prds",
@@ -718,25 +749,39 @@ export function CostGroupsTable({
718
749
  footer: totals.specs,
719
750
  },
720
751
  {
721
- key: "evidences",
722
- label: locale === "pt-BR" ? "Evidências" : "Evidence",
723
- render: (row: CostGroupRow) => row.evidence_count,
752
+ key: "tasks",
753
+ label: locale === "pt-BR" ? "Tarefas criadas" : "Tasks created",
754
+ render: (row: CostGroupRow) => row.task_count ?? 0,
724
755
  align: "right" as const,
725
- footer: totals.evidences,
756
+ footer: totals.tasks,
757
+ },
758
+ {
759
+ key: "runs",
760
+ label: "Runs",
761
+ render: (row: CostGroupRow) => row.run_count,
762
+ align: "right" as const,
763
+ footer: totals.runs,
726
764
  },
727
765
  {
728
766
  key: "tests",
729
- label: "Tests",
767
+ label: locale === "pt-BR" ? "Testes" : "Tests",
730
768
  render: (row: CostGroupRow) => row.test_count,
731
769
  align: "right" as const,
732
770
  footer: totals.tests,
733
771
  },
772
+ {
773
+ key: "evidences",
774
+ label: locale === "pt-BR" ? "Evidências" : "Evidence",
775
+ render: (row: CostGroupRow) => row.evidence_count,
776
+ align: "right" as const,
777
+ footer: totals.evidences,
778
+ },
734
779
  ]),
735
780
  {
736
781
  key: "duration",
737
782
  label: "Tempo",
738
- render: (row) => formatDurationCoverage(row.duration, locale),
739
- sortValue: (row) => (row.duration.coverage_ratio > 0 ? row.duration.known_sum : null),
783
+ render: (row) => formatTokenBackedDuration(row.duration, row.total_tokens, locale),
784
+ sortValue: (row) => (hasKnownDuration(row.duration) ? row.duration.known_sum : null),
740
785
  align: "right",
741
786
  footer: <output aria-label={totalAriaLabel}>{totalDurationDisplay}</output>,
742
787
  },
@@ -750,7 +795,14 @@ export function CostGroupsTable({
750
795
  },
751
796
  {
752
797
  key: "cost",
753
- label: locale === "pt-BR" ? "Custo" : "Cost",
798
+ label:
799
+ period === undefined
800
+ ? locale === "pt-BR"
801
+ ? "Custo"
802
+ : "Cost"
803
+ : locale === "pt-BR"
804
+ ? "Custos"
805
+ : "Costs",
754
806
  render: (row) =>
755
807
  formatAuditableCurrency(
756
808
  currency === "BRL" ? row.estimated_brl : row.estimated_usd,