fix(desktop): align usage activity with model calls - #3697
Conversation
55cb537 to
d56b43d
Compare
|
Sourcing Usage from the Host authority is the right move, and the pagination guards (offset echo, strictly advancing [P2] Loading every page costs the Host O(N²)
At 10k records that is 100 pages × tens of thousands of Related: [P2]
|
…tch, degrade, canonical fixture) Follow-up to the Astro-Han review on apache#3697. Findings addressed: - Provenance is no longer dropped: loadUsageStats carries the canonical summary provenance onto UsageStats, and the page mirrors Session Inspector — the total-cost card shows "cost unavailable" instead of a misleading $0.00 when nothing was priced, and an incompleteness banner appears when records are unreadable/pending or the log was truncated. Shared estimatedUsageCost/hasUnavailableUsage helpers live in core. - Reconnect no longer shows a silent zero: the usage refetch effect and the stored/gating key now include the selected Host's lifecycle epoch, so a same-hostId in-place replacement refetches instead of clearing to a stale null. Summary cards render an em dash while unloaded rather than fabricating 0 / $0.00. - Degrade instead of erroring: a summary/logs count mismatch (e.g. a catch-up race after a Host restart) keeps the canonical total and marks the activity list incomplete rather than throwing the whole page. - Provider breakdown groups by connection slug, not raw provider type, so two connections to the same provider stay two rows. - MAX_ACTIVITY_RECORDS truncates with a logsTruncated signal instead of raising "invalid Usage projection"; paging stops at the cap. - Per-page catch-up removed: readCanonicalUsage only repairs on the first page (summary always repairs, so provenance stays honest), cutting a projection write per activity page. - E2E fixture now seeds the CANONICAL model-call ledger via AgentRun model_call_attempt_recorded events (tools stay on legacy telemetry), so the canonical merge branch is actually exercised end to end; the misleading "canonical" comment is corrected. Tests: rewrite the reconcile test to assert graceful degrade; add truncation, provenance-passthrough, and connection-grouping cases; add core coverage for the new provenance presentation helpers. Note: the O(N^2) store read is only partially mitigated here (first-page catch-up + cap). Pushing pagination into SQL is left as a follow-up.
2ba51cf to
39a66f0
Compare
…tch, degrade, canonical fixture) Follow-up to the Astro-Han review on apache#3697. Findings addressed: - Provenance is no longer dropped: loadUsageStats carries the canonical summary provenance onto UsageStats, and the page mirrors Session Inspector — the total-cost card shows "cost unavailable" instead of a misleading $0.00 when nothing was priced, and an incompleteness banner appears when records are unreadable/pending or the log was truncated. Shared estimatedUsageCost/hasUnavailableUsage helpers live in core. - Reconnect no longer shows a silent zero: the usage refetch effect and the stored/gating key now include the selected Host's lifecycle epoch, so a same-hostId in-place replacement refetches instead of clearing to a stale null. Summary cards render an em dash while unloaded rather than fabricating 0 / $0.00. - Degrade instead of erroring: a summary/logs count mismatch (e.g. a catch-up race after a Host restart) keeps the canonical total and marks the activity list incomplete rather than throwing the whole page. - Provider breakdown groups by connection slug, not raw provider type, so two connections to the same provider stay two rows. - MAX_ACTIVITY_RECORDS truncates with a logsTruncated signal instead of raising "invalid Usage projection"; paging stops at the cap. - Per-page catch-up removed: readCanonicalUsage only repairs on the first page (summary always repairs, so provenance stays honest), cutting a projection write per activity page. - E2E fixture now seeds the CANONICAL model-call ledger via AgentRun model_call_attempt_recorded events (tools stay on legacy telemetry), so the canonical merge branch is actually exercised end to end; the misleading "canonical" comment is corrected. Tests: rewrite the reconcile test to assert graceful degrade; add truncation, provenance-passthrough, and connection-grouping cases; add core coverage for the new provenance presentation helpers. Note: the O(N^2) store read is only partially mitigated here (first-page catch-up + cap). Pushing pagination into SQL is left as a follow-up.
39a66f0 to
63cd47c
Compare
…tch, degrade, canonical fixture) Follow-up to the Astro-Han review on apache#3697. Findings addressed: - Provenance is no longer dropped: loadUsageStats carries the canonical summary provenance onto UsageStats, and the page mirrors Session Inspector — the total-cost card shows "cost unavailable" instead of a misleading $0.00 when nothing was priced, and an incompleteness banner appears when records are unreadable/pending or the log was truncated. Shared estimatedUsageCost/hasUnavailableUsage helpers live in core. - Reconnect no longer shows a silent zero: the usage refetch effect and the stored/gating key now include the selected Host's lifecycle epoch, so a same-hostId in-place replacement refetches instead of clearing to a stale null. Summary cards render an em dash while unloaded rather than fabricating 0 / $0.00. - Degrade instead of erroring: a summary/logs count mismatch (e.g. a catch-up race after a Host restart) keeps the canonical total and marks the activity list incomplete rather than throwing the whole page. - Provider breakdown groups by connection slug, not raw provider type, so two connections to the same provider stay two rows. - MAX_ACTIVITY_RECORDS truncates with a logsTruncated signal instead of raising "invalid Usage projection"; paging stops at the cap. - Per-page catch-up removed: readCanonicalUsage only repairs on the first page (summary always repairs, so provenance stays honest), cutting a projection write per activity page. - E2E fixture now seeds the CANONICAL model-call ledger via AgentRun model_call_attempt_recorded events (tools stay on legacy telemetry), so the canonical merge branch is actually exercised end to end; the misleading "canonical" comment is corrected. Tests: rewrite the reconcile test to assert graceful degrade; add truncation, provenance-passthrough, and connection-grouping cases; add core coverage for the new provenance presentation helpers. Note: the O(N^2) store read is only partially mitigated here (first-page catch-up + cap). Pushing pagination into SQL is left as a follow-up.
63cd47c to
378f505
Compare
…tch, degrade, canonical fixture) Follow-up to the Astro-Han review on apache#3697. Findings addressed: - Provenance is no longer dropped: loadUsageStats carries the canonical summary provenance onto UsageStats, and the page mirrors Session Inspector — the total-cost card shows "cost unavailable" instead of a misleading $0.00 when nothing was priced, and an incompleteness banner appears when records are unreadable/pending or the log was truncated. Shared estimatedUsageCost/hasUnavailableUsage helpers live in core. - Reconnect no longer shows a silent zero: the usage refetch effect and the stored/gating key now include the selected Host's lifecycle epoch, so a same-hostId in-place replacement refetches instead of clearing to a stale null. Summary cards render an em dash while unloaded rather than fabricating 0 / $0.00. - Degrade instead of erroring: a summary/logs count mismatch (e.g. a catch-up race after a Host restart) keeps the canonical total and marks the activity list incomplete rather than throwing the whole page. - Provider breakdown groups by connection slug, not raw provider type, so two connections to the same provider stay two rows. - MAX_ACTIVITY_RECORDS truncates with a logsTruncated signal instead of raising "invalid Usage projection"; paging stops at the cap. - Per-page catch-up removed: readCanonicalUsage only repairs on the first page (summary always repairs, so provenance stays honest), cutting a projection write per activity page. - E2E fixture now seeds the CANONICAL model-call ledger via AgentRun model_call_attempt_recorded events (tools stay on legacy telemetry), so the canonical merge branch is actually exercised end to end; the misleading "canonical" comment is corrected. Tests: rewrite the reconcile test to assert graceful degrade; add truncation, provenance-passthrough, and connection-grouping cases; add core coverage for the new provenance presentation helpers. Note: the O(N^2) store read is only partially mitigated here (first-page catch-up + cap). Pushing pagination into SQL is left as a follow-up.
378f505 to
55e523b
Compare
…tch, degrade, canonical fixture) Follow-up to the Astro-Han review on apache#3697. Findings addressed: - Provenance is no longer dropped: loadUsageStats carries the canonical summary provenance onto UsageStats, and the page mirrors Session Inspector — the total-cost card shows "cost unavailable" instead of a misleading $0.00 when nothing was priced, and an incompleteness banner appears when records are unreadable/pending or the log was truncated. Shared estimatedUsageCost/hasUnavailableUsage helpers live in core. - Reconnect no longer shows a silent zero: the usage refetch effect and the stored/gating key now include the selected Host's lifecycle epoch, so a same-hostId in-place replacement refetches instead of clearing to a stale null. Summary cards render an em dash while unloaded rather than fabricating 0 / $0.00. - Degrade instead of erroring: a summary/logs count mismatch (e.g. a catch-up race after a Host restart) keeps the canonical total and marks the activity list incomplete rather than throwing the whole page. - Provider breakdown groups by connection slug, not raw provider type, so two connections to the same provider stay two rows. - MAX_ACTIVITY_RECORDS truncates with a logsTruncated signal instead of raising "invalid Usage projection"; paging stops at the cap. - Per-page catch-up removed: readCanonicalUsage only repairs on the first page (summary always repairs, so provenance stays honest), cutting a projection write per activity page. - E2E fixture now seeds the CANONICAL model-call ledger via AgentRun model_call_attempt_recorded events (tools stay on legacy telemetry), so the canonical merge branch is actually exercised end to end; the misleading "canonical" comment is corrected. Tests: rewrite the reconcile test to assert graceful degrade; add truncation, provenance-passthrough, and connection-grouping cases; add core coverage for the new provenance presentation helpers. Note: the O(N^2) store read is only partially mitigated here (first-page catch-up + cap). Pushing pagination into SQL is left as a follow-up.
55e523b to
38b0e9b
Compare
…tch, degrade, canonical fixture) Follow-up to the Astro-Han review on apache#3697. Findings addressed: - Provenance is no longer dropped: loadUsageStats carries the canonical summary provenance onto UsageStats, and the page mirrors Session Inspector — the total-cost card shows "cost unavailable" instead of a misleading $0.00 when nothing was priced, and an incompleteness banner appears when records are unreadable/pending or the log was truncated. Shared estimatedUsageCost/hasUnavailableUsage helpers live in core. - Reconnect no longer shows a silent zero: the usage refetch effect and the stored/gating key now include the selected Host's lifecycle epoch, so a same-hostId in-place replacement refetches instead of clearing to a stale null. Summary cards render an em dash while unloaded rather than fabricating 0 / $0.00. - Degrade instead of erroring: a summary/logs count mismatch (e.g. a catch-up race after a Host restart) keeps the canonical total and marks the activity list incomplete rather than throwing the whole page. - Provider breakdown groups by connection slug, not raw provider type, so two connections to the same provider stay two rows. - MAX_ACTIVITY_RECORDS truncates with a logsTruncated signal instead of raising "invalid Usage projection"; paging stops at the cap. - Per-page catch-up removed: readCanonicalUsage only repairs on the first page (summary always repairs, so provenance stays honest), cutting a projection write per activity page. - E2E fixture now seeds the CANONICAL model-call ledger via AgentRun model_call_attempt_recorded events (tools stay on legacy telemetry), so the canonical merge branch is actually exercised end to end; the misleading "canonical" comment is corrected. Tests: rewrite the reconcile test to assert graceful degrade; add truncation, provenance-passthrough, and connection-grouping cases; add core coverage for the new provenance presentation helpers. Note: the O(N^2) store read is only partially mitigated here (first-page catch-up + cap). Pushing pagination into SQL is left as a follow-up.
38b0e9b to
aa2e5f1
Compare
…tch, degrade, canonical fixture) Follow-up to the Astro-Han review on apache#3697. Findings addressed: - Provenance is no longer dropped: loadUsageStats carries the canonical summary provenance onto UsageStats, and the page mirrors Session Inspector — the total-cost card shows "cost unavailable" instead of a misleading $0.00 when nothing was priced, and an incompleteness banner appears when records are unreadable/pending or the log was truncated. Shared estimatedUsageCost/hasUnavailableUsage helpers live in core. - Reconnect no longer shows a silent zero: the usage refetch effect and the stored/gating key now include the selected Host's lifecycle epoch, so a same-hostId in-place replacement refetches instead of clearing to a stale null. Summary cards render an em dash while unloaded rather than fabricating 0 / $0.00. - Degrade instead of erroring: a summary/logs count mismatch (e.g. a catch-up race after a Host restart) keeps the canonical total and marks the activity list incomplete rather than throwing the whole page. - Provider breakdown groups by connection slug, not raw provider type, so two connections to the same provider stay two rows. - MAX_ACTIVITY_RECORDS truncates with a logsTruncated signal instead of raising "invalid Usage projection"; paging stops at the cap. - Per-page catch-up removed: readCanonicalUsage only repairs on the first page (summary always repairs, so provenance stays honest), cutting a projection write per activity page. - E2E fixture now seeds the CANONICAL model-call ledger via AgentRun model_call_attempt_recorded events (tools stay on legacy telemetry), so the canonical merge branch is actually exercised end to end; the misleading "canonical" comment is corrected. Tests: rewrite the reconcile test to assert graceful degrade; add truncation, provenance-passthrough, and connection-grouping cases; add core coverage for the new provenance presentation helpers. Note: the O(N^2) store read is only partially mitigated here (first-page catch-up + cap). Pushing pagination into SQL is left as a follow-up.
f8d35be to
6989087
Compare
|
Relationship note: PRs #3697 and #3761 both close #3695 and overlap in the Usage Statistics migration, including This comment records the relationship only; it is not a merge decision. Automated review note posted by @未开智选手. This is not an independent human review; a human should verify the conclusion. |
Read usage summary and activity from the Runtime Host canonical usage authority so Usage Statistics and Daily Review share the same model-call count. Keep tool calls visible as separately labelled activity and page both sources completely. Generated-by: OpenAI Codex
The UsageLongTail/UsageNarrow play asserted findByRole('tab', { name:
usageCopy.tabs[0] }) with an exact string. The tab renders a count badge
via endContent, which Astryx folds into the accessible name (e.g.
'活动记录 5'), so the exact match never resolved and the storybook
render smoke failed both stories. Match the label as a prefix RegExp,
consistent with how accessibility-coverage queries workbar tabs.
The UsageLongTail/UsageNarrow play asserted findByRole('tab', ...), but
Astryx's TabList renders a <nav> of <button> tabs — there is no ARIA
`tab` role anywhere (its own TabList tests reach tabs via getByRole
'button'). So the query never matched, regardless of the name matcher;
the earlier prefix-RegExp fix only touched the name and left the wrong
role in place, so both stories kept failing the render smoke.
Query the tab by `button` with the same label-prefix RegExp (the count
badge folds into the accessible name after the label, e.g. '活动记录 5').
Verified against @astryxdesign/core@0.4.5: TabList => role navigation,
Tab => role button, zero role="tab"; getByRole('button', {name:
/^活动记录/}) uniquely resolves the requests tab.
…tch, degrade, canonical fixture) Follow-up to the Astro-Han review on apache#3697. Findings addressed: - Provenance is no longer dropped: loadUsageStats carries the canonical summary provenance onto UsageStats, and the page mirrors Session Inspector — the total-cost card shows "cost unavailable" instead of a misleading $0.00 when nothing was priced, and an incompleteness banner appears when records are unreadable/pending or the log was truncated. Shared estimatedUsageCost/hasUnavailableUsage helpers live in core. - Reconnect no longer shows a silent zero: the usage refetch effect and the stored/gating key now include the selected Host's lifecycle epoch, so a same-hostId in-place replacement refetches instead of clearing to a stale null. Summary cards render an em dash while unloaded rather than fabricating 0 / $0.00. - Degrade instead of erroring: a summary/logs count mismatch (e.g. a catch-up race after a Host restart) keeps the canonical total and marks the activity list incomplete rather than throwing the whole page. - Provider breakdown groups by connection slug, not raw provider type, so two connections to the same provider stay two rows. - MAX_ACTIVITY_RECORDS truncates with a logsTruncated signal instead of raising "invalid Usage projection"; paging stops at the cap. - Per-page catch-up removed: readCanonicalUsage only repairs on the first page (summary always repairs, so provenance stays honest), cutting a projection write per activity page. - E2E fixture now seeds the CANONICAL model-call ledger via AgentRun model_call_attempt_recorded events (tools stay on legacy telemetry), so the canonical merge branch is actually exercised end to end; the misleading "canonical" comment is corrected. Tests: rewrite the reconcile test to assert graceful degrade; add truncation, provenance-passthrough, and connection-grouping cases; add core coverage for the new provenance presentation helpers. Note: the O(N^2) store read is only partially mitigated here (first-page catch-up + cap). Pushing pagination into SQL is left as a follow-up.
6989087 to
436c934
Compare
M4n5ter
left a comment
There was a problem hiding this comment.
Reviewed exact head 436c934c97dfd0f7ba0ede8d594e2b14e299b1a1 after its rebase onto current main. The six rebased patches are patch-equivalent to the previously published branch. The change removes the legacy local Usage owner, keeps Runtime Host as the single data authority, and preserves incomplete/unpriced provenance instead of fabricating zeroes. The complete repository build, 58 focused tests, and Biome checks passed locally. I found no blocking issue; the inline P2 is a recoverable loading failure and can be fixed as a follow-up.
Posted by an automated review agent operated by @M4n5ter. This is not an independent human review and does not satisfy the committer review required by CONTRIBUTING.md. A human is accountable for this comment — please push back if anything here is wrong.
简体中文
本条评论由 @M4n5ter 运行的自动化审查程序发出。它不构成 CONTRIBUTING.md 所要求的独立人类审查,也不能替代人类审查。有人类对本条评论负责,如有错误请直接指出。
| throw invalidUsageProjection(); | ||
| } | ||
| total ??= result.total; | ||
| if (result.total !== total) throw invalidUsageProjection(); |
There was a problem hiding this comment.
[P2] Please make pagination tolerate a projection catch-up between pages. The query freezes its time range, but recovery can still materialize older model-call records whose timestamps fall inside that range after page 1 has been returned. If the first page reports total = 101 and a pending projection is committed before page 2, the next response reports total = 102; this guard turns the whole Usage load into invalid Usage projection. I reproduced that exact 101→102 sequence through the production IPC handler. Existing tests only cover a stable multi-page total and a one-page summary/log mismatch, so neither reaches this branch. This is recoverable by refreshing and therefore does not block approval, but a revision-pinned page snapshot or one bounded restart of the paged read would prevent the transient failure.
Posted by an automated review agent operated by @M4n5ter. This is not an independent human review and does not satisfy the committer review required by CONTRIBUTING.md. A human is accountable for this comment — please push back if anything here is wrong.
简体中文
本条评论由 @M4n5ter 运行的自动化审查程序发出。它不构成 CONTRIBUTING.md 所要求的独立人类审查,也不能替代人类审查。有人类对本条评论负责,如有错误请直接指出。
Summary
Fixes #3695
Refs #2128
Verification
node --test apps/desktop/dist/main/__tests__/runtime-host-usage-ipc-main.test.js apps/desktop/dist/main/__tests__/desktop-session-projection.test.js apps/desktop/dist/main/__tests__/settings-resource-state.test.js apps/desktop/dist/main/__tests__/runtime-host-settings-generation.test.js— 28 passednpm --workspace @maka/desktop run typecheck— passednpx biome check <16 changed files>— passednpm --workspace @maka/desktop run build:renderer— passednpm --workspace @maka/desktop run build-storybook— passednode scripts/asf-license-headers.mjs check— the changed files pass; the repository-wide command reports only pre-existing untrackeddocs/contribution/files, which are not part of this PRAI use
Select exactly one:
Tool(s) and scope: OpenAI Codex diagnosed the divergent Usage data paths, implemented the Runtime Host adapter and UI/type updates, resolved the rebase conflict, and added regression tests and fixture coverage.
Checklist
Does this PR entail a change in behavior?