|
|
@@ -1,6 +1,6 @@
|
|
|
import { describe, expect, test } from "bun:test"
|
|
|
import type { Message } from "@opencode-ai/sdk/v2/client"
|
|
|
-import { getSessionContextMetrics } from "./session-context-metrics"
|
|
|
+import { getSessionContext, getSessionTokenTotal } from "./session-context-metrics"
|
|
|
|
|
|
const assistant = (
|
|
|
id: string,
|
|
|
@@ -37,8 +37,8 @@ const user = (id: string) => {
|
|
|
} as unknown as Message
|
|
|
}
|
|
|
|
|
|
-describe("getSessionContextMetrics", () => {
|
|
|
- test("computes totals and usage from latest assistant with tokens", () => {
|
|
|
+describe("getSessionContext", () => {
|
|
|
+ test("computes usage from latest assistant with tokens", () => {
|
|
|
const messages = [
|
|
|
user("u1"),
|
|
|
assistant("a1", { input: 0, output: 0, reasoning: 0, read: 0, write: 0 }, 0.5),
|
|
|
@@ -57,45 +57,52 @@ describe("getSessionContextMetrics", () => {
|
|
|
},
|
|
|
]
|
|
|
|
|
|
- const metrics = getSessionContextMetrics(messages, providers)
|
|
|
+ const ctx = getSessionContext(messages, providers)
|
|
|
|
|
|
- expect(metrics.totalCost).toBe(1.75)
|
|
|
- expect(metrics.context?.message.id).toBe("a2")
|
|
|
- expect(metrics.context?.total).toBe(500)
|
|
|
- expect(metrics.context?.usage).toBe(50)
|
|
|
- expect(metrics.context?.providerLabel).toBe("OpenAI")
|
|
|
- expect(metrics.context?.modelLabel).toBe("GPT-4.1")
|
|
|
+ expect(ctx?.message.id).toBe("a2")
|
|
|
+ expect(ctx?.usage).toBe(50)
|
|
|
+ expect(ctx?.providerLabel).toBe("OpenAI")
|
|
|
+ expect(ctx?.modelLabel).toBe("GPT-4.1")
|
|
|
})
|
|
|
|
|
|
test("preserves fallback labels and null usage when model metadata is missing", () => {
|
|
|
const messages = [assistant("a1", { input: 40, output: 10, reasoning: 0, read: 0, write: 0 }, 0.1, "p-1", "m-1")]
|
|
|
const providers = [{ id: "p-1", models: {} }]
|
|
|
|
|
|
- const metrics = getSessionContextMetrics(messages, providers)
|
|
|
+ const ctx = getSessionContext(messages, providers)
|
|
|
|
|
|
- expect(metrics.context?.providerLabel).toBe("p-1")
|
|
|
- expect(metrics.context?.modelLabel).toBe("m-1")
|
|
|
- expect(metrics.context?.limit).toBeUndefined()
|
|
|
- expect(metrics.context?.usage).toBeNull()
|
|
|
+ expect(ctx?.providerLabel).toBe("p-1")
|
|
|
+ expect(ctx?.modelLabel).toBe("m-1")
|
|
|
+ expect(ctx?.limit).toBeUndefined()
|
|
|
+ expect(ctx?.usage).toBeNull()
|
|
|
})
|
|
|
|
|
|
test("recomputes when message array is mutated in place", () => {
|
|
|
const messages = [assistant("a1", { input: 10, output: 10, reasoning: 10, read: 10, write: 10 }, 0.25)]
|
|
|
const providers = [{ id: "openai", models: {} }]
|
|
|
|
|
|
- const one = getSessionContextMetrics(messages, providers)
|
|
|
+ const one = getSessionContext(messages, providers)
|
|
|
messages.push(assistant("a2", { input: 100, output: 20, reasoning: 0, read: 0, write: 0 }, 0.75))
|
|
|
- const two = getSessionContextMetrics(messages, providers)
|
|
|
+ const two = getSessionContext(messages, providers)
|
|
|
|
|
|
- expect(one.context?.message.id).toBe("a1")
|
|
|
- expect(two.context?.message.id).toBe("a2")
|
|
|
- expect(two.totalCost).toBe(1)
|
|
|
+ expect(one?.message.id).toBe("a1")
|
|
|
+ expect(two?.message.id).toBe("a2")
|
|
|
})
|
|
|
|
|
|
- test("returns empty metrics when inputs are undefined", () => {
|
|
|
- const metrics = getSessionContextMetrics(undefined, undefined)
|
|
|
+ test("returns undefined when inputs are undefined", () => {
|
|
|
+ const ctx = getSessionContext(undefined, undefined)
|
|
|
|
|
|
- expect(metrics.totalCost).toBe(0)
|
|
|
- expect(metrics.context).toBeUndefined()
|
|
|
+ expect(ctx).toBeUndefined()
|
|
|
+ })
|
|
|
+
|
|
|
+ test("computes stored session token totals", () => {
|
|
|
+ expect(
|
|
|
+ getSessionTokenTotal({
|
|
|
+ input: 10,
|
|
|
+ output: 20,
|
|
|
+ reasoning: 30,
|
|
|
+ cache: { read: 40, write: 50 },
|
|
|
+ }),
|
|
|
+ ).toBe(150)
|
|
|
})
|
|
|
})
|