Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
171efa3
feat(desktop): refine usage history ranges and real data
dashhuang Sep 2, 2026
c2698e3
chore(design): refresh usage history surface inventory
dashhuang Sep 2, 2026
1437201
fix(desktop): refine usage heatmap layout and intensity
dashhuang Sep 2, 2026
8ec1f10
fix(desktop): query complete usage history sessions
dashhuang Sep 2, 2026
e344803
fix(usage): preserve unbounded history windows
dashhuang Sep 2, 2026
e18b21d
fix(desktop): use pill shape for usage chart controls
dashhuang Sep 2, 2026
154f9db
fix(usage): guard history reads and exact-day tasks
dashhuang Sep 2, 2026
68be224
fix(usage): address history review feedback
dashhuang Sep 2, 2026
cfe93b6
fix(usage): preserve activity and heatmap windows
dashhuang Sep 2, 2026
334f116
fix(usage): hide duplicate today metric
dashhuang Sep 2, 2026
38f17af
fix(usage): hide today task table
dashhuang Sep 2, 2026
f1877e7
fix(usage): close exact-range and loading gaps
dashhuang Sep 2, 2026
4d344e3
fix(usage): use pill cells for clickable heatmap
dashhuang Sep 2, 2026
bc86a8c
fix(usage): scope task snapshots to account lifecycle
dashhuang Sep 2, 2026
08e4af7
fix(usage): close pending data and bridge contracts
dashhuang Sep 2, 2026
08733ae
fix(usage): align heatmap metric and selection states
dashhuang Sep 3, 2026
9b91a46
fix(usage): keep model colors aligned across ranges
dashhuang Sep 3, 2026
18f8077
fix(usage): preserve canonical task token totals
dashhuang Sep 3, 2026
252796d
fix(usage): refresh task totals on token updates
dashhuang Sep 3, 2026
4c5abcc
fix(usage): narrow task snapshot live update scope
dashhuang Sep 3, 2026
6dd9dbd
fix(usage): narrow history session payload
dashhuang Sep 3, 2026
c589cbb
fix(usage): narrow history session bridge types
dashhuang Sep 3, 2026
c8d7794
fix(usage): keep today heatmap cell clickable
dashhuang Sep 3, 2026
8861d8f
fix(usage): sync today chart selection
dashhuang Sep 3, 2026
504756c
fix(usage): avoid duplicate today option
dashhuang Sep 3, 2026
edd485d
fix(usage): distinguish loading from empty history
dashhuang Sep 3, 2026
17fe370
fix(usage): distinguish load failure from loading
dashhuang Sep 3, 2026
96ffc93
fix(usage): complete interactive chart semantics
dashhuang Sep 3, 2026
9dddf13
fix(usage): enlarge chart date hit targets
dashhuang Sep 3, 2026
0046b11
fix(usage): preserve daily bar hit width
dashhuang Sep 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const h = vi.hoisted(() => {

return {
ipcHandle: vi.fn(),
assertTrustedAppRendererEvent: vi.fn(),
logDebug: vi.fn(),
logInfo: vi.fn(),
queryResults,
Expand Down Expand Up @@ -89,6 +90,9 @@ vi.mock('../agent-island/service.js', () => ({
vi.mock('../imageCacheStore', () => ({ removeSession: vi.fn() }));
vi.mock('../messagePersistBroadcaster', () => ({ noteSessionClearBoundary: vi.fn() }));
vi.mock('../sessionTaskSummary.js', () => ({ backfillPinnedSessionSummaries: vi.fn() }));
vi.mock('../security/trustedAppRenderer.js', () => ({
assertTrustedAppRendererEvent: h.assertTrustedAppRendererEvent,
}));

import { registerSessionIpc } from '../localDb/ipc/sessions.js';

Expand Down Expand Up @@ -195,6 +199,59 @@ describe('local-db:sessions:list includePinned', () => {
expect(h.queryResults).toHaveLength(1);
});

it('returns the full sessions set for the usage-history query without message projections', async () => {
const handler = sessionsListHandler();
h.queryResults.push([
sessionRow('recent', { totalTokenUsage: 20 }),
sessionRow('old', { totalTokenUsage: 200 }),
]);

const result = await handler({}, 20, 'all', { usageHistory: true });

expect(result.map((s) => s.id)).toEqual(['recent', 'old']);
expect(result[0]).toEqual({
id: 'recent',
title: 'recent',
model: 'sonnet',
providerId: null,
totalTokenUsage: 20,
contextTokens: 0,
contextWindow: 0,
userSendAt: null,
updatedAt: new Date(1_700_000_000_000).toISOString(),
});
expect(result[0]).not.toHaveProperty('workingDir');
const selectCalls = h.fakeDb.select.mock.calls as unknown as Array<unknown[]>;
const projection = selectCalls[0]?.[0] as Record<string, unknown> | undefined;
expect(Object.keys(projection ?? {})).toEqual([
'id',
'title',
'model',
'providerId',
'totalTokenUsage',
'contextTokens',
'contextWindow',
'userSendAt',
'updatedAt',
]);
expect(h.fakeDb.select).toHaveBeenCalledTimes(1);
expect(h.listQuery).not.toHaveBeenCalled();
expect(h.queryResults).toHaveLength(0);
expect(h.assertTrustedAppRendererEvent).toHaveBeenCalledWith({});
});

it('rejects an untrusted renderer before running the unbounded usage-history query', async () => {
const handler = sessionsListHandler();
h.assertTrustedAppRendererEvent.mockImplementationOnce(() => {
throw new Error('[PERMISSION_DENIED]');
});

await expect(handler({}, 20, 'all', { usageHistory: true })).rejects.toThrow(
'[PERMISSION_DENIED]',
);
expect(h.fakeDb.select).not.toHaveBeenCalled();
});

it('also includes pinned rows for the all-status bucket used by mobile detail filters', async () => {
const handler = sessionsListHandler();
h.queryResults.push(
Expand Down
Loading