mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
The readline UI lives inside @deepseek-ai/dsh-stdio-agent as the in-package stdio-chat module; the packages/support/ui-stdio package is gone. The app's front-door cluster always includes this UI and nothing else composes it, so the boundary bought manifest/tsconfig/module-graph/ README/publint surface for a helper that is not independently swappable — and a product app no longer depends on a support package documented as not-product-surface. createStdioChat, the StdioRuntime test seam, and both unit suites moved verbatim (imports rewired to the module path); the named name/inject/Config/apply export shape stays, being the contract the app's ctx.plugin mount consumes. Coverage stays per-file 100%; the built-bin smoke under plain node and both keyless Loader-path smokes prove the published artifact and the demos end-to-end. Implements docs/rfc/implemented/simplification/2026-07-04-fold-stdio-ui-helper.md (moved from proposed/ and amended to the shipped shape).
54 lines
1.7 KiB
TypeScript
54 lines
1.7 KiB
TypeScript
import { EventEmitter } from 'node:events'
|
|
import type { Readable, Writable } from 'node:stream'
|
|
import { describe, expect, it, vi } from 'vitest'
|
|
import type { Context } from 'cordis'
|
|
import type { StdioRuntime } from '../src/stdio-chat.ts'
|
|
|
|
const createInterface = vi.hoisted(() => vi.fn(() => {
|
|
const reader = new EventEmitter() as EventEmitter & { close(): void }
|
|
reader.close = vi.fn()
|
|
return reader
|
|
}))
|
|
|
|
vi.mock('node:readline', () => ({ createInterface }))
|
|
|
|
function fakeContext(): Context {
|
|
return {
|
|
on: vi.fn(() => vi.fn()),
|
|
effect: vi.fn((callback: () => () => void) => callback()),
|
|
// The UI seeds its label map from the registry at install; this suite only
|
|
// exercises readline terminal-mode selection, so an empty roster suffices.
|
|
agents: { list: vi.fn(() => []) },
|
|
} as unknown as Context
|
|
}
|
|
|
|
function fakeRuntime(inputIsTTY: boolean, outputIsTTY: boolean): StdioRuntime {
|
|
return {
|
|
input: { isTTY: inputIsTTY } as Readable & { isTTY: boolean },
|
|
output: { isTTY: outputIsTTY, write: vi.fn(() => true) } as unknown as Writable & { isTTY: boolean },
|
|
exit: vi.fn(),
|
|
}
|
|
}
|
|
|
|
describe('createStdioChat readline mode', () => {
|
|
it('enables terminal editing only when both stdio streams are TTYs', async () => {
|
|
const { createStdioChat } = await import('../src/stdio-chat.ts')
|
|
|
|
const tty = fakeRuntime(true, true)
|
|
createStdioChat(fakeContext(), {}, tty)
|
|
expect(createInterface).toHaveBeenLastCalledWith({
|
|
input: tty.input,
|
|
output: tty.output,
|
|
terminal: true,
|
|
})
|
|
|
|
const piped = fakeRuntime(true, false)
|
|
createStdioChat(fakeContext(), {}, piped)
|
|
expect(createInterface).toHaveBeenLastCalledWith({
|
|
input: piped.input,
|
|
output: piped.output,
|
|
terminal: false,
|
|
})
|
|
})
|
|
})
|