feat: ship skill and MCP workflows with signed updater for v0.0.7
This commit is contained in:
1 parent
1b52df0603
commit
a01085c656
136 files changed
+18646
-217
No files matched your search
@@ -0,0 +1,73 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { createContextUsageService, type ContextUsageDependencies } from '../src/main/context-usage-service'
|
||||
import type { ChatMessage, ContextUsageBreakdown } from '../src/shared/types'
|
||||
|
||||
const sample = {
|
||||
usage: { inputTokens: 1200, outputTokens: 100, totalTokens: 1300 },
|
||||
contextWindow: 10_000,
|
||||
source: 'upstream' as const,
|
||||
sampledAt: 100,
|
||||
requestId: 'request-a',
|
||||
modelId: 'model-a'
|
||||
}
|
||||
const assistant = (overrides: Partial<ChatMessage> = {}): ChatMessage => ({
|
||||
id: 'assistant-a',
|
||||
role: 'assistant',
|
||||
content: 'answer',
|
||||
modelId: 'model-a',
|
||||
requestId: 'request-a',
|
||||
contextUsage: sample,
|
||||
createdAt: 1,
|
||||
status: 'done',
|
||||
...overrides
|
||||
})
|
||||
const breakdown: ContextUsageBreakdown = {
|
||||
requestId: 'request-a',
|
||||
sequence: 3,
|
||||
sampledAt: 101,
|
||||
modelId: 'model-a',
|
||||
contextWindow: 10_000,
|
||||
method: 'native-summary',
|
||||
scope: 'provider-request',
|
||||
counts: { system: 100, tools: 100, conversation: 900, mcp: 50, skills: 50, other: 0 },
|
||||
inputTokens: 1200,
|
||||
partial: false
|
||||
}
|
||||
|
||||
function service(overrides: Partial<ContextUsageDependencies> = {}) {
|
||||
const dependencies: ContextUsageDependencies = {
|
||||
messages: async () => [assistant()],
|
||||
modelId: async () => 'model-a',
|
||||
running: () => false,
|
||||
summary: async () => undefined,
|
||||
persistIfCurrent: async () => undefined,
|
||||
...overrides
|
||||
}
|
||||
return createContextUsageService(dependencies)
|
||||
}
|
||||
|
||||
assert.deepEqual(await service({ messages: async () => [] }).get('empty'),
|
||||
{ status: 'unavailable', reason: '发送消息后可查看用量' })
|
||||
|
||||
const latest = await service().get('latest')
|
||||
assert.equal(latest.status, 'latest')
|
||||
assert.equal(latest.sample?.usage.inputTokens, 1200)
|
||||
|
||||
const previous = await service({ modelId: async () => 'model-b' }).get('previous')
|
||||
assert.equal(previous.status, 'previous')
|
||||
assert.equal(previous.reason, '来自切换模型前的最近请求')
|
||||
|
||||
const running = await service({ modelId: async () => 'model-b', running: () => true }).get('running')
|
||||
assert.equal(running.status, 'latest', 'the active run must not be relabelled when the next-send model changes')
|
||||
|
||||
const summary = await service({ summary: async () => breakdown }).get('summary')
|
||||
assert.equal(summary.breakdown?.sequence, 3)
|
||||
assert.equal(summary.status, 'latest', 'a matching native summary augments the current request without replacing its upstream total')
|
||||
|
||||
const mismatched = await service({ summary: async () => ({ ...breakdown, requestId: 'older-request' }) }).get('mismatch')
|
||||
assert.equal(mismatched.breakdown, undefined, 'a late summary for another request must not attach to the latest assistant message')
|
||||
|
||||
const summaryFailure = await service({ summary: async () => { throw new Error('query failed') } }).get('failure')
|
||||
assert.equal(summaryFailure.sample?.usage.inputTokens, 1200, 'summary failures retain the real streamed usage sample')
|
||||
|
||||
console.log('context-usage-regression: latest, previous, active-run, summary identity and failure cases passed')
|
||||
Reference in new issue
Block a user