refactor(web): project usage and snapshot request context
This commit is contained in:
@@ -102,7 +102,7 @@ describe('runtime client apply', () => {
|
||||
expect(bench.api.callsOf('session.create')).toHaveLength(1)
|
||||
})
|
||||
|
||||
it('clears connection-local Session state on disconnect but not connected', async () => {
|
||||
it('clears connection-local request telemetry on reconnect but not connected', async () => {
|
||||
const bench = await mount()
|
||||
const sessions = bench.ctx.get('sessions') as SessionsService
|
||||
bench.sinks?.onHostEnvelope?.({
|
||||
@@ -112,21 +112,8 @@ describe('runtime client apply', () => {
|
||||
await Promise.resolve()
|
||||
const session = sessions.binding('s-state' as never)?.session
|
||||
if (session === undefined) throw new Error('session binding missing')
|
||||
const currentMetrics = {
|
||||
projectionRevision: 4,
|
||||
logRevision: 10,
|
||||
uncachedInputTokens: 10,
|
||||
outputTokens: 4,
|
||||
cacheReadTokens: 90,
|
||||
cacheWriteTokens: 3,
|
||||
contextTokens: 35,
|
||||
}
|
||||
bench.sinks?.onMuxEnvelope?.({
|
||||
rpcId: 'metrics' as never,
|
||||
payload: { type: 'session/metrics', sessionId: 's-state', metrics: currentMetrics } as never,
|
||||
})
|
||||
bench.sinks?.onMuxEnvelope?.({
|
||||
rpcId: 'capacity' as never,
|
||||
rpcId: 'request' as never,
|
||||
payload: {
|
||||
type: 'session/model-request',
|
||||
sessionId: 's-state',
|
||||
@@ -134,19 +121,20 @@ describe('runtime client apply', () => {
|
||||
step: 1,
|
||||
provider: 'test',
|
||||
model: 'alpha',
|
||||
contextTokens: 32_000,
|
||||
contextWindow: 128_000,
|
||||
} as never,
|
||||
})
|
||||
|
||||
bench.sinks?.onConnected?.()
|
||||
expect(session.getSnapshot()).toMatchObject({
|
||||
metrics: currentMetrics,
|
||||
modelRequestContextWindow: 128_000,
|
||||
expect(session.getSnapshot().modelRequest).toMatchObject({
|
||||
model: 'alpha',
|
||||
contextTokens: 32_000,
|
||||
contextWindow: 128_000,
|
||||
})
|
||||
|
||||
bench.sinks?.onDisconnected?.()
|
||||
expect(session.getSnapshot().metrics).toBeNull()
|
||||
expect(session.getSnapshot().modelRequestContextWindow).toBeUndefined()
|
||||
bench.sinks?.onStateChange?.('reconnecting')
|
||||
expect(session.getSnapshot().modelRequest).toBeNull()
|
||||
})
|
||||
|
||||
it('stops the stream loop when the plugin fiber unloads', async () => {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import type { CommandId } from '@deepseek-ai/dsh-commands/brand'
|
||||
import type {
|
||||
ClientResponse, CommandDescriptor, HostFrame, IApiClient, ModelTarget, MuxFrame,
|
||||
RpcError, RpcReceipt, RpcRequest, RpcResponse, SessionId, SessionMetrics, SessionModels,
|
||||
RpcError, RpcReceipt, RpcRequest, RpcResponse, SessionId, SessionModels,
|
||||
SessionProjectionsBlock, SkillEntry,
|
||||
WorkspaceId, WorkspaceView,
|
||||
} from '@deepseek-ai/dsh-client-connection/client'
|
||||
@@ -69,7 +69,6 @@ export class FakeApiClient implements IApiClient {
|
||||
events: never[]
|
||||
hasMore: boolean
|
||||
projections?: SessionProjectionsBlock
|
||||
metrics?: SessionMetrics
|
||||
}>> =
|
||||
() => Promise.resolve(ok({ events: [], hasMore: false }))
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import type { SessionId, SessionMetrics } from '@deepseek-ai/dsh-client-connection/client'
|
||||
import type { SessionId } from '@deepseek-ai/dsh-client-connection/client'
|
||||
import { SessionManager } from '../src/client/sessions/manager.ts'
|
||||
import { FakeApiClient, deferred, err, ok } from './fake-api.ts'
|
||||
import { entries, plainTurn } from './event-script.ts'
|
||||
@@ -41,7 +41,7 @@ describe('instances', () => {
|
||||
expect(manager.get(S2).getSnapshot().pending).toEqual([])
|
||||
})
|
||||
|
||||
it('retains the latest transient model capacity until lazy instantiation', () => {
|
||||
it('retains the latest transient request snapshot until lazy instantiation', () => {
|
||||
const api = new FakeApiClient()
|
||||
const manager = new SessionManager(api)
|
||||
manager.handleMuxEnvelope({
|
||||
@@ -53,6 +53,7 @@ describe('instances', () => {
|
||||
step: 1,
|
||||
provider: 'test',
|
||||
model: 'alpha',
|
||||
contextTokens: 12_000,
|
||||
contextWindow: 128_000,
|
||||
},
|
||||
})
|
||||
@@ -65,14 +66,22 @@ describe('instances', () => {
|
||||
step: 2,
|
||||
provider: 'test',
|
||||
model: 'beta',
|
||||
contextTokens: 32_000,
|
||||
contextWindow: 256_000,
|
||||
},
|
||||
})
|
||||
|
||||
expect(manager.get(S1).getSnapshot().modelRequestContextWindow).toBe(256_000)
|
||||
expect(manager.get(S1).getSnapshot().modelRequest).toEqual({
|
||||
turn: 1,
|
||||
step: 2,
|
||||
provider: 'test',
|
||||
model: 'beta',
|
||||
contextTokens: 32_000,
|
||||
contextWindow: 256_000,
|
||||
})
|
||||
})
|
||||
|
||||
it('retains explicit capacity clearing before lazy instantiation', () => {
|
||||
it('retains whole-frame replacement before lazy instantiation', () => {
|
||||
const api = new FakeApiClient()
|
||||
const manager = new SessionManager(api)
|
||||
manager.handleMuxEnvelope({
|
||||
@@ -99,10 +108,15 @@ describe('instances', () => {
|
||||
},
|
||||
})
|
||||
|
||||
expect(manager.get(S1).getSnapshot().modelRequestContextWindow).toBeUndefined()
|
||||
expect(manager.get(S1).getSnapshot().modelRequest).toEqual({
|
||||
turn: 1,
|
||||
step: 2,
|
||||
provider: 'test',
|
||||
model: 'unknown-capacity',
|
||||
})
|
||||
})
|
||||
|
||||
it('clears retained capacity on subscribed and resident capacity on removal', () => {
|
||||
it('clears retained request telemetry on subscribed and removal', () => {
|
||||
const api = new FakeApiClient()
|
||||
const manager = new SessionManager(api)
|
||||
manager.handleMuxEnvelope({
|
||||
@@ -122,7 +136,7 @@ describe('instances', () => {
|
||||
payload: { type: 'session/subscribed', sessionId: S1, lastSeq: 0 },
|
||||
})
|
||||
const session = manager.get(S1)
|
||||
expect(session.getSnapshot().modelRequestContextWindow).toBeUndefined()
|
||||
expect(session.getSnapshot().modelRequest).toBeNull()
|
||||
|
||||
manager.handleMuxEnvelope({
|
||||
rpcId: 'request-after-subscribe' as never,
|
||||
@@ -136,12 +150,12 @@ describe('instances', () => {
|
||||
contextWindow: 256_000,
|
||||
},
|
||||
})
|
||||
expect(session.getSnapshot().modelRequestContextWindow).toBe(256_000)
|
||||
expect(session.getSnapshot().modelRequest?.contextWindow).toBe(256_000)
|
||||
manager.handleHostEnvelope({
|
||||
rpcId: 'removed' as never,
|
||||
payload: { type: 'host/session-removed', sessionId: S1 },
|
||||
})
|
||||
expect(session.getSnapshot().modelRequestContextWindow).toBeUndefined()
|
||||
expect(session.getSnapshot().modelRequest).toBeNull()
|
||||
|
||||
manager.handleMuxEnvelope({
|
||||
rpcId: 'request-before-lazy-removal' as never,
|
||||
@@ -159,28 +173,15 @@ describe('instances', () => {
|
||||
rpcId: 'lazy-removed' as never,
|
||||
payload: { type: 'host/session-removed', sessionId: S2 },
|
||||
})
|
||||
expect(manager.get(S2).getSnapshot().modelRequestContextWindow).toBeUndefined()
|
||||
expect(manager.get(S2).getSnapshot().modelRequest).toBeNull()
|
||||
})
|
||||
|
||||
it('clears resident metrics and capacity plus lazy capacity before reconnect', () => {
|
||||
it('clears resident and lazy request telemetry on disconnect', () => {
|
||||
const api = new FakeApiClient()
|
||||
const manager = new SessionManager(api)
|
||||
const session = manager.get(S1)
|
||||
const currentMetrics: SessionMetrics = {
|
||||
projectionRevision: 4,
|
||||
logRevision: 10,
|
||||
uncachedInputTokens: 10,
|
||||
outputTokens: 4,
|
||||
cacheReadTokens: 90,
|
||||
cacheWriteTokens: 3,
|
||||
contextTokens: 35,
|
||||
}
|
||||
manager.handleMuxEnvelope({
|
||||
rpcId: 'metrics' as never,
|
||||
payload: { type: 'session/metrics', sessionId: S1, metrics: currentMetrics },
|
||||
})
|
||||
manager.handleMuxEnvelope({
|
||||
rpcId: 'resident-capacity' as never,
|
||||
rpcId: 'resident-request' as never,
|
||||
payload: {
|
||||
type: 'session/model-request',
|
||||
sessionId: S1,
|
||||
@@ -188,11 +189,12 @@ describe('instances', () => {
|
||||
step: 1,
|
||||
provider: 'test',
|
||||
model: 'resident',
|
||||
contextTokens: 35,
|
||||
contextWindow: 128_000,
|
||||
},
|
||||
})
|
||||
manager.handleMuxEnvelope({
|
||||
rpcId: 'lazy-capacity' as never,
|
||||
rpcId: 'lazy-request' as never,
|
||||
payload: {
|
||||
type: 'session/model-request',
|
||||
sessionId: S2,
|
||||
@@ -200,19 +202,20 @@ describe('instances', () => {
|
||||
step: 1,
|
||||
provider: 'test',
|
||||
model: 'lazy',
|
||||
contextTokens: 70,
|
||||
contextWindow: 256_000,
|
||||
},
|
||||
})
|
||||
expect(session.getSnapshot()).toMatchObject({
|
||||
metrics: currentMetrics,
|
||||
modelRequestContextWindow: 128_000,
|
||||
expect(session.getSnapshot().modelRequest).toMatchObject({
|
||||
model: 'resident',
|
||||
contextTokens: 35,
|
||||
contextWindow: 128_000,
|
||||
})
|
||||
|
||||
manager.handleReconnecting()
|
||||
manager.handleDisconnected()
|
||||
|
||||
expect(session.getSnapshot().metrics).toBeNull()
|
||||
expect(session.getSnapshot().modelRequestContextWindow).toBeUndefined()
|
||||
expect(manager.get(S2).getSnapshot().modelRequestContextWindow).toBeUndefined()
|
||||
expect(session.getSnapshot().modelRequest).toBeNull()
|
||||
expect(manager.get(S2).getSnapshot().modelRequest).toBeNull()
|
||||
})
|
||||
|
||||
it('caps the pending buffer at 32 keeping the newest, and drops it on session-removed', () => {
|
||||
|
||||
@@ -10,7 +10,7 @@ import { describe, expect, it, vi } from 'vitest'
|
||||
import { Context } from 'cordis'
|
||||
import type { SessionEvent } from '@deepseek-ai/dsh-session/types'
|
||||
import type {
|
||||
SessionId, SessionMetrics, SessionProjectionsBlock,
|
||||
SessionId, SessionProjectionsBlock,
|
||||
} from '@deepseek-ai/dsh-client-connection/client'
|
||||
import { Session } from '../src/client/sessions/session.ts'
|
||||
import { FakeApiClient, deferred, err, ok } from './fake-api.ts'
|
||||
@@ -29,34 +29,15 @@ function histResponse(
|
||||
events: SessionEvent[],
|
||||
hasMore = false,
|
||||
projections?: SessionProjectionsBlock,
|
||||
metrics?: SessionMetrics,
|
||||
) {
|
||||
// history now returns HistoryEntry[] ({event, view?}); these tests are view-less.
|
||||
return Promise.resolve(ok({
|
||||
events: entries(events) as never[],
|
||||
hasMore,
|
||||
...projections === undefined ? {} : { projections },
|
||||
...metrics === undefined ? {} : { metrics },
|
||||
}))
|
||||
}
|
||||
|
||||
function metrics(
|
||||
projectionRevision: number,
|
||||
logRevision: number,
|
||||
over: Partial<SessionMetrics> = {},
|
||||
): SessionMetrics {
|
||||
return {
|
||||
projectionRevision,
|
||||
logRevision,
|
||||
uncachedInputTokens: 10,
|
||||
outputTokens: 4,
|
||||
cacheReadTokens: 90,
|
||||
cacheWriteTokens: 3,
|
||||
contextTokens: 35,
|
||||
...over,
|
||||
}
|
||||
}
|
||||
|
||||
describe('open', () => {
|
||||
it('installs the tail page: cold → loading → open with window and nodes in place', async () => {
|
||||
const { api, session } = makeSession()
|
||||
@@ -70,19 +51,7 @@ describe('open', () => {
|
||||
expect(snapshot.openState).toBe('open')
|
||||
expect(snapshot.hasMore).toBe(true)
|
||||
expect(snapshot.nodes.map(n => n.kind)).toEqual(['user', 'assistant'])
|
||||
expect(snapshot.metrics).toBeNull()
|
||||
})
|
||||
|
||||
it('installs full-log metrics independently of older history pages', async () => {
|
||||
const { api, session } = makeSession()
|
||||
const tailMetrics = metrics(4, 106)
|
||||
api.onHistory = () => histResponse(plainTurn(100, 3, '问', '答'), true, undefined, tailMetrics)
|
||||
await session.open()
|
||||
expect(session.getSnapshot().metrics).toBe(tailMetrics)
|
||||
|
||||
api.onHistory = () => histResponse(plainTurn(94, 2, '旧问', '旧答'))
|
||||
await session.loadOlder()
|
||||
expect(session.getSnapshot().metrics).toBe(tailMetrics)
|
||||
expect(snapshot.modelRequest).toBeNull()
|
||||
})
|
||||
|
||||
it('is idempotent: concurrent opens share one history call, reopening when open is a no-op', async () => {
|
||||
@@ -147,17 +116,8 @@ describe('live event path', () => {
|
||||
expect(session.getSnapshot().nodes).toEqual(before.nodes)
|
||||
})
|
||||
|
||||
it('keeps live capacity separate from durable metrics, replaces or clears it on requests, and resets at subscription', async () => {
|
||||
it('replaces the whole request snapshot, clears omitted fields, and resets at subscription', async () => {
|
||||
const { session } = await opened()
|
||||
const current = metrics(8, 10)
|
||||
session.handleMuxEnvelope('m1' as never, {
|
||||
type: 'session/metrics',
|
||||
sessionId: SID,
|
||||
metrics: current,
|
||||
})
|
||||
expect(session.getSnapshot().metrics).toBe(current)
|
||||
expect(session.getSnapshot().modelRequestContextWindow).toBeUndefined()
|
||||
|
||||
session.handleMuxEnvelope('request-1' as never, {
|
||||
type: 'session/model-request',
|
||||
sessionId: SID,
|
||||
@@ -165,32 +125,17 @@ describe('live event path', () => {
|
||||
step: 1,
|
||||
provider: 'test',
|
||||
model: 'alpha',
|
||||
contextTokens: 32_000,
|
||||
contextWindow: 128_000,
|
||||
})
|
||||
expect(session.getSnapshot().metrics).toBe(current)
|
||||
expect(session.getSnapshot().modelRequestContextWindow).toBe(128_000)
|
||||
|
||||
session.handleMuxEnvelope('m2' as never, {
|
||||
type: 'session/metrics',
|
||||
sessionId: SID,
|
||||
metrics: metrics(9, 9, { uncachedInputTokens: 1 }),
|
||||
expect(session.getSnapshot().modelRequest).toEqual({
|
||||
turn: 1,
|
||||
step: 1,
|
||||
provider: 'test',
|
||||
model: 'alpha',
|
||||
contextTokens: 32_000,
|
||||
contextWindow: 128_000,
|
||||
})
|
||||
session.handleMuxEnvelope('m3' as never, {
|
||||
type: 'session/metrics',
|
||||
sessionId: SID,
|
||||
metrics: metrics(7, 11, { uncachedInputTokens: 2 }),
|
||||
})
|
||||
expect(session.getSnapshot().metrics).toBe(current)
|
||||
expect(session.getSnapshot().modelRequestContextWindow).toBe(128_000)
|
||||
|
||||
const ordinaryUpdate = metrics(9, 11, { contextTokens: 40 })
|
||||
session.handleMuxEnvelope('m4' as never, {
|
||||
type: 'session/metrics',
|
||||
sessionId: SID,
|
||||
metrics: ordinaryUpdate,
|
||||
})
|
||||
expect(session.getSnapshot().metrics).toBe(ordinaryUpdate)
|
||||
expect(session.getSnapshot().modelRequestContextWindow).toBe(128_000)
|
||||
|
||||
session.handleMuxEnvelope('request-2' as never, {
|
||||
type: 'session/model-request',
|
||||
@@ -200,16 +145,19 @@ describe('live event path', () => {
|
||||
provider: 'test',
|
||||
model: 'without-capacity',
|
||||
})
|
||||
expect(session.getSnapshot().metrics).toEqual(ordinaryUpdate)
|
||||
expect(session.getSnapshot().modelRequestContextWindow).toBeUndefined()
|
||||
expect(session.getSnapshot().modelRequest).toEqual({
|
||||
turn: 2,
|
||||
step: 1,
|
||||
provider: 'test',
|
||||
model: 'without-capacity',
|
||||
})
|
||||
|
||||
session.handleMuxEnvelope('sub' as never, {
|
||||
type: 'session/subscribed',
|
||||
sessionId: SID,
|
||||
lastSeq: 5,
|
||||
})
|
||||
expect(session.getSnapshot().metrics).toBeNull()
|
||||
expect(session.getSnapshot().modelRequestContextWindow).toBeUndefined()
|
||||
expect(session.getSnapshot().modelRequest).toBeNull()
|
||||
session.handleMuxEnvelope('request-3' as never, {
|
||||
type: 'session/model-request',
|
||||
sessionId: SID,
|
||||
@@ -217,19 +165,17 @@ describe('live event path', () => {
|
||||
step: 1,
|
||||
provider: 'test',
|
||||
model: 'beta',
|
||||
contextTokens: 20,
|
||||
contextWindow: 256_000,
|
||||
})
|
||||
const nextGeneration = metrics(0, 10, { contextTokens: 20 })
|
||||
session.handleMuxEnvelope('m5' as never, {
|
||||
type: 'session/metrics',
|
||||
sessionId: SID,
|
||||
metrics: nextGeneration,
|
||||
expect(session.getSnapshot().modelRequest).toMatchObject({
|
||||
turn: 3,
|
||||
contextTokens: 20,
|
||||
contextWindow: 256_000,
|
||||
})
|
||||
expect(session.getSnapshot().metrics).toBe(nextGeneration)
|
||||
expect(session.getSnapshot().modelRequestContextWindow).toBe(256_000)
|
||||
})
|
||||
|
||||
it('publishes a subscribed reset when capacity arrived before durable metrics', async () => {
|
||||
it('publishes a subscribed reset when request telemetry arrived first', async () => {
|
||||
const { session } = await opened()
|
||||
session.handleMuxEnvelope('request' as never, {
|
||||
type: 'session/model-request',
|
||||
@@ -238,17 +184,17 @@ describe('live event path', () => {
|
||||
step: 1,
|
||||
provider: 'test',
|
||||
model: 'alpha',
|
||||
contextTokens: 8_000,
|
||||
contextWindow: 128_000,
|
||||
})
|
||||
expect(session.getSnapshot().metrics).toBeNull()
|
||||
expect(session.getSnapshot().modelRequestContextWindow).toBe(128_000)
|
||||
expect(session.getSnapshot().modelRequest?.contextWindow).toBe(128_000)
|
||||
|
||||
session.handleMuxEnvelope('sub' as never, {
|
||||
type: 'session/subscribed',
|
||||
sessionId: SID,
|
||||
lastSeq: 5,
|
||||
})
|
||||
expect(session.getSnapshot().modelRequestContextWindow).toBeUndefined()
|
||||
expect(session.getSnapshot().modelRequest).toBeNull()
|
||||
})
|
||||
|
||||
it('materializes a command node from live lifecycle frames and reproduces it from a history window', async () => {
|
||||
@@ -876,72 +822,61 @@ describe('remaining branches', () => {
|
||||
})
|
||||
|
||||
describe('resync', () => {
|
||||
it('fences pre-disconnect history behind a fresh mux metrics baseline', async () => {
|
||||
it('clears request telemetry on reconnect and drops a stale in-flight history response', async () => {
|
||||
const { api, session } = makeSession()
|
||||
const stale = deferred<Awaited<ReturnType<FakeApiClient['onHistory']>>>()
|
||||
api.onHistory = () => stale.promise
|
||||
const opening = session.open()
|
||||
const oldLiveMetrics = metrics(8, 10)
|
||||
session.handleMuxEnvelope('old-metrics' as never, {
|
||||
type: 'session/metrics',
|
||||
sessionId: SID,
|
||||
metrics: oldLiveMetrics,
|
||||
})
|
||||
session.handleMuxEnvelope('old-capacity' as never, {
|
||||
session.handleMuxEnvelope('old-request' as never, {
|
||||
type: 'session/model-request',
|
||||
sessionId: SID,
|
||||
turn: 1,
|
||||
step: 1,
|
||||
provider: 'test',
|
||||
model: 'old',
|
||||
contextTokens: 20,
|
||||
contextWindow: 128_000,
|
||||
})
|
||||
|
||||
session.handleReconnecting()
|
||||
expect(session.getSnapshot().metrics).toBeNull()
|
||||
expect(session.getSnapshot().modelRequestContextWindow).toBeUndefined()
|
||||
const freshMetrics = metrics(0, 1, { contextTokens: 20 })
|
||||
session.handleMuxEnvelope('fresh-metrics' as never, {
|
||||
type: 'session/metrics',
|
||||
sessionId: SID,
|
||||
metrics: freshMetrics,
|
||||
})
|
||||
expect(session.getSnapshot().modelRequest).toBeNull()
|
||||
|
||||
stale.resolve(ok({
|
||||
events: entries(plainTurn(0, 0, '旧问', '旧答')) as never[],
|
||||
hasMore: false,
|
||||
metrics: metrics(99, 99, { contextTokens: 999 }),
|
||||
}))
|
||||
await opening
|
||||
expect(session.getSnapshot().nodes).toEqual([])
|
||||
expect(session.getSnapshot().metrics).toBe(freshMetrics)
|
||||
expect(session.getSnapshot().modelRequest).toBeNull()
|
||||
|
||||
api.onHistory = () => histResponse(plainTurn(6, 1, '新问', '新答'))
|
||||
await session.resync()
|
||||
expect(session.getSnapshot().openState).toBe('open')
|
||||
expect(session.getSnapshot().nodes.map(node => node.seq)).toEqual([7, 9])
|
||||
expect(session.getSnapshot().metrics).toBe(freshMetrics)
|
||||
expect(session.getSnapshot().modelRequest).toBeNull()
|
||||
})
|
||||
|
||||
it('preserves fresh-generation metrics that arrive before a failing history refresh', async () => {
|
||||
it('preserves a fresh-generation request snapshot when history resync fails', async () => {
|
||||
const { api, session } = makeSession()
|
||||
const oldMetrics = metrics(8, 10)
|
||||
api.onHistory = () => histResponse(plainTurn(0, 0, 'a', 'b'), false, undefined, oldMetrics)
|
||||
api.onHistory = () => histResponse(plainTurn(0, 0, 'a', 'b'))
|
||||
await session.open()
|
||||
expect(session.getSnapshot().metrics).toBe(oldMetrics)
|
||||
|
||||
session.handleMuxEnvelope('sub' as never, {
|
||||
type: 'session/subscribed',
|
||||
sessionId: SID,
|
||||
lastSeq: 5,
|
||||
})
|
||||
expect(session.getSnapshot().metrics).toBeNull()
|
||||
expect(session.getSnapshot().modelRequest).toBeNull()
|
||||
|
||||
const freshMetrics = metrics(0, 10, { contextTokens: 20 })
|
||||
session.handleMuxEnvelope('fresh-metrics' as never, {
|
||||
type: 'session/metrics',
|
||||
session.handleMuxEnvelope('fresh-request' as never, {
|
||||
type: 'session/model-request',
|
||||
sessionId: SID,
|
||||
metrics: freshMetrics,
|
||||
turn: 2,
|
||||
step: 1,
|
||||
provider: 'test',
|
||||
model: 'fresh',
|
||||
contextTokens: 20,
|
||||
contextWindow: 256_000,
|
||||
})
|
||||
api.onHistory = () => Promise.resolve(err({
|
||||
code: 'internal',
|
||||
@@ -953,7 +888,14 @@ describe('resync', () => {
|
||||
|
||||
expect(session.getSnapshot()).toMatchObject({
|
||||
openState: 'error',
|
||||
metrics: freshMetrics,
|
||||
modelRequest: {
|
||||
turn: 2,
|
||||
step: 1,
|
||||
provider: 'test',
|
||||
model: 'fresh',
|
||||
contextTokens: 20,
|
||||
contextWindow: 256_000,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user