Skip to content

Commit 907edb4

Browse files
committed
Merge branch 'main' into fix/onboarding
2 parents 1505d20 + 1708e5b commit 907edb4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+2289
-646
lines changed

.claude/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
{
2+
"permissions": {
3+
"deny": ["Read(**/dist/**)"]
4+
},
25
"hooks": {
36
"Stop": [
47
{

.github/dependabot.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,24 @@ version: 2
22
updates:
33
- package-ecosystem: "github-actions"
44
directory: "/"
5+
cooldown:
6+
default-days: 5
57
schedule:
68
interval: "daily"
79

810
- package-ecosystem: "docker"
911
directory: "/"
12+
cooldown:
13+
default-days: 5
1014
schedule:
1115
interval: "monthly"
1216

1317
- package-ecosystem: "npm"
1418
directory: "/"
1519
schedule:
1620
interval: "weekly"
21+
cooldown:
22+
default-days: 5
1723
groups:
1824
abinnovision:
1925
patterns:

.github/workflows/autofix.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ jobs:
66
autofix:
77
runs-on: ubuntu-latest
88

9-
if: ${{ github.actor == 'steebchen' }}
10-
119
steps:
1210
- name: Autofix
1311
uses: steebchen/actions/autofix@v0.14.1

apps/api/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"bcrypt-ts": "7.0.0",
3131
"better-auth": "1.2.7",
3232
"dotenv": "16.5.0",
33-
"drizzle-zod": "0.7.1",
33+
"drizzle-zod": "0.8.3",
3434
"gateway": "workspace:*",
3535
"hono": "^4.9.7",
3636
"hono-openapi": "^0.4.6",

apps/api/src/routes/activity.spec.ts

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,4 +245,149 @@ describe("activity endpoint", () => {
245245
const res = await app.request("/activity?days=7");
246246
expect(res.status).toBe(401);
247247
});
248+
249+
test("GET /activity should correctly aggregate token counts", async () => {
250+
// Clear existing logs and insert test data with known values
251+
await db.delete(tables.log);
252+
253+
const today = new Date();
254+
const yesterday = new Date(today);
255+
yesterday.setDate(yesterday.getDate() - 1);
256+
257+
await db.insert(tables.log).values([
258+
{
259+
id: "token-test-1",
260+
requestId: "token-test-1",
261+
createdAt: today,
262+
updatedAt: today,
263+
organizationId: "test-org-id",
264+
projectId: "test-project-id",
265+
apiKeyId: "test-api-key-id",
266+
duration: 1000,
267+
requestedModel: "gpt-4",
268+
requestedProvider: "openai",
269+
usedModel: "gpt-4",
270+
usedProvider: "openai",
271+
responseSize: 1000,
272+
promptTokens: "100",
273+
completionTokens: "200",
274+
totalTokens: "300",
275+
cost: 0.1,
276+
inputCost: 0.05,
277+
outputCost: 0.05,
278+
requestCost: 0,
279+
messages: JSON.stringify([{ role: "user", content: "Test" }]),
280+
mode: "api-keys",
281+
usedMode: "api-keys",
282+
},
283+
{
284+
id: "token-test-2",
285+
requestId: "token-test-2",
286+
createdAt: today,
287+
updatedAt: today,
288+
organizationId: "test-org-id",
289+
projectId: "test-project-id",
290+
apiKeyId: "test-api-key-id",
291+
duration: 1500,
292+
requestedModel: "gpt-4",
293+
requestedProvider: "openai",
294+
usedModel: "gpt-4",
295+
usedProvider: "openai",
296+
responseSize: 1500,
297+
promptTokens: "150",
298+
completionTokens: "250",
299+
totalTokens: "400",
300+
cost: 0.15,
301+
inputCost: 0.07,
302+
outputCost: 0.08,
303+
requestCost: 0,
304+
messages: JSON.stringify([{ role: "user", content: "Test2" }]),
305+
mode: "api-keys",
306+
usedMode: "api-keys",
307+
},
308+
{
309+
id: "token-test-3",
310+
requestId: "token-test-3",
311+
createdAt: yesterday,
312+
updatedAt: yesterday,
313+
organizationId: "test-org-id",
314+
projectId: "test-project-id",
315+
apiKeyId: "test-api-key-id",
316+
duration: 2000,
317+
requestedModel: "claude-3-sonnet",
318+
requestedProvider: "anthropic",
319+
usedModel: "claude-3-sonnet",
320+
usedProvider: "anthropic",
321+
responseSize: 2000,
322+
promptTokens: "300",
323+
completionTokens: "500",
324+
totalTokens: "800",
325+
cost: 0.25,
326+
inputCost: 0.1,
327+
outputCost: 0.15,
328+
requestCost: 0,
329+
messages: JSON.stringify([{ role: "user", content: "Test3" }]),
330+
mode: "api-keys",
331+
usedMode: "api-keys",
332+
},
333+
]);
334+
335+
const res = await app.request("/activity?days=7", {
336+
headers: {
337+
Cookie: token,
338+
},
339+
});
340+
341+
expect(res.status).toBe(200);
342+
const data = await res.json();
343+
344+
// Verify the response structure
345+
expect(Array.isArray(data.activity)).toBe(true);
346+
expect(data.activity.length).toBeGreaterThan(0);
347+
348+
// Calculate totals from the response
349+
const totalRequests = data.activity.reduce(
350+
(sum: number, day: any) => sum + day.requestCount,
351+
0,
352+
);
353+
const totalTokens = data.activity.reduce(
354+
(sum: number, day: any) => sum + day.totalTokens,
355+
0,
356+
);
357+
const totalInputTokens = data.activity.reduce(
358+
(sum: number, day: any) => sum + day.inputTokens,
359+
0,
360+
);
361+
const totalOutputTokens = data.activity.reduce(
362+
(sum: number, day: any) => sum + day.outputTokens,
363+
0,
364+
);
365+
const totalCost = data.activity.reduce(
366+
(sum: number, day: any) => sum + day.cost,
367+
0,
368+
);
369+
370+
// Verify correct aggregation
371+
expect(totalRequests).toBe(3);
372+
expect(totalTokens).toBe(1500); // 300 + 400 + 800
373+
expect(totalInputTokens).toBe(550); // 100 + 150 + 300
374+
expect(totalOutputTokens).toBe(950); // 200 + 250 + 500
375+
expect(totalCost).toBeCloseTo(0.5, 2); // 0.10 + 0.15 + 0.25
376+
377+
// Verify individual days
378+
const todayData = data.activity.find((day: any) => day.requestCount === 2);
379+
const yesterdayData = data.activity.find(
380+
(day: any) => day.requestCount === 1,
381+
);
382+
383+
expect(todayData).toBeDefined();
384+
expect(todayData.totalTokens).toBe(700); // 300 + 400
385+
expect(todayData.inputTokens).toBe(250); // 100 + 150
386+
expect(todayData.outputTokens).toBe(450); // 200 + 250
387+
388+
expect(yesterdayData).toBeDefined();
389+
expect(yesterdayData.totalTokens).toBe(800);
390+
expect(yesterdayData.inputTokens).toBe(300);
391+
expect(yesterdayData.outputTokens).toBe(500);
392+
});
248393
});

0 commit comments

Comments
 (0)