Files
deepseek-harness/packages/client/ui-openrouter-usage/tests/cost-dock.client.spec.tsx
Coder 8719fa84f0
Some checks failed
CI / windows node 24 / wine blocking (push) Has been skipped
CI / node 22.19 (push) Has been skipped
CI / node 26 (push) Has been skipped
CI / python 3.10 / keyless SDK (push) Has been skipped
CI / python runtime / release-shaped Linux x64 (push) Has been skipped
CI / wine apt cache (push) Successful in 7s
CI / serial / linux (push) Has been skipped
Deploy documentation / build (push) Failing after 1m25s
Deploy documentation / deploy (push) Has been skipped
Landlock Run / Matrix (push) Successful in 5s
Release (vendor) / Pack npm tarballs (push) Failing after 2m47s
Release (dsh) / Pack npm tarballs (push) Failing after 1m56s
Sandbox / sandbox e2e (landlock, ubuntu-24.04) (push) Failing after 1m57s
Sandbox / sandbox e2e (bwrap, ubuntu-latest) (push) Failing after 1m19s
Release (vendor) / Publish to npm (push) Has been skipped
Release (dsh) / Publish to npm (push) Has been skipped
CI / serial / windows (self-hosted standby) (push) Has been cancelled
CI / larger-runner-benchmark (16, linux, dsh-ubuntu-24-04-16core, typecheck) (push) Has been cancelled
Landlock Run / darwin (no platform package — degradation proof) (push) Has been cancelled
Landlock Run / ${{ matrix.platform }} (push) Has been cancelled
CI / node 24 / static (push) Has been cancelled
CI / node 24 / coverage (push) Has been cancelled
CI / node 24 / snapshots and artifacts (push) Has been cancelled
CI / windows node 24 / native complete (push) Has been cancelled
CI / serial / linux (self-hosted standby) (push) Has been cancelled
CI / serial / macos (push) Has been cancelled
CI / larger-runner-benchmark (16, windows, dsh-windows-2025-16core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (32, windows, dsh-windows-2025-32core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (4, windows, dsh-windows-2025-4core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (64, windows, dsh-windows-2025-64core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (8, windows, dsh-windows-2025-8core, production-site) (push) Has been cancelled
CI / larger-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, typecheck) (push) Has been cancelled
CI / larger-runner-benchmark (96, windows, dsh-windows-2025-96core, production-site) (push) Has been cancelled
CI / consolidated-runner-benchmark (16, linux, dsh-ubuntu-24-04-16core, 16) (push) Has been cancelled
CI / consolidated-runner-benchmark (16, windows, dsh-windows-2025-16core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (32, linux, dsh-ubuntu-24-04-32core, 32) (push) Has been cancelled
CI / consolidated-runner-benchmark (32, windows, dsh-windows-2025-32core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (4, linux, dsh-ubuntu-24-04-4core, 4) (push) Has been cancelled
CI / consolidated-runner-benchmark (4, windows, dsh-windows-2025-4core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (64, linux, dsh-ubuntu-24-04-64core, 32) (push) Has been cancelled
CI / consolidated-runner-benchmark (64, windows, dsh-windows-2025-64core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, 8) (push) Has been cancelled
CI / consolidated-runner-benchmark (8, windows, dsh-windows-2025-8core, 2) (push) Has been cancelled
CI / consolidated-runner-benchmark (96, linux, dsh-ubuntu-24-04-96core, 32) (push) Has been cancelled
CI / consolidated-runner-benchmark (96, windows, dsh-windows-2025-96core, 2) (push) Has been cancelled
CI / all checks passed (push) Has been cancelled
Sandbox / sandbox e2e (seatbelt, macos-latest) (push) Has been cancelled
CI / larger-runner-benchmark (8, linux, dsh-ubuntu-24-04-8core, typecheck) (push) Has been cancelled
Sandbox / sandbox e2e (landlock, ubuntu-24.04-arm) (push) Has been cancelled
E2E (real DeepSeek API) / e2e (push) Failing after 1m24s
feat: add economy/maximum presets, tool-lab and subagent-cursor extensions
- new economy and maximum agent presets with three-role pipeline skill
- new packages/extensions/tool-lab (home-lab ComfyUI/Docling/Whishper tools)
- new packages/subagent/subagent-cursor provider
- openrouter balance UI with on-demand refresh
- session projection context-seed boundary fold
- regenerate docs catalogs; keep local searxng benchmark scripts
2026-08-23 22:12:30 +07:00

139 lines
5.9 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// @vitest-environment jsdom
// CostDock presentation: renders the running session cost from the
// openRouterCost projection plus the subagent subtree read off the session
// list, and nothing at all until a step was priced.
import { act, cleanup, render, screen } from '@testing-library/react'
import { afterEach, describe, expect, it, vi } from 'vitest'
import { makeTranslate } from '@deepseek-ai/dsh-client-test-runtime'
import { zh as commonZh } from '@deepseek-ai/dsh-client-locale/src/locales/zh.ts'
import { CostDock } from '../src/client/CostDock.tsx'
import { zh } from '../src/client/locales.ts'
afterEach(cleanup)
const t = makeTranslate(zh, commonZh)
const PARENT = 'session-parent'
/** One session-list row as much of it as the dock reads. */
interface Row {
id: string
parentId?: string
origin?: 'subagent'
cost?: { totalUsd: number; pricedSteps: number; unknownModelSteps: number }
}
/** A `useSessions` stub serving `byId` built from the given rows. */
function sessionsHook(rows: readonly Row[]) {
const byId: Record<string, unknown> = {}
for (const row of rows) {
byId[row.id] = {
id: row.id,
...row.parentId === undefined ? {} : { parentId: row.parentId },
...row.origin === undefined ? {} : { origin: row.origin },
...row.cost === undefined
? {}
: { projectionValues: { openRouterCost: { ...row.cost, currency: 'USD' } } },
}
}
return (selector: (state: { byId: Record<string, unknown> }) => unknown) => selector({ byId })
}
function makeProps(over: Partial<Parameters<typeof CostDock>[0]> = {}, rows: readonly Row[] = []) {
return {
sessionId: PARENT,
useProjection: vi.fn(() => undefined),
useSessions: sessionsHook(rows),
t,
...over,
} as unknown as Parameters<typeof CostDock>[0]
}
describe('CostDock', () => {
it('renders nothing while the projection is absent or priced zero steps', () => {
for (const value of [undefined, { totalUsd: 0, pricedSteps: 0, unknownModelSteps: 0, currency: 'USD' }]) {
const { container } = render(<CostDock {...makeProps({ useProjection: () => value })} />)
expect(container.firstChild).toBeNull()
cleanup()
}
})
it('renders the priced session cost as a USD figure', () => {
render(<CostDock {...makeProps({
useProjection: () => ({ totalUsd: 1.2345, pricedSteps: 2, unknownModelSteps: 0, currency: 'USD' }),
})} />)
expect(screen.getByText('会话费用 $1.23')).toBeTruthy()
})
it('surfaces the unknown-pricing step count in a tooltip when present', () => {
render(<CostDock {...makeProps({
useProjection: () => ({ totalUsd: 0.5, pricedSteps: 1, unknownModelSteps: 3, currency: 'USD' }),
})} />)
expect(screen.getByText('会话费用 $0.50').getAttribute('title')).toBe('包含 3 个未知定价步骤')
})
it('omits the tooltip when every step priced', () => {
render(<CostDock {...makeProps({
useProjection: () => ({ totalUsd: 0.5, pricedSteps: 1, unknownModelSteps: 0, currency: 'USD' }),
})} />)
expect(screen.getByText('会话费用 $0.50').getAttribute('title')).toBeNull()
})
it('reads the projection through the openRouterCost key', () => {
const useProjection = vi.fn(() => undefined)
render(<CostDock {...makeProps({ useProjection })} />)
act(() => {})
expect(useProjection).toHaveBeenCalledWith('openRouterCost')
})
it('adds the subagent subtree to the figure and names its share', () => {
render(<CostDock {...makeProps(
{ useProjection: () => ({ totalUsd: 1, pricedSteps: 1, unknownModelSteps: 0, currency: 'USD' }) },
[{ id: 'child', parentId: PARENT, origin: 'subagent', cost: { totalUsd: 0.5, pricedSteps: 1, unknownModelSteps: 1 } }],
)} />)
const row = screen.getByText('会话费用 $1.50(含子代理 $0.50')
expect(row.getAttribute('title')).toBe('包含 1 个未知定价步骤')
})
it('follows a nested subagent chain and ignores non-subagent children', () => {
render(<CostDock {...makeProps(
{ useProjection: () => ({ totalUsd: 1, pricedSteps: 1, unknownModelSteps: 0, currency: 'USD' }) },
[
{ id: 'child', parentId: PARENT, origin: 'subagent', cost: { totalUsd: 0.25, pricedSteps: 1, unknownModelSteps: 0 } },
{ id: 'grandchild', parentId: 'child', origin: 'subagent', cost: { totalUsd: 0.125, pricedSteps: 1, unknownModelSteps: 0 } },
// An ordinary fork of the same parent is not delegated work.
{ id: 'sibling', parentId: PARENT, cost: { totalUsd: 9, pricedSteps: 1, unknownModelSteps: 0 } },
],
)} />)
expect(screen.getByText('会话费用 $1.38(含子代理 $0.38')).toBeTruthy()
})
it('shows the subagent subtree alone when the session itself priced nothing', () => {
render(<CostDock {...makeProps(
{ useProjection: () => undefined },
[{ id: 'child', parentId: PARENT, origin: 'subagent', cost: { totalUsd: 0.75, pricedSteps: 2, unknownModelSteps: 0 } }],
)} />)
expect(screen.getByText('会话费用 $0.75(含子代理 $0.75')).toBeTruthy()
})
it('skips a descendant the client holds no projection value for', () => {
render(<CostDock {...makeProps(
{ useProjection: () => ({ totalUsd: 2, pricedSteps: 1, unknownModelSteps: 0, currency: 'USD' }) },
[{ id: 'cold-child', parentId: PARENT, origin: 'subagent' }],
)} />)
expect(screen.getByText('会话费用 $2.00')).toBeTruthy()
})
it('terminates on a parentId cycle', () => {
render(<CostDock {...makeProps(
{ useProjection: () => ({ totalUsd: 1, pricedSteps: 1, unknownModelSteps: 0, currency: 'USD' }) },
[
{ id: 'a', parentId: PARENT, origin: 'subagent', cost: { totalUsd: 0.5, pricedSteps: 1, unknownModelSteps: 0 } },
{ id: PARENT, parentId: 'a', origin: 'subagent', cost: { totalUsd: 99, pricedSteps: 1, unknownModelSteps: 0 } },
],
)} />)
expect(screen.getByText('会话费用 $1.50(含子代理 $0.50')).toBeTruthy()
})
})