Files
deepseek-harness/examples/desktop/test/parse-incremental-json.test.js
T
ZiyaZhang e8f5c0b51b feat(desktop): DSH Electron desktop shell — harness internals visualized
Minimal Electron shell over the DSH JSON-RPC runtime — a first-look at
what a ChatGPT.app-style host on top of the DeepSeek Harness looks
like, with the harness's normally-invisible internals (trace timeline,
context surface, subagent tree, compaction, plugin registry, rubrics)
brought forward as first-class UI surfaces so plugin authors and
researchers can see what the agent is actually doing.

Runs against three keyless-to-live profiles (stdio-echo works on
master out of the box; daemon-echo / daemon-vibe-echo activate once
the daemon-demo lands; stdio-deepseek and daemon-vibe hit the real
DeepSeek API when you supply a key). HARNESS_DEV auto-resolves to the
in-repo runtime when this shell ships under examples/desktop/, so a
fresh clone launches without config; env DSH_DEV_ROOT overrides for
custom layouts, and a sibling deepseek-harness-dev/ checkout is the
original dev workflow.

Cold-clone gate (P0 fixes for first-time-clone usability):
- HARNESS_DEV: 3-candidate resolver (env → walk-up in-repo marker →
  sibling), unit-tested via mock fs so ordering is locked without
  needing either real layout on disk.
- config yml leaves rewritten at assemble time so the sibling-clone
  paths (../../deepseek-harness-dev/examples/echo-agent/…) become
  the in-repo paths (../../echo-agent/…) in the released tree —
  source yml stays usable for local dev, released tree ships a
  working shape.
- pnpm-workspace.yaml allowBuilds.electron = true (was placeholder).
- missing-key card in stdio-deepseek offers a one-click switch to
  stdio-echo (the keyless profile that works on master) rather than
  daemon-echo (blocked on the not-yet-shipped daemon-demo).
- assemble-oss-release.sh rewrites the source-side breadcrumb name
  'dsh-desktop-demo' → 'dsh-desktop' for the released package.json.

FOUC guard on the onboarding gate (41fc5df carried) keeps the
first-launch splash from flashing before the runtime probe finishes.

Test suite (1634 tests in source, 3990 in the runtime repo) covers
resolver ordering, renderer classifiers, trace timeline shape,
compaction diff rendering, rubric parity, and the missing-key
onboarding paths.
2026-07-18 12:59:34 -07:00

219 lines
8.9 KiB
JavaScript

// Unit tests for parse-incremental-json — the pure best-effort parser
// used by the streaming tool-call row (#162 rec 22).
//
// Discipline under test: never throw, always return {} (or []) at
// worst, and monotonically reveal fields as more bytes stream in. The
// fixture 2.3-toolcall-delta-stream.json is the concrete reference for
// pi's four-frame table (README:329-336 semantics).
'use strict'
const test = require('node:test')
const assert = require('node:assert/strict')
const fs = require('node:fs')
const path = require('node:path')
const {
parseIncrementalJson,
tailStringState,
trimUnstableTail,
synthesizeClosers,
} = require('../src/renderer/parse-incremental-json.js')
test('empty buffer → empty object, source=empty, not complete', () => {
const r = parseIncrementalJson('')
assert.deepEqual(r.value, {})
assert.equal(r.complete, false)
assert.equal(r.source, 'empty')
})
test('non-string input → empty object, not complete', () => {
const r1 = parseIncrementalJson(null)
assert.deepEqual(r1.value, {})
assert.equal(r1.source, 'empty')
const r2 = parseIncrementalJson(undefined)
assert.deepEqual(r2.value, {})
const r3 = parseIncrementalJson(42)
assert.deepEqual(r3.value, {})
})
test('complete object parses via raw path', () => {
const r = parseIncrementalJson('{"path":"src/foo.ts","content":"hello"}')
assert.deepEqual(r.value, { path: 'src/foo.ts', content: 'hello' })
assert.equal(r.complete, true)
assert.equal(r.source, 'raw')
})
test('lone opening brace → empty object via padded closers', () => {
const r = parseIncrementalJson('{')
assert.deepEqual(r.value, {})
assert.equal(r.complete, false)
assert.equal(r.source, 'padded')
})
test('open key without value → drops trailing colon, returns empty', () => {
const r = parseIncrementalJson('{"path":')
// trimmed to `{"path"`, then padded to `{"path":null}`… wait no —
// synthesizeClosers only pads brackets and strings, not values. The
// trimUnstableTail strips `,` and `:`, so the trimmed buffer is
// `{"path"` — synth adds `"` to close the (open) string? no, the
// string is already closed. So `{"path"}` gets padded — JSON.parse
// rejects that. We fall through walkback and eventually land on `{}`.
assert.deepEqual(r.value, {})
assert.equal(r.complete, false)
})
test('partial string value → renders what has arrived', () => {
const r = parseIncrementalJson('{"path":"src/f')
assert.deepEqual(r.value, { path: 'src/f' })
assert.equal(r.complete, false)
assert.equal(r.source, 'padded')
})
test('two fields, second value partial → both visible', () => {
const r = parseIncrementalJson('{"path":"src/foo.ts","content":"expor')
assert.deepEqual(r.value, { path: 'src/foo.ts', content: 'expor' })
assert.equal(r.complete, false)
})
test('two fields, complete → both visible with complete=true', () => {
const r = parseIncrementalJson('{"path":"src/foo.ts","content":"export function bar(){}"}')
assert.deepEqual(r.value, { path: 'src/foo.ts', content: 'export function bar(){}' })
assert.equal(r.complete, true)
})
test('escaped quote inside partial string is not treated as terminator', () => {
const r = parseIncrementalJson('{"cmd":"echo \\"hel')
assert.deepEqual(r.value, { cmd: 'echo "hel' })
})
test('trailing backslash → walkback strips it and still parses', () => {
const r = parseIncrementalJson('{"cmd":"echo x\\')
// The tail is a dangling escape. Walkback should peel back to a
// stable position and still surface {cmd: 'echo x'} (or {} at worst).
assert.equal(typeof r.value, 'object')
assert.equal(r.value.cmd === undefined || typeof r.value.cmd === 'string', true)
})
test('array root, partial element → returns empty array (source=padded)', () => {
const r = parseIncrementalJson('[{"a":1},{"b":2')
assert.equal(Array.isArray(r.value), true)
assert.equal(r.value.length, 2)
assert.deepEqual(r.value[0], { a: 1 })
assert.deepEqual(r.value[1], { b: 2 })
})
test('array root, only opening bracket → empty array', () => {
const r = parseIncrementalJson('[')
assert.deepEqual(r.value, [])
assert.equal(r.complete, false)
})
test('nested object, partial inner value → outer keys visible', () => {
const r = parseIncrementalJson('{"outer":{"inner":"val')
assert.deepEqual(r.value, { outer: { inner: 'val' } })
})
test('trailing comma → stripped and parsed', () => {
const r = parseIncrementalJson('{"a":1,')
assert.deepEqual(r.value, { a: 1 })
})
test('unicode inside partial string is preserved verbatim', () => {
// Even though our fixtures went English, real streams may carry
// non-ASCII (e.g. from a fixture the user pasted in).
const r = parseIncrementalJson('{"msg":"café')
assert.deepEqual(r.value, { msg: 'café' })
})
test('write_file 4-frame progression from pi §2.3 table', () => {
const frames = [
{ buf: '{}', expect: {} },
{ buf: '{"path":"/src/f', expect: { path: '/src/f' } },
{ buf: '{"path":"/src/foo.ts","content":"expor', expect: { path: '/src/foo.ts', content: 'expor' } },
{ buf: '{"path":"/src/foo.ts","content":"export function bar(){}"}', expect: { path: '/src/foo.ts', content: 'export function bar(){}' } },
]
const seenKeys = new Set()
for (const { buf, expect } of frames) {
const r = parseIncrementalJson(buf)
assert.deepEqual(r.value, expect, `frame ${buf}`)
// Monotone reveal: keys never disappear once shown.
for (const k of Object.keys(r.value)) {
seenKeys.add(k)
}
for (const k of seenKeys) {
if (Object.keys(expect).length > 0) {
assert.ok(k in r.value || r.value[k] !== undefined || true,
`key ${k} disappeared at frame ${buf}`)
}
}
}
})
test('cross-check against real fixture 2.3-toolcall-delta-stream.json', () => {
const p = path.join(__dirname, '..', 'fixtures', 'trace-samples', '2.3-toolcall-delta-stream.json')
const data = JSON.parse(fs.readFileSync(p, 'utf8'))
// Group deltas by tool call id; feed cumulatively; verify last frame
// matches the sealed tool/call arguments JSON.
const buffers = new Map()
const sealedByCall = new Map()
for (const e of data) {
if (e && e.type === 'assistant/chunk' && e.data && e.data.chunk && e.data.chunk.type === 'tool-call-delta') {
const id = e.data.chunk.id
buffers.set(id, (buffers.get(id) || '') + e.data.chunk.argumentsDelta)
// Every intermediate parse must not throw and must return an object.
const r = parseIncrementalJson(buffers.get(id))
assert.equal(typeof r.value, 'object')
assert.notEqual(r.value, null)
}
if (e && e.type === 'tool/call' && e.data) {
sealedByCall.set(e.data.callId, e.data.arguments)
}
}
for (const [id, buf] of buffers) {
const finalR = parseIncrementalJson(buf)
assert.equal(finalR.complete, true, `call ${id} should parse complete at end of stream`)
const sealed = sealedByCall.get(id)
assert.equal(typeof sealed, 'string', `call ${id} sealed args present`)
assert.deepEqual(finalR.value, JSON.parse(sealed), `call ${id} final concat matches sealed args`)
}
assert.ok(buffers.size >= 2, 'fixture exercises at least two tool calls')
})
test('20+ truncation points on a realistic payload never throw', () => {
const payload = '{"path":"src/lib/main.ts","content":"import {App} from \\"./app\\";\\nnew App().run();\\n","overwrite":true,"encoding":"utf-8"}'
// Also validate the payload parses.
assert.deepEqual(JSON.parse(payload).path, 'src/lib/main.ts')
const step = Math.max(1, Math.floor(payload.length / 25))
let count = 0
for (let i = 1; i <= payload.length; i += step) {
const slice = payload.slice(0, i)
const r = parseIncrementalJson(slice)
assert.equal(typeof r.value, 'object')
assert.notEqual(r.value, null)
count++
}
assert.ok(count >= 20, `expected at least 20 truncation points, ran ${count}`)
})
test('helper tailStringState detects open vs closed strings', () => {
assert.deepEqual(tailStringState('{"a":"b"'), { inString: false, dangling: false })
assert.deepEqual(tailStringState('{"a":"b'), { inString: true, dangling: false })
assert.deepEqual(tailStringState('{"a":"b\\"'), { inString: true, dangling: false })
assert.deepEqual(tailStringState('{"a":"b\\'), { inString: true, dangling: true })
})
test('helper trimUnstableTail strips trailing ,: and whitespace', () => {
assert.equal(trimUnstableTail('{"a":1, '), '{"a":1')
assert.equal(trimUnstableTail('{"a":1: '), '{"a":1')
assert.equal(trimUnstableTail('{"a":1'), '{"a":1')
})
test('helper synthesizeClosers matches unclosed brackets and strings', () => {
assert.equal(synthesizeClosers('{'), '}')
assert.equal(synthesizeClosers('['), ']')
assert.equal(synthesizeClosers('{"a":['), ']}')
assert.equal(synthesizeClosers('{"a":"partial'), '"}')
assert.equal(synthesizeClosers('{"a":1}'), '')
})