refactor: apply repository naming contract

Apply the accepted pre-release package, service, type, directory, and role renames as one repository-wide change.
This commit is contained in:
Tianyi Cui
2026-08-13 00:36:22 +08:00
parent 101df7cf58
commit a2d0f7f411
3281 changed files with 21730 additions and 21592 deletions

View File

@@ -0,0 +1,160 @@
import type { Context } from '@deepseek-ai/cordis'
import type { SessionEvent } from '@deepseek-ai/dsh-session'
import { describe, expect, it, vi } from 'vitest'
import { runFixtureTurn } from '../src/agent-turn.ts'
type Listener = (session: unknown, event: SessionEvent) => void
const event = (value: object): SessionEvent => value as unknown as SessionEvent
function turnHarness(): {
readonly ctx: Context
readonly session: { readonly id: string }
readonly foreignSession: object
readonly emit: (session: unknown, value: object) => void
readonly setFollowup: (callback: (message: { readonly id: unknown }) => void) => void
readonly whenIdle: ReturnType<typeof vi.fn>
readonly disposeListener: ReturnType<typeof vi.fn>
readonly flush: ReturnType<typeof vi.fn>
} {
const session = { id: 'fixture-session' }
const foreignSession = {}
let listener: Listener | undefined
let followup = (_message: { readonly id: unknown }): void => {}
const whenIdle = vi.fn(async () => {})
const disposeListener = vi.fn()
const flush = vi.fn(async () => {})
const agent = {
session,
whenIdle,
followup: vi.fn((message: { readonly id: unknown }) => { followup(message) }),
}
const ctx = {
get: (name: string) => name === 'agents' ? { roots: () => [agent] } : undefined,
on: (_name: string, callback: Listener) => {
listener = callback
return disposeListener
},
sessions: { flush },
} as unknown as Context
return {
ctx,
session,
foreignSession,
emit: (target, value) => { listener?.(target, event(value)) },
setFollowup: (callback) => { followup = callback },
whenIdle,
disposeListener,
flush,
}
}
describe('runFixtureTurn', () => {
it.each([
['no agent registry', undefined, 0],
['multiple roots', { roots: () => [{}, {}] }, 2],
])('rejects %s', async (_label, registry, count) => {
const ctx = { get: () => registry } as unknown as Context
await expect(runFixtureTurn(ctx, { task: 'ignored' }))
.rejects.toThrow(`fixture turn requires exactly one top-level agent, found ${count}`)
})
it('observes only the owned interval and returns its final text and deduplicated usage', async () => {
const harness = turnHarness()
const observed: SessionEvent[] = []
harness.setFollowup((message) => {
harness.emit(harness.foreignSession, {
type: 'assistant/message', seq: 0, time: 0, data: { message: { content: [] } },
})
harness.emit(harness.session, {
type: 'step/start', seq: 0, time: 0, data: { turn: 1, step: 1 },
})
harness.emit(harness.session, {
type: 'agent/inbox/spliced', seq: 1, time: 1, data: { inserted: [{ id: 'other' }] },
})
harness.emit(harness.session, {
type: 'agent/inbox/spliced', seq: 2, time: 2, data: { inserted: [message] },
})
harness.emit(harness.session, {
type: 'assistant/chunk', seq: 3, time: 3,
data: { turn: 1, step: 1, chunk: { type: 'text-delta', text: 'partial' } },
})
harness.emit(harness.session, {
type: 'assistant/chunk', seq: 4, time: 4,
data: {
turn: 1,
step: 1,
chunk: { type: 'usage', usage: { inputTokens: 2, outputTokens: 3, reasoningTokens: 1 } },
},
})
harness.emit(harness.session, {
type: 'assistant/message', seq: 5, time: 5,
data: {
turn: 1,
step: 1,
message: { content: [{ type: 'text', text: 'final answer' }] },
usage: { inputTokens: 4, outputTokens: 5, cacheReadTokens: 6 },
},
})
harness.emit(harness.session, {
type: 'assistant/chunk', seq: 6, time: 6,
data: {
turn: 1,
step: 2,
chunk: { type: 'usage', usage: { inputTokens: 1, outputTokens: 2, cacheWriteTokens: 7, reasoningTokens: 2 } },
},
})
harness.emit(harness.session, {
type: 'assistant/message', seq: 7, time: 7,
data: { turn: 1, step: 2, message: { content: [{ type: 'tool-call' }] } },
})
harness.emit(harness.foreignSession, {
type: 'assistant/message', seq: 8, time: 8, data: { message: { content: [] } },
})
})
await expect(runFixtureTurn(harness.ctx, {
task: 'prove the fixture',
onEvent: (_sessionId, current) => { observed.push(current) },
})).resolves.toEqual({
type: 'result',
sessionId: 'fixture-session',
output: 'final answer',
usage: {
inputTokens: 5,
outputTokens: 7,
cacheReadTokens: 6,
cacheWriteTokens: 7,
reasoningTokens: 2,
},
})
expect(observed.map(current => current.seq)).toEqual([2, 3, 4, 5, 6, 7])
expect(harness.whenIdle).toHaveBeenCalledTimes(2)
expect(harness.flush).toHaveBeenCalledWith(harness.session)
expect(harness.disposeListener).toHaveBeenCalledOnce()
})
it('omits usage when the interval records none', async () => {
const harness = turnHarness()
harness.setFollowup((message) => {
harness.emit(harness.session, {
type: 'agent/inbox/spliced', seq: 0, time: 0, data: { inserted: [message] },
})
})
await expect(runFixtureTurn(harness.ctx, { task: 'no model step' })).resolves.toEqual({
type: 'result',
sessionId: 'fixture-session',
output: '',
})
})
it('always removes its listener when the turn fails', async () => {
const harness = turnHarness()
harness.whenIdle.mockResolvedValueOnce(undefined).mockRejectedValueOnce(new Error('turn failed'))
await expect(runFixtureTurn(harness.ctx, { task: 'fail' })).rejects.toThrow('turn failed')
expect(harness.disposeListener).toHaveBeenCalledOnce()
expect(harness.flush).not.toHaveBeenCalled()
})
})

View File

@@ -0,0 +1,105 @@
import { afterEach, describe, expect, it } from 'vitest'
import {
EXAMPLE_MODE_ENV,
resolveExampleLaunch,
resolveExampleMode,
} from '@deepseek-ai/dsh-loader-smoke'
const SRC_BIN = '/repo/packages/examples/acp-demo/src/bin.ts'
const TSCONFIG = '/repo/tsconfig.json'
const originalMode = process.env[EXAMPLE_MODE_ENV]
afterEach(() => {
if (originalMode === undefined) Reflect.deleteProperty(process.env, EXAMPLE_MODE_ENV)
else process.env[EXAMPLE_MODE_ENV] = originalMode
})
describe('resolveExampleMode', () => {
it('defaults absent/empty/src to src', () => {
Reflect.deleteProperty(process.env, EXAMPLE_MODE_ENV)
expect(resolveExampleMode()).toBe('src')
expect(resolveExampleMode('')).toBe('src')
expect(resolveExampleMode('src')).toBe('src')
})
it('accepts lib', () => {
expect(resolveExampleMode('lib')).toBe('lib')
})
it('throws on any other value', () => {
expect(() => resolveExampleMode('prod')).toThrow(/must be 'src' or 'lib'/)
})
it('reads the environment when no argument is given', () => {
process.env[EXAMPLE_MODE_ENV] = 'lib'
expect(resolveExampleMode()).toBe('lib')
Reflect.deleteProperty(process.env, EXAMPLE_MODE_ENV)
expect(resolveExampleMode()).toBe('src')
})
})
describe('resolveExampleLaunch', () => {
it('src mode: --import tsx on the source bin with the tsconfig paths env', () => {
const { command, args, env } = resolveExampleLaunch({
srcBin: SRC_BIN,
configArgs: ['./cordis.yml'],
mode: 'src',
tsconfigPath: TSCONFIG,
})
expect(command).toBe(process.execPath)
expect(args).toContain('--import')
expect(args).toContain(SRC_BIN)
expect(args[args.length - 1]).toBe('./cordis.yml')
expect(env.TSX_TSCONFIG_PATH).toBe(TSCONFIG)
})
it('src mode: throws without a tsconfig path', () => {
expect(() => resolveExampleLaunch({ srcBin: SRC_BIN, mode: 'src' })).toThrow(/needs tsconfigPath/)
})
it('lib mode: plain node on the derived lib bin, no tsx and no paths env', () => {
const { args, env } = resolveExampleLaunch({
srcBin: SRC_BIN,
configArgs: ['--config', './cordis.yml'],
mode: 'lib',
env: { DSH_HOME: '/tmp/home' },
})
expect(args).not.toContain('--import')
expect(args).toContain('/repo/packages/examples/acp-demo/lib/bin.js')
expect(args.slice(-2)).toEqual(['--config', './cordis.yml'])
expect(env.TSX_TSCONFIG_PATH).toBeUndefined()
expect(env.DSH_HOME).toBe('/tmp/home')
})
it('lib mode: uses an explicit plain-Node bin when provided', () => {
const fixture = '/repo/fixture.ts'
const { args } = resolveExampleLaunch({ srcBin: fixture, libBin: fixture, mode: 'lib' })
expect(args).toContain(fixture)
})
it('lib mode: rewrites only the last /src/ segment', () => {
const { args } = resolveExampleLaunch({
srcBin: '/repo/src/packages/examples/acp-demo/src/bin.ts',
mode: 'lib',
})
expect(args).toContain('/repo/src/packages/examples/acp-demo/lib/bin.js')
})
it('lib mode: derives the built bin from a Windows source path', () => {
const { args } = resolveExampleLaunch({
srcBin: String.raw`D:\repo\src\packages\examples\acp-demo\src\bin.ts`,
mode: 'lib',
})
expect(args).toContain(String.raw`D:\repo\src\packages\examples\acp-demo\lib\bin.js`)
})
it('lib mode: throws when the bin has no /src/ segment', () => {
expect(() => resolveExampleLaunch({ srcBin: '/repo/lib/bin.js', mode: 'lib' })).toThrow(/"\/src\/" segment/)
})
it('defaults the mode from the environment', () => {
process.env[EXAMPLE_MODE_ENV] = 'lib'
const { args } = resolveExampleLaunch({ srcBin: SRC_BIN })
expect(args).toContain('/repo/packages/examples/acp-demo/lib/bin.js')
})
})

View File

@@ -0,0 +1,4 @@
/** Non-zero subprocess fixture for the Loader-smoke harness. */
console.error('fixture failed')
process.exitCode = 7

View File

@@ -0,0 +1,4 @@
/** Deadline subprocess fixture for the Loader-smoke harness. */
console.log('fixture hanging')
setInterval(() => {}, 1_000)

View File

@@ -0,0 +1,17 @@
/** Successful subprocess fixture for the Loader-smoke harness. */
let input = ''
process.stdin.setEncoding('utf8')
process.stdin.on('data', (chunk: string) => { input += chunk })
process.stdin.on('end', () => {
console.log(JSON.stringify({
configPath: process.argv[2],
args: process.argv.slice(2),
cwd: process.cwd(),
dshHome: process.env.DSH_HOME,
agentsHome: process.env.DSH_AGENTS_HOME,
marker: process.env.LOADER_SMOKE_MARKER,
input,
}))
console.error('fixture stderr')
})

View File

@@ -0,0 +1,117 @@
import { existsSync } from 'node:fs'
import { readFile, writeFile } from 'node:fs/promises'
import { join } from 'node:path'
import { fileURLToPath } from 'node:url'
import { describe, expect, it } from 'vitest'
import { LOADER_SMOKE_TEST_TIMEOUT_MS, runLoaderSmoke } from '@deepseek-ai/dsh-loader-smoke'
const configPath = '/tmp/fixture.cordis.yml'
const tsconfigPath = fileURLToPath(new URL('../../../../tsconfig.json', import.meta.url))
const fixture = (name: string): string => fileURLToPath(new URL(`./fixtures/${name}.ts`, import.meta.url))
// macOS realpaths temp dirs into /private; TMPDIR may live under /var or /tmp.
const canonicalTempPath = (path: string): string => path.replace(/^\/private(?=\/(?:var|tmp)\/)/, '')
describe('runLoaderSmoke', () => {
it('isolates the process, closes stdin, captures output, and removes the cwd', async () => {
const result = await runLoaderSmoke({
label: 'success fixture',
tempDirPrefix: 'loader-smoke-success-',
binScript: fixture('success'),
configPath,
tsconfigPath,
mode: 'src',
env: { LOADER_SMOKE_MARKER: 'present' },
})
const output = JSON.parse(result.stdout) as {
configPath: string
args: string[]
cwd: string
dshHome: string
agentsHome: string
marker: string
input: string
}
expect(output).toMatchObject({
configPath,
args: [configPath],
marker: 'present',
input: '',
})
expect(canonicalTempPath(output.dshHome)).toBe(canonicalTempPath(join(output.cwd, '.dsh')))
expect(canonicalTempPath(output.agentsHome)).toBe(canonicalTempPath(join(output.cwd, '.agents')))
expect(result.stderr).toContain('fixture stderr')
expect(existsSync(output.cwd)).toBe(false)
}, LOADER_SMOKE_TEST_TIMEOUT_MS)
it('passes an arbitrary bin argv and inspects world state before cleanup', async () => {
let inspected = ''
let marker = ''
const result = await runLoaderSmoke({
label: 'argv fixture',
tempDirPrefix: 'loader-smoke-argv-',
binScript: fixture('success'),
libBinScript: fixture('success'),
configPath,
binArgs: ['--config', configPath, '--output-format', 'json', 'task with spaces'],
tsconfigPath,
prepare: cwd => writeFile(join(cwd, 'marker.txt'), 'prepared'),
inspect: async (cwd) => {
inspected = cwd
marker = await readFile(join(cwd, 'marker.txt'), 'utf8')
},
})
const output = JSON.parse(result.stdout) as { args: string[]; cwd: string }
expect(output.args).toEqual(['--config', configPath, '--output-format', 'json', 'task with spaces'])
expect(canonicalTempPath(inspected)).toBe(canonicalTempPath(output.cwd))
expect(marker).toBe('prepared')
expect(existsSync(inspected)).toBe(false)
}, LOADER_SMOKE_TEST_TIMEOUT_MS)
it('rejects a non-zero exit with captured diagnostics', async () => {
await expect(runLoaderSmoke({
label: 'failure fixture',
tempDirPrefix: 'loader-smoke-fail-',
binScript: fixture('fail'),
libBinScript: fixture('fail'),
configPath,
tsconfigPath,
})).rejects.toThrow('failure fixture exited 7 (expected 0). stdout:\n\nstderr:\nfixture failed')
})
it('accepts a declared expected failure exit and rejects any other outcome', async () => {
// A scenario pinning a designed failure surface declares its exit code…
const declared = await runLoaderSmoke({
label: 'declared failure fixture',
tempDirPrefix: 'loader-smoke-declared-fail-',
binScript: fixture('fail'),
libBinScript: fixture('fail'),
configPath,
tsconfigPath,
expectedExitCode: 7,
})
expect(declared.stderr).toBe('fixture failed\n')
// …and a run that succeeds instead still fails the smoke.
await expect(runLoaderSmoke({
label: 'unexpectedly clean fixture',
tempDirPrefix: 'loader-smoke-clean-',
binScript: fixture('success'),
libBinScript: fixture('success'),
configPath,
tsconfigPath,
expectedExitCode: 7,
})).rejects.toThrow(/exited 0 \(expected 7\)/)
})
it('kills a process at its deadline and reports captured output', async () => {
await expect(runLoaderSmoke({
label: 'hanging fixture',
tempDirPrefix: 'loader-smoke-hang-',
binScript: fixture('hang'),
libBinScript: fixture('hang'),
configPath,
tsconfigPath,
processTimeoutMs: 100,
})).rejects.toThrow('hanging fixture did not exit within 0.1s.')
})
})