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:
@@ -0,0 +1,280 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import Loader from '@deepseek-ai/cordis-plugin-loader'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import CommandRuntime, { type CommandResult } from '@deepseek-ai/dsh-commands'
|
||||
import {
|
||||
CompactionId,
|
||||
CompactionEngine,
|
||||
ManualCompactionError,
|
||||
type CompactionAgentContext,
|
||||
type CompactionResult,
|
||||
type CompactionTrigger,
|
||||
type ManualCompactAgentContext,
|
||||
} from '@deepseek-ai/dsh-compaction'
|
||||
import { Session, SessionId } from '@deepseek-ai/dsh-session'
|
||||
import * as commandCompact from '@deepseek-ai/dsh-command-compact'
|
||||
|
||||
const COMPACTION_ID = CompactionId('command-compact-test')
|
||||
|
||||
const RESULT: CompactionResult = {
|
||||
compactionId: COMPACTION_ID,
|
||||
startSeq: 1,
|
||||
summarySeq: 2,
|
||||
endSeq: 3,
|
||||
summary: [{ type: 'text', text: 'summary' }],
|
||||
shadowedRange: { start: 1, end: 7 },
|
||||
shadowedSeqs: [1, 3, 7],
|
||||
shadowedTokenCount: 42,
|
||||
}
|
||||
|
||||
class StubCompactionEngine extends CompactionEngine {
|
||||
result: CompactionResult | null = RESULT
|
||||
failure: unknown
|
||||
operation: (() => Promise<CompactionResult | null>) | undefined
|
||||
calls: { agent: ManualCompactAgentContext; signal: AbortSignal }[] = []
|
||||
|
||||
override compactIfNeeded(
|
||||
_agent: CompactionAgentContext,
|
||||
_trigger: CompactionTrigger,
|
||||
_signal: AbortSignal,
|
||||
): Promise<CompactionResult | null> {
|
||||
return Promise.resolve(null)
|
||||
}
|
||||
|
||||
override compactRegion(): Promise<CompactionResult> {
|
||||
return Promise.resolve(RESULT)
|
||||
}
|
||||
|
||||
override compactNow(
|
||||
agent: ManualCompactAgentContext,
|
||||
signal: AbortSignal,
|
||||
sourceCommandId?: Parameters<CompactionEngine['compactNow']>[2],
|
||||
): Promise<CompactionResult | null> {
|
||||
this.calls.push({ agent, signal })
|
||||
if (this.operation !== undefined) return this.operation()
|
||||
return this.failure === undefined
|
||||
? Promise.resolve(this.result === null ? null : this.appendResult(agent, this.result, sourceCommandId))
|
||||
// oxlint-disable-next-line typescript/prefer-promise-reject-errors -- exercise arbitrary backend rejection values.
|
||||
: Promise.reject(this.failure)
|
||||
}
|
||||
|
||||
private appendResult(
|
||||
agent: ManualCompactAgentContext,
|
||||
result: CompactionResult,
|
||||
sourceCommandId: Parameters<CompactionEngine['compactNow']>[2],
|
||||
): CompactionResult {
|
||||
const provenance = {
|
||||
compactionId: result.compactionId,
|
||||
...sourceCommandId === undefined ? {} : { sourceCommandId },
|
||||
}
|
||||
agent.session.append('compaction/start', { ...provenance, turn: null })
|
||||
agent.session.append('compaction/summary', {
|
||||
...provenance,
|
||||
summary: result.summary,
|
||||
shadowedRange: result.shadowedRange,
|
||||
shadowedSeqs: result.shadowedSeqs,
|
||||
shadowedTokenCount: result.shadowedTokenCount,
|
||||
provider: 'command-test',
|
||||
model: 'command-test',
|
||||
})
|
||||
agent.session.append('compaction/end', { ...provenance, turn: null })
|
||||
return { ...result, ...provenance }
|
||||
}
|
||||
}
|
||||
|
||||
interface Harness {
|
||||
readonly ctx: Context
|
||||
readonly compact: StubCompactionEngine
|
||||
readonly agent: Agent
|
||||
readonly plugin: Awaited<ReturnType<Context['plugin']>>
|
||||
}
|
||||
|
||||
async function harness(): Promise<Harness> {
|
||||
const ctx = new Context()
|
||||
await ctx.plugin(CommandRuntime)
|
||||
const compact = new StubCompactionEngine(ctx)
|
||||
const plugin = await ctx.plugin(commandCompact)
|
||||
const session = Session.create(SessionId('command-compact'))
|
||||
const agent = {
|
||||
session,
|
||||
status: 'idle',
|
||||
options: {},
|
||||
reserveTurnAdmission: () => () => undefined,
|
||||
} as unknown as Agent
|
||||
return { ctx, compact, agent, plugin }
|
||||
}
|
||||
|
||||
async function run(
|
||||
test: Harness,
|
||||
suffix = '',
|
||||
controller = new AbortController(),
|
||||
): Promise<NonNullable<Awaited<ReturnType<CommandRuntime['execute']>>>> {
|
||||
const execution = await test.ctx.commands.execute(test.agent, `/compact${suffix}`, controller.signal)
|
||||
if (execution === undefined) throw new Error('compact command was not registered')
|
||||
return execution
|
||||
}
|
||||
|
||||
/** Assert the executor-owned lifecycle pair and absence from model history. */
|
||||
function expectLastLifecycle(
|
||||
test: Harness,
|
||||
args: string,
|
||||
outcome: CommandResult,
|
||||
): string {
|
||||
const lifecycle = test.agent.session.events
|
||||
.filter(event => event.type === 'command/run' || event.type === 'command/done')
|
||||
.slice(-2)
|
||||
const runEvent = lifecycle[0]
|
||||
const doneEvent = lifecycle[1]
|
||||
if (runEvent?.type !== 'command/run' || doneEvent?.type !== 'command/done') {
|
||||
throw new Error(`expected command lifecycle pair, got ${lifecycle.map(event => event.type).join(',')}`)
|
||||
}
|
||||
expect(lifecycle.map(event => ({ type: event.type, data: event.data }))).toEqual([
|
||||
{
|
||||
type: 'command/run',
|
||||
data: {
|
||||
commandId: runEvent.data.commandId,
|
||||
name: 'compact',
|
||||
args,
|
||||
source: { kind: 'user' },
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'command/done',
|
||||
data: {
|
||||
commandId: runEvent.data.commandId,
|
||||
...outcome,
|
||||
},
|
||||
},
|
||||
])
|
||||
expect(doneEvent.data.commandId).toBe(runEvent.data.commandId)
|
||||
expect(test.agent.session.surface.nodes).toEqual([])
|
||||
expect(test.agent.session.deriveMessages()).toEqual([])
|
||||
return runEvent.data.commandId
|
||||
}
|
||||
|
||||
describe('@deepseek-ai/dsh-command-compact registration', () => {
|
||||
it('registers one argument-free command with Loader-safe exports and disposes it', async () => {
|
||||
const test = await harness()
|
||||
expect(commandCompact.name).toBe('command-compact')
|
||||
expect(commandCompact.inject).toEqual(['commands', 'compaction'])
|
||||
expect('default' in commandCompact).toBe(false)
|
||||
const loader = Object.create(Loader.prototype) as Loader
|
||||
expect(loader.unwrapExports(commandCompact)).toBe(commandCompact)
|
||||
expect(test.ctx.commands.list(test.agent)).toContainEqual({
|
||||
name: 'compact',
|
||||
description: 'Compact older conversation history',
|
||||
})
|
||||
|
||||
await test.plugin.dispose()
|
||||
expect(test.ctx.commands.find(test.agent, 'compact')).toBeUndefined()
|
||||
})
|
||||
})
|
||||
|
||||
describe('/compact human command', () => {
|
||||
it('reports success with useful accounting and forwards the exact target and signal', async () => {
|
||||
const test = await harness()
|
||||
const controller = new AbortController()
|
||||
const execution = await run(test, '', controller)
|
||||
expect(execution.result).toEqual({
|
||||
kind: 'success',
|
||||
text: 'Compacted 3 history items (~42 tokens).',
|
||||
sourceEventSeq: RESULT.summarySeq,
|
||||
})
|
||||
expect(execution.commandId).toBe(expectLastLifecycle(test, '', execution.result))
|
||||
expect(test.compact.calls).toEqual([{ agent: test.agent, signal: controller.signal }])
|
||||
})
|
||||
|
||||
it('returns direct no-history and argument-rejection results', async () => {
|
||||
const test = await harness()
|
||||
test.compact.result = null
|
||||
const empty = await run(test)
|
||||
expect(empty.result).toEqual({
|
||||
kind: 'success',
|
||||
text: 'No compactable history yet.',
|
||||
})
|
||||
expect(empty.commandId).toBe(expectLastLifecycle(test, '', empty.result))
|
||||
|
||||
const rejected = await run(test, ' now')
|
||||
expect(rejected.result).toEqual({
|
||||
kind: 'error',
|
||||
text: 'Usage: /compact (no arguments)',
|
||||
})
|
||||
expect(rejected.commandId).toBe(expectLastLifecycle(test, ' now', rejected.result))
|
||||
expect(test.compact.calls).toHaveLength(1)
|
||||
})
|
||||
|
||||
it.each([
|
||||
['busy', 'Compaction is unavailable because this process has an active compaction, or the agent is not idle.'],
|
||||
['cancelled', 'Compaction cancelled.'],
|
||||
['changed', 'The history selected for compaction changed before it could be replaced. The conversation is unchanged; the attempt is recorded in the session log.'],
|
||||
['summary', 'Compaction could not produce a useful summary. The conversation is unchanged; the attempt is recorded in the session log.'],
|
||||
['commit', 'Compaction did not finish cleanly; some session history may have changed. Inspect the current session state before retrying.'],
|
||||
['persistence', 'Compaction finished, but the session could not be saved.'],
|
||||
] as const)('maps expected %s failures to direct errors', async (code, text) => {
|
||||
const test = await harness()
|
||||
test.compact.failure = new ManualCompactionError(code, 'backend detail')
|
||||
const execution = await run(test)
|
||||
expect(execution.result).toEqual({ kind: 'error', text })
|
||||
expect(execution.commandId).toBe(expectLastLifecycle(test, '', execution.result))
|
||||
})
|
||||
|
||||
it('preserves cancellation and unexpected implementation failures', async () => {
|
||||
const cancelled = await harness()
|
||||
const controller = new AbortController()
|
||||
const abort = new Error('operator cancelled')
|
||||
cancelled.compact.operation = () => {
|
||||
controller.abort(abort)
|
||||
return Promise.reject(new ManualCompactionError('summary', 'late failure'))
|
||||
}
|
||||
await expect(run(cancelled, '', controller)).rejects.toBe(abort)
|
||||
expectLastLifecycle(cancelled, '', { kind: 'error', text: abort.message })
|
||||
|
||||
const unexpected = await harness()
|
||||
const bug = new Error('unexpected backend bug')
|
||||
unexpected.compact.failure = bug
|
||||
await expect(run(unexpected)).rejects.toBe(bug)
|
||||
expectLastLifecycle(unexpected, '', { kind: 'error', text: bug.message })
|
||||
})
|
||||
|
||||
it('drains an aborted handler through close and flush before plugin disposal settles', async () => {
|
||||
const test = await harness()
|
||||
const controller = new AbortController()
|
||||
const abort = new Error('operator cancelled')
|
||||
const started = Promise.withResolvers<undefined>()
|
||||
const allowClose = Promise.withResolvers<undefined>()
|
||||
const closed = Promise.withResolvers<undefined>()
|
||||
const allowFlush = Promise.withResolvers<undefined>()
|
||||
const flushed = Promise.withResolvers<undefined>()
|
||||
test.compact.operation = async () => {
|
||||
started.resolve(undefined)
|
||||
await allowClose.promise
|
||||
closed.resolve(undefined)
|
||||
await allowFlush.promise
|
||||
flushed.resolve(undefined)
|
||||
throw abort
|
||||
}
|
||||
|
||||
const execution = run(test, '', controller)
|
||||
await started.promise
|
||||
controller.abort(abort)
|
||||
await expect(execution).rejects.toBe(abort)
|
||||
|
||||
let disposed = false
|
||||
const disposal = test.plugin.dispose()
|
||||
void disposal.then(() => { disposed = true })
|
||||
await new Promise(resolve => setTimeout(resolve, 0))
|
||||
expect(test.ctx.commands.find(test.agent, 'compact')).toBeUndefined()
|
||||
expect(disposed).toBe(false)
|
||||
|
||||
allowClose.resolve(undefined)
|
||||
await closed.promise
|
||||
await new Promise(resolve => setTimeout(resolve, 0))
|
||||
expect(disposed).toBe(false)
|
||||
|
||||
allowFlush.resolve(undefined)
|
||||
await flushed.promise
|
||||
await disposal
|
||||
expect(disposed).toBe(true)
|
||||
})
|
||||
})
|
||||
18
packages/compaction/command-compact/tests/invariant.spec.ts
Normal file
18
packages/compaction/command-compact/tests/invariant.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import * as invariant from '@deepseek-ai/dsh-command-compact/invariant'
|
||||
|
||||
describe('command-compact invariant companion', () => {
|
||||
it('registers the package-owned no-op installer', async () => {
|
||||
const register = vi.fn().mockReturnValue(() => {})
|
||||
const ctx = { invariants: { register } } as never
|
||||
const dispose = await invariant.apply(ctx)
|
||||
expect(invariant.name).toBe('command-compact-invariant')
|
||||
expect(invariant.inject).toEqual(['invariants'])
|
||||
expect(register).toHaveBeenCalledWith('@deepseek-ai/dsh-command-compact', expect.any(Function))
|
||||
expect(() => {
|
||||
const install = register.mock.calls[0]![1] as () => void
|
||||
install()
|
||||
}).not.toThrow()
|
||||
expect(dispose).toBeTypeOf('function')
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,185 @@
|
||||
import { mkdtemp, rm, writeFile } from 'node:fs/promises'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { pathToFileURL } from 'node:url'
|
||||
import { afterEach, describe, expect, it } from 'vitest'
|
||||
import { Context } from '@deepseek-ai/cordis'
|
||||
import Loader from '@deepseek-ai/cordis-plugin-loader'
|
||||
import Include from '@deepseek-ai/cordis-plugin-include'
|
||||
import type { Agent } from '@deepseek-ai/dsh-agent'
|
||||
import CommandRuntime from '@deepseek-ai/dsh-commands'
|
||||
import {
|
||||
CompactionId,
|
||||
CompactionEngine,
|
||||
type CompactionAgentContext,
|
||||
type CompactionResult,
|
||||
type CompactionTrigger,
|
||||
type ManualCompactAgentContext,
|
||||
} from '@deepseek-ai/dsh-compaction'
|
||||
import * as commandCompact from '@deepseek-ai/dsh-command-compact'
|
||||
import { Session, SessionId } from '@deepseek-ai/dsh-session'
|
||||
|
||||
const COMPACTION_ID = CompactionId('loader-command-compact-test')
|
||||
|
||||
const RESULT: CompactionResult = {
|
||||
compactionId: COMPACTION_ID,
|
||||
startSeq: 1,
|
||||
summarySeq: 2,
|
||||
endSeq: 3,
|
||||
summary: [{ type: 'text', text: 'loader summary' }],
|
||||
shadowedRange: { start: 3, end: 8 },
|
||||
shadowedSeqs: [3, 5, 8],
|
||||
shadowedTokenCount: 99,
|
||||
}
|
||||
|
||||
class LoaderCompactionEngine extends CompactionEngine {
|
||||
override compactIfNeeded(
|
||||
_agent: CompactionAgentContext,
|
||||
_trigger: CompactionTrigger,
|
||||
_signal: AbortSignal,
|
||||
): Promise<CompactionResult | null> {
|
||||
return Promise.resolve(null)
|
||||
}
|
||||
|
||||
override compactRegion(): Promise<CompactionResult> {
|
||||
return Promise.resolve(RESULT)
|
||||
}
|
||||
|
||||
override compactNow(
|
||||
agent: ManualCompactAgentContext,
|
||||
_signal: AbortSignal,
|
||||
sourceCommandId?: Parameters<CompactionEngine['compactNow']>[2],
|
||||
): Promise<CompactionResult | null> {
|
||||
const provenance = {
|
||||
compactionId: RESULT.compactionId,
|
||||
...sourceCommandId === undefined ? {} : { sourceCommandId },
|
||||
}
|
||||
agent.session.append('compaction/start', { ...provenance, turn: null })
|
||||
agent.session.append('compaction/summary', {
|
||||
...provenance,
|
||||
summary: RESULT.summary,
|
||||
shadowedRange: RESULT.shadowedRange,
|
||||
shadowedSeqs: RESULT.shadowedSeqs,
|
||||
shadowedTokenCount: RESULT.shadowedTokenCount,
|
||||
provider: 'loader-test',
|
||||
model: 'loader-test',
|
||||
})
|
||||
agent.session.append('compaction/end', { ...provenance, turn: null })
|
||||
return Promise.resolve({ ...RESULT, ...provenance })
|
||||
}
|
||||
}
|
||||
|
||||
let root: string | undefined
|
||||
let context: Context | undefined
|
||||
|
||||
afterEach(async () => {
|
||||
await context?.fiber.dispose()
|
||||
context = undefined
|
||||
if (root !== undefined) await rm(root, { recursive: true, force: true })
|
||||
root = undefined
|
||||
})
|
||||
|
||||
describe('command-compact real Loader composition', () => {
|
||||
it('discovers and executes /compact through the assembled command plane', async () => {
|
||||
root = await mkdtemp(join(tmpdir(), 'dsh-command-compact-loader-'))
|
||||
const configPath = join(root, 'cordis.yml')
|
||||
await writeFile(configPath, [
|
||||
"- name: '@deepseek-ai/dsh-commands'",
|
||||
"- name: '@test/compact-backend'",
|
||||
"- name: '@deepseek-ai/dsh-command-compact'",
|
||||
'',
|
||||
].join('\n'))
|
||||
|
||||
context = new Context()
|
||||
context.baseUrl = pathToFileURL(root).href + '/'
|
||||
await context.plugin(Loader)
|
||||
context.loader.builtins.include = Include
|
||||
const modules = new Map<string, unknown>([
|
||||
['@deepseek-ai/dsh-commands', CommandRuntime],
|
||||
['@test/compact-backend', LoaderCompactionEngine],
|
||||
['@deepseek-ai/dsh-command-compact', commandCompact],
|
||||
])
|
||||
context.loader.internal = {
|
||||
version: 'v2',
|
||||
async import(specifier: string) {
|
||||
if (!modules.has(specifier)) throw new Error(`unexpected Loader import: ${specifier}`)
|
||||
return modules.get(specifier)
|
||||
},
|
||||
} as unknown as NonNullable<typeof context.loader.internal>
|
||||
await context.loader.create({
|
||||
name: 'cordis:include',
|
||||
config: { path: pathToFileURL(configPath).href },
|
||||
})
|
||||
await context.loader.await()
|
||||
|
||||
const session = Session.create(SessionId('loader-command-compact'))
|
||||
const agent = {
|
||||
session,
|
||||
status: 'idle',
|
||||
options: {},
|
||||
reserveTurnAdmission: () => () => undefined,
|
||||
} as unknown as Agent
|
||||
expect(context.commands.list(agent)).toContainEqual({
|
||||
name: 'compact',
|
||||
description: 'Compact older conversation history',
|
||||
})
|
||||
const execution = await context.commands.execute(agent, '/compact', new AbortController().signal)
|
||||
if (execution === undefined) throw new Error('Loader composition did not resolve /compact')
|
||||
expect(execution.result).toEqual({
|
||||
kind: 'success',
|
||||
text: 'Compacted 3 history items (~99 tokens).',
|
||||
sourceEventSeq: RESULT.summarySeq,
|
||||
})
|
||||
expect(session.events.map(event => ({ type: event.type, data: event.data }))).toEqual([
|
||||
{
|
||||
type: 'command/run',
|
||||
data: {
|
||||
commandId: execution.commandId,
|
||||
name: 'compact',
|
||||
args: '',
|
||||
source: { kind: 'user' },
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'compaction/start',
|
||||
data: {
|
||||
compactionId: COMPACTION_ID,
|
||||
sourceCommandId: execution.commandId,
|
||||
turn: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'compaction/summary',
|
||||
data: {
|
||||
compactionId: COMPACTION_ID,
|
||||
sourceCommandId: execution.commandId,
|
||||
summary: RESULT.summary,
|
||||
shadowedRange: RESULT.shadowedRange,
|
||||
shadowedSeqs: RESULT.shadowedSeqs,
|
||||
shadowedTokenCount: RESULT.shadowedTokenCount,
|
||||
provider: 'loader-test',
|
||||
model: 'loader-test',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'compaction/end',
|
||||
data: {
|
||||
compactionId: COMPACTION_ID,
|
||||
sourceCommandId: execution.commandId,
|
||||
turn: null,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'command/done',
|
||||
data: {
|
||||
commandId: execution.commandId,
|
||||
kind: 'success',
|
||||
text: 'Compacted 3 history items (~99 tokens).',
|
||||
sourceEventSeq: RESULT.summarySeq,
|
||||
},
|
||||
},
|
||||
])
|
||||
expect(session.surface.nodes).toEqual([])
|
||||
expect(session.deriveMessages()).toEqual([])
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user