feat: add docs website
This commit is contained in:
85
website/zh-CN/api/cordis/context.md
Normal file
85
website/zh-CN/api/cordis/context.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# Context
|
||||
|
||||
上下文对象是 Cordis 的核心。所有服务、方法、属性都通过 `ctx` 访问。
|
||||
|
||||
## 服务与混入
|
||||
|
||||
Context 基于组合式 API 设计,大部分属性和方法挂载在服务上。以下是核心 API:
|
||||
|
||||
- [`ctx.on`](./events#ctx-on) — 注册事件监听器
|
||||
- [`ctx.emit`](./events#ctx-emit) — 触发事件
|
||||
- [`ctx.bail`](./events#ctx-bail) — 短路事件
|
||||
- [`ctx.serial`](./events#ctx-serial) — 顺序异步事件
|
||||
- [`ctx.waterfall`](./events#ctx-waterfall) — 管道事件
|
||||
- [`ctx.effect`](./fiber#fiber-effect) — 注册可逆效果
|
||||
- [`ctx.plugin`](./registry#ctx-plugin) — 加载子插件
|
||||
- [`ctx.inject`](./registry#ctx-inject) — 获取依赖的插件
|
||||
- [`ctx.get`](#ctx-get) — 获取服务
|
||||
- [`ctx.set`](#ctx-set) — 设置服务
|
||||
- [`ctx.provide`](#ctx-provide) — 声明服务
|
||||
|
||||
## 实例属性
|
||||
|
||||
### ctx.fiber
|
||||
|
||||
- **类型:** [`Fiber`](./fiber)
|
||||
|
||||
当前上下文的作用域对象。
|
||||
|
||||
## 实例方法
|
||||
|
||||
### ctx.extend(meta)
|
||||
|
||||
- **meta:** `object`
|
||||
- **返回值:** `Context`
|
||||
|
||||
构造一个以当前上下文为原型的新上下文实例。
|
||||
|
||||
### ctx.intercept(name, config)
|
||||
|
||||
- **name:** `string` 服务名称
|
||||
- **config:** `object` 配置拦截
|
||||
- **返回值:** `Context`
|
||||
|
||||
为指定服务添加一层配置拦截,返回新的上下文实例。
|
||||
|
||||
### ctx.isolate(name, label?)
|
||||
|
||||
- **name:** `string` 服务名称
|
||||
- **label:** `symbol` 隔离域符号(可选)
|
||||
- **返回值:** `Context`
|
||||
|
||||
创建一个针对指定服务的隔离域,返回新的上下文实例。隔离域中的同名服务互不影响。
|
||||
|
||||
### ctx.get(name)
|
||||
|
||||
- **name:** `string` 服务名称
|
||||
- **返回值:** `Service | undefined`
|
||||
|
||||
获取指定名称的服务实例。
|
||||
|
||||
### ctx.set(name, value)
|
||||
|
||||
- **name:** `string` 服务名称
|
||||
- **value:** `any` 服务值
|
||||
|
||||
设置指定名称的服务。
|
||||
|
||||
### ctx.provide(name, value?, options?)
|
||||
|
||||
- **name:** `string` 服务名称
|
||||
- **value:** `any` 初始值(可选)
|
||||
- **options:** `object`
|
||||
- **返回值:** `void`
|
||||
|
||||
声明一个服务。声明后其他插件可以通过 `inject` 依赖它。
|
||||
|
||||
## 静态属性
|
||||
|
||||
### Context.events
|
||||
|
||||
内置事件服务的 symbol key。
|
||||
|
||||
### Context.current
|
||||
|
||||
当前活跃的 Context 实例(在异步链中通过 AsyncLocalStorage 追踪)。
|
||||
120
website/zh-CN/api/cordis/events.md
Normal file
120
website/zh-CN/api/cordis/events.md
Normal file
@@ -0,0 +1,120 @@
|
||||
# Events
|
||||
|
||||
`ctx.events` 是内置服务,提供事件系统相关的全部 API。
|
||||
|
||||
## 实例方法
|
||||
|
||||
### ctx.on(event, listener, options?) {#ctx-on}
|
||||
|
||||
- **event:** `string` 事件名称
|
||||
- **listener:** `Function` 事件监听器
|
||||
- **options:** `object`
|
||||
- **prepend:** `boolean` 是否注册为前置(默认 `false`)
|
||||
- **global:** `boolean` 是否注册为全局(默认 `false`)
|
||||
- **返回值:** `() => void` 取消注册函数
|
||||
|
||||
注册一个事件监听器。返回的函数可用于手动取消注册,但通常不需要——插件卸载时会自动清理。
|
||||
|
||||
```typescript
|
||||
ctx.on('agent/turn-end', (data) => {
|
||||
console.log('turn ended:', data)
|
||||
})
|
||||
```
|
||||
|
||||
### ctx.emit(thisArg?, event, ...args) {#ctx-emit}
|
||||
|
||||
- **thisArg:** `any` 监听器的 `this` 参数(可选)
|
||||
- **event:** `string` 事件名称
|
||||
- **args:** `any[]` 事件参数
|
||||
- **返回值:** `void`
|
||||
|
||||
同步触发所有匹配的监听器(并行,不等待异步完成)。
|
||||
|
||||
### ctx.parallel(thisArg?, event, ...args)
|
||||
|
||||
- 签名同 `emit`
|
||||
- **返回值:** `Promise<void>`
|
||||
|
||||
异步触发所有匹配的监听器(并行等待)。
|
||||
|
||||
### ctx.bail(thisArg?, event, ...args) {#ctx-bail}
|
||||
|
||||
- **返回值:** `any`
|
||||
|
||||
同步依次触发监听器。第一个返回非 `undefined`/`null`/`false` 值的监听器停止链并返回该值。
|
||||
|
||||
### ctx.serial(thisArg?, event, ...args) {#ctx-serial}
|
||||
|
||||
- **返回值:** `Promise<any>`
|
||||
|
||||
异步依次触发监听器。语义同 `bail` 的异步版本。
|
||||
|
||||
### ctx.waterfall(thisArg?, event, ...args) {#ctx-waterfall}
|
||||
|
||||
- **返回值:** `Promise<any>`
|
||||
|
||||
管道模式:每个监听器接收前一个的输出。监听器内部必须调用 `next()` 才会传递给下一个。
|
||||
|
||||
```typescript
|
||||
// 注册
|
||||
ctx.on('llm/pre-request', async (messages, next) => {
|
||||
messages.push(extraMsg)
|
||||
return next(messages) // 必须调用
|
||||
})
|
||||
|
||||
// 触发
|
||||
const result = await ctx.waterfall('llm/pre-request', initialMessages)
|
||||
```
|
||||
|
||||
::: warning
|
||||
不调用 `next()` 即为否决 (veto)——管道终止。这是设计行为,用于拦截/网关。
|
||||
:::
|
||||
|
||||
## Harness 内置事件
|
||||
|
||||
### agent/pre-step
|
||||
|
||||
- **触发模式:** serial
|
||||
- **参数:** `{ agentId, turnIndex }`
|
||||
|
||||
Agent 执行一步之前触发。
|
||||
|
||||
### agent/post-step
|
||||
|
||||
- **触发模式:** emit
|
||||
- **参数:** `{ agentId, turnIndex, blocks }`
|
||||
|
||||
Agent 执行一步之后触发。
|
||||
|
||||
### tool/call
|
||||
|
||||
- **触发模式:** emit
|
||||
- **参数:** `{ name, args, callId }`
|
||||
|
||||
Tool 被模型调用时触发。
|
||||
|
||||
### tool/result
|
||||
|
||||
- **触发模式:** emit
|
||||
- **参数:** `{ name, result, callId }`
|
||||
|
||||
Tool 返回结果时触发。
|
||||
|
||||
### session/event
|
||||
|
||||
- **触发模式:** emit
|
||||
- **参数:** `SessionEvent`
|
||||
|
||||
会话事件被记录时触发。
|
||||
|
||||
### compact/start
|
||||
|
||||
- **触发模式:** emit
|
||||
|
||||
上下文压缩开始。
|
||||
|
||||
### compact/end
|
||||
|
||||
- **触发模式:** emit
|
||||
|
||||
上下文压缩结束。
|
||||
108
website/zh-CN/api/cordis/fiber.md
Normal file
108
website/zh-CN/api/cordis/fiber.md
Normal file
@@ -0,0 +1,108 @@
|
||||
# Fiber
|
||||
|
||||
Fiber(作用域)是插件实例的运行时容器,管理其生命周期和效果。
|
||||
|
||||
## 状态机
|
||||
|
||||
```
|
||||
PENDING → LOADING → ACTIVE → UNLOADING → DISPOSED
|
||||
↘ FAILED
|
||||
```
|
||||
|
||||
| 状态 | 数值 | 含义 |
|
||||
|------|------|------|
|
||||
| PENDING | 0 | 依赖未就绪,等待中 |
|
||||
| LOADING | 1 | 正在执行 `apply` |
|
||||
| ACTIVE | 2 | 运行中 |
|
||||
| FAILED | 3 | `apply` 抛出异常 |
|
||||
| UNLOADING | 4 | 正在撤销效果 |
|
||||
| DISPOSED | 5 | 已完全卸载 |
|
||||
|
||||
## 实例属性
|
||||
|
||||
### fiber.uid
|
||||
|
||||
- **类型:** `number`
|
||||
|
||||
Fiber 的唯一标识符。
|
||||
|
||||
### fiber.status
|
||||
|
||||
- **类型:** `number`
|
||||
|
||||
当前状态(见状态机)。
|
||||
|
||||
### fiber.config
|
||||
|
||||
- **类型:** `object`
|
||||
|
||||
传递给插件的配置对象。
|
||||
|
||||
### fiber.error
|
||||
|
||||
- **类型:** `Error | undefined`
|
||||
|
||||
如果状态是 FAILED,包含导致失败的异常。
|
||||
|
||||
## 实例方法
|
||||
|
||||
### fiber.effect(callback) {#fiber-effect}
|
||||
|
||||
- **callback:** `() => (() => void) | void`
|
||||
- **返回值:** `() => void`
|
||||
|
||||
注册一个效果。`callback` 在 Fiber 激活时执行;如果返回函数,该函数在 Fiber dispose 时执行。
|
||||
|
||||
```typescript
|
||||
ctx.effect(() => {
|
||||
const timer = setInterval(tick, 1000)
|
||||
return () => clearInterval(timer)
|
||||
})
|
||||
```
|
||||
|
||||
等价地可以通过 `ctx.effect()` 调用(ctx 代理到当前 fiber)。
|
||||
|
||||
### fiber.dispose()
|
||||
|
||||
- **返回值:** `Promise<void>`
|
||||
|
||||
手动 dispose 该 Fiber。按注册逆序撤销所有效果,递归 dispose 所有子 Fiber。
|
||||
|
||||
```typescript
|
||||
const child = ctx.plugin(somePlugin)
|
||||
// 之后:
|
||||
await child.dispose()
|
||||
```
|
||||
|
||||
### fiber.update(config)
|
||||
|
||||
- **config:** `object` 新配置
|
||||
- **返回值:** `void`
|
||||
|
||||
热更新配置。如果新旧配置不同,触发 dispose + 重新 apply。
|
||||
|
||||
### fiber.restart()
|
||||
|
||||
- **返回值:** `void`
|
||||
|
||||
强制重启:dispose 后重新加载。
|
||||
|
||||
### fiber.then(resolve, reject?)
|
||||
|
||||
- **返回值:** `Promise<void>`
|
||||
|
||||
使 Fiber 可以被 `await`:等到状态进入 ACTIVE 或 FAILED。
|
||||
|
||||
```typescript
|
||||
const fiber = ctx.plugin(myPlugin)
|
||||
await fiber // 等待插件加载完成
|
||||
```
|
||||
|
||||
## 访问当前 Fiber
|
||||
|
||||
```typescript
|
||||
export function apply(ctx: Context) {
|
||||
const fiber = ctx.fiber // 当前插件的 Fiber
|
||||
console.log(fiber.status) // 1 (LOADING, 因为正在 apply 中)
|
||||
}
|
||||
```
|
||||
87
website/zh-CN/api/cordis/registry.md
Normal file
87
website/zh-CN/api/cordis/registry.md
Normal file
@@ -0,0 +1,87 @@
|
||||
# Registry
|
||||
|
||||
插件注册表,管理插件的加载和依赖解析。
|
||||
|
||||
## 实例方法
|
||||
|
||||
### ctx.plugin(plugin, config?) {#ctx-plugin}
|
||||
|
||||
- **plugin:** `Plugin` 插件(函数、对象或类)
|
||||
- **config:** `object` 传递给插件的配置(可选)
|
||||
- **返回值:** `Fiber`
|
||||
|
||||
加载一个子插件,返回其 Fiber。子 Fiber 的生命周期绑定到父上下文。
|
||||
|
||||
```typescript
|
||||
// 函数插件
|
||||
ctx.plugin(myPlugin, { key: 'value' })
|
||||
|
||||
// 类插件
|
||||
ctx.plugin(MyService)
|
||||
|
||||
// 返回的 Fiber 可以 await 或 dispose
|
||||
const fiber = ctx.plugin(myPlugin)
|
||||
await fiber
|
||||
```
|
||||
|
||||
### ctx.inject(names, callback) {#ctx-inject}
|
||||
|
||||
- **names:** `string[]` 服务名列表
|
||||
- **callback:** `(ctx: Context) => void`
|
||||
- **返回值:** `() => void`
|
||||
|
||||
等待指定服务全部就绪后执行 callback。如果服务消失,callback 的效果会自动撤销;服务恢复后重新执行。
|
||||
|
||||
```typescript
|
||||
ctx.inject(['tools', 'llm'], (ctx) => {
|
||||
// tools 和 llm 都就绪了
|
||||
ctx.tools.register(/* ... */)
|
||||
})
|
||||
```
|
||||
|
||||
这是 `export const inject = [...]` 声明的底层 API。大多数情况下直接使用声明式写法即可。
|
||||
|
||||
## 插件形态
|
||||
|
||||
`ctx.plugin()` 接受三种插件形态:
|
||||
|
||||
### 函数插件
|
||||
|
||||
```typescript
|
||||
function myPlugin(ctx: Context, config?: Config) {
|
||||
// ...
|
||||
}
|
||||
myPlugin.name = 'my-plugin'
|
||||
myPlugin.inject = ['tools']
|
||||
```
|
||||
|
||||
### 对象插件
|
||||
|
||||
```typescript
|
||||
const myPlugin = {
|
||||
name: 'my-plugin',
|
||||
inject: ['tools'],
|
||||
apply(ctx: Context, config?: Config) {
|
||||
// ...
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 类插件(Service)
|
||||
|
||||
```typescript
|
||||
class MyService extends Service {
|
||||
static inject = ['tools']
|
||||
constructor(ctx: Context) {
|
||||
super(ctx, 'myService')
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 插件元信息
|
||||
|
||||
| 属性 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `name` | `string` | 插件名称(日志用) |
|
||||
| `inject` | `string[] \| { required?: string[], optional?: string[] }` | 依赖声明 |
|
||||
| `Config` | `Schema \| object` | 配置 schema 或默认值 |
|
||||
97
website/zh-CN/api/cordis/service.md
Normal file
97
website/zh-CN/api/cordis/service.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# Service
|
||||
|
||||
Service 基类,用于创建对外暴露能力的插件。
|
||||
|
||||
## 基本用法
|
||||
|
||||
```typescript
|
||||
import { Service, type Context } from 'cordis'
|
||||
|
||||
declare module 'cordis' {
|
||||
interface Context {
|
||||
myService: MyService
|
||||
}
|
||||
}
|
||||
|
||||
export default class MyService extends Service {
|
||||
constructor(ctx: Context) {
|
||||
super(ctx, 'myService')
|
||||
}
|
||||
|
||||
// 公开方法
|
||||
doSomething() {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
加载后,其他插件可通过 `ctx.myService` 访问。
|
||||
|
||||
## 构造函数
|
||||
|
||||
### new Service(ctx, name)
|
||||
|
||||
- **ctx:** `Context` 上下文
|
||||
- **name:** `string` 服务名(注册到 `ctx[name]`)
|
||||
|
||||
## 实例属性
|
||||
|
||||
### service.ctx
|
||||
|
||||
- **类型:** `Context`
|
||||
|
||||
该服务绑定的上下文。
|
||||
|
||||
### service\[Service.tracker\]
|
||||
|
||||
- **类型:** `object`
|
||||
|
||||
服务追踪信息(名称、绑定状态等)。
|
||||
|
||||
## 生命周期
|
||||
|
||||
Service 子类可以覆写以下方法:
|
||||
|
||||
### start()
|
||||
|
||||
服务激活时调用。在这里初始化资源。
|
||||
|
||||
### stop()
|
||||
|
||||
服务停用时调用。在这里释放资源。
|
||||
|
||||
## 静态属性
|
||||
|
||||
### Service.inject
|
||||
|
||||
- **类型:** `string[] | { required?: string[], optional?: string[] }`
|
||||
|
||||
声明本服务依赖的其他服务。
|
||||
|
||||
## 与 inject 的关系
|
||||
|
||||
当一个 Service 被加载:
|
||||
1. 框架为该服务名创建声明 (`ctx.provide`)
|
||||
2. 实例赋值到 `ctx[name]`
|
||||
3. 依赖该服务的所有 Fiber 从 PENDING 转为 LOADING
|
||||
|
||||
当 Service 被卸载:
|
||||
1. `ctx[name]` 被置为 `undefined`
|
||||
2. 依赖它的 Fiber 被 dispose
|
||||
3. 当新的 provider 出现时,dependant Fiber 重新加载
|
||||
|
||||
## 示例:Harness 中的 Service
|
||||
|
||||
```typescript
|
||||
// dsh-tools 的 ToolRegistry 就是一个 Service
|
||||
export class ToolRegistry extends Service {
|
||||
constructor(ctx: Context) {
|
||||
super(ctx, 'tools')
|
||||
}
|
||||
|
||||
register(tool: ToolDefinition): () => void {
|
||||
// ...注册逻辑
|
||||
return dispose
|
||||
}
|
||||
}
|
||||
```
|
||||
85
website/zh-CN/api/harness/agent.md
Normal file
85
website/zh-CN/api/harness/agent.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# Agent (dsh-agent)
|
||||
|
||||
Agent 实例管理和生命周期。
|
||||
|
||||
**包名:** `@deepseek-ai/dsh-agent`
|
||||
**服务名:** `ctx.agents`
|
||||
|
||||
## Agent Service
|
||||
|
||||
### ctx.agents.create(options)
|
||||
|
||||
- **options:** `AgentOptions`
|
||||
- **返回值:** `Agent`
|
||||
|
||||
创建一个新的 Agent 实例。
|
||||
|
||||
### ctx.agents.get(id)
|
||||
|
||||
- **id:** `AgentId`
|
||||
- **返回值:** `Agent | undefined`
|
||||
|
||||
获取指定 ID 的 Agent 实例。
|
||||
|
||||
## AgentOptions
|
||||
|
||||
```typescript
|
||||
interface AgentOptions {
|
||||
/** Agent ID(branded) */
|
||||
id?: AgentId
|
||||
/** 使用的模型名 */
|
||||
model: string
|
||||
/** 系统提示词(支持 {{model}} 变量) */
|
||||
persona?: string
|
||||
/** 关联的 session */
|
||||
session?: Session
|
||||
}
|
||||
```
|
||||
|
||||
## Agent 实例
|
||||
|
||||
### agent.id
|
||||
|
||||
- **类型:** `AgentId`
|
||||
|
||||
Agent 的唯一标识符(branded string)。
|
||||
|
||||
### agent.model
|
||||
|
||||
- **类型:** `string`
|
||||
|
||||
Agent 使用的模型名。
|
||||
|
||||
### agent.step(input)
|
||||
|
||||
- **input:** `ContentBlock[]`
|
||||
- **返回值:** `Promise<StepResult>`
|
||||
|
||||
执行一步:将输入发送给模型,获取响应,执行 tool calls。这是 agent-loop 内部使用的核心方法。
|
||||
|
||||
## Agent Loop
|
||||
|
||||
Agent 的执行循环由 `dsh-agent-loop` 管理。它:
|
||||
|
||||
1. 组装 system prompt + 历史消息 + 当前输入
|
||||
2. 调用 LLM(通过 `ctx.llm`)
|
||||
3. 解析响应中的 tool calls
|
||||
4. 执行 tools
|
||||
5. 将 tool results 追加到 session
|
||||
6. 如果 finish reason 是 `tool-calls`,回到步骤 2
|
||||
|
||||
### 扩展点
|
||||
|
||||
- `agent/pre-step` 事件 — 在每一步 LLM 调用前触发
|
||||
- `agent/post-step` 事件 — 在每一步完成后触发
|
||||
- `llm/pre-request` waterfall — 可修改发送给模型的消息
|
||||
|
||||
## AgentId
|
||||
|
||||
Opaque branded string:
|
||||
|
||||
```typescript
|
||||
import { AgentId } from '@deepseek-ai/dsh-agent'
|
||||
|
||||
const id = AgentId('main')
|
||||
```
|
||||
81
website/zh-CN/api/harness/bash.md
Normal file
81
website/zh-CN/api/harness/bash.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# Bash (dsh-bash)
|
||||
|
||||
Bash 命令执行接口。
|
||||
|
||||
**接口包:** `@deepseek-ai/dsh-bash`
|
||||
**实现:** `@deepseek-ai/dsh-bash-local`
|
||||
**消费者:** `@deepseek-ai/dsh-tool-bash`(内置于 agent-core)
|
||||
|
||||
## Bash Service
|
||||
|
||||
### ctx.bash.execute(request)
|
||||
|
||||
- **request:** `BashRequest`
|
||||
- **返回值:** `Promise<BashResult>`
|
||||
|
||||
执行一个 bash 命令。
|
||||
|
||||
## BashRequest
|
||||
|
||||
```typescript
|
||||
interface BashRequest {
|
||||
/** 要执行的命令 */
|
||||
command: string
|
||||
/** 工作目录 */
|
||||
workdir?: string
|
||||
/** 超时时间 (ms) */
|
||||
timeoutMs?: number
|
||||
}
|
||||
```
|
||||
|
||||
## BashResult
|
||||
|
||||
```typescript
|
||||
interface BashResult {
|
||||
/** 退出码 */
|
||||
exitCode: number
|
||||
/** stdout 输出 */
|
||||
stdout: string
|
||||
/** stderr 输出 */
|
||||
stderr: string
|
||||
/** 是否超时 */
|
||||
timedOut: boolean
|
||||
}
|
||||
```
|
||||
|
||||
## 配置 (dsh-bash-local)
|
||||
|
||||
```typescript
|
||||
interface Config {
|
||||
/** 命令超时时间,默认 120000 (2 分钟) */
|
||||
timeoutMs: number
|
||||
}
|
||||
```
|
||||
|
||||
在 `cordis.yml` 中:
|
||||
|
||||
```yaml
|
||||
- name: '@deepseek-ai/dsh-bash-local'
|
||||
config:
|
||||
timeoutMs: 60000
|
||||
```
|
||||
|
||||
## 模型可用的 Tools
|
||||
|
||||
`dsh-tool-bash` 向模型暴露以下 tools(由 `agent-core` 捆绑):
|
||||
|
||||
| Tool | 说明 |
|
||||
|------|------|
|
||||
| `bash` | 执行命令(同步,等待完成) |
|
||||
| `bash_output` | 获取后台命令的输出 |
|
||||
| `bash_kill` | 终止后台命令 |
|
||||
|
||||
## 设计模式
|
||||
|
||||
Bash 是 Harness 的"能力三件套"典型案例:
|
||||
|
||||
- `dsh-bash`(接口):定义 `ctx.bash` 和 `BashRequest`/`BashResult` 类型
|
||||
- `dsh-bash-local`(实现):通过 `child_process.spawn` 在本地执行
|
||||
- `dsh-tool-bash`(消费者):将能力包装为模型可调用的 tool
|
||||
|
||||
换一个沙箱执行器只需替换 `dsh-bash-local`,接口和 tool 不变。
|
||||
78
website/zh-CN/api/harness/fs.md
Normal file
78
website/zh-CN/api/harness/fs.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# Filesystem (dsh-fs)
|
||||
|
||||
文件系统操作接口。
|
||||
|
||||
**接口包:** `@deepseek-ai/dsh-fs`
|
||||
**实现:** `@deepseek-ai/dsh-fs-local` + `@deepseek-ai/dsh-fs-policy`
|
||||
**消费者:** `@deepseek-ai/dsh-tool-fs`
|
||||
|
||||
## FS Service
|
||||
|
||||
### ctx.fs.read(path, options?)
|
||||
|
||||
- **path:** `string`
|
||||
- **options:** `{ offset?: number; limit?: number }`
|
||||
- **返回值:** `Promise<string>`
|
||||
|
||||
读取文件内容。
|
||||
|
||||
### ctx.fs.write(path, content)
|
||||
|
||||
- **path:** `string`
|
||||
- **content:** `string`
|
||||
- **返回值:** `Promise<void>`
|
||||
|
||||
写入文件(覆盖)。
|
||||
|
||||
### ctx.fs.edit(path, edits)
|
||||
|
||||
- **path:** `string`
|
||||
- **edits:** `Edit[]`
|
||||
- **返回值:** `Promise<void>`
|
||||
|
||||
对文件执行精确的字符串替换编辑。
|
||||
|
||||
### ctx.fs.stat(path)
|
||||
|
||||
- **path:** `string`
|
||||
- **返回值:** `Promise<FileStat>`
|
||||
|
||||
获取文件/目录信息。
|
||||
|
||||
## 配置 (dsh-fs-local)
|
||||
|
||||
```typescript
|
||||
interface Config {
|
||||
/** 工作目录(相对路径的基准) */
|
||||
cwd: string
|
||||
}
|
||||
```
|
||||
|
||||
## 策略门 (dsh-fs-policy)
|
||||
|
||||
`dsh-fs-policy` 是一个可选的中间层插件,实现 read-before-write/edit 策略——模型必须先读取文件才能写入或编辑。这防止模型盲目覆盖文件。
|
||||
|
||||
在 `cordis.yml` 中,它位于 `fs-local` 和 `tool-fs` 之间:
|
||||
|
||||
```yaml
|
||||
- name: '@deepseek-ai/dsh-fs-local'
|
||||
config:
|
||||
cwd: !!js process.cwd()
|
||||
- name: '@deepseek-ai/dsh-fs-policy'
|
||||
- name: '@deepseek-ai/dsh-tool-fs'
|
||||
```
|
||||
|
||||
## 模型可用的 Tools
|
||||
|
||||
| Tool | 说明 |
|
||||
|------|------|
|
||||
| `read` | 读取文件内容(支持 offset/limit) |
|
||||
| `write` | 写入文件(需要先 read) |
|
||||
| `edit` | 精确字符串替换(需要先 read) |
|
||||
|
||||
## 三件套结构
|
||||
|
||||
- `dsh-fs`:接口定义
|
||||
- `dsh-fs-local`:本地文件系统实现
|
||||
- `dsh-fs-policy`:策略门(read-before-write 检查)
|
||||
- `dsh-tool-fs`:模型 tool 层
|
||||
124
website/zh-CN/api/harness/llm.md
Normal file
124
website/zh-CN/api/harness/llm.md
Normal file
@@ -0,0 +1,124 @@
|
||||
# LLM (dsh-llm)
|
||||
|
||||
LLM 服务接口和适配器注册。
|
||||
|
||||
**包名:** `@deepseek-ai/dsh-llm`
|
||||
**服务名:** `ctx.llm`
|
||||
|
||||
## LLM Service
|
||||
|
||||
### ctx.llm.registerAdapter(models, adapter)
|
||||
|
||||
- **models:** `string[]` 该适配器支持的模型名列表
|
||||
- **adapter:** `LlmAdapter` 适配器实例
|
||||
- **返回值:** `() => void` disposer
|
||||
|
||||
注册一个 LLM 适配器。当请求中指定的模型名在 `models` 列表中时,路由到该适配器。
|
||||
|
||||
```typescript
|
||||
ctx.llm.registerAdapter(['deepseek-v4-flash', 'deepseek-v4-pro'], adapter)
|
||||
```
|
||||
|
||||
## LlmAdapter
|
||||
|
||||
适配器基类。子类必须实现 `stream()` 方法。
|
||||
|
||||
### stream(options)
|
||||
|
||||
- **options:** `GenerateOptions`
|
||||
- **返回值:** `AsyncIterable<StreamChunk>`
|
||||
|
||||
将统一请求格式转换为具体 API 的流式调用。
|
||||
|
||||
## GenerateOptions
|
||||
|
||||
```typescript
|
||||
interface GenerateOptions {
|
||||
model: string
|
||||
messages: Message[]
|
||||
tools?: ToolSpec[]
|
||||
system?: string
|
||||
maxTokens?: number
|
||||
temperature?: number
|
||||
}
|
||||
```
|
||||
|
||||
| 字段 | 说明 |
|
||||
|------|------|
|
||||
| `model` | 请求的模型名 |
|
||||
| `messages` | 对话历史 |
|
||||
| `tools` | 当前可用的 tool 列表(JSON Schema 格式) |
|
||||
| `system` | 系统提示词 |
|
||||
| `maxTokens` | 最大输出 token |
|
||||
| `temperature` | 采样温度 |
|
||||
|
||||
## StreamChunk
|
||||
|
||||
流式响应的增量 chunk 类型:
|
||||
|
||||
```typescript
|
||||
type StreamChunk =
|
||||
| { type: 'block-start'; index: number; blockType: 'text' | 'tool-call' }
|
||||
| { type: 'text-delta'; index: number; text: string }
|
||||
| { type: 'tool-call-delta'; index: number; id: CallId; name: string; argumentsDelta: string }
|
||||
| { type: 'block-end'; index: number; block: ContentBlock }
|
||||
| { type: 'usage'; usage: TokenUsage }
|
||||
| { type: 'finish'; reason: FinishReason }
|
||||
```
|
||||
|
||||
### 协议规则
|
||||
|
||||
1. 每个内容块以 `block-start` 开始,以 `block-end` 结束
|
||||
2. `index` 从 0 递增
|
||||
3. `text-delta` 只在 `blockType: 'text'` 的块中
|
||||
4. `tool-call-delta` 只在 `blockType: 'tool-call'` 的块中
|
||||
5. `usage` 在 `finish` 之前
|
||||
6. `finish` 必须是最后一个 chunk
|
||||
|
||||
## CallId
|
||||
|
||||
Tool call 的 opaque branded ID:
|
||||
|
||||
```typescript
|
||||
import { CallId } from '@deepseek-ai/dsh-llm'
|
||||
|
||||
const id = CallId('call-abc123')
|
||||
```
|
||||
|
||||
## TokenUsage
|
||||
|
||||
```typescript
|
||||
interface TokenUsage {
|
||||
inputTokens: number
|
||||
outputTokens: number
|
||||
}
|
||||
```
|
||||
|
||||
## FinishReason
|
||||
|
||||
```typescript
|
||||
type FinishReason =
|
||||
| { kind: 'stop' }
|
||||
| { kind: 'tool-calls' }
|
||||
| { kind: 'max-tokens' }
|
||||
```
|
||||
|
||||
## Message
|
||||
|
||||
对话消息类型:
|
||||
|
||||
```typescript
|
||||
interface Message {
|
||||
role: 'user' | 'assistant'
|
||||
content: ContentBlock[]
|
||||
}
|
||||
```
|
||||
|
||||
## ContentBlock
|
||||
|
||||
```typescript
|
||||
type ContentBlock =
|
||||
| { type: 'text'; text: string }
|
||||
| { type: 'tool-call'; id: CallId; name: string; arguments: string }
|
||||
| { type: 'tool-result'; callId: CallId; content: ContentBlock[]; isError?: boolean }
|
||||
```
|
||||
56
website/zh-CN/api/harness/session.md
Normal file
56
website/zh-CN/api/harness/session.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# Session (dsh-session)
|
||||
|
||||
会话事件流管理。
|
||||
|
||||
**包名:** `@deepseek-ai/dsh-session`
|
||||
**服务名:** `ctx.session`
|
||||
|
||||
## 概述
|
||||
|
||||
Session 是 Agent 的对话状态容器。所有模型可见的内容都必须经过 session 事件流记录——这是"model-visible = logged"原则的实现。
|
||||
|
||||
## SessionSurface
|
||||
|
||||
会话的外部接口,用于查询当前状态。
|
||||
|
||||
### surface.messages
|
||||
|
||||
- **类型:** `Message[]`
|
||||
|
||||
当前会话的完整消息列表(经过 compaction 处理后的视图)。
|
||||
|
||||
### surface.events
|
||||
|
||||
- **类型:** `SessionEvent[]`
|
||||
|
||||
原始事件流。
|
||||
|
||||
## SessionEvent
|
||||
|
||||
会话中所有变更以事件形式记录:
|
||||
|
||||
```typescript
|
||||
type SessionEvent =
|
||||
| { type: 'user/message'; content: ContentBlock[] }
|
||||
| { type: 'assistant/message'; content: ContentBlock[] }
|
||||
| { type: 'tool/call'; name: string; args: unknown; callId: CallId }
|
||||
| { type: 'tool/result'; callId: CallId; content: ContentBlock[]; isError?: boolean }
|
||||
| { type: 'compact/start'; range: [number, number] }
|
||||
| { type: 'compact/end'; summary: string }
|
||||
| { type: 'todo/write'; items: TodoItem[] }
|
||||
// ... 更多事件类型
|
||||
```
|
||||
|
||||
## 设计原则
|
||||
|
||||
### Model-visible = Logged
|
||||
|
||||
任何到达模型请求的内容都必须能从 session log 重建。如果你要引入新的模型可见输入,必须先定义对应的 session event。
|
||||
|
||||
### 事件是 append-only
|
||||
|
||||
Session 事件流是只追加的。修改历史(如 compaction)通过新事件(compact/start + compact/end)表达,而不是修改旧事件。
|
||||
|
||||
### 持久化
|
||||
|
||||
Session 事件流可以通过 `dsh-session-persistence` 持久化到磁盘(JSONL 或 SQLite),实现跨进程恢复。
|
||||
85
website/zh-CN/api/harness/subagent.md
Normal file
85
website/zh-CN/api/harness/subagent.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# Subagent (dsh-subagent)
|
||||
|
||||
子代理委派接口。
|
||||
|
||||
**接口包:** `@deepseek-ai/dsh-subagent`
|
||||
**实现:** `@deepseek-ai/dsh-subagent-spawn` / `@deepseek-ai/dsh-subagent-fork`
|
||||
**消费者:** `@deepseek-ai/dsh-tool-subagent`
|
||||
|
||||
## Subagent Service
|
||||
|
||||
### ctx.subagent.run(request)
|
||||
|
||||
- **request:** `SubagentRequest`
|
||||
- **返回值:** `Promise<SubagentResult>`
|
||||
|
||||
委派一个任务给子代理执行。
|
||||
|
||||
## SubagentRequest
|
||||
|
||||
```typescript
|
||||
interface SubagentRequest {
|
||||
/** 使用的 provider 名称 */
|
||||
provider: string
|
||||
/** 委派给子代理的提示 */
|
||||
prompt: string
|
||||
/** 子代理使用的模型(可选,默认继承父) */
|
||||
model?: string
|
||||
}
|
||||
```
|
||||
|
||||
## SubagentResult
|
||||
|
||||
```typescript
|
||||
interface SubagentResult {
|
||||
/** 子代理的最终回复 */
|
||||
response: string
|
||||
}
|
||||
```
|
||||
|
||||
## Provider 模式
|
||||
|
||||
Subagent 支持多种"后端"(provider),通过配置选择:
|
||||
|
||||
### spawn
|
||||
|
||||
创建一个全新的子代理实例,没有父级的对话历史:
|
||||
|
||||
```yaml
|
||||
- name: '@deepseek-ai/dsh-subagent-spawn'
|
||||
config:
|
||||
providerName: spawn
|
||||
```
|
||||
|
||||
### fork
|
||||
|
||||
创建一个携带父级已完成 turn 前缀的子代理,子代理"知道"父级的对话上下文:
|
||||
|
||||
```yaml
|
||||
- name: '@deepseek-ai/dsh-subagent-fork'
|
||||
config:
|
||||
providerName: fork
|
||||
```
|
||||
|
||||
## 模型可用的 Tools
|
||||
|
||||
通过 `dsh-tool-subagent` 暴露。可以加载多次,每次绑定不同 provider:
|
||||
|
||||
```yaml
|
||||
# 暴露为 "subagent" tool,使用 spawn 后端
|
||||
- name: '@deepseek-ai/dsh-tool-subagent'
|
||||
config:
|
||||
provider: spawn
|
||||
toolName: subagent
|
||||
|
||||
# 暴露为 "subagent_fork" tool,使用 fork 后端
|
||||
- name: '@deepseek-ai/dsh-tool-subagent'
|
||||
config:
|
||||
provider: fork
|
||||
toolName: subagent_fork
|
||||
```
|
||||
|
||||
## 使用场景
|
||||
|
||||
- **spawn** — 独立子任务(如"搜索这个问题"),子代理不需要知道父级上下文
|
||||
- **fork** — 需要上下文的子任务(如"基于我们刚才讨论的,去实现这个"),子代理继承父级的对话前缀
|
||||
122
website/zh-CN/api/harness/tools.md
Normal file
122
website/zh-CN/api/harness/tools.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# Tools (dsh-tools)
|
||||
|
||||
Tool 注册表和 `defineTool` DSL。
|
||||
|
||||
**包名:** `@deepseek-ai/dsh-tools`
|
||||
**服务名:** `ctx.tools`
|
||||
|
||||
## ToolRegistry
|
||||
|
||||
### ctx.tools.register(tool)
|
||||
|
||||
- **tool:** `ToolDefinition`
|
||||
- **返回值:** `() => void` disposer
|
||||
|
||||
注册一个 tool。返回的 disposer 可手动撤销注册(通常不需要,插件卸载时自动撤销)。
|
||||
|
||||
## defineTool\<S\>(options)
|
||||
|
||||
类型安全的 tool 定义辅助函数。
|
||||
|
||||
```typescript
|
||||
import { defineTool } from '@deepseek-ai/dsh-tools'
|
||||
|
||||
const tool = defineTool({
|
||||
name: 'read_file',
|
||||
description: 'Read a file from disk.',
|
||||
parameters: {
|
||||
path: { type: 'string', required: true, description: 'Absolute file path' },
|
||||
offset: { type: 'number' },
|
||||
limit: { type: 'number', description: 'Max lines to read' },
|
||||
},
|
||||
async execute(args) {
|
||||
// args: { path: string; offset?: number; limit?: number }
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### DefineToolOptions\<S\>
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `name` | `string` | Tool 名称(全局唯一) |
|
||||
| `description` | `string` | 发送给模型的描述 |
|
||||
| `parameters` | `SchemaSpec` | 参数 schema(见下文) |
|
||||
| `execute` | `(args: InferArgs<S>, exec: ToolExecution) => Promise<ToolExecuteReturn>` | 执行函数 |
|
||||
| `presentCall?` | `(args: InferArgs<S>) => ToolCallView \| undefined` | UI 展示(纯函数) |
|
||||
| `presentResult?` | `(args: InferArgs<S>, result: ToolResult) => ToolResultView \| undefined` | 结果 UI 展示(纯函数) |
|
||||
|
||||
## SchemaSpec
|
||||
|
||||
参数 schema DSL。每个属性是一个 `SchemaProp`:
|
||||
|
||||
```typescript
|
||||
interface SchemaProp {
|
||||
type: 'string' | 'number' | 'boolean' | 'object' | 'array'
|
||||
required?: true
|
||||
description?: string
|
||||
enum?: string[]
|
||||
properties?: SchemaSpec // type: 'object' 时
|
||||
items?: SchemaProp // type: 'array' 时
|
||||
}
|
||||
```
|
||||
|
||||
### 类型推导 (InferArgs)
|
||||
|
||||
`InferArgs<S>` 自动从 `SchemaSpec` 推导 TypeScript 类型:
|
||||
|
||||
- `required: true` → 必填字段
|
||||
- 无 `required` → 可选字段(`?`)
|
||||
- `type: 'object'` + `properties` → 递归推导嵌套对象
|
||||
- `type: 'array'` + `items` → 推导为数组
|
||||
|
||||
## ToolDefinition
|
||||
|
||||
运行时 tool 定义(`defineTool` 的返回值):
|
||||
|
||||
```typescript
|
||||
interface ToolDefinition {
|
||||
name: string
|
||||
description: string
|
||||
parameters: Record<string, unknown> // JSON Schema
|
||||
execute(args: unknown, exec: ToolExecution): Promise<ToolExecuteReturn>
|
||||
presentCall?(args: unknown): ToolCallView | undefined
|
||||
presentResult?(args: unknown, result: ToolResult): ToolResultView | undefined
|
||||
}
|
||||
```
|
||||
|
||||
## ToolExecuteReturn
|
||||
|
||||
```typescript
|
||||
type ToolExecuteReturn =
|
||||
| ContentBlock[] // 仅内容
|
||||
| { content: ContentBlock[]; meta?: unknown } // 内容 + 元信息
|
||||
```
|
||||
|
||||
## ToolArgsError
|
||||
|
||||
当模型生成的参数不匹配 schema 时抛出:
|
||||
|
||||
```typescript
|
||||
class ToolArgsError extends HarnessError {
|
||||
code: 'INVALID_ARGS'
|
||||
violations: string[]
|
||||
}
|
||||
```
|
||||
|
||||
框架自动捕获并转换为 `isError` 结果返回给模型。
|
||||
|
||||
## validateArgs(spec, args)
|
||||
|
||||
- **spec:** `SchemaSpec`
|
||||
- **args:** `unknown`
|
||||
- **返回值:** `string[]` 违规信息列表(空 = 合法)
|
||||
|
||||
手动校验参数。`defineTool` 内部使用,通常不需要直接调用。
|
||||
|
||||
## schemaSpecToJsonSchema(spec)
|
||||
|
||||
- **spec:** `SchemaSpec`
|
||||
- **返回值:** `JsonSchemaObject`
|
||||
|
||||
将 SchemaSpec 转换为标准 JSON Schema。用于发送给模型的 wire format。
|
||||
25
website/zh-CN/api/index.md
Normal file
25
website/zh-CN/api/index.md
Normal file
@@ -0,0 +1,25 @@
|
||||
# API 参考
|
||||
|
||||
本节提供 DeepSeek Harness 的完整 API 参考文档,分为两部分:
|
||||
|
||||
## 框架 API
|
||||
|
||||
Cordis 微内核提供的基础能力,所有插件开发都建立在这些 API 之上:
|
||||
|
||||
- [Context](./cordis/context) — 上下文对象,所有服务和方法的入口
|
||||
- [Events](./cordis/events) — 事件系统 API(emit / on / bail / serial / waterfall)
|
||||
- [Fiber](./cordis/fiber) — 作用域生命周期(状态机、effect、dispose)
|
||||
- [Registry](./cordis/registry) — 插件注册(plugin / inject)
|
||||
- [Service](./cordis/service) — 服务基类
|
||||
|
||||
## Harness API
|
||||
|
||||
DeepSeek Harness SDK 提供的扩展 API,用于构建 Agent 能力:
|
||||
|
||||
- [Tools (dsh-tools)](./harness/tools) — Tool 注册、defineTool DSL、Schema 类型系统
|
||||
- [LLM (dsh-llm)](./harness/llm) — LLM 服务、适配器注册、StreamChunk 协议
|
||||
- [Session (dsh-session)](./harness/session) — 会话事件流、消息类型
|
||||
- [Agent (dsh-agent)](./harness/agent) — Agent 实例管理、生命周期
|
||||
- [Bash (dsh-bash)](./harness/bash) — Bash 执行接口
|
||||
- [Filesystem (dsh-fs)](./harness/fs) — 文件系统接口
|
||||
- [Subagent (dsh-subagent)](./harness/subagent) — 子代理委派接口
|
||||
Reference in New Issue
Block a user