mirror of
https://github.com/AgentSeal/codeburn.git
synced 2026-08-11 09:34:45 +00:00
refactor(pricing): fan-out batch 3 — hermes, kiro, codewhale
This commit is contained in:
parent
7bc5f3b044
commit
c56f872cf3
6 changed files with 62 additions and 73 deletions
|
|
@ -4,7 +4,7 @@ import { join } from 'path'
|
|||
|
||||
import { extractBashCommands } from '../bash-utils.js'
|
||||
import { readSessionFile } from '../fs-utils.js'
|
||||
import { calculateCost, getShortModelName } from '../models.js'
|
||||
import { getShortModelName } from '../models.js'
|
||||
import type { ToolCall } from '../types.js'
|
||||
import type { ParsedProviderCall, Provider, SessionParser, SessionSource } from './types.js'
|
||||
|
||||
|
|
@ -390,10 +390,9 @@ function createParser(source: SessionSource, seenKeys: Set<string>): SessionPars
|
|||
const totalTokens = safeTokenCount(metadata.total_tokens)
|
||||
const model = metadata.model ?? metadata.model_provider ?? 'unknown'
|
||||
const localCost = reportedCost(metadata.cost)
|
||||
const costUSD = localCost.exact
|
||||
? localCost.value
|
||||
: calculateCost(model, totalTokens, 0, 0, 0, 0)
|
||||
if (totalTokens === 0 && costUSD === 0) return
|
||||
// Match the pre-lift guard exactly: it skipped zero-token sessions whose
|
||||
// COMPUTED cost was 0 — which included an exact recorded cost of 0.
|
||||
if (totalTokens === 0 && (!localCost.exact || localCost.value === 0)) return
|
||||
|
||||
const deduplicationKey = `codewhale:${metadata.id}`
|
||||
if (seenKeys.has(deduplicationKey)) return
|
||||
|
|
@ -420,7 +419,9 @@ function createParser(source: SessionSource, seenKeys: Set<string>): SessionPars
|
|||
cachedInputTokens: 0,
|
||||
reasoningTokens: 0,
|
||||
webSearchRequests,
|
||||
costUSD,
|
||||
...(localCost.exact
|
||||
? { costUSD: localCost.value, costBasis: 'measured' as const }
|
||||
: { costBasis: 'estimated' as const }),
|
||||
costIsEstimated: !localCost.exact,
|
||||
tools,
|
||||
bashCommands,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { readdir, stat } from 'fs/promises'
|
|||
import { basename, dirname, join } from 'path'
|
||||
import { homedir } from 'os'
|
||||
|
||||
import { calculateCost, getShortModelName } from '../models.js'
|
||||
import { getShortModelName } from '../models.js'
|
||||
import { isSqliteAvailable, getSqliteLoadError, openDatabase, isSqliteBusyError, type SqliteDatabase } from '../sqlite.js'
|
||||
import type { Provider, SessionSource, SessionParser, ParsedProviderCall } from './types.js'
|
||||
import type { ToolCall } from '../types.js'
|
||||
|
|
@ -390,23 +390,12 @@ function createParser(source: SessionSource, seenKeys: Set<string>, hermesHome:
|
|||
seenKeys.add(dedupKey)
|
||||
|
||||
// Hermes bills reasoning tokens at the output rate (same as Gemini).
|
||||
// The LiteLLM model table is used as a fallback when Hermes has not
|
||||
// stored an actual or estimated cost for the session.
|
||||
const calculatedCost = calculateCost(
|
||||
model,
|
||||
inputTokens,
|
||||
outputTokens + reasoningTokens,
|
||||
cacheWriteTokens,
|
||||
cacheReadTokens,
|
||||
0,
|
||||
)
|
||||
// When Hermes stored an actual or estimated cost, pass it as measured;
|
||||
// otherwise the pricing pass will estimate from token buckets.
|
||||
const recordedCost =
|
||||
(row.actual_cost_usd ?? 0) > 0 ? row.actual_cost_usd!
|
||||
: (row.estimated_cost_usd ?? 0) > 0 ? row.estimated_cost_usd!
|
||||
: null
|
||||
// When Hermes stored no cost (e.g. subscription-billed sessions), the
|
||||
// figure is our LiteLLM-priced estimate from the session token totals.
|
||||
const costUSD = recordedCost ?? calculatedCost
|
||||
const costIsEstimated = recordedCost === null
|
||||
|
||||
result = {
|
||||
|
|
@ -419,7 +408,9 @@ function createParser(source: SessionSource, seenKeys: Set<string>, hermesHome:
|
|||
cachedInputTokens: cacheReadTokens,
|
||||
reasoningTokens,
|
||||
webSearchRequests: 0,
|
||||
costUSD,
|
||||
...(recordedCost !== null
|
||||
? { costUSD: recordedCost, costBasis: 'measured' as const }
|
||||
: { costBasis: 'estimated' as const }),
|
||||
costIsEstimated,
|
||||
tools,
|
||||
bashCommands,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import { basename, dirname, extname, join } from 'path'
|
|||
import { homedir } from 'os'
|
||||
|
||||
import { readSessionFile } from '../fs-utils.js'
|
||||
import { calculateCost } from '../models.js'
|
||||
import { estimateTokensFromChars } from '../token-estimate.js'
|
||||
import type { ToolCall } from '../types.js'
|
||||
import type { Provider, SessionSource, SessionParser, ParsedProviderCall } from './types.js'
|
||||
|
|
@ -227,7 +226,6 @@ function parseChatFile(data: KiroChatFile, sessionId: string, project: string, s
|
|||
|
||||
const outputTokens = estimateTokensFromChars(totalOutputChars)
|
||||
const inputTokens = estimateTokensFromChars(pendingUserMessage.length)
|
||||
const costUSD = calculateCost(modelId, inputTokens, outputTokens, 0, 0, 0)
|
||||
const tsDate = parseKiroTimestamp(metadata.startTime)
|
||||
if (!tsDate) return results
|
||||
const timestamp = tsDate.toISOString()
|
||||
|
|
@ -243,7 +241,7 @@ function parseChatFile(data: KiroChatFile, sessionId: string, project: string, s
|
|||
cachedInputTokens: 0,
|
||||
reasoningTokens: 0,
|
||||
webSearchRequests: 0,
|
||||
costUSD,
|
||||
costBasis: 'estimated',
|
||||
costIsEstimated: true,
|
||||
tools: [...new Set(allTools)],
|
||||
bashCommands: [],
|
||||
|
|
@ -377,9 +375,6 @@ function parseModernExecution(data: KiroModernExecution, sourcePath: string, see
|
|||
// Prefer real metered credits at the public overage rate; fall back to
|
||||
// token-estimated pricing when the execution has no usage data — same
|
||||
// contract as the CLI and v2 parsers.
|
||||
const costUSD = executionCredits > 0
|
||||
? executionCredits * USD_PER_KIRO_CREDIT
|
||||
: calculateCost(modelId, inputTokens, outputTokens, 0, 0, 0)
|
||||
seenKeys.add(dedupKey)
|
||||
|
||||
results.push({
|
||||
|
|
@ -392,7 +387,9 @@ function parseModernExecution(data: KiroModernExecution, sourcePath: string, see
|
|||
cachedInputTokens: 0,
|
||||
reasoningTokens: 0,
|
||||
webSearchRequests: 0,
|
||||
costUSD,
|
||||
...(executionCredits > 0
|
||||
? { costUSD: executionCredits * USD_PER_KIRO_CREDIT, costBasis: 'measured' as const }
|
||||
: { costBasis: 'estimated' as const }),
|
||||
costIsEstimated: executionCredits === 0,
|
||||
tools: [...new Set(allTools)],
|
||||
bashCommands: [],
|
||||
|
|
@ -473,9 +470,6 @@ function parseCliSession(meta: KiroCliSessionMeta, entries: KiroCliEntry[], seen
|
|||
const turnCredits = turnMeta?.metering_usage
|
||||
? turnMeta.metering_usage.reduce((sum, m) => sum + m.value, 0)
|
||||
: 0
|
||||
const costUSD = turnCredits > 0
|
||||
? turnCredits * USD_PER_KIRO_CREDIT
|
||||
: calculateCost(modelId, inputTokens, outputTokens, 0, 0, 0)
|
||||
seenKeys.add(dedupKey)
|
||||
|
||||
results.push({
|
||||
|
|
@ -488,7 +482,9 @@ function parseCliSession(meta: KiroCliSessionMeta, entries: KiroCliEntry[], seen
|
|||
cachedInputTokens: 0,
|
||||
reasoningTokens: 0,
|
||||
webSearchRequests: 0,
|
||||
costUSD,
|
||||
...(turnCredits > 0
|
||||
? { costUSD: turnCredits * USD_PER_KIRO_CREDIT, costBasis: 'measured' as const }
|
||||
: { costBasis: 'estimated' as const }),
|
||||
costIsEstimated: turnCredits === 0,
|
||||
tools: [...new Set(allTools)],
|
||||
bashCommands: [],
|
||||
|
|
@ -633,7 +629,6 @@ async function parseWorkspaceSession(record: Record<string, unknown>, source: Se
|
|||
|
||||
const inputTokens = estimateTokensFromChars(inputChars)
|
||||
const outputTokens = estimateTokensFromChars(outputChars)
|
||||
const costUSD = calculateCost(modelId, inputTokens, outputTokens, 0, 0, 0)
|
||||
|
||||
results.push({
|
||||
provider: 'kiro',
|
||||
|
|
@ -645,7 +640,7 @@ async function parseWorkspaceSession(record: Record<string, unknown>, source: Se
|
|||
cachedInputTokens: 0,
|
||||
reasoningTokens: 0,
|
||||
webSearchRequests: 0,
|
||||
costUSD,
|
||||
costBasis: 'estimated',
|
||||
costIsEstimated: true,
|
||||
tools: [...new Set(allTools)],
|
||||
bashCommands: [],
|
||||
|
|
@ -743,9 +738,6 @@ async function parseV2Session(source: SessionSource, seenKeys: Set<string>): Pro
|
|||
// no usage_summary (e.g. still in progress or null usage). Reasoning
|
||||
// text is billed as output, so combine it for pricing only (same as
|
||||
// the codex provider).
|
||||
const costUSD = turnCredits > 0
|
||||
? turnCredits * USD_PER_KIRO_CREDIT
|
||||
: calculateCost(modelId, inputTokens, outputTokens + reasoningTokens, 0, 0, 0)
|
||||
results.push({
|
||||
provider: 'kiro',
|
||||
model: modelId,
|
||||
|
|
@ -756,7 +748,9 @@ async function parseV2Session(source: SessionSource, seenKeys: Set<string>): Pro
|
|||
cachedInputTokens: 0,
|
||||
reasoningTokens,
|
||||
webSearchRequests: 0,
|
||||
costUSD,
|
||||
...(turnCredits > 0
|
||||
? { costUSD: turnCredits * USD_PER_KIRO_CREDIT, costBasis: 'measured' as const }
|
||||
: { costBasis: 'estimated' as const }),
|
||||
costIsEstimated: turnCredits === 0,
|
||||
tools: [...new Set(tools)],
|
||||
bashCommands: [],
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { tmpdir } from 'os'
|
|||
import { join } from 'path'
|
||||
|
||||
import { clearSessionCache, parseAllSessions } from '../../src/parser.js'
|
||||
import { priceProviderCall } from '../../src/pricing-pass.js'
|
||||
import { sessionCachePath } from '../../src/session-cache.js'
|
||||
import { MAX_SESSION_FILE_BYTES } from '../../src/fs-utils.js'
|
||||
import { codewhale, createCodeWhaleProvider } from '../../src/providers/codewhale.js'
|
||||
|
|
@ -64,7 +65,7 @@ async function parseOne(path: string, seenKeys = new Set<string>()): Promise<Par
|
|||
const source = { path, project: 'fixture', provider: 'codewhale' }
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for await (const call of codewhale.createSessionParser(source, seenKeys).parse()) {
|
||||
calls.push(call)
|
||||
calls.push(priceProviderCall(call))
|
||||
}
|
||||
return calls
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { createRequire } from 'node:module'
|
|||
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { calculateCost } from '../../src/models.js'
|
||||
import { priceProviderCall } from '../../src/pricing-pass.js'
|
||||
import { createHermesProvider } from '../../src/providers/hermes.js'
|
||||
import { isSqliteAvailable } from '../../src/sqlite.js'
|
||||
import type { ParsedProviderCall } from '../../src/providers/types.js'
|
||||
|
|
@ -190,7 +191,7 @@ async function collectCalls(hermesHome: string, sourcePath: string): Promise<Par
|
|||
const provider = createHermesProvider(hermesHome)
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for await (const call of provider.createSessionParser({ path: sourcePath, project: 'hermes', provider: 'hermes' }, new Set()).parse()) {
|
||||
calls.push(call)
|
||||
calls.push(priceProviderCall(call))
|
||||
}
|
||||
return calls
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { mkdtemp, mkdir, writeFile, rm } from 'fs/promises'
|
|||
import { join } from 'path'
|
||||
import { tmpdir, homedir } from 'os'
|
||||
|
||||
import { priceProviderCall } from '../../src/pricing-pass.js'
|
||||
import { kiro, createKiroProvider } from '../../src/providers/kiro.js'
|
||||
import type { ParsedProviderCall } from '../../src/providers/types.js'
|
||||
|
||||
|
|
@ -99,7 +100,7 @@ describe('kiro provider - chat file parsing', () => {
|
|||
|
||||
const source = { path: chatPath, project: 'myproject', provider: 'kiro' }
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(call)
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(priceProviderCall(call))
|
||||
|
||||
expect(calls).toHaveLength(1)
|
||||
const call = calls[0]!
|
||||
|
|
@ -123,7 +124,7 @@ describe('kiro provider - chat file parsing', () => {
|
|||
|
||||
const source = { path: chatPath, project: 'test', provider: 'kiro' }
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(call)
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(priceProviderCall(call))
|
||||
|
||||
expect(calls).toHaveLength(1)
|
||||
expect(calls[0]!.model).toBe('kiro-auto')
|
||||
|
|
@ -158,7 +159,7 @@ describe('kiro provider - chat file parsing', () => {
|
|||
|
||||
const source = { path: chatPath, project: 'test', provider: 'kiro' }
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(call)
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(priceProviderCall(call))
|
||||
|
||||
expect(calls).toHaveLength(0)
|
||||
})
|
||||
|
|
@ -174,10 +175,10 @@ describe('kiro provider - chat file parsing', () => {
|
|||
const seenKeys = new Set<string>()
|
||||
|
||||
const calls1: ParsedProviderCall[] = []
|
||||
for await (const call of kiro.createSessionParser(source, seenKeys).parse()) calls1.push(call)
|
||||
for await (const call of kiro.createSessionParser(source, seenKeys).parse()) calls1.push(priceProviderCall(call))
|
||||
|
||||
const calls2: ParsedProviderCall[] = []
|
||||
for await (const call of kiro.createSessionParser(source, seenKeys).parse()) calls2.push(call)
|
||||
for await (const call of kiro.createSessionParser(source, seenKeys).parse()) calls2.push(priceProviderCall(call))
|
||||
|
||||
expect(calls1).toHaveLength(1)
|
||||
expect(calls2).toHaveLength(0)
|
||||
|
|
@ -186,7 +187,7 @@ describe('kiro provider - chat file parsing', () => {
|
|||
it('returns empty for missing file', async () => {
|
||||
const source = { path: '/nonexistent/test.chat', project: 'test', provider: 'kiro' }
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(call)
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(priceProviderCall(call))
|
||||
expect(calls).toHaveLength(0)
|
||||
})
|
||||
|
||||
|
|
@ -199,7 +200,7 @@ describe('kiro provider - chat file parsing', () => {
|
|||
|
||||
const source = { path: chatPath, project: 'test', provider: 'kiro' }
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(call)
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(priceProviderCall(call))
|
||||
expect(calls).toHaveLength(0)
|
||||
})
|
||||
|
||||
|
|
@ -213,7 +214,7 @@ describe('kiro provider - chat file parsing', () => {
|
|||
|
||||
const source = { path: chatPath, project: 'test', provider: 'kiro' }
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(call)
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(priceProviderCall(call))
|
||||
|
||||
expect(calls).toHaveLength(1)
|
||||
expect(calls[0]!.outputTokens).toBe(109)
|
||||
|
|
@ -231,7 +232,7 @@ describe('kiro provider - chat file parsing', () => {
|
|||
|
||||
const source = { path: chatPath, project: 'test', provider: 'kiro' }
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(call)
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(priceProviderCall(call))
|
||||
|
||||
expect(calls).toHaveLength(1)
|
||||
expect(calls[0]!.model).toBe('claude-haiku-4-5')
|
||||
|
|
@ -250,7 +251,7 @@ describe('kiro provider - chat file parsing', () => {
|
|||
|
||||
const source = { path: chatPath, project: 'test', provider: 'kiro' }
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(call)
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(priceProviderCall(call))
|
||||
|
||||
expect(calls).toHaveLength(1)
|
||||
expect(calls[0]!.sessionId).toBe('my-workflow-id')
|
||||
|
|
@ -272,7 +273,7 @@ describe('kiro provider - chat file parsing', () => {
|
|||
|
||||
const source = { path: executionPath, project: 'test', provider: 'kiro' }
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(call)
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(priceProviderCall(call))
|
||||
|
||||
expect(calls).toHaveLength(1)
|
||||
const call = calls[0]!
|
||||
|
|
@ -303,7 +304,7 @@ describe('kiro provider - chat file parsing', () => {
|
|||
|
||||
const source = { path: indexPath, project: 'test', provider: 'kiro' }
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(call)
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(priceProviderCall(call))
|
||||
|
||||
expect(calls).toHaveLength(0)
|
||||
})
|
||||
|
|
@ -325,7 +326,7 @@ describe('kiro provider - chat file parsing', () => {
|
|||
|
||||
const source = { path: executionPath, project: 'test', provider: 'kiro' }
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(call)
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(priceProviderCall(call))
|
||||
|
||||
expect(calls).toHaveLength(1)
|
||||
expect(calls[0]!.model).toBe('kiro-auto')
|
||||
|
|
@ -345,7 +346,7 @@ describe('kiro provider - chat file parsing', () => {
|
|||
|
||||
const source = { path: executionPath, project: 'test', provider: 'kiro' }
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(call)
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(priceProviderCall(call))
|
||||
|
||||
expect(calls).toHaveLength(1)
|
||||
expect(calls[0]!.timestamp).toBe('2026-04-27T23:36:40.000Z')
|
||||
|
|
@ -363,7 +364,7 @@ describe('kiro provider - chat file parsing', () => {
|
|||
|
||||
const source = { path: executionPath, project: 'test', provider: 'kiro' }
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(call)
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(priceProviderCall(call))
|
||||
|
||||
expect(calls).toHaveLength(1)
|
||||
expect(calls[0]!.timestamp).toBe('2026-04-27T23:36:40.000Z')
|
||||
|
|
@ -421,7 +422,7 @@ describe('kiro provider - chat file parsing', () => {
|
|||
|
||||
const source = { path: executionPath, project: 'test', provider: 'kiro' }
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(call)
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(priceProviderCall(call))
|
||||
|
||||
expect(calls).toHaveLength(1)
|
||||
expect(calls[0]!.userMessage).toBe(`request from ${key}`)
|
||||
|
|
@ -448,7 +449,7 @@ describe('kiro provider - chat file parsing', () => {
|
|||
|
||||
const source = { path: executionPath, project: 'test', provider: 'kiro' }
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(call)
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(priceProviderCall(call))
|
||||
|
||||
expect(calls).toHaveLength(1)
|
||||
expect(calls[0]!.tools).toEqual(['Bash'])
|
||||
|
|
@ -474,7 +475,7 @@ describe('kiro provider - chat file parsing', () => {
|
|||
|
||||
const source = { path: executionPath, project: 'test', provider: 'kiro' }
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(call)
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(priceProviderCall(call))
|
||||
|
||||
expect(calls).toHaveLength(1)
|
||||
expect(calls[0]!.tools).toEqual(['Edit'])
|
||||
|
|
@ -677,7 +678,7 @@ describe('kiro provider - CLI session discovery', () => {
|
|||
|
||||
const source = { path: join(cliDir, `${sessionId}.jsonl`), project: 'test-project', provider: 'kiro' }
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(call)
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(priceProviderCall(call))
|
||||
|
||||
expect(calls).toHaveLength(1)
|
||||
const call = calls[0]!
|
||||
|
|
@ -719,7 +720,7 @@ describe('kiro provider - CLI session discovery', () => {
|
|||
|
||||
const source = { path: join(cliDir, `${sessionId}.jsonl`), project: 'multi', provider: 'kiro' }
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(call)
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(priceProviderCall(call))
|
||||
|
||||
expect(calls).toHaveLength(2)
|
||||
expect(calls[0]!.userMessage).toBe('first question')
|
||||
|
|
@ -749,7 +750,7 @@ describe('kiro provider - CLI session discovery', () => {
|
|||
|
||||
const source = { path: join(cliDir, `${sessionId}.jsonl`), project: 'test-project', provider: 'kiro' }
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(call)
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(priceProviderCall(call))
|
||||
|
||||
expect(calls).toHaveLength(1)
|
||||
// Token-priced at the session's real model, not $0 — same fallback
|
||||
|
|
@ -783,7 +784,7 @@ describe('kiro provider - CLI session discovery', () => {
|
|||
|
||||
const source = { path: join(cliDir, `${sessionId}.jsonl`), project: 'test-project', provider: 'kiro' }
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(call)
|
||||
for await (const call of kiro.createSessionParser(source, new Set()).parse()) calls.push(priceProviderCall(call))
|
||||
|
||||
expect(calls).toHaveLength(1)
|
||||
expect(calls[0]!.costIsEstimated).toBe(true)
|
||||
|
|
@ -839,7 +840,7 @@ describe('kiro provider - context.messages with entries', () => {
|
|||
const calls: ParsedProviderCall[] = []
|
||||
for (const source of sessions) {
|
||||
for await (const call of provider.createSessionParser(source, new Set()).parse()) {
|
||||
calls.push(call)
|
||||
calls.push(priceProviderCall(call))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -879,7 +880,7 @@ describe('kiro provider - context.messages with entries', () => {
|
|||
const calls: ParsedProviderCall[] = []
|
||||
for (const source of sessions) {
|
||||
for await (const call of provider.createSessionParser(source, new Set()).parse()) {
|
||||
calls.push(call)
|
||||
calls.push(priceProviderCall(call))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -919,7 +920,7 @@ describe('kiro provider - context.messages with entries', () => {
|
|||
const calls: ParsedProviderCall[] = []
|
||||
for (const source of sessions) {
|
||||
for await (const call of provider.createSessionParser(source, new Set()).parse()) {
|
||||
calls.push(call)
|
||||
calls.push(priceProviderCall(call))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -947,7 +948,7 @@ describe('kiro provider - context.messages with entries', () => {
|
|||
const calls: ParsedProviderCall[] = []
|
||||
for (const source of sessions) {
|
||||
for await (const call of provider.createSessionParser(source, new Set()).parse()) {
|
||||
calls.push(call)
|
||||
calls.push(priceProviderCall(call))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -996,7 +997,7 @@ describe('kiro provider - workspace-sessions format', () => {
|
|||
const calls: ParsedProviderCall[] = []
|
||||
for (const source of wsSessions) {
|
||||
for await (const call of provider.createSessionParser(source, new Set()).parse()) {
|
||||
calls.push(call)
|
||||
calls.push(priceProviderCall(call))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1032,7 +1033,7 @@ describe('kiro provider - workspace-sessions format', () => {
|
|||
const calls: ParsedProviderCall[] = []
|
||||
for (const source of sessions) {
|
||||
for await (const call of provider.createSessionParser(source, new Set()).parse()) {
|
||||
calls.push(call)
|
||||
calls.push(priceProviderCall(call))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1139,7 +1140,7 @@ describe('kiro provider - v2 sess_ format', () => {
|
|||
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for (const source of v2) {
|
||||
for await (const call of provider.createSessionParser(source, new Set()).parse()) calls.push(call)
|
||||
for await (const call of provider.createSessionParser(source, new Set()).parse()) calls.push(priceProviderCall(call))
|
||||
}
|
||||
|
||||
expect(calls).toHaveLength(2)
|
||||
|
|
@ -1173,7 +1174,7 @@ describe('kiro provider - v2 sess_ format', () => {
|
|||
const sources = await provider.discoverSessions()
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for (const source of sources) {
|
||||
for await (const call of provider.createSessionParser(source, new Set()).parse()) calls.push(call)
|
||||
for await (const call of provider.createSessionParser(source, new Set()).parse()) calls.push(priceProviderCall(call))
|
||||
}
|
||||
|
||||
expect(calls).toHaveLength(2)
|
||||
|
|
@ -1199,7 +1200,7 @@ describe('kiro provider - v2 sess_ format', () => {
|
|||
const sources = await provider.discoverSessions()
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for (const source of sources) {
|
||||
for await (const call of provider.createSessionParser(source, new Set()).parse()) calls.push(call)
|
||||
for await (const call of provider.createSessionParser(source, new Set()).parse()) calls.push(priceProviderCall(call))
|
||||
}
|
||||
|
||||
expect(calls).toHaveLength(2)
|
||||
|
|
@ -1218,7 +1219,7 @@ describe('kiro provider - v2 sess_ format', () => {
|
|||
const sources = await provider.discoverSessions()
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for (const source of sources) {
|
||||
for await (const call of provider.createSessionParser(source, new Set()).parse()) calls.push(call)
|
||||
for await (const call of provider.createSessionParser(source, new Set()).parse()) calls.push(priceProviderCall(call))
|
||||
}
|
||||
|
||||
expect(calls).toHaveLength(1)
|
||||
|
|
@ -1325,7 +1326,7 @@ describe('kiro provider - mixed-format coexistence (legacy + v1 + workspace-sess
|
|||
const seenKeys = new Set<string>()
|
||||
const calls: ParsedProviderCall[] = []
|
||||
for (const source of sources) {
|
||||
for await (const call of provider.createSessionParser(source, seenKeys).parse()) calls.push(call)
|
||||
for await (const call of provider.createSessionParser(source, seenKeys).parse()) calls.push(priceProviderCall(call))
|
||||
}
|
||||
return calls
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue