Merge remote-tracking branch 'origin/master' into claude/unified-environment-credentials-c8841a

# Conflicts:
#	.agents/notes/implemented/feature/2026-07-20-dsh-cli-personal-config.i18n.yaml
#	.agents/notes/implemented/feature/2026-07-20-dsh-cli-personal-config.md
#	.agents/notes/implemented/feature/2026-07-20-dsh-cli-personal-config.zh.md
#	apps/cli/config/base.cordis.yml
#	apps/cli/package.json
#	apps/cli/reference/README.i18n.yaml
#	apps/cli/reference/README.md
#	apps/cli/reference/README.zh.md
#	apps/cli/src/app-cli-entry.ts
#	apps/cli/src/args.ts
#	apps/cli/src/bin.ts
#	apps/cli/src/config.ts
#	apps/cli/src/dump-config.ts
#	apps/cli/src/headless.ts
#	apps/cli/src/web.ts
#	apps/cli/tests/args.spec.ts
#	apps/cli/tests/built-bin.e2e.ts
#	apps/cli/tests/headless-shutdown.e2e.ts
#	apps/cli/tsconfig.json
#	docs/user/guide/config.i18n.yaml
#	docs/user/guide/config.md
#	docs/user/guide/config.zh.md
#	examples/mcp-memory/README.i18n.yaml
#	examples/mcp-memory/README.md
#	examples/mcp-memory/README.zh.md
#	packages/bundle/web-app/cordis.patch.yml
#	packages/cordis/repository-plugin/README.i18n.yaml
#	packages/cordis/repository-plugin/README.md
#	packages/cordis/repository-plugin/README.zh.md
#	packages/credentials/credentials-local/README.i18n.yaml
#	packages/credentials/credentials-local/README.md
#	packages/credentials/credentials-local/README.zh.md
#	packages/ui/app-boot/README.i18n.yaml
#	packages/ui/app-boot/README.md
#	packages/ui/app-boot/README.zh.md
#	packages/ui/app-boot/src/index.ts
#	packages/ui/app-boot/tests/config-reload.spec.ts
#	packages/ui/app-boot/tests/user-patches.spec.ts
#	pnpm-lock.yaml
This commit is contained in:
Yichen Jiang
2026-08-06 21:34:45 +08:00
352 changed files with 7632 additions and 3268 deletions

View File

@@ -84,13 +84,13 @@ export function apply(ctx: Context): void {
// runs, so the queued FIFO order is what the transcript records. The first
// child enqueue is the initial delegation, which also pins the real child id.
let accepted = 0
ctx.on('agent/inbox/inserted', (agent) => {
ctx.on('agent/inbox/inserted', ({ agent }) => {
if (agent.session.header.parentSession === undefined) return
if (realChildId === undefined) realChildId = agent.session.header.id
accepted += 1
if (accepted >= 3) followupsAccepted.resolve(undefined)
})
ctx.on('agent/pre-step', async (agent, _messages, _context, next) => {
ctx.on('agent/pre-step', async ({ agent }, next) => {
if (agent.session.header.parentSession !== undefined) await followupsAccepted.promise
return next()
})

View File

@@ -302,7 +302,7 @@ describe('Code Mode typed values: keyless real-worker contracts', () => {
function waitForIdle(harness: Context, agent: Agent): Promise<void> {
return new Promise((resolve) => {
const dispose = harness.on('agent/status', (subject, status) => {
const dispose = harness.on('agent/status', ({ agent: subject, status }) => {
if (subject === agent && status === 'idle') {
dispose()
resolve()

View File

@@ -59,7 +59,7 @@ export const inject = ['llm']
/** Register the keyless `cli-mock` adapter. */
export function apply(ctx: Context): void {
ctx.llm.registerAdapter(['cli-mock'], new CliMockAdapter())
ctx.on('agent/request', async (_agent, _turn, step, _signal, next) => {
ctx.on('agent/request', async ({ step }, next) => {
const config = await next()
return step === 2 ? { ...config, reasoningEffort: OFF } : config
})

View File

@@ -7,7 +7,7 @@ export const name = 'seed-goal'
export const inject = ['goals']
export function apply(ctx: Context): void {
ctx.on('agent/pre-step', (agent, _messages, _context, next) => {
ctx.on('agent/pre-step', ({ agent }, next) => {
if (ctx.goals.get(agent) === undefined) {
ctx.goals.create(agent, {
objective: 'Prove the composed goal survives in the session log',

View File

@@ -84,7 +84,7 @@ export async function codingHarness(workdir: string, options: CodingHarnessOptio
export function waitForIdle(ctx: Context, agent: Agent): Promise<void> {
return new Promise((resolve) => {
const dispose = ctx.on('agent/status', (subject, status) => {
const dispose = ctx.on('agent/status', ({ agent: subject, status }) => {
if (subject === agent && status === 'idle') {
dispose()
resolve()

View File

@@ -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: 6e4c68277a99b2ac739bdfb71e6c36dfbef44e86
README.zh.md: 29ab7d7888fd0a4aa622bf2ef9e3618bace47b17
README.md: 023e6aefce0e78cbbf52620426376e1dd0a6b8cf
README.zh.md: 44ace680cd583f41903437a69c62e30817308ba2

View File

@@ -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 across runs, merge the chosen file's single `insert` patch into your own overlay and name it on every launch (`dsh --config ~/.dsh/mcp.yml`). Do not copy over an existing overlay: it may already contain unrelated 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 across runs, merge the chosen file's single `insert` patch
```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.

View File

@@ -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 --config ~/.dsh/mcp.yml`。不要覆盖已有的覆盖文件,其中可能已经包含无关的 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` 作为环境覆盖项。

View File

@@ -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