fix(desktop): session Graph node order — sort by seq + repair turn/user reversal, node label previews

Also picks up two files the previous sync batch missed
(test/artifact-compact-row.test.js, docs/qa-artifact-compact/).
This commit is contained in:
ZiyaZhang
2026-07-19 23:31:19 -07:00
parent fcbf6ff813
commit 3b49a948e0
13 changed files with 737 additions and 14 deletions

View File

@@ -69,9 +69,11 @@ test('modelsFor: the profile default model IS in its supported list (no self-mis
}
})
// PROFILE_MODELS mirrors the `id` fields in each DeepSeek model catalog so
// the renderer cannot drift from the runtime's validated configuration.
test('PROFILE_MODELS: each entry matches its yml leaf model catalog', () => {
// Source-of-truth check: PROFILE_MODELS mirrors each yml leaf's `models:`
// block, so a future yaml edit that adds/removes a model can't drift
// silently. We parse the yaml the shell-way — one leaf per profile — and
// compare the `models:` list line-by-line.
test('PROFILE_MODELS: each entry matches its yml leaf models: block', () => {
const leafFor = {
'daemon-echo': null, // mock-llm — no models: block in yaml, always mock-echo
'stdio-echo': null, // mock-llm — ditto
@@ -89,8 +91,11 @@ test('PROFILE_MODELS: each entry matches its yml leaf model catalog', () => {
continue
}
const yaml = fs.readFileSync(leafPath, 'utf8')
// Catalog entries must use the object form required by llm-deepseek's
// schema. A scalar entry leaves yamlModels empty and fails this test.
// Find the `models:` block under `llm-deepseek` and collect its
// `- <name>` entries. The block is 6-space-indented, sits inside a
// `config:` map, and terminates when the indent drops back to a
// 2-space `- id:` list item. Bail early at the first line whose
// trim doesn't start with `- ` after the models: header.
const lines = yaml.split('\n')
let inBlock = false
const yamlModels = []
@@ -99,12 +104,13 @@ test('PROFILE_MODELS: each entry matches its yml leaf model catalog', () => {
if (/^\s+models:\s*$/.test(rawLine)) { inBlock = true; continue }
continue
}
const m = /^\s+-\s+id:\s+([\w-]+)\s*$/.exec(rawLine)
// Inside the block: entries look like ` - deepseek-v4-flash`.
const m = /^\s+-\s+([\w-]+)\s*$/.exec(rawLine)
if (m) { yamlModels.push(m[1]); continue }
// Any other non-empty line terminates the block.
if (rawLine.trim() !== '') break
}
assert.ok(yamlModels.length > 0, `${leafPath}: models must contain object entries with id fields`)
assert.ok(yamlModels.length > 0, `${leafPath}: parsed empty models: block`)
assert.deepEqual(expected.slice().sort(), yamlModels.slice().sort(),
`${profileName} PROFILE_MODELS drift vs ${path.basename(leafPath)}: expected ${JSON.stringify(yamlModels)}, got ${JSON.stringify(expected)}`)
}