mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
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.
88 lines
3.5 KiB
JavaScript
88 lines
3.5 KiB
JavaScript
'use strict'
|
|
|
|
const test = require('node:test')
|
|
const assert = require('node:assert/strict')
|
|
|
|
const M = require('../src/renderer/subagent-drilldown.js')
|
|
|
|
test('buildSubagentDrilldown: infers tool defs from child tool/call events', () => {
|
|
const events = [
|
|
{ type: 'user/message', seq: 1, data: { content: [{ type: 'text', text: 'go' }] } },
|
|
{ type: 'tool/call', seq: 2, data: { name: 'read_file', arguments: '{"path":"a.md"}' } },
|
|
{ type: 'tool/call', seq: 3, data: { name: 'search', arguments: '{"q":"hello"}' } },
|
|
{ type: 'tool/call', seq: 4, data: { name: 'read_file', arguments: '{"path":"b.md"}' } },
|
|
]
|
|
const v = M.buildSubagentDrilldown({ childEvents: events })
|
|
assert.equal(v.toolDefs.length, 2)
|
|
assert.equal(v.toolDefsSource, 'inferred')
|
|
const names = v.toolDefs.map((t) => t.name).sort()
|
|
assert.deepEqual(names, ['read_file', 'search'])
|
|
// firstSeq should be the first occurrence.
|
|
const rf = v.toolDefs.find((t) => t.name === 'read_file')
|
|
assert.equal(rf.firstSeq, 2)
|
|
})
|
|
|
|
test('buildSubagentDrilldown: explicit toolDefs override inferred', () => {
|
|
const v = M.buildSubagentDrilldown({
|
|
toolDefs: ['read_file', 'bash', 'search'],
|
|
childEvents: [{ type: 'tool/call', seq: 1, data: { name: 'other' } }],
|
|
})
|
|
assert.equal(v.toolDefsSource, 'explicit')
|
|
assert.deepEqual(v.toolDefs.map((t) => t.name), ['read_file', 'bash', 'search'])
|
|
})
|
|
|
|
test('buildSubagentDrilldown: inboundQuery from parent-seed user/message', () => {
|
|
const events = [
|
|
{ type: 'user/message', seq: 1,
|
|
data: {
|
|
content: [{ type: 'text', text: 'go find X for the parent' }],
|
|
source: { kind: 'plugin', plugin: 'subagent-search' },
|
|
} },
|
|
{ type: 'tool/call', seq: 2, data: { name: 'search' } },
|
|
]
|
|
const v = M.buildSubagentDrilldown({ childEvents: events })
|
|
assert.equal(v.inboundQuery.source, 'seed-event')
|
|
assert.match(v.inboundQuery.text, /find X/)
|
|
assert.equal(v.inboundQuery.seq, 1)
|
|
})
|
|
|
|
test('buildSubagentDrilldown: explicit parentQuery wins', () => {
|
|
const v = M.buildSubagentDrilldown({ parentQuery: 'summarise these docs' })
|
|
assert.equal(v.inboundQuery.source, 'explicit')
|
|
assert.equal(v.inboundQuery.text, 'summarise these docs')
|
|
})
|
|
|
|
test('buildSubagentDrilldown: falls back to first user/message when no plugin-tagged seed', () => {
|
|
const v = M.buildSubagentDrilldown({
|
|
childEvents: [{ type: 'user/message', seq: 5, data: { content: [{ type: 'text', text: 'raw seed' }] } }],
|
|
})
|
|
assert.equal(v.inboundQuery.source, 'seed-event')
|
|
assert.equal(v.inboundQuery.text, 'raw seed')
|
|
})
|
|
|
|
test('buildSubagentDrilldown: empty spec → empty view', () => {
|
|
const v = M.buildSubagentDrilldown({})
|
|
assert.equal(v.toolDefs.length, 0)
|
|
assert.equal(v.toolDefsSource, 'empty')
|
|
assert.equal(v.inboundQuery.source, 'empty')
|
|
assert.equal(v.inboundQuery.text, '')
|
|
})
|
|
|
|
test('buildSubagentDrilldown: parentQuery accepts ContentBlock[] and preserves blocks', () => {
|
|
const blocks = [{ type: 'text', text: 'A' }, { type: 'text', text: 'B' }]
|
|
const v = M.buildSubagentDrilldown({ parentQuery: blocks })
|
|
assert.equal(v.inboundQuery.source, 'explicit')
|
|
assert.equal(v.inboundQuery.text, 'A\nB')
|
|
assert.equal(v.inboundQuery.blocks, blocks)
|
|
})
|
|
|
|
test('buildSubagentDrilldown: preserves seq of the seed event when inferring', () => {
|
|
const v = M.buildSubagentDrilldown({
|
|
childEvents: [
|
|
{ type: 'assistant/chunk', seq: 5, data: { content: [{ type: 'text', text: 'hello' }] } },
|
|
{ type: 'user/message', seq: 7, data: { content: [{ type: 'text', text: 'seed' }] } },
|
|
],
|
|
})
|
|
assert.equal(v.inboundQuery.seq, 7)
|
|
})
|