8 · DSH 运行时能力

平台要的每一项能力,DSH 底座都已有对应的 seam(能力缝)。本页是一张「平台能力 ↔ DSH seam ↔ 关键 API/包」对照表, 加上业务插件该怎样接入(注入 vs 可选获取),以及一个「最小可用智能体」的装配骨架。

怎么用这一页

动手加功能前,先在下表里找到对应 seam。seam 是 DSH 声明并保证的扩展点,业务插件只做「翻译 / 编排」,不重实现。 路由前缀 / 领域表 / 三件套的落地写法见 7 · 业务插件开发(模板)。

能力映射总表#

平台能力DSH seam关键 API / 包
跑一个智能体 ctx.agents create / resume / AgentOptions / setup;packages/core/agent-loop
智能体预设(提示词 + 工具 + 技能的组合) ctx.agentPresets register / mount / recompose / select;packages/preset/agent-preset
多智能体 / 委派 ctx.subagents registerProvider / start / startContinuable;packages/subagent/*
提示词分段 ctx.systemPrompt section / variable / tools
模型 provider / 路由 ctx.llm registerAdapter / registerConfigurableProviders / listModels / prepareCall / stream;packages/llm/*
凭据 ctx.credentials credentials-local;packages/credentials
工具 ctx.tools register / restrict / schemas / guard
MCP 每服务器一行 @deepseek-ai/dsh-mcp-client;ctx.mcpResources ACP 会话级还可经 ctx.plugin 动态挂载;工具名以 mcp__<server>__<tool> 进入工具面
技能 ctx.skills + dsh-skill-filesystem register / registerProvider;技能目录 <DSH_HOME>/skills
工作流 packages/workflow 工作流执行;packages/schedule / packages/webhook
后台任务 packages/jobs + dsh-tool-jobs 任务编排与 jobs 工具面
沙箱 packages/sandbox/* sandbox-local / policy / bash-sandbox / fs-sandbox
会话与回放 packages/session* session-persistence-jsonl / session-query
动态装卸插件 ctx.loader / ctx.pluginManager create / update / remove;installBundle / listPlugins / inspect(@Remote)
运行时自修改(生成插件) packages/extensions ctx.dynamicCordisRunner / ctx.cordisInspect
对外接口 / SDK packages/api / packages/sdk / packages/acp remote BFF / JSON-RPC / ACP 自动化
可观测 packages/telemetry otel;另有 packages/feedback / packages/guard
审批 ctx.approval 对敏感工具调用设人工确认门(与 guard 配合)

业务插件常用注入:硬依赖 vs 可选#

插件通过 inject 声明硬依赖——取不到就不加载(降级为「插件缺失」,而不是半死不活)。 其余底座服务一律用 ctx.get(...) 取,缺了只降级对应能力,绝不挂起插件。

硬依赖(缺则不加载)
tssrc/index.ts
export const inject = [
  'webServer',
  'infraConfig',
  'auth',
  'infraDatabase'
]

分别提供:HTTP 路由注册、配置台账读取、会话与鉴权、共享库连接池。

可选(缺则降级)
ts取可选服务
const llm  = ctx.get('llm')          // 缺 → 动态模型不可用
const agents = ctx.get('agents')    // 缺 → 业务生成不可用
const tools  = ctx.get('tools')     // 缺 → 动态工具未注册
const loader = ctx.get('loader')    // 缺 → MCP 未装配
const presets = ctx.get('agentPresets') // 缺 → 不挂 preset
为什么必须分清楚

cordis 插件取未声明的服务会直接抛错,且错误发生在宿主启动阶段。所以四个硬依赖必须写进 inject; 而 llm / agents / tools / loader / agentPresets 用 ctx.get 取, 取不到只记一条 warn 并降级。

契约副本从哪来

跨插件值导入被构建门禁止,服务是唯一通道,所以消费方各自持一份契约副本(模板里是 src/contract.ts), 只声明自己真正用到的成员,避免 import 宿主类型。

最小可用智能体#

「取模型 → ctx.agents.create → 跑一轮 → 回轨迹」四步,就是模板 runtime/run.ts 的骨架。

ts一次生成任务的骨架(伪代码)
// 1) 取模型:页面登记的模型在运行时被注册成 provider 路由 yyjz-<modelId>
const route = modelRegistrar?.routeOf(modelId)   // → 'yyjz-<modelId>'

// 2) 起会话:setup 里挂 preset + 注册提示词段 + 收敛工具白名单
const handle = await agents.create({
  sessionId,
  meta: { cwd: process.cwd() },
  agentOptions: { provider: route, model: modelName },
  setup: composeSetup(ctx, composition, log),     // → agentPresets.mount / systemPrompt.section / tools.restrict
})

// 3) 跑一轮:先等创建期收敛,记日志起点,再发 user 消息,最后等停稳
await handle.agent.whenIdle()
const firstSeq = handle.agent.session.seq
handle.agent.followup(userMessage(userText))
await handle.agent.whenIdle()

// 4) 回轨迹:以会话日志(durable source of truth)为准,实时流只用于透传增量
const text = readAssistantText(handle.agent.session, firstSeq)
await handle.dispose()
读日志,不读流

失败原因(turn/end)只出现在会话日志里,实时流(agent/assistant-stream)只承载文本增量。 所以「一次生成任务的最终产出」从日志里取,流只用来做 SSE 透传。

先确认底座已有对应机制,不要另造一层

这是模板的硬约束,也是本手册的底线:新增「模型 / 工具 / 技能 / MCP / 子智能体」相关能力前, 先在本页总表里确认底座已有对应 seam——能注册就注册,能翻译就翻译。 不自建 agent 循环、不自建 MCP 客户端、不自建技能机制、不引外部服务。 只有确实缺 seam 时,才考虑向上游底座提需求,而不是在业务插件里埋第二套。