mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
Merge branch 'codex/fix-compact-agents-reinjection' into codex/fix-resume-baseline-dedup
This commit is contained in:
40
examples/acp-agent/tests/fixtures/subagent/subagent-claude-code/cordis.yml
vendored
Normal file
40
examples/acp-agent/tests/fixtures/subagent/subagent-claude-code/cordis.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
# Test-only composition of both public opt-in providers and foreground tools.
|
||||
# The owning e2e boots this tree but never invokes a model or product process.
|
||||
- id: fixture
|
||||
name: './fixture.ts'
|
||||
|
||||
- id: subagent
|
||||
name: '@deepseek-ai/dsh-subagent'
|
||||
|
||||
- id: subprocess
|
||||
name: '@deepseek-ai/dsh-subprocess-local'
|
||||
|
||||
- id: subagent-codex
|
||||
name: '@deepseek-ai/dsh-subagent-codex'
|
||||
|
||||
- id: subagent-claude-code
|
||||
name: '@deepseek-ai/dsh-subagent-claude-code'
|
||||
|
||||
- id: tool-subagent-codex
|
||||
name: '@deepseek-ai/dsh-tool-subagent'
|
||||
config:
|
||||
provider: codex
|
||||
toolName: subagent_codex
|
||||
enableRunInBackground: false
|
||||
maxDepth: 'provider-managed'
|
||||
|
||||
- id: tool-subagent-claude-code
|
||||
name: '@deepseek-ai/dsh-tool-subagent'
|
||||
config:
|
||||
provider: claude-code
|
||||
toolName: subagent_claude_code
|
||||
enableRunInBackground: false
|
||||
maxDepth: 'provider-managed'
|
||||
|
||||
- id: cli-agent
|
||||
name: '@deepseek-ai/dsh-cli-demo'
|
||||
config:
|
||||
provider: mock
|
||||
model: mock-delegate
|
||||
persona: 'This composition test must not start a model turn.'
|
||||
workspaceContext: false
|
||||
65
examples/acp-agent/tests/fixtures/subagent/subagent-claude-code/driver.ts
vendored
Normal file
65
examples/acp-agent/tests/fixtures/subagent/subagent-claude-code/driver.ts
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env node
|
||||
/** Inspect both public product-provider compositions without invoking them. */
|
||||
|
||||
import { boot, resolveConfigPath } from '@deepseek-ai/dsh-app-boot'
|
||||
import type {} from '@deepseek-ai/dsh-subagent'
|
||||
import type {} from '@deepseek-ai/dsh-tools'
|
||||
|
||||
const configPath = process.argv[2]
|
||||
if (configPath === undefined) {
|
||||
throw new Error('product-provider Loader composition driver requires a config path')
|
||||
}
|
||||
|
||||
let starts = 0
|
||||
const ctx = await boot(
|
||||
'product-provider-loader-composition',
|
||||
resolveConfigPath(configPath, undefined),
|
||||
undefined,
|
||||
(hostCtx) => {
|
||||
hostCtx.on('subagent/start', () => {
|
||||
starts += 1
|
||||
})
|
||||
},
|
||||
)
|
||||
|
||||
try {
|
||||
const providerNames = ['codex', 'claude-code'] as const
|
||||
const toolNames = ['subagent_codex', 'subagent_claude_code'] as const
|
||||
const providers = providerNames.map((providerName) => {
|
||||
const provider = ctx.subagents.getProvider(providerName)
|
||||
if (provider === undefined) {
|
||||
throw new Error(`${providerName} provider was not registered`)
|
||||
}
|
||||
return {
|
||||
name: provider.name,
|
||||
capabilities: provider.capabilities,
|
||||
inheritsParentContext: provider.inheritsParentContext,
|
||||
}
|
||||
})
|
||||
const tools = toolNames.map((toolName) => {
|
||||
const tool = ctx.tools.schemas().find(schema => schema.name === toolName)
|
||||
if (tool === undefined) throw new Error(`${toolName} tool was not registered`)
|
||||
const properties = tool.parameters.properties
|
||||
if (
|
||||
typeof properties !== 'object'
|
||||
|| properties === null
|
||||
|| Array.isArray(properties)
|
||||
) {
|
||||
throw new Error(`${toolName} has invalid parameter properties`)
|
||||
}
|
||||
return {
|
||||
name: tool.name,
|
||||
parameterNames: Object.keys(properties).sort(),
|
||||
required: tool.parameters.required,
|
||||
}
|
||||
})
|
||||
|
||||
process.stdout.write(`${JSON.stringify({
|
||||
registeredProviders: ctx.subagents.list(),
|
||||
providers,
|
||||
tools,
|
||||
starts,
|
||||
})}\n`)
|
||||
} finally {
|
||||
await ctx.fiber.dispose()
|
||||
}
|
||||
7
examples/acp-agent/tests/fixtures/subagent/subagent-claude-code/fixture.ts
vendored
Normal file
7
examples/acp-agent/tests/fixtures/subagent/subagent-claude-code/fixture.ts
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
/** Reuse the composition-only parent adapter shared by the product providers. */
|
||||
|
||||
export {
|
||||
apply,
|
||||
inject,
|
||||
name,
|
||||
} from '../subagent-codex/fixture.ts'
|
||||
29
examples/acp-agent/tests/fixtures/subagent/subagent-codex/cordis.yml
vendored
Normal file
29
examples/acp-agent/tests/fixtures/subagent/subagent-codex/cordis.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
# Test-only composition of the public opt-in provider and foreground tool.
|
||||
# The owning e2e boots this tree but never invokes the model or Codex.
|
||||
- id: fixture
|
||||
name: './fixture.ts'
|
||||
|
||||
- id: subagent
|
||||
name: '@deepseek-ai/dsh-subagent'
|
||||
|
||||
- id: subprocess
|
||||
name: '@deepseek-ai/dsh-subprocess-local'
|
||||
|
||||
- id: subagent-codex
|
||||
name: '@deepseek-ai/dsh-subagent-codex'
|
||||
|
||||
- id: tool-subagent-codex
|
||||
name: '@deepseek-ai/dsh-tool-subagent'
|
||||
config:
|
||||
provider: codex
|
||||
toolName: subagent_codex
|
||||
enableRunInBackground: false
|
||||
maxDepth: 'provider-managed'
|
||||
|
||||
- id: cli-agent
|
||||
name: '@deepseek-ai/dsh-cli-demo'
|
||||
config:
|
||||
provider: mock
|
||||
model: mock-delegate
|
||||
persona: 'This composition test must not start a model turn.'
|
||||
workspaceContext: false
|
||||
51
examples/acp-agent/tests/fixtures/subagent/subagent-codex/driver.ts
vendored
Normal file
51
examples/acp-agent/tests/fixtures/subagent/subagent-codex/driver.ts
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env node
|
||||
/** Inspect the public Codex provider composition without invoking the product. */
|
||||
|
||||
import { boot, resolveConfigPath } from '@deepseek-ai/dsh-app-boot'
|
||||
import type {} from '@deepseek-ai/dsh-subagent'
|
||||
import type {} from '@deepseek-ai/dsh-tools'
|
||||
|
||||
const configPath = process.argv[2]
|
||||
if (configPath === undefined) {
|
||||
throw new Error('subagent-codex Loader composition driver requires a config path')
|
||||
}
|
||||
|
||||
let starts = 0
|
||||
const ctx = await boot(
|
||||
'subagent-codex-loader-composition',
|
||||
resolveConfigPath(configPath, undefined),
|
||||
undefined,
|
||||
(hostCtx) => {
|
||||
hostCtx.on('subagent/start', () => {
|
||||
starts += 1
|
||||
})
|
||||
},
|
||||
)
|
||||
|
||||
try {
|
||||
const provider = ctx.subagents.getProvider('codex')
|
||||
if (provider === undefined) throw new Error('Codex provider was not registered')
|
||||
const tool = ctx.tools.schemas().find(schema => schema.name === 'subagent_codex')
|
||||
if (tool === undefined) throw new Error('subagent_codex tool was not registered')
|
||||
const properties = tool.parameters.properties
|
||||
if (typeof properties !== 'object' || properties === null || Array.isArray(properties)) {
|
||||
throw new Error('subagent_codex tool has invalid parameter properties')
|
||||
}
|
||||
|
||||
process.stdout.write(`${JSON.stringify({
|
||||
providers: ctx.subagents.list(),
|
||||
provider: {
|
||||
name: provider.name,
|
||||
capabilities: provider.capabilities,
|
||||
inheritsParentContext: provider.inheritsParentContext,
|
||||
},
|
||||
tool: {
|
||||
name: tool.name,
|
||||
parameterNames: Object.keys(properties).sort(),
|
||||
required: tool.parameters.required,
|
||||
},
|
||||
starts,
|
||||
})}\n`)
|
||||
} finally {
|
||||
await ctx.fiber.dispose()
|
||||
}
|
||||
22
examples/acp-agent/tests/fixtures/subagent/subagent-codex/fixture.ts
vendored
Normal file
22
examples/acp-agent/tests/fixtures/subagent/subagent-codex/fixture.ts
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
/** Parent adapter that fails if the composition-only Loader test starts a turn. */
|
||||
|
||||
import type { Context } from 'cordis'
|
||||
import type { GenerateOptions, StreamChunk } from '@deepseek-ai/dsh-llm'
|
||||
import { LlmAdapter } from '@deepseek-ai/dsh-llm'
|
||||
|
||||
class CompositionOnlyAdapter extends LlmAdapter {
|
||||
async * stream(_options: GenerateOptions): AsyncIterable<StreamChunk> {
|
||||
throw new Error('subagent-codex Loader composition must not invoke a model')
|
||||
}
|
||||
}
|
||||
|
||||
export const name = 'codex-loader-composition-fixture'
|
||||
export const inject = ['llm']
|
||||
|
||||
/**
|
||||
* Register a parent adapter solely so the host composition is complete.
|
||||
* @param ctx - Loader context supplying the LLM seam.
|
||||
*/
|
||||
export function apply(ctx: Context): void {
|
||||
ctx.llm.registerAdapter(['mock'], new CompositionOnlyAdapter())
|
||||
}
|
||||
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write examples/mcp-memory/README.md
|
||||
README.md: b5dd7ffc4ad248d38e108d9aa28c7c26e0c76913
|
||||
README.zh.md: ea27dc1a5bd644de13d4ecad8afcae3a7452160e
|
||||
README.md: 023e6aefce0e78cbbf52620426376e1dd0a6b8cf
|
||||
README.zh.md: 44ace680cd583f41903437a69c62e30817308ba2
|
||||
|
||||
@@ -25,10 +25,10 @@ The stdio bridge deliberately removes ambient credential-shaped and `DSH_*` vari
|
||||
Pass one overlay to DSH:
|
||||
|
||||
```sh
|
||||
dsh --config "$PWD/examples/mcp-memory/memorix.cordis.yml"
|
||||
dsh web --patch "$PWD/examples/mcp-memory/memorix.cordis.yml"
|
||||
```
|
||||
|
||||
Replace the filename with `mcp-reference-memory.cordis.yml` or `engram.cordis.yml`. The path may point to a copied file anywhere on disk. No memory server is present in the shipped composition, so omitting `--config` keeps all three disabled.
|
||||
Replace the filename with `mcp-reference-memory.cordis.yml` or `engram.cordis.yml`. The path may point to a copied file anywhere on disk. No memory server is present in the shipped composition, so omitting `--patch` keeps all three disabled.
|
||||
|
||||
Without a repository checkout, download the selected overlay directly:
|
||||
|
||||
@@ -37,12 +37,12 @@ mkdir -p "${DSH_HOME:-$HOME/.dsh}"
|
||||
curl --fail --location \
|
||||
--output "${DSH_HOME:-$HOME/.dsh}/memory.cordis.yml" \
|
||||
https://raw.githubusercontent.com/deepseek-harness/deepseek-harness/master/examples/mcp-memory/memorix.cordis.yml
|
||||
dsh --config "${DSH_HOME:-$HOME/.dsh}/memory.cordis.yml"
|
||||
dsh web --patch "${DSH_HOME:-$HOME/.dsh}/memory.cordis.yml"
|
||||
```
|
||||
|
||||
Replace `memorix.cordis.yml` in the URL with either of the other filenames to select it. Review a downloaded overlay before running it: Cordis configuration can contain executable `!!js` expressions.
|
||||
|
||||
To keep the selection in personal configuration, merge the chosen file's single `insert` patch into `$DSH_HOME/config.yaml` (normally `~/.dsh/config.yaml`). Do not copy over an existing file: it may already contain unrelated personal patches.
|
||||
To keep the selection across runs, merge the chosen file's single `insert` patch into a user patch layer — `$DSH_HOME/profiles/<name>/cordis.patch.yml` for one profile, or `$DSH_HOME/cordis.patch.yml` for every profile on the machine. Do not copy over an existing file: it may already contain unrelated user patches.
|
||||
|
||||
## Provider setup
|
||||
|
||||
@@ -50,7 +50,7 @@ To keep the selection in personal configuration, merge the chosen file's single
|
||||
|
||||
```sh
|
||||
npm install --global memorix@1.3.0
|
||||
dsh --config "$PWD/examples/mcp-memory/memorix.cordis.yml"
|
||||
dsh web --patch "$PWD/examples/mcp-memory/memorix.cordis.yml"
|
||||
```
|
||||
|
||||
Memorix works in local heuristic mode without an LLM or embedding service. Configure optional providers in Memorix's own `~/.memorix/config.toml` or project `memorix.toml`. The example keeps Memorix's Git-project identity from the DSH working directory and uses Memorix's own `~/.memorix/data` default. Set `MEMORIX_DATA_DIR` before starting DSH to override it.
|
||||
@@ -59,7 +59,7 @@ Memorix works in local heuristic mode without an LLM or embedding service. Confi
|
||||
|
||||
```sh
|
||||
npm install --global @modelcontextprotocol/server-memory@2026.7.4
|
||||
dsh --config "$PWD/examples/mcp-memory/mcp-reference-memory.cordis.yml"
|
||||
dsh web --patch "$PWD/examples/mcp-memory/mcp-reference-memory.cordis.yml"
|
||||
```
|
||||
|
||||
This reference server stores a local knowledge graph and exposes entity, relation, observation, read, search, and open tools. It needs no model or embedding service. The example stores its JSONL at `$HOME/.dsh-mcp-reference-memory.jsonl` instead of the installed npm package directory. Set `MEMORY_FILE_PATH` before starting DSH to override it.
|
||||
@@ -70,7 +70,7 @@ Search is case-insensitive substring matching over entity names, types, and obse
|
||||
|
||||
```sh
|
||||
go install github.com/Gentleman-Programming/engram/cmd/engram@v1.20.0
|
||||
dsh --config "$PWD/examples/mcp-memory/engram.cordis.yml"
|
||||
dsh web --patch "$PWD/examples/mcp-memory/engram.cordis.yml"
|
||||
```
|
||||
|
||||
Engram owns storage and project selection: it uses `~/.engram` by default, detects the Git project from the DSH working directory, and accepts `ENGRAM_DATA_DIR` or `ENGRAM_PROJECT` as ambient overrides.
|
||||
|
||||
@@ -25,10 +25,10 @@ stdio 桥接器在启动子进程前会主动移除环境中名称类似凭据
|
||||
将一份 overlay 传给 DSH:
|
||||
|
||||
```sh
|
||||
dsh --config "$PWD/examples/mcp-memory/memorix.cordis.yml"
|
||||
dsh web --patch "$PWD/examples/mcp-memory/memorix.cordis.yml"
|
||||
```
|
||||
|
||||
请将文件名替换为 `mcp-reference-memory.cordis.yml` 或 `engram.cordis.yml`。该路径可以指向磁盘任意位置的一份复制文件。交付组合不包含任何记忆服务器,因此不传 `--config` 就会让这三项全部保持关闭。
|
||||
请将文件名替换为 `mcp-reference-memory.cordis.yml` 或 `engram.cordis.yml`。该路径可以指向磁盘任意位置的一份复制文件。交付组合不包含任何记忆服务器,因此不传 `--patch` 就会让这三项全部保持关闭。
|
||||
|
||||
如果本地没有仓库 checkout,可直接下载所选 overlay:
|
||||
|
||||
@@ -37,12 +37,12 @@ mkdir -p "${DSH_HOME:-$HOME/.dsh}"
|
||||
curl --fail --location \
|
||||
--output "${DSH_HOME:-$HOME/.dsh}/memory.cordis.yml" \
|
||||
https://raw.githubusercontent.com/deepseek-harness/deepseek-harness/master/examples/mcp-memory/memorix.cordis.yml
|
||||
dsh --config "${DSH_HOME:-$HOME/.dsh}/memory.cordis.yml"
|
||||
dsh web --patch "${DSH_HOME:-$HOME/.dsh}/memory.cordis.yml"
|
||||
```
|
||||
|
||||
若要选择另外任一配置,请将 URL 中的 `memorix.cordis.yml` 替换为对应文件名。运行下载的 overlay 前,请先审阅其内容:Cordis 配置可以包含可执行的 `!!js` 表达式。
|
||||
|
||||
如果要把所选配置保存在个人配置中,请将对应文件中的单个 `insert` patch 合并到 `$DSH_HOME/config.yaml`(通常是 `~/.dsh/config.yaml`)。不要覆盖已有文件,其中可能已经包含无关的个人 patch。
|
||||
如果要跨次运行保留所选配置,请将对应文件中的单个 `insert` patch 合并到用户 patch 层:只对一个 profile 生效则写入 `$DSH_HOME/profiles/<name>/cordis.patch.yml`,对本机所有 profile 生效则写入 `$DSH_HOME/cordis.patch.yml`。不要覆盖已有文件,其中可能已经包含无关的用户 patch。
|
||||
|
||||
## 提供方设置
|
||||
|
||||
@@ -50,7 +50,7 @@ dsh --config "${DSH_HOME:-$HOME/.dsh}/memory.cordis.yml"
|
||||
|
||||
```sh
|
||||
npm install --global memorix@1.3.0
|
||||
dsh --config "$PWD/examples/mcp-memory/memorix.cordis.yml"
|
||||
dsh web --patch "$PWD/examples/mcp-memory/memorix.cordis.yml"
|
||||
```
|
||||
|
||||
Memorix 无需 LLM(大语言模型)或 embedding 服务,即可在本地启发式模式下运行。请在 Memorix 自己的 `~/.memorix/config.toml` 或项目 `memorix.toml` 中配置可选提供方。该示例沿用 DSH 工作目录中的 Git 项目标识,并使用 Memorix 自身的默认目录 `~/.memorix/data`。若要覆盖该目录,请在启动 DSH 前设置 `MEMORIX_DATA_DIR`。
|
||||
@@ -59,7 +59,7 @@ Memorix 无需 LLM(大语言模型)或 embedding 服务,即可在本地启
|
||||
|
||||
```sh
|
||||
npm install --global @modelcontextprotocol/server-memory@2026.7.4
|
||||
dsh --config "$PWD/examples/mcp-memory/mcp-reference-memory.cordis.yml"
|
||||
dsh web --patch "$PWD/examples/mcp-memory/mcp-reference-memory.cordis.yml"
|
||||
```
|
||||
|
||||
该参考服务器存储本地知识图谱,并公开实体、关系、观察、读取、搜索和打开工具。它不需要模型或 embedding 服务。该示例将 JSONL 存储在 `$HOME/.dsh-mcp-reference-memory.jsonl`,而不是已安装的 npm 包目录中。若要覆盖该路径,请在启动 DSH 前设置 `MEMORY_FILE_PATH`。
|
||||
@@ -70,7 +70,7 @@ dsh --config "$PWD/examples/mcp-memory/mcp-reference-memory.cordis.yml"
|
||||
|
||||
```sh
|
||||
go install github.com/Gentleman-Programming/engram/cmd/engram@v1.20.0
|
||||
dsh --config "$PWD/examples/mcp-memory/engram.cordis.yml"
|
||||
dsh web --patch "$PWD/examples/mcp-memory/engram.cordis.yml"
|
||||
```
|
||||
|
||||
Engram 负责存储和项目选择:它默认使用 `~/.engram`,从 DSH 工作目录检测 Git 项目,并接受 `ENGRAM_DATA_DIR` 或 `ENGRAM_PROJECT` 作为环境覆盖项。
|
||||
|
||||
@@ -67,6 +67,8 @@
|
||||
"@deepseek-ai/dsh-spill-policy": "workspace:*",
|
||||
"@deepseek-ai/dsh-subagent": "workspace:*",
|
||||
"@deepseek-ai/dsh-subagent-acp": "workspace:*",
|
||||
"@deepseek-ai/dsh-subagent-claude-code": "workspace:*",
|
||||
"@deepseek-ai/dsh-subagent-codex": "workspace:*",
|
||||
"@deepseek-ai/dsh-subagent-dsh-sdk": "workspace:*",
|
||||
"@deepseek-ai/dsh-subagent-fork": "workspace:*",
|
||||
"@deepseek-ai/dsh-subagent-spawn": "workspace:*",
|
||||
|
||||
@@ -1,21 +1,16 @@
|
||||
# Opt-in Web composition for inspecting the self-referential Cordis tools.
|
||||
# Temporary Plugin code can reach every injected live capability; treat this
|
||||
# deployment like shell access, not as a security boundary.
|
||||
# This file is an OVERLAY over the shipped web composition (`base.cordis.yml` +
|
||||
# `web.cordis.yml`), not a tree: `dsh web --config` applies it as one more
|
||||
# sibling patch list at the same include level, so these patches reach base and
|
||||
# overlay rows alike. A patch replaces the targeted row's whole `config`.
|
||||
# This file is a PATCH OVERLAY over the web profile (dsh-base + dsh-web-app
|
||||
# bundle layers), not a tree: `dsh web --patch` applies it as one more sibling
|
||||
# patch list at the same include level, so these patches reach every bundle
|
||||
# row. A patch replaces the targeted row's whole `config`.
|
||||
|
||||
# AppCLIEntry normally injects the assembly-owned dist path before `dsh web`
|
||||
# boots; pinning the port here keeps this demo off the default 3080.
|
||||
# Pinning the port here keeps this demo off the default 3080.
|
||||
- id: webserver
|
||||
config:
|
||||
host: 127.0.0.1
|
||||
port: 3081
|
||||
# Plain concatenation, not URL.pathname: a cwd with spaces
|
||||
# percent-encodes through the URL round-trip and the encoded
|
||||
# path never resolves.
|
||||
distIndex: !!js "process.cwd() + '/apps/web/dist/index.html'"
|
||||
|
||||
- insert:
|
||||
- id: tool-cordis
|
||||
|
||||
Reference in New Issue
Block a user