mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-15 16:14:26 +00:00
fix(ui): tighten analytics session and query contracts
This commit is contained in:
1 parent
e95b354297
commit
b2e4be310d
9 files changed
+162
-106
No files matched your search
@@ -175,94 +175,98 @@ describe('cliproxy usage syncer', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('migrates legacy v2 snapshots forward before merging new history', async () => {
|
||||
await runWithScopedConfigDir(ccsDir, async () => {
|
||||
const snapshotPath = path.join(ccsDir, 'cache', 'cliproxy-usage', 'latest.json');
|
||||
fs.mkdirSync(path.dirname(snapshotPath), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
snapshotPath,
|
||||
JSON.stringify({
|
||||
version: 2,
|
||||
timestamp: Date.now() - 60_000,
|
||||
daily: [
|
||||
{
|
||||
date: '2026-03-01',
|
||||
source: 'cliproxy',
|
||||
inputTokens: 100,
|
||||
outputTokens: 20,
|
||||
cacheCreationTokens: 0,
|
||||
cacheReadTokens: 10,
|
||||
cost: 0.2,
|
||||
totalCost: 0.2,
|
||||
modelsUsed: ['gemini-2.5-pro'],
|
||||
modelBreakdowns: [
|
||||
{
|
||||
modelName: 'gemini-2.5-pro',
|
||||
inputTokens: 100,
|
||||
outputTokens: 20,
|
||||
cacheCreationTokens: 0,
|
||||
cacheReadTokens: 10,
|
||||
cost: 0.2,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
hourly: [
|
||||
{
|
||||
hour: '2026-03-01 12:00',
|
||||
source: 'cliproxy',
|
||||
requestCount: 7,
|
||||
inputTokens: 100,
|
||||
outputTokens: 20,
|
||||
cacheCreationTokens: 0,
|
||||
cacheReadTokens: 10,
|
||||
cost: 0.2,
|
||||
totalCost: 0.2,
|
||||
modelsUsed: ['gemini-2.5-pro'],
|
||||
modelBreakdowns: [
|
||||
{
|
||||
modelName: 'gemini-2.5-pro',
|
||||
inputTokens: 100,
|
||||
outputTokens: 20,
|
||||
cacheCreationTokens: 0,
|
||||
cacheReadTokens: 10,
|
||||
cost: 0.2,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
monthly: [
|
||||
{
|
||||
month: '2026-03',
|
||||
source: 'cliproxy',
|
||||
inputTokens: 100,
|
||||
outputTokens: 20,
|
||||
cacheCreationTokens: 0,
|
||||
cacheReadTokens: 10,
|
||||
totalCost: 0.2,
|
||||
modelsUsed: ['gemini-2.5-pro'],
|
||||
modelBreakdowns: [
|
||||
{
|
||||
modelName: 'gemini-2.5-pro',
|
||||
inputTokens: 100,
|
||||
outputTokens: 20,
|
||||
cacheCreationTokens: 0,
|
||||
cacheReadTokens: 10,
|
||||
cost: 0.2,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}),
|
||||
'utf-8'
|
||||
);
|
||||
it('migrates legacy v1 and v2 snapshots forward before merging new history', async () => {
|
||||
for (const version of [1, 2]) {
|
||||
await runWithScopedConfigDir(ccsDir, async () => {
|
||||
const snapshotPath = path.join(ccsDir, 'cache', 'cliproxy-usage', 'latest.json');
|
||||
fs.mkdirSync(path.dirname(snapshotPath), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
snapshotPath,
|
||||
JSON.stringify({
|
||||
version,
|
||||
timestamp: Date.now() - 60_000,
|
||||
daily: [
|
||||
{
|
||||
date: '2026-03-01',
|
||||
source: 'cliproxy',
|
||||
inputTokens: 100,
|
||||
outputTokens: 20,
|
||||
cacheCreationTokens: 0,
|
||||
cacheReadTokens: 10,
|
||||
cost: 0.2,
|
||||
totalCost: 0.2,
|
||||
modelsUsed: ['gemini-2.5-pro'],
|
||||
modelBreakdowns: [
|
||||
{
|
||||
modelName: 'gemini-2.5-pro',
|
||||
inputTokens: 100,
|
||||
outputTokens: 20,
|
||||
cacheCreationTokens: 0,
|
||||
cacheReadTokens: 10,
|
||||
cost: 0.2,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
hourly: [
|
||||
{
|
||||
hour: '2026-03-01 12:00',
|
||||
source: 'cliproxy',
|
||||
requestCount: 7,
|
||||
inputTokens: 100,
|
||||
outputTokens: 20,
|
||||
cacheCreationTokens: 0,
|
||||
cacheReadTokens: 10,
|
||||
cost: 0.2,
|
||||
totalCost: 0.2,
|
||||
modelsUsed: ['gemini-2.5-pro'],
|
||||
modelBreakdowns: [
|
||||
{
|
||||
modelName: 'gemini-2.5-pro',
|
||||
inputTokens: 100,
|
||||
outputTokens: 20,
|
||||
cacheCreationTokens: 0,
|
||||
cacheReadTokens: 10,
|
||||
cost: 0.2,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
monthly: [
|
||||
{
|
||||
month: '2026-03',
|
||||
source: 'cliproxy',
|
||||
inputTokens: 100,
|
||||
outputTokens: 20,
|
||||
cacheCreationTokens: 0,
|
||||
cacheReadTokens: 10,
|
||||
totalCost: 0.2,
|
||||
modelsUsed: ['gemini-2.5-pro'],
|
||||
modelBreakdowns: [
|
||||
{
|
||||
modelName: 'gemini-2.5-pro',
|
||||
inputTokens: 100,
|
||||
outputTokens: 20,
|
||||
cacheCreationTokens: 0,
|
||||
cacheReadTokens: 10,
|
||||
cost: 0.2,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}),
|
||||
'utf-8'
|
||||
);
|
||||
|
||||
await syncCliproxyUsage(() => Promise.resolve(buildResponse(200, '2026-03-02T12:00:00.000Z')));
|
||||
await syncCliproxyUsage(() =>
|
||||
Promise.resolve(buildResponse(200, '2026-03-02T12:00:00.000Z'))
|
||||
);
|
||||
|
||||
const cached = await loadCachedCliproxyData();
|
||||
expect(cached.daily.map((entry) => entry.date)).toEqual(['2026-03-02', '2026-03-01']);
|
||||
expect(cached.hourly.find((entry) => entry.hour === '2026-03-01 12:00')?.requestCount).toBe(7);
|
||||
});
|
||||
const cached = await loadCachedCliproxyData();
|
||||
expect(cached.daily.map((entry) => entry.date)).toEqual(['2026-03-02', '2026-03-01']);
|
||||
expect(cached.hourly.find((entry) => entry.hour === '2026-03-01 12:00')?.requestCount).toBe(7);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it('prunes history details older than the configured retention window', async () => {
|
||||
|
||||
Reference in new issue
Block a user