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

@@ -1,12 +1,12 @@
import { describe, expect, it } from 'vitest'
import { Context } from '@deepseek-ai/cordis'
import LlmService, { createUserMessage, type StreamChunk } from '@deepseek-ai/dsh-llm'
import LlmRuntime, { createUserMessage, type StreamChunk } from '@deepseek-ai/dsh-llm'
import SessionStore, { SessionId, type SessionEvent } from '@deepseek-ai/dsh-session'
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
import ToolRegistry, { defineContentToolFixture } from '@deepseek-ai/dsh-tools'
import ToolRuntime, { defineContentToolFixture } from '@deepseek-ai/dsh-tools'
import AgentRegistry, { type Agent } from '@deepseek-ai/dsh-agent'
import AgentLoop from '@deepseek-ai/dsh-agent-loop'
import PlanModeService, { foldPlanMode } from '@deepseek-ai/dsh-plan-mode'
import PlanModeController, { foldPlanMode } from '@deepseek-ai/dsh-plan-mode'
import { MockAdapter, textResponse, toolCallResponse } from '../../../core/agent-loop/tests/mock-adapter.ts'
const PLAN_CONFIG = { section: 'Test plan mode instructions.' }
@@ -21,13 +21,13 @@ const PLAN_CONFIG = { section: 'Test plan mode instructions.' }
*/
async function harness(adapter: MockAdapter): Promise<Context> {
const ctx = new Context()
await ctx.plugin(LlmService)
await ctx.plugin(LlmRuntime)
await ctx.plugin(SessionStore)
await ctx.plugin(SystemPrompt)
await ctx.plugin(ToolRegistry)
await ctx.plugin(ToolRuntime)
await ctx.plugin(AgentRegistry)
await ctx.plugin(AgentLoop, { agents: [] })
await ctx.plugin(PlanModeService, PLAN_CONFIG)
await ctx.plugin(PlanModeController, PLAN_CONFIG)
ctx.llm.registerAdapter(['mock'], adapter)
for (const name of ['read', 'write']) {
ctx.tools.register(defineContentToolFixture({

View File

@@ -2,12 +2,12 @@ import { describe, expect, it } from 'vitest'
import { Context } from '@deepseek-ai/cordis'
import SessionStore, { Session, SessionId, type SessionEvent } from '@deepseek-ai/dsh-session'
import * as PlanModeInvariant from '@deepseek-ai/dsh-plan-mode/invariant'
import InvariantService from '@deepseek-ai/dsh-invariants'
import InvariantRegistry from '@deepseek-ai/dsh-invariants'
async function setup(): Promise<Context> {
const ctx = new Context()
await ctx.plugin(SessionStore)
await ctx.plugin(InvariantService, { enabled: true })
await ctx.plugin(InvariantRegistry, { enabled: true })
await ctx.plugin(PlanModeInvariant)
return ctx
}
@@ -67,7 +67,7 @@ describe('plan-mode stream invariants', () => {
session.append('turn/start', { turn: 1 })
session.append('plan/mode', { active: 'plan' as unknown as boolean })
session.append('turn/end', { turn: 1, reason: { kind: 'completed' } })
await ctx.plugin(InvariantService, { enabled: true })
await ctx.plugin(InvariantRegistry, { enabled: true })
await expect(ctx.plugin(PlanModeInvariant).then(() => undefined)).rejects.toThrow(/expected a boolean/)
})
@@ -79,7 +79,7 @@ describe('plan-mode stream invariants', () => {
session.append('turn/start', { turn: 1 })
session.append('plan/mode', { active: true })
session.append('turn/end', { turn: 1, reason: { kind: 'completed' } })
await ctx.plugin(InvariantService, { enabled: true })
await ctx.plugin(InvariantRegistry, { enabled: true })
await expect(ctx.plugin(PlanModeInvariant).then(() => undefined)).resolves.toBeUndefined()
})
@@ -88,7 +88,7 @@ describe('plan-mode stream invariants', () => {
const ctx = new Context()
await ctx.plugin(SessionStore)
ctx.sessions.create().append('plan/mode', { active: true })
await ctx.plugin(InvariantService, { enabled: true })
await ctx.plugin(InvariantRegistry, { enabled: true })
await expect(ctx.plugin(PlanModeInvariant).then(() => undefined)).resolves.toBeUndefined()
})

View File

@@ -2,16 +2,16 @@ import { describe, expect, it, vi } from 'vitest'
import { Context } from '@deepseek-ai/cordis'
import { createUserMessage, CallId } from '@deepseek-ai/dsh-llm'
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
import ToolRegistry, { RUN_CODE_NAME, defineContentToolFixture } from '@deepseek-ai/dsh-tools'
import ToolRuntime, { RUN_CODE_NAME, defineContentToolFixture } from '@deepseek-ai/dsh-tools'
import { Session, SessionId, type UserMessage } from '@deepseek-ai/dsh-session'
import AgentRegistry, { agentEvents, type Agent } from '@deepseek-ai/dsh-agent'
import { createScope } from '@deepseek-ai/dsh-scope'
import UserInteractionService, {
UserInteractionError, type AskUserQuestionRequest,
} from '@deepseek-ai/dsh-user-interaction'
import CommandService from '@deepseek-ai/dsh-commands'
import UserQuestionService, {
UserQuestionError, type AskUserQuestionRequest,
} from '@deepseek-ai/dsh-user-questions'
import CommandRuntime from '@deepseek-ai/dsh-commands'
import { CodeRuntime, type CodeRunRequest, type CodeRunResult } from '@deepseek-ai/dsh-code-runtime'
import PlanModeService, { EXIT_PLAN_MODE, foldPlanMode, resolveConfig } from '../src/index.ts'
import PlanModeController, { EXIT_PLAN_MODE, foldPlanMode, resolveConfig } from '../src/index.ts'
import type { PlanModeConfig } from '../src/index.ts'
const TEST_PLAN_SECTION = 'Test plan mode instructions.'
@@ -19,7 +19,7 @@ const PLAN_CONFIG = { section: TEST_PLAN_SECTION } satisfies PlanModeConfig
/**
* Drives the REAL plugin: mounts `dsh-plan-mode` beside real `SystemPrompt` and
* `ToolRegistry` services, with fake Agents carrying real `Session`s and a
* `ToolRuntime` services, with fake Agents carrying real `Session`s and a
* real scoped `agent.ctx` minted through `createScope`.
* Request boundaries are simulated by dispatching the real pre-step waterfall
* and the following `step/start` session event used by the loop.
@@ -68,8 +68,8 @@ function assembleFor(ctx: Context, agent: Agent) {
async function setup(config: PlanModeConfig = PLAN_CONFIG): Promise<Context> {
const ctx = new Context()
await ctx.plugin(SystemPrompt)
await ctx.plugin(ToolRegistry)
await ctx.plugin(PlanModeService, config)
await ctx.plugin(ToolRuntime)
await ctx.plugin(PlanModeController, config)
return ctx
}
@@ -281,8 +281,8 @@ describe('the boundary flush', () => {
it('removes the pre-step flush when the plugin fiber is disposed', async () => {
const ctx = new Context()
await ctx.plugin(SystemPrompt)
await ctx.plugin(ToolRegistry)
const fiber = await ctx.plugin(PlanModeService, PLAN_CONFIG)
await ctx.plugin(ToolRuntime)
const fiber = await ctx.plugin(PlanModeController, PLAN_CONFIG)
const agent = await agentWithSession(ctx)
openTurn(agent.session)
ctx.planMode.set(agent, true)
@@ -433,13 +433,13 @@ describe('the soft layer', () => {
// Plan guidance does not filter the registry or later assembly additions.
const ctx = new Context()
await ctx.plugin(SystemPrompt)
await ctx.plugin(ToolRegistry)
await ctx.plugin(ToolRuntime)
ctx.on('system-prompt/assemble', async (_assembly, _context, next) => {
const final = await next()
final.tools = [...final.tools, { name: 'added-later', description: 'added after next()', parameters: {} }]
return final
})
await ctx.plugin(PlanModeService, PLAN_CONFIG)
await ctx.plugin(PlanModeController, PLAN_CONFIG)
registerNamedTools(ctx, ['read'])
const planning = await agentWithSession(ctx, 'planning', { active: true })
expect((await assembleFor(ctx, planning)).tools.map(tool => tool.name))
@@ -459,9 +459,9 @@ describe('the soft layer', () => {
}
const ctx = new Context()
await ctx.plugin(SystemPrompt)
await ctx.plugin(ToolRegistry, { mode: 'code' })
await ctx.plugin(ToolRuntime, { mode: 'code' })
await ctx.plugin(FakeRuntime)
await ctx.plugin(PlanModeService, PLAN_CONFIG)
await ctx.plugin(PlanModeController, PLAN_CONFIG)
registerNamedTools(ctx, ['read', 'write'])
const agent = await agentWithSession(ctx, 'agent-1', { active: true })
const assembly = await assembleFor(ctx, agent)
@@ -480,9 +480,9 @@ describe('the soft layer', () => {
}
const ctx = new Context()
await ctx.plugin(SystemPrompt)
await ctx.plugin(ToolRegistry, { mode: 'both' })
await ctx.plugin(ToolRuntime, { mode: 'both' })
await ctx.plugin(FakeRuntime)
await ctx.plugin(PlanModeService, PLAN_CONFIG)
await ctx.plugin(PlanModeController, PLAN_CONFIG)
registerNamedTools(ctx, ['read', 'write'])
const agent = await agentWithSession(ctx, 'agent-1', { active: true })
const assembly = await assembleFor(ctx, agent)
@@ -501,9 +501,9 @@ describe('the soft layer', () => {
}
const withPlanMode = new Context()
await withPlanMode.plugin(SystemPrompt)
await withPlanMode.plugin(ToolRegistry, { mode: 'code' })
await withPlanMode.plugin(ToolRuntime, { mode: 'code' })
await withPlanMode.plugin(FakeRuntime)
await withPlanMode.plugin(PlanModeService, PLAN_CONFIG)
await withPlanMode.plugin(PlanModeController, PLAN_CONFIG)
registerNamedTools(withPlanMode, ['read', 'write'])
const agent = await agentWithSession(withPlanMode)
const defaultSdk = (await assembleFor(withPlanMode, agent)).sections.find(section => section.name === 'tools:sdk')?.text ?? ''
@@ -516,7 +516,7 @@ describe('the soft layer', () => {
// with a deployment that does not compose plan mode at all.
const bare = new Context()
await bare.plugin(SystemPrompt)
await bare.plugin(ToolRegistry, { mode: 'code' })
await bare.plugin(ToolRuntime, { mode: 'code' })
await bare.plugin(FakeRuntime)
registerNamedTools(bare, ['read', 'write'])
const bareSdk = (await bare.systemPrompt.assemble({ agent })).sections.find(section => section.name === 'tools:sdk')?.text ?? ''
@@ -553,7 +553,7 @@ describe('/plan', () => {
expect(bare.get('commands')).toBeUndefined()
const ctx = await setup()
await ctx.plugin(CommandService)
await ctx.plugin(CommandRuntime)
// The `ctx.inject` child mounts asynchronously once `commands` resolves.
await new Promise(resolve => setImmediate(resolve))
const plainAgent = await agentWithSession(ctx, 'plain-plan-command')
@@ -595,7 +595,7 @@ describe('/plan', () => {
it('leaves active plan mode, cancels a pending entry, and treats inactive exit as idempotent', async () => {
const ctx = await setup()
await ctx.plugin(CommandService)
await ctx.plugin(CommandRuntime)
await new Promise(resolve => setImmediate(resolve))
const signal = new AbortController().signal
@@ -633,7 +633,7 @@ describe('/plan', () => {
it('idle sessions get the immediate-commit copy on both /plan and /plan off', async () => {
const ctx = await setup()
await ctx.plugin(CommandService)
await ctx.plugin(CommandRuntime)
await new Promise(resolve => setImmediate(resolve))
const signal = new AbortController().signal
const agent = await agentWithSession(ctx, 'idle-plan-command')
@@ -648,9 +648,9 @@ describe('/plan', () => {
it('removes the contributed command when the plan-mode plugin is disposed', async () => {
const ctx = new Context()
await ctx.plugin(SystemPrompt)
await ctx.plugin(ToolRegistry)
await ctx.plugin(CommandService)
const fiber = await ctx.plugin(PlanModeService, PLAN_CONFIG)
await ctx.plugin(ToolRuntime)
await ctx.plugin(CommandRuntime)
const fiber = await ctx.plugin(PlanModeController, PLAN_CONFIG)
await new Promise(resolve => setImmediate(resolve))
const agent = await agentWithSession(ctx)
expect(ctx.commands.list(agent).map(command => command.name)).toEqual(['plan'])
@@ -665,10 +665,10 @@ describe('exit_plan_mode', () => {
async function setupWithReview(answer?: { selected: string[]; custom?: string }) {
const ctx = await setup()
await ctx.plugin(AgentRegistry)
await ctx.plugin(UserInteractionService)
await ctx.plugin(UserQuestionService)
const asked: AskUserQuestionRequest[] = []
if (answer !== undefined) {
ctx.userInteraction.registerProvider({
ctx.userQuestions.registerProvider({
ask: (request) => {
asked.push(request)
return Promise.resolve({ answers: [{ id: 'plan-review', ...answer }] })
@@ -725,12 +725,12 @@ describe('exit_plan_mode', () => {
expect(foldPlanMode(agent.session.events)).toBe(true)
})
it('degrades to the manual exit when no user-interaction seam is composed', async () => {
it('degrades to the manual exit when no user-questions seam is composed', async () => {
const ctx = await setup()
const agent = await agentWithSession(ctx, 'agent-1', { active: true })
const result = await callExit(ctx, agent)
expect(result.isError).toBe(true)
expect(result.content).toEqual([{ type: 'text', text: 'Error: no user-interaction channel is available to review the plan; ask the user to switch the session mode instead' }])
expect(result.content).toEqual([{ type: 'text', text: 'Error: no user-questions channel is available to review the plan; ask the user to switch the session mode instead' }])
expect(foldPlanMode(agent.session.events)).toBe(true)
})
@@ -738,16 +738,16 @@ describe('exit_plan_mode', () => {
const { ctx, agent } = await setupWithReview()
const result = await callExit(ctx, agent)
expect(result.isError).toBe(true)
expect(result.content).toEqual([{ type: 'text', text: 'Error: no user-interaction provider is registered' }])
expect(result.content).toEqual([{ type: 'text', text: 'Error: no user-questions provider is registered' }])
expect(foldPlanMode(agent.session.events)).toBe(true)
})
it('rejects review from a runtime-owned agent with consumer-neutral guidance', async () => {
const ctx = await setup()
await ctx.plugin(AgentRegistry)
await ctx.plugin(UserInteractionService)
await ctx.plugin(UserQuestionService)
const ask = vi.fn(async () => ({ answers: [{ id: 'plan-review', selected: ['Approve'] }] }))
ctx.userInteraction.registerProvider({ ask })
ctx.userQuestions.registerProvider({ ask })
const root = await agentWithSession(ctx, 'review-root')
const child = await agentWithSession(ctx, 'review-child', { active: true, owner: root })
@@ -794,13 +794,13 @@ describe('exit_plan_mode', () => {
}
const ctx = new Context()
await ctx.plugin(SystemPrompt)
await ctx.plugin(ToolRegistry, { mode: 'code' })
await ctx.plugin(ToolRuntime, { mode: 'code' })
await ctx.plugin(ExitRuntime)
await ctx.plugin(PlanModeService, PLAN_CONFIG)
await ctx.plugin(PlanModeController, PLAN_CONFIG)
await ctx.plugin(AgentRegistry)
await ctx.plugin(UserInteractionService)
await ctx.plugin(UserQuestionService)
const asked: AskUserQuestionRequest[] = []
ctx.userInteraction.registerProvider({
ctx.userQuestions.registerProvider({
ask: (request) => {
asked.push(request)
return Promise.resolve({ answers: [{ id: 'plan-review', selected: ['Approve'] }] })
@@ -899,7 +899,7 @@ describe('exit_plan_mode', () => {
it('treats duplicate review answer items as non-consent', async () => {
const { ctx, agent } = await setupWithReview()
ctx.userInteraction.registerProvider({
ctx.userQuestions.registerProvider({
ask: () => Promise.resolve({ answers: [
{ id: 'plan-review', selected: ['Approve'] },
{ id: 'plan-review', selected: ['Keep planning'] },
@@ -913,7 +913,7 @@ describe('exit_plan_mode', () => {
it('a missing answer item reads as keep-planning', async () => {
const { ctx, agent } = await setupWithReview()
ctx.userInteraction.registerProvider({ ask: () => Promise.resolve({ answers: [] }) })
ctx.userQuestions.registerProvider({ ask: () => Promise.resolve({ answers: [] }) })
const result = await callExit(ctx, agent)
expect(result.isError).toBe(true)
expect(result.content).toEqual([{ type: 'text', text: 'Error: The user chose to keep planning; revise the plan and present it again.' }])
@@ -931,8 +931,8 @@ describe('exit_plan_mode', () => {
it('reads a dismissed review as the user taking the turn back, not as a failure', async () => {
const { ctx, agent } = await setupWithReview()
ctx.userInteraction.registerProvider({
ask: () => Promise.reject(new UserInteractionError(
ctx.userQuestions.registerProvider({
ask: () => Promise.reject(new UserQuestionError(
'the user cancelled ask_user_question', 'ASK_CANCELLED')),
})
const result = await callExit(ctx, agent)
@@ -943,8 +943,8 @@ describe('exit_plan_mode', () => {
it('leaves every other review failure its own message', async () => {
const { ctx, agent } = await setupWithReview()
ctx.userInteraction.registerProvider({
ask: () => Promise.reject(new UserInteractionError(
ctx.userQuestions.registerProvider({
ask: () => Promise.reject(new UserQuestionError(
'ask_user_question was aborted before the user answered', 'ASK_ABORTED')),
})
const result = await callExit(ctx, agent)
@@ -970,12 +970,12 @@ describe('exit_plan_mode', () => {
it('fails the call when the plugin is disposed while the review awaits (no phantom exit)', async () => {
const ctx = new Context()
await ctx.plugin(SystemPrompt)
await ctx.plugin(ToolRegistry)
const fiber = await ctx.plugin(PlanModeService, PLAN_CONFIG)
await ctx.plugin(ToolRuntime)
const fiber = await ctx.plugin(PlanModeController, PLAN_CONFIG)
await ctx.plugin(AgentRegistry)
await ctx.plugin(UserInteractionService)
await ctx.plugin(UserQuestionService)
let answer!: (value: { answers: { id: string; selected: string[] }[] }) => void
ctx.userInteraction.registerProvider({
ctx.userQuestions.registerProvider({
ask: () => new Promise((resolve) => { answer = resolve }),
})
const agent = await agentWithSession(ctx, 'agent-1', { active: true })
@@ -994,7 +994,7 @@ describe('exit_plan_mode', () => {
it('a throwing provider surfaces as the corrective isError and the mode stays plan', async () => {
const { ctx, agent } = await setupWithReview()
ctx.userInteraction.registerProvider({ ask: () => { throw new Error('review aborted') } })
ctx.userQuestions.registerProvider({ ask: () => { throw new Error('review aborted') } })
const result = await callExit(ctx, agent)
expect(result.isError).toBe(true)
expect(result.content).toEqual([{ type: 'text', text: 'Error: review aborted' }])
@@ -1034,12 +1034,12 @@ describe('HMR disposal', () => {
it('unregisters the service, listeners, prompt section, and stable exit tool with the plugin fiber', async () => {
const ctx = new Context()
await ctx.plugin(SystemPrompt)
await ctx.plugin(ToolRegistry)
const fiber = await ctx.plugin(PlanModeService, PLAN_CONFIG)
await ctx.plugin(ToolRuntime)
const fiber = await ctx.plugin(PlanModeController, PLAN_CONFIG)
const agent = await agentWithSession(ctx, 'disposed-recovery')
openTurn(agent.session)
ctx.planMode.set(agent, true)
expect(ctx.get('planMode')).toBeInstanceOf(PlanModeService)
expect(ctx.get('planMode')).toBeInstanceOf(PlanModeController)
expect(ctx.tools.get(EXIT_PLAN_MODE)).toBeDefined()
expect((await ctx.systemPrompt.assemble()).sections.map(section => section.name)).toContain('plan:policy')

View File

@@ -16,11 +16,11 @@ import type { Agent } from '@deepseek-ai/dsh-agent'
import SessionStore from '@deepseek-ai/dsh-session'
import type { Session } from '@deepseek-ai/dsh-session'
import SystemPrompt from '@deepseek-ai/dsh-system-prompt'
import ToolRegistry from '@deepseek-ai/dsh-tools'
import ToolRuntime from '@deepseek-ai/dsh-tools'
import SessionProjectionRegistry from '@deepseek-ai/dsh-session-projection'
import UserInteractionService from '@deepseek-ai/dsh-user-interaction'
import UserQuestionService from '@deepseek-ai/dsh-user-questions'
import { CommandId } from '@deepseek-ai/dsh-commands/brand'
import PlanModeService from '@deepseek-ai/dsh-plan-mode'
import PlanModeController from '@deepseek-ai/dsh-plan-mode'
interface Bench {
ctx: Context
@@ -32,11 +32,11 @@ async function harness(withPlanMode: boolean): Promise<Bench> {
const ctx = new Context()
await ctx.plugin(SessionStore)
await ctx.plugin(SystemPrompt, { persona: '' })
await ctx.plugin(ToolRegistry)
await ctx.plugin(UserInteractionService)
await ctx.plugin(ToolRuntime)
await ctx.plugin(UserQuestionService)
await ctx.plugin(AgentRegistry)
await ctx.plugin(SessionProjectionRegistry)
if (withPlanMode) await ctx.plugin(PlanModeService, { section: 'plan policy' })
if (withPlanMode) await ctx.plugin(PlanModeController, { section: 'plan policy' })
const session = ctx.sessions.create()
ctx.agents.register({ id: session.id, session, status: 'idle', ctx } as Agent)
return {
@@ -115,7 +115,7 @@ describe('plan projection unit', () => {
it('drops the key when the plan-mode fiber unloads (HMR safety)', async () => {
const bench = await harness(false)
const fiber = await bench.ctx.plugin(PlanModeService, { section: 'plan policy' })
const fiber = await bench.ctx.plugin(PlanModeController, { section: 'plan policy' })
expect(bench.values().plan).toEqual({ active: false, pending: false })
await fiber.dispose()
expect('plan' in bench.values()).toBe(false)