feat(desktop): context page deepening — window bar + compact Config + intervention marker + subagent drilldown
Four Context-page enhancements (lane-ctx-deep, F1-F4): - F1 context window breakdown: replace percentage-only card header with a stacked-bar breakdown of input / cached / output token buckets, plus a right-side gauge showing the live window occupancy ratio. - F2 compact Config tab: fold the sprawling profile Config editor into a Config tab on the Context page card, with the same yml-leaf ordering as the top-of-window profile picker. - F3 intervention marker: on the intervention timeline, emit a marker glyph at each user-intervention row (turn-flow-glyph-style) so the card scans as a single stream instead of a header + separate list. - F4 subagent drilldown: when a turn's tool trace hits a subagent, the Trace panel's Config + Output tabs get a second row of Subagent Config / Subagent Output tabs immediately below, driven by the same fold-in-place shape the parent panel already uses. 4 new renderer modules (compact-config-model / context-window-breakdown / intervention-timeline / subagent-drilldown), 6 new test files (41 tests, all node --test style), 4 QA shoot scripts for CDP-driven regression screenshots.
This commit is contained in:
112
examples/desktop/test/compact-config-model.test.js
Normal file
112
examples/desktop/test/compact-config-model.test.js
Normal file
@@ -0,0 +1,112 @@
|
||||
'use strict'
|
||||
|
||||
const test = require('node:test')
|
||||
const assert = require('node:assert/strict')
|
||||
|
||||
const M = require('../src/renderer/compact-config-model.js')
|
||||
|
||||
let _seq = 0
|
||||
function nextSeq() { _seq += 1; return _seq }
|
||||
function reset() { _seq = 0 }
|
||||
|
||||
function userMsg(text = 'hi') {
|
||||
return { type: 'user/message', seq: nextSeq(), data: { content: [{ type: 'text', text }] } }
|
||||
}
|
||||
function assistantMsg(text = 'ok', usage = null) {
|
||||
const ev = { type: 'assistant/message', seq: nextSeq(), data: { content: [{ type: 'text', text }] } }
|
||||
if (usage) ev.data.usage = usage
|
||||
return ev
|
||||
}
|
||||
function compact(model = 'deepseek-chat', maxTokens = 512) {
|
||||
return {
|
||||
type: 'compact/summary',
|
||||
seq: nextSeq(),
|
||||
data: { summary: [{ type: 'text', text: 's' }], model, maxTokens, shadowedTokenCount: 8000 },
|
||||
}
|
||||
}
|
||||
|
||||
test('resolveThreshold: explicit override → server source', () => {
|
||||
const r = M.resolveThreshold({ thresholdTokens: 50000 })
|
||||
assert.equal(r.tokens, 50000)
|
||||
assert.equal(r.source, 'server')
|
||||
})
|
||||
|
||||
test('resolveThreshold: budget → 0.75 × budget, assumed source', () => {
|
||||
const r = M.resolveThreshold({ budgetTokens: 128000 })
|
||||
assert.equal(r.tokens, 96000)
|
||||
assert.equal(r.source, 'assumed')
|
||||
})
|
||||
|
||||
test('resolveThreshold: no info → default 96000', () => {
|
||||
const r = M.resolveThreshold({})
|
||||
assert.equal(r.tokens, M.DEFAULT_THRESHOLD_TOKENS)
|
||||
assert.equal(r.source, 'assumed')
|
||||
})
|
||||
|
||||
test('buildCompactConfigView: counts triggersFired from compact events', () => {
|
||||
reset()
|
||||
const events = [userMsg(), assistantMsg(), compact(), userMsg(), assistantMsg(), compact()]
|
||||
const view = M.buildCompactConfigView(events)
|
||||
assert.equal(view.triggersFired, 2)
|
||||
})
|
||||
|
||||
test('buildCompactConfigView: lastCompactSeq points at final compact event', () => {
|
||||
reset()
|
||||
const events = [userMsg(), compact(), userMsg(), assistantMsg()]
|
||||
const cLast = compact()
|
||||
events.push(cLast)
|
||||
const view = M.buildCompactConfigView(events)
|
||||
assert.equal(view.lastCompactSeq, cLast.seq)
|
||||
})
|
||||
|
||||
test('buildCompactConfigView: tokensSinceLastCompact resets on compact', () => {
|
||||
reset()
|
||||
const events = [userMsg('x'.repeat(4000)), compact(), userMsg('y'.repeat(400))]
|
||||
const view = M.buildCompactConfigView(events)
|
||||
assert.ok(view.tokensSinceLastCompact < 500, 'reset means we count only tokens after the compact')
|
||||
assert.ok(view.tokensSinceLastCompact > 0, 'post-compact user msg still counted')
|
||||
})
|
||||
|
||||
test('buildCompactConfigView: progressPct + level scale with threshold', () => {
|
||||
reset()
|
||||
const bigMsg = { type: 'user/message', seq: nextSeq(), data: { content: [{ type: 'text', text: 'x'.repeat(400000) }] } }
|
||||
const view = M.buildCompactConfigView([bigMsg], { thresholdTokens: 96000 })
|
||||
assert.ok(view.progressPct >= 95, `expected critical level, got ${view.progressPct}%`)
|
||||
assert.equal(view.progressLevel, 'critical')
|
||||
})
|
||||
|
||||
test('buildCompactConfigView: tokensUntilNext floors at 0', () => {
|
||||
reset()
|
||||
const bigMsg = { type: 'user/message', seq: nextSeq(), data: { content: [{ type: 'text', text: 'x'.repeat(500000) }] } }
|
||||
const view = M.buildCompactConfigView([bigMsg], { thresholdTokens: 96000 })
|
||||
assert.equal(view.tokensUntilNext, 0)
|
||||
})
|
||||
|
||||
test('buildCompactConfigView: empty events → zeroed view', () => {
|
||||
const view = M.buildCompactConfigView([])
|
||||
assert.equal(view.triggersFired, 0)
|
||||
assert.equal(view.currentTokens, 0)
|
||||
assert.equal(view.lastCompactSeq, null)
|
||||
assert.equal(view.progressLevel, 'nominal')
|
||||
})
|
||||
|
||||
test('buildCompactConfigView: strategy override wins over inferred default', () => {
|
||||
const view = M.buildCompactConfigView([], { strategyName: 'sliding-window' })
|
||||
assert.equal(view.strategyName, 'sliding-window')
|
||||
})
|
||||
|
||||
test('buildCompactConfigView: last policy carries model + maxSummaryTokens', () => {
|
||||
reset()
|
||||
const events = [compact('deepseek-chat-v3', 1024)]
|
||||
const view = M.buildCompactConfigView(events)
|
||||
assert.equal(view.model, 'deepseek-chat-v3')
|
||||
assert.equal(view.maxSummaryTokens, 1024)
|
||||
})
|
||||
|
||||
test('levelForPct thresholds', () => {
|
||||
assert.equal(M.levelForPct(0), 'nominal')
|
||||
assert.equal(M.levelForPct(49), 'nominal')
|
||||
assert.equal(M.levelForPct(50), 'warn')
|
||||
assert.equal(M.levelForPct(80), 'high')
|
||||
assert.equal(M.levelForPct(95), 'critical')
|
||||
})
|
||||
Reference in New Issue
Block a user