Merge remote-tracking branch 'origin/master' into xtr/react-loop-simplification
# Conflicts: # .agents/notes/implemented/architecture/2026-06-21-bounded-llm-request-recovery.i18n.yaml # .agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.i18n.yaml # .agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.md # .agents/notes/implemented/feature/2026-06-18-compaction-capability-seam.zh.md # .agents/notes/implemented/feature/2026-07-06-sandbox.i18n.yaml # .agents/notes/implemented/feature/2026-07-06-sandbox.md # .agents/notes/implemented/feature/2026-07-06-sandbox.zh.md # .agents/notes/implemented/feature/2026-07-27-tmux-location-context.i18n.yaml # .agents/notes/implemented/simplification/2026-06-20-public-agent-stop-surface.i18n.yaml # .agents/notes/implemented/simplification/2026-07-28-remove-synthetic-log-only-turns.i18n.yaml # .agents/notes/implemented/simplification/2026-07-30-private-agent-send.i18n.yaml # docs/architecture.i18n.yaml # docs/architecture.md # docs/architecture.zh.md # docs/config-catalog.md # docs/cordis-catalog/events.md # docs/cordis-catalog/services.md # docs/core-data-structures/compaction.i18n.yaml # docs/core-data-structures/core.i18n.yaml # docs/core-data-structures/core.md # docs/core-data-structures/core.zh.md # docs/core-data-structures/llm-streaming.i18n.yaml # docs/core-data-structures/llm-streaming.md # docs/core-data-structures/llm-streaming.zh.md # docs/core-data-structures/session.i18n.yaml # docs/event-producer-consumer.md # docs/module-graph.md # docs/persistence-catalog.md # examples/acp-agent/tests/goal-snapshots/goal-session/session.expected.jsonl # examples/acp-agent/tests/snapshots/advanced-toolchain/session.1.jsonl # examples/acp-agent/tests/snapshots/advanced-toolchain/session.2.jsonl # examples/acp-agent/tests/snapshots/advanced-toolchain/session.jsonl # examples/acp-agent/tests/snapshots/bash-spill/session.jsonl # examples/acp-agent/tests/snapshots/bash-tool-turn/session.jsonl # examples/acp-agent/tests/snapshots/both-mode-turn/session.jsonl # examples/acp-agent/tests/snapshots/cancel-tool-calls/session.jsonl # examples/acp-agent/tests/snapshots/cancel/session.jsonl # examples/acp-agent/tests/snapshots/code-mode-turn/session.jsonl # examples/acp-agent/tests/snapshots/code-mode-workspace-context/session.jsonl # examples/acp-agent/tests/snapshots/cordis-inspect-jsdoc/session.jsonl # examples/acp-agent/tests/snapshots/empty-response-retry/session.jsonl # examples/acp-agent/tests/snapshots/error-finish/session.jsonl # examples/acp-agent/tests/snapshots/escalation-approved/session.jsonl # examples/acp-agent/tests/snapshots/escalation-rejected/session.jsonl # examples/acp-agent/tests/snapshots/fs-edit/session.jsonl # examples/acp-agent/tests/snapshots/fs-escalation-approved/session.jsonl # examples/acp-agent/tests/snapshots/fs-glob-sampling/session.jsonl # examples/acp-agent/tests/snapshots/fs-policy-reject/session.jsonl # examples/acp-agent/tests/snapshots/fs-read-window/session.jsonl # examples/acp-agent/tests/snapshots/fs-read/session.jsonl # examples/acp-agent/tests/snapshots/fs-write-overwrite/session.jsonl # examples/acp-agent/tests/snapshots/fs-write/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-invalid-matcher/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-posttool-block/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-posttool-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-pretool-ask/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-pretool-deny/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-promptsubmit-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-cc-stop-continue/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-invalid-matcher/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-posttool-block/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-posttool-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-pretool-block/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-promptsubmit-context/session.jsonl # examples/acp-agent/tests/snapshots/hook-codex-stop-continue/session.jsonl # examples/acp-agent/tests/snapshots/lsp-definition/session.jsonl # examples/acp-agent/tests/snapshots/multi-turn/session.jsonl # examples/acp-agent/tests/snapshots/packed-chunks/session.jsonl # examples/acp-agent/tests/snapshots/parallel-tool-calls/session.jsonl # examples/acp-agent/tests/snapshots/pty-tools/session.jsonl # examples/acp-agent/tests/snapshots/repeat-tool-guard/session.jsonl # examples/acp-agent/tests/snapshots/session-query-spill/session.jsonl # examples/acp-agent/tests/snapshots/session-sandbox-root/session.jsonl # examples/acp-agent/tests/snapshots/session-title-after-turn/session.jsonl # examples/acp-agent/tests/snapshots/skill-load/session.jsonl # examples/acp-agent/tests/snapshots/subagent-depth-two-rejection/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-depth-two-rejection/session.2.jsonl # examples/acp-agent/tests/snapshots/subagent-depth-two-rejection/session.jsonl # examples/acp-agent/tests/snapshots/subagent-fork/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-fork/session.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.2.jsonl # examples/acp-agent/tests/snapshots/subagent-mixed/session.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.2.jsonl # examples/acp-agent/tests/snapshots/subagent-multi/session.jsonl # examples/acp-agent/tests/snapshots/subagent-spawn/session.1.jsonl # examples/acp-agent/tests/snapshots/subagent-spawn/session.jsonl # examples/acp-agent/tests/snapshots/text-turn/session.jsonl # examples/acp-agent/tests/snapshots/todo-write/session.jsonl # examples/acp-agent/tests/snapshots/tool-call-turn/session.jsonl # examples/acp-agent/tests/snapshots/web-fetch/session.jsonl # examples/acp-agent/tests/snapshots/workflow-run/session.1.jsonl # examples/acp-agent/tests/snapshots/workflow-run/session.jsonl # examples/acp-agent/tests/snapshots/workspace-context/session.jsonl # examples/acp-agent/tests/snapshots/workspace-edit/session.jsonl # examples/headless-agent/tests/semantic-checkpoint-snapshots/tool-outcome-unknown/session.expected.jsonl # examples/headless-agent/tests/snapshots/advanced-toolchain/session.1.jsonl # examples/headless-agent/tests/snapshots/advanced-toolchain/session.2.jsonl # examples/headless-agent/tests/snapshots/advanced-toolchain/session.jsonl # examples/headless-agent/tests/snapshots/advanced-toolchain/stream-json.expected.jsonl # examples/headless-agent/tests/snapshots/goal-tools/stream-json.expected.jsonl # examples/headless-agent/tests/snapshots/missing-credential/stream-json.expected.jsonl # examples/headless-agent/tests/snapshots/provider-retry/stream-json.expected.jsonl # examples/headless-agent/tests/snapshots/pty-tools/session.jsonl # examples/headless-agent/tests/snapshots/pty-tools/stream-json.expected.jsonl # examples/headless-agent/tests/snapshots/ralph-loop/stream-json.expected.jsonl # examples/headless-agent/tests/subagent-inheritance-snapshots/parent-override/child.expected.jsonl # examples/headless-agent/tests/subagent-inheritance-snapshots/parent-override/parent.expected.jsonl # examples/jsonrpc-agent/tests/snapshots/bash-tool/notifications.expected.jsonl # examples/jsonrpc-agent/tests/snapshots/bash-tool/session.jsonl # examples/jsonrpc-agent/tests/snapshots/persistent-tools/notifications.expected.jsonl # examples/jsonrpc-agent/tests/snapshots/persistent-tools/session.jsonl # examples/jsonrpc-agent/tests/snapshots/subagent-spawn/notifications.expected.jsonl # examples/jsonrpc-agent/tests/snapshots/subagent-spawn/session.1.jsonl # examples/jsonrpc-agent/tests/snapshots/subagent-spawn/session.jsonl # examples/jsonrpc-agent/tests/snapshots/text-turn/notifications.expected.jsonl # examples/jsonrpc-agent/tests/snapshots/text-turn/session.jsonl # packages/client/runtime/README.i18n.yaml # packages/client/runtime/src/client/sessions/request-inspection.ts # packages/compact/compact-basic/README.i18n.yaml # packages/compact/compact-basic/README.md # packages/compact/compact-basic/README.zh.md # packages/compact/compact-basic/src/index.ts # packages/context/time-context/tests/time-context.spec.ts # packages/context/tmux-context/README.i18n.yaml # packages/context/tmux-context/tests/tmux-context.spec.ts # packages/context/workspace-context/tests/workspace-context.spec.ts # packages/cordis/tool-cordis/src/api-catalog.ts # packages/core/agent-loop/README.i18n.yaml # packages/core/agent-loop/README.md # packages/core/agent-loop/README.zh.md # packages/core/agent-loop/src/agent.ts # packages/core/agent/README.i18n.yaml # packages/core/agent/README.md # packages/core/agent/README.zh.md # packages/core/agent/src/types.ts # packages/core/session/README.i18n.yaml # packages/core/session/README.md # packages/core/session/README.zh.md # packages/fs/tool-str-replace-editor/tests/tools.spec.ts # packages/goal/command-goal/tests/command-goal.spec.ts # packages/goal/goal/tests/goal.spec.ts # packages/host/apiproxy/README.i18n.yaml # packages/host/apiproxy/README.md # packages/host/apiproxy/README.zh.md # packages/host/apiproxy/src/api/index.ts # packages/host/apiproxy/tests/api-proxy-workspace.spec.ts # packages/llm/llm/README.i18n.yaml # packages/llm/llm/README.md # packages/llm/llm/README.zh.md # packages/llm/llm/src/index.ts # packages/pty/pty-local/tests/index.spec.ts # packages/pty/pty-local/tests/local.spec.ts # packages/pty/pty/tests/service.spec.ts # packages/pty/tool-bash-persistent/tests/loader-composition.spec.ts # packages/pty/tool-bash-persistent/tests/tools.spec.ts # packages/pty/tool-pty/tests/loader-composition.spec.ts # packages/pty/tool-pty/tests/tools.spec.ts # packages/session-persistence/session-checkpoint-policy/tests/crash-recovery.e2e.ts # packages/skill/tool-skill/tests/tool-skill.spec.ts # packages/tasks/tasks-local/tests/tasks.spec.ts # packages/ui/tui/README.i18n.yaml # packages/ui/tui/tests/tui.spec.ts # packages/ui/user-approval/src/index.ts # packages/ui/user-approval/tests/approval.spec.ts
This commit is contained in:
@@ -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/README.md
|
||||
README.md: a502f34128da497586d593f64d0ce1c05f68a067
|
||||
README.zh.md: e3c111bb6a8f67899b6f434345baa3b47640b7ee
|
||||
README.md: 64e9804eb69367588e926791039c453b0a9aede9
|
||||
README.zh.md: dd26b9e3f35c2d3350da77ce04bd77b4660ced1b
|
||||
|
||||
@@ -4,6 +4,10 @@ English | [中文](README.zh.md)
|
||||
|
||||
Runnable demos (not workspaces) that showcase how the harness is wired. Each example is a **thin leaf**: either a `cordis.yml` tree that picks swappable backends and loads one app package, or an **overlay** — a patch list `dsh --config` applies over the shipped composition ([`apps/cli/config/base.cordis.yml`](../apps/cli/config/base.cordis.yml) plus a surface overlay). Bundled compositions live in [`@deepseek-ai/dsh-cli-demo`](../packages/examples/cli-demo), [`@deepseek-ai/dsh-acp-demo`](../packages/examples/acp-demo), and their shared [`@deepseek-ai/dsh-agent-spine-demo`](../packages/examples/agent-spine-demo) bundle; the `dsh` surfaces use flat config trees instead. There is no `start.ts`; the terminal `demo:*` scripts boot through the [`dsh`](../apps/cli/README.md) CLI, and the headless/ACP scripts invoke the `cli-demo`/`acp-demo` bins.
|
||||
|
||||
## mcp-memory
|
||||
|
||||
Three default-off reference overlays connect a memory MCP server through the generic MCP client. Pick one file and pass it to `dsh --config`; DSH does not install or configure the upstream memory system. See [mcp-memory/README.md](mcp-memory/README.md) for pinned prerequisites, identity mapping, the shared optional prompt, and the write → fresh-session recall → use verification recipe.
|
||||
|
||||
## headless-agent
|
||||
|
||||
A non-interactive agent demo that accepts one positional task, runs one complete model/tool turn on the `@deepseek-ai/dsh-cli-demo` app, persists a fresh session, prints `text`, `json`, or `stream-json`, and exits.
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
|
||||
展示 harness 如何接线的可运行演示(不是 workspace)。每个示例都是一个 **轻量叶节点**:要么是一份选择可替换后端、加载一个应用包(package)的 `cordis.yml` 配置树,要么是一个 **overlay**——由 `dsh --config` 叠加到交付组合([`apps/cli/config/base.cordis.yml`](../apps/cli/config/base.cordis.yml) 加一份 surface overlay)之上的 patch 列表。成组的组合位于 [`@deepseek-ai/dsh-cli-demo`](../packages/examples/cli-demo)、[`@deepseek-ai/dsh-acp-demo`](../packages/examples/acp-demo) 及它们共享的 [`@deepseek-ai/dsh-agent-spine-demo`](../packages/examples/agent-spine-demo) 组合包中;`dsh` 的各 surface 则改用平铺 config tree。没有 `start.ts`;终端 `demo:*` 脚本通过 [`dsh`](../apps/cli/README.md) CLI(命令行界面)启动,无头/ACP(Agent Client Protocol)脚本则调用 `cli-demo`/`acp-demo` bin。
|
||||
|
||||
## mcp-memory
|
||||
|
||||
三份默认关闭的参考 overlay 通过通用 MCP 客户端连接一个记忆 MCP 服务器。选择其中一份文件传给 `dsh --config`;DSH 不负责安装或配置上游记忆系统。版本固定的前置条件、身份映射、可选的共用提示词,以及「写入 → 新会话召回 → 使用」验证流程详见 [mcp-memory/README.md](mcp-memory/README.md)。
|
||||
|
||||
## headless-agent
|
||||
|
||||
非交互式 agent(智能体)演示:接受一个位置任务,在 `@deepseek-ai/dsh-cli-demo` 应用上运行一个完整模型/工具轮次,持久化新会话,打印 `text`、`json` 或 `stream-json`,然后退出。
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
- id: sandbox-policy
|
||||
name: '@deepseek-ai/dsh-sandbox-policy'
|
||||
config:
|
||||
mode: danger-full-access
|
||||
mode: workspace-write
|
||||
workspaceRoot: /tmp
|
||||
- insert:
|
||||
- id: llm-replay
|
||||
|
||||
@@ -113,6 +113,7 @@ const SCENARIOS: Scenario[] = [
|
||||
name: 'session-query-spill',
|
||||
hasModelTurn: true,
|
||||
recorded: false,
|
||||
overridden: true,
|
||||
pinsHeader: true,
|
||||
headerClass: 'session-query',
|
||||
configPath: SESSION_QUERY_CONFIG,
|
||||
@@ -301,6 +302,7 @@ const SCENARIOS: Scenario[] = [
|
||||
recorded: true,
|
||||
pinsHeader: true,
|
||||
headerClass: 'sandbox',
|
||||
systemPromptSource: 'text-turn',
|
||||
toolSchemasSource: 'text-turn',
|
||||
env: { DSH_PERMISSION_MODE: 'workspace-write' },
|
||||
},
|
||||
|
||||
@@ -17,9 +17,6 @@ Track every background task id you start. You are notified in-session when a tas
|
||||
|
||||
Use goal tools for one long-running completion objective in the current session. create_goal may infer goal intent from a direct human request in any language; do not create a goal for routine single-turn work. Call get_goal before update_goal and copy its exact goal_id and revision. After session resume or fork, an active goal is disarmed: when a human asks to continue or resume in any wording or language, use update_goal action resume to rearm it. Mark complete only when the objective is actually achieved. Mark blocked only after the same blocking condition persists for at least 3 consecutive goal rounds, and report that concrete condition in blocked_reason; difficulty, uncertainty, or useful remaining work is not blocked.
|
||||
|
||||
Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).
|
||||
<!-- dsh-user-approval-policy:never -->
|
||||
|
||||
Use the workflow tool ONLY when the user explicitly asks for a workflow or for large multi-agent orchestration: you write a JavaScript script (the tool description documents the exact format) that fans work out across many subagents with phases and structured results. For one or two delegations, prefer plain subagent calls.
|
||||
|
||||
Use the ralph tool ONLY when the direct human explicitly asks for a Ralph loop or fresh-agent iterative execution. Each Ralph round starts a fresh child with no conversation seed and uses the shared workspace as durable memory. Completion and blockers are worker reports, not independent evaluation. Use same-session goal tools for ordinary long-running objectives, and plain subagents or workflows for bounded delegation and fan-out.
|
||||
|
||||
@@ -17,9 +17,6 @@ Track every background task id you start. You are notified in-session when a tas
|
||||
|
||||
Use goal tools for one long-running completion objective in the current session. create_goal may infer goal intent from a direct human request in any language; do not create a goal for routine single-turn work. Call get_goal before update_goal and copy its exact goal_id and revision. After session resume or fork, an active goal is disarmed: when a human asks to continue or resume in any wording or language, use update_goal action resume to rearm it. Mark complete only when the objective is actually achieved. Mark blocked only after the same blocking condition persists for at least 3 consecutive goal rounds, and report that concrete condition in blocked_reason; difficulty, uncertainty, or useful remaining work is not blocked.
|
||||
|
||||
Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).
|
||||
<!-- dsh-user-approval-policy:never -->
|
||||
|
||||
Use the workflow tool ONLY when the user explicitly asks for a workflow or for large multi-agent orchestration: you write a JavaScript script (the tool description documents the exact format) that fans work out across many subagents with phases and structured results. For one or two delegations, prefer plain subagent calls.
|
||||
|
||||
Use the ralph tool ONLY when the direct human explicitly asks for a Ralph loop or fresh-agent iterative execution. Each Ralph round starts a fresh child with no conversation seed and uses the shared workspace as durable memory. Completion and blockers are worker reports, not independent evaluation. Use same-session goal tools for ordinary long-running objectives, and plain subagents or workflows for bounded delegation and fan-out.
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
You are an AI agent powered by the DeepSeek Harness SDK.
|
||||
|
||||
You are a coding assistant powered by the deepseek-v4-flash model. Your working directory is {{cwd}}. Your bash tool runs under a file sandbox — a `[sandbox: file access denied …]` result is policy, not a command bug.
|
||||
|
||||
Verify your work by running the code or tests. Keep answers brief and factual.
|
||||
|
||||
|
||||
Use the read tool — not shell commands like cat — to inspect text files. Results include line numbers. Use offset and limit to continue reading large files.
|
||||
|
||||
Use the write tool to create files or completely replace file contents. Existing files are overwritten, so read an existing file first (the default fs-policy requires it) and prefer edit for targeted changes.
|
||||
|
||||
Use the edit tool for targeted changes to existing UTF-8 text files. It replaces literal old_string with new_string; by default old_string must appear exactly once. If old_string appears multiple times, provide a more specific old_string or set replace_all to true. Read the file first (the default fs-policy requires it), unless you just created or edited it in this session.
|
||||
|
||||
Check the [exit code: N] marker on every bash result; investigate failures before moving on.
|
||||
|
||||
Track every background task id you start. You are notified in-session when a task finishes — do not busy-poll or sleep on one; keep working on independent steps and do not duplicate a running task's work. Before giving a final answer, collect every still-relevant task with task_output (set wait: true only when you are genuinely blocked on it), and task_kill tasks that stopped mattering.
|
||||
|
||||
Use goal tools for one long-running completion objective in the current session. create_goal may infer goal intent from a direct human request in any language; do not create a goal for routine single-turn work. Call get_goal before update_goal and copy its exact goal_id and revision. After session resume or fork, an active goal is disarmed: when a human asks to continue or resume in any wording or language, use update_goal action resume to rearm it. Mark complete only when the objective is actually achieved. Mark blocked only after the same blocking condition persists for at least 3 consecutive goal rounds, and report that concrete condition in blocked_reason; difficulty, uncertainty, or useful remaining work is not blocked.
|
||||
|
||||
<!-- dsh-user-approval-policy:ask -->
|
||||
|
||||
Use the workflow tool ONLY when the user explicitly asks for a workflow or for large multi-agent orchestration: you write a JavaScript script (the tool description documents the exact format) that fans work out across many subagents with phases and structured results. For one or two delegations, prefer plain subagent calls.
|
||||
|
||||
Use the ralph tool ONLY when the direct human explicitly asks for a Ralph loop or fresh-agent iterative execution. Each Ralph round starts a fresh child with no conversation seed and uses the shared workspace as durable memory. Completion and blockers are worker reports, not independent evaluation. Use same-session goal tools for ordinary long-running objectives, and plain subagents or workflows for bounded delegation and fan-out.
|
||||
@@ -19,9 +19,6 @@ Use search/read for ordinary navigation. Use lsp when textual matches are ambigu
|
||||
|
||||
Use goal tools for one long-running completion objective in the current session. create_goal may infer goal intent from a direct human request in any language; do not create a goal for routine single-turn work. Call get_goal before update_goal and copy its exact goal_id and revision. After session resume or fork, an active goal is disarmed: when a human asks to continue or resume in any wording or language, use update_goal action resume to rearm it. Mark complete only when the objective is actually achieved. Mark blocked only after the same blocking condition persists for at least 3 consecutive goal rounds, and report that concrete condition in blocked_reason; difficulty, uncertainty, or useful remaining work is not blocked.
|
||||
|
||||
Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).
|
||||
<!-- dsh-user-approval-policy:never -->
|
||||
|
||||
Use the workflow tool ONLY when the user explicitly asks for a workflow or for large multi-agent orchestration: you write a JavaScript script (the tool description documents the exact format) that fans work out across many subagents with phases and structured results. For one or two delegations, prefer plain subagent calls.
|
||||
|
||||
Use the ralph tool ONLY when the direct human explicitly asks for a Ralph loop or fresh-agent iterative execution. Each Ralph round starts a fresh child with no conversation seed and uses the shared workspace as durable memory. Completion and blockers are worker reports, not independent evaluation. Use same-session goal tools for ordinary long-running objectives, and plain subagents or workflows for bounded delegation and fan-out.
|
||||
|
||||
@@ -19,9 +19,6 @@ Track every background task id you start. You are notified in-session when a tas
|
||||
|
||||
Use goal tools for one long-running completion objective in the current session. create_goal may infer goal intent from a direct human request in any language; do not create a goal for routine single-turn work. Call get_goal before update_goal and copy its exact goal_id and revision. After session resume or fork, an active goal is disarmed: when a human asks to continue or resume in any wording or language, use update_goal action resume to rearm it. Mark complete only when the objective is actually achieved. Mark blocked only after the same blocking condition persists for at least 3 consecutive goal rounds, and report that concrete condition in blocked_reason; difficulty, uncertainty, or useful remaining work is not blocked.
|
||||
|
||||
Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).
|
||||
<!-- dsh-user-approval-policy:never -->
|
||||
|
||||
Use the workflow tool ONLY when the user explicitly asks for a workflow or for large multi-agent orchestration: you write a JavaScript script (the tool description documents the exact format) that fans work out across many subagents with phases and structured results. For one or two delegations, prefer plain subagent calls.
|
||||
|
||||
Use the ralph tool ONLY when the direct human explicitly asks for a Ralph loop or fresh-agent iterative execution. Each Ralph round starts a fresh child with no conversation seed and uses the shared workspace as durable memory. Completion and blockers are worker reports, not independent evaluation. Use same-session goal tools for ordinary long-running objectives, and plain subagents or workflows for bounded delegation and fan-out.
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
"steps": [
|
||||
{ "op": "initialize" },
|
||||
{ "op": "newSession" },
|
||||
{ "op": "prompt", "text": "Read request event 4 with session_event_read, verify the complete spill was retained, then reply DONE." }
|
||||
{ "op": "prompt", "text": "Read request event 5 with session_event_read, verify the complete spill was retained, then reply DONE." }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
[
|
||||
{
|
||||
"kind": "chunks",
|
||||
"chunks": [
|
||||
{ "type": "block-start", "index": 0, "blockType": "tool-call" },
|
||||
{ "type": "tool-call-delta", "index": 0, "id": "call_session_query_spill", "name": "session_event_read", "argumentsDelta": "{\"seq\":5}" },
|
||||
{ "type": "block-end", "index": 0, "block": { "type": "tool-call", "id": "call_session_query_spill", "name": "session_event_read", "arguments": "{\"seq\":5}" } },
|
||||
{ "type": "usage", "usage": { "inputTokens": 10, "outputTokens": 5 } },
|
||||
{ "type": "finish", "reason": { "kind": "tool-calls" } }
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "chunks",
|
||||
"chunks": [
|
||||
{ "type": "block-start", "index": 0, "blockType": "tool-call" },
|
||||
{ "type": "tool-call-delta", "index": 0, "id": "call_verify_session_query_spill", "name": "bash", "argumentsDelta": "{\"command\":\"file=$(find /tmp/dsh-acp-snap-035d1d054 -name '*-session_event_read.txt' -type f); grep -q request/header \\\"$file\\\" && grep -q session_event_search \\\"$file\\\" && echo SPILL_CANONICAL_OK\",\"description\":\"Verify complete session query spill\"}" },
|
||||
{ "type": "block-end", "index": 0, "block": { "type": "tool-call", "id": "call_verify_session_query_spill", "name": "bash", "arguments": "{\"command\":\"file=$(find /tmp/dsh-acp-snap-035d1d054 -name '*-session_event_read.txt' -type f); grep -q request/header \\\"$file\\\" && grep -q session_event_search \\\"$file\\\" && echo SPILL_CANONICAL_OK\",\"description\":\"Verify complete session query spill\"}" } },
|
||||
{ "type": "usage", "usage": { "inputTokens": 10, "outputTokens": 5 } },
|
||||
{ "type": "finish", "reason": { "kind": "tool-calls" } }
|
||||
]
|
||||
},
|
||||
{
|
||||
"kind": "chunks",
|
||||
"chunks": [
|
||||
{ "type": "block-start", "index": 0, "blockType": "text" },
|
||||
{ "type": "text-delta", "index": 0, "text": "DONE" },
|
||||
{ "type": "block-end", "index": 0, "block": { "type": "text", "text": "DONE" } },
|
||||
{ "type": "usage", "usage": { "inputTokens": 10, "outputTokens": 2 } },
|
||||
{ "type": "finish", "reason": { "kind": "stop" } }
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -19,9 +19,6 @@ Use session_search to find relevant work from prior sessions, or session_event_s
|
||||
|
||||
Use goal tools for one long-running completion objective in the current session. create_goal may infer goal intent from a direct human request in any language; do not create a goal for routine single-turn work. Call get_goal before update_goal and copy its exact goal_id and revision. After session resume or fork, an active goal is disarmed: when a human asks to continue or resume in any wording or language, use update_goal action resume to rearm it. Mark complete only when the objective is actually achieved. Mark blocked only after the same blocking condition persists for at least 3 consecutive goal rounds, and report that concrete condition in blocked_reason; difficulty, uncertainty, or useful remaining work is not blocked.
|
||||
|
||||
Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).
|
||||
<!-- dsh-user-approval-policy:never -->
|
||||
|
||||
Use the workflow tool ONLY when the user explicitly asks for a workflow or for large multi-agent orchestration: you write a JavaScript script (the tool description documents the exact format) that fans work out across many subagents with phases and structured results. For one or two delegations, prefer plain subagent calls.
|
||||
|
||||
Use the ralph tool ONLY when the direct human explicitly asks for a Ralph loop or fresh-agent iterative execution. Each Ralph round starts a fresh child with no conversation seed and uses the shared workspace as durable memory. Completion and blockers are worker reports, not independent evaluation. Use same-session goal tools for ordinary long-running objectives, and plain subagents or workflows for bounded delegation and fan-out.
|
||||
|
||||
@@ -17,9 +17,6 @@ Track every background task id you start. You are notified in-session when a tas
|
||||
|
||||
Use goal tools for one long-running completion objective in the current session. create_goal may infer goal intent from a direct human request in any language; do not create a goal for routine single-turn work. Call get_goal before update_goal and copy its exact goal_id and revision. After session resume or fork, an active goal is disarmed: when a human asks to continue or resume in any wording or language, use update_goal action resume to rearm it. Mark complete only when the objective is actually achieved. Mark blocked only after the same blocking condition persists for at least 3 consecutive goal rounds, and report that concrete condition in blocked_reason; difficulty, uncertainty, or useful remaining work is not blocked.
|
||||
|
||||
Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).
|
||||
<!-- dsh-user-approval-policy:never -->
|
||||
|
||||
Use the workflow tool ONLY when the user explicitly asks for a workflow or for large multi-agent orchestration: you write a JavaScript script (the tool description documents the exact format) that fans work out across many subagents with phases and structured results. For one or two delegations, prefer plain subagent calls.
|
||||
|
||||
Use the ralph tool ONLY when the direct human explicitly asks for a Ralph loop or fresh-agent iterative execution. Each Ralph round starts a fresh child with no conversation seed and uses the shared workspace as durable memory. Completion and blockers are worker reports, not independent evaluation. Use same-session goal tools for ordinary long-running objectives, and plain subagents or workflows for bounded delegation and fan-out.
|
||||
|
||||
@@ -19,9 +19,6 @@ Use the web_fetch tool to retrieve the content of a specific HTTP(S) URL (for ex
|
||||
|
||||
Use goal tools for one long-running completion objective in the current session. create_goal may infer goal intent from a direct human request in any language; do not create a goal for routine single-turn work. Call get_goal before update_goal and copy its exact goal_id and revision. After session resume or fork, an active goal is disarmed: when a human asks to continue or resume in any wording or language, use update_goal action resume to rearm it. Mark complete only when the objective is actually achieved. Mark blocked only after the same blocking condition persists for at least 3 consecutive goal rounds, and report that concrete condition in blocked_reason; difficulty, uncertainty, or useful remaining work is not blocked.
|
||||
|
||||
Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).
|
||||
<!-- dsh-user-approval-policy:never -->
|
||||
|
||||
Use the workflow tool ONLY when the user explicitly asks for a workflow or for large multi-agent orchestration: you write a JavaScript script (the tool description documents the exact format) that fans work out across many subagents with phases and structured results. For one or two delegations, prefer plain subagent calls.
|
||||
|
||||
Use the ralph tool ONLY when the direct human explicitly asks for a Ralph loop or fresh-agent iterative execution. Each Ralph round starts a fresh child with no conversation seed and uses the shared workspace as durable memory. Completion and blockers are worker reports, not independent evaluation. Use same-session goal tools for ordinary long-running objectives, and plain subagents or workflows for bounded delegation and fan-out.
|
||||
|
||||
@@ -17,9 +17,6 @@ Track every background task id you start. You are notified in-session when a tas
|
||||
|
||||
Use goal tools for one long-running completion objective in the current session. create_goal may infer goal intent from a direct human request in any language; do not create a goal for routine single-turn work. Call get_goal before update_goal and copy its exact goal_id and revision. After session resume or fork, an active goal is disarmed: when a human asks to continue or resume in any wording or language, use update_goal action resume to rearm it. Mark complete only when the objective is actually achieved. Mark blocked only after the same blocking condition persists for at least 3 consecutive goal rounds, and report that concrete condition in blocked_reason; difficulty, uncertainty, or useful remaining work is not blocked.
|
||||
|
||||
Approval prompts are disabled in this session: actions that require approval are rejected automatically — do not request sandbox escalation (do not set `sandbox_permissions`).
|
||||
<!-- dsh-user-approval-policy:never -->
|
||||
|
||||
Use the workflow tool ONLY when the user explicitly asks for a workflow or for large multi-agent orchestration: you write a JavaScript script (the tool description documents the exact format) that fans work out across many subagents with phases and structured results. For one or two delegations, prefer plain subagent calls.
|
||||
|
||||
Use the ralph tool ONLY when the direct human explicitly asks for a Ralph loop or fresh-agent iterative execution. Each Ralph round starts a fresh child with no conversation seed and uses the shared workspace as durable memory. Completion and blockers are worker reports, not independent evaluation. Use same-session goal tools for ordinary long-running objectives, and plain subagents or workflows for bounded delegation and fan-out.
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
name: '@deepseek-ai/dsh-llm-deepseek'
|
||||
disabled: true
|
||||
- insert:
|
||||
- id: sandbox-policy
|
||||
name: '@deepseek-ai/dsh-sandbox-policy'
|
||||
config:
|
||||
mode: danger-full-access
|
||||
- id: pty
|
||||
name: '@deepseek-ai/dsh-pty'
|
||||
- id: pty-snapshot-backend
|
||||
|
||||
6
examples/headless-agent/tests/fixtures/startup-activation-error/activation-error.mjs
vendored
Normal file
6
examples/headless-agent/tests/fixtures/startup-activation-error/activation-error.mjs
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
/** Fail activation with a deterministic stack so the user-visible startup diagnostic is snapshot-stable. */
|
||||
export function apply() {
|
||||
const failure = new Error('startup activation snapshot failure')
|
||||
failure.stack = 'Error: startup activation snapshot failure\n at activation-error-fixture'
|
||||
throw failure
|
||||
}
|
||||
2
examples/headless-agent/tests/fixtures/startup-activation-error/cordis.yml
vendored
Normal file
2
examples/headless-agent/tests/fixtures/startup-activation-error/cordis.yml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
- id: activation-error
|
||||
name: ./activation-error.mjs
|
||||
@@ -8,6 +8,7 @@
|
||||
- id: telemetry-redact-rule
|
||||
name: './telemetry-redact-rule.ts'
|
||||
|
||||
# Managed child-process groups required by the bash executor.
|
||||
- id: subprocess
|
||||
name: '@deepseek-ai/dsh-subprocess-local'
|
||||
|
||||
|
||||
@@ -33,6 +33,8 @@ const credentialsScenarioDir = join(snapshotsDir, 'missing-credential')
|
||||
const credentialsConfigPath = fileURLToPath(new URL('../credentials.cordis.snapshot.yml', import.meta.url))
|
||||
const ralphScenarioDir = join(snapshotsDir, 'ralph-loop')
|
||||
const ralphConfigPath = fileURLToPath(new URL('../ralph.cordis.snapshot.yml', import.meta.url))
|
||||
const startupFailureConfigPath = fileURLToPath(new URL('./fixtures/startup-activation-error/cordis.yml', import.meta.url))
|
||||
const startupFailureExpected = join(snapshotsDir, 'startup-activation-error', 'stderr.expected.txt')
|
||||
const binScript = fileURLToPath(new URL('../../../packages/examples/cli-demo/src/bin.ts', import.meta.url))
|
||||
const tsconfigPath = fileURLToPath(new URL('../../../tsconfig.json', import.meta.url))
|
||||
const reasoningConfigPath = fileURLToPath(new URL('./fixtures/cli.cordis.yml', import.meta.url))
|
||||
@@ -167,6 +169,20 @@ async function persistedLogs(cwd: string): Promise<PersistedLog[]> {
|
||||
}
|
||||
|
||||
describe('headless stream-json snapshots', () => {
|
||||
it('prints the original Loader activation error through the assembled one-shot app', async () => {
|
||||
const result = await runLoaderSmoke({
|
||||
label: 'headless startup activation error snapshot',
|
||||
tempDirPrefix: 'headless-snapshot-startup-error-',
|
||||
binScript,
|
||||
configPath: startupFailureConfigPath,
|
||||
binArgs: ['--config', startupFailureConfigPath, '--output-format', 'stream-json', 'unreachable task'],
|
||||
tsconfigPath,
|
||||
expectedExitCode: 1,
|
||||
})
|
||||
expect(result.stdout).toBe('')
|
||||
await expect(result.stderr).toMatchFileSnapshot(startupFailureExpected)
|
||||
}, LOADER_SMOKE_TEST_TIMEOUT_MS)
|
||||
|
||||
it('retries a transient provider failure through the one-shot app', async () => {
|
||||
const prompt = await scenarioPrompt(retryScenarioDir, 'provider-retry')
|
||||
const streamExpected = join(retryScenarioDir, 'stream-json.expected.jsonl')
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
dsh-cli-demo: dsh-cli-demo: 1 entry did not activate
|
||||
./activation-error.mjs: Error: startup activation snapshot failure
|
||||
at activation-error-fixture
|
||||
@@ -97,6 +97,26 @@ describe('parent-only override inheritance snapshot', () => {
|
||||
data: { mode: 'read-only', source: 'delegation' },
|
||||
})
|
||||
|
||||
const runtimeContexts = (content: string): string[] => content.trimEnd().split('\n').flatMap((line) => {
|
||||
const record = JSON.parse(line) as {
|
||||
type?: string
|
||||
data?: { source?: { kind?: string; plugin?: string }; content?: Array<{ type?: string; text?: unknown }> }
|
||||
}
|
||||
if (record.type !== 'user/message'
|
||||
|| record.data?.source?.kind !== 'plugin'
|
||||
|| record.data.source.plugin !== '@deepseek-ai/dsh-system-prompt') return []
|
||||
return record.data.content?.flatMap(block => block.type === 'text' && typeof block.text === 'string' ? [block.text] : []) ?? []
|
||||
})
|
||||
const policyContexts = [...runtimeContexts(parent), ...runtimeContexts(child)]
|
||||
expect(policyContexts).toHaveLength(2)
|
||||
for (const context of policyContexts) {
|
||||
expect(context).toContain('Any available operation enforced by the DSH file sandbox cannot modify files in the standing mode.')
|
||||
expect(context).toContain('Do not refuse a required modification from this policy alone')
|
||||
expect(context).not.toContain('write and edit tools')
|
||||
expect(context).not.toContain('one-shot bash commands')
|
||||
expect(context).not.toContain('terminal sessions')
|
||||
}
|
||||
|
||||
const context: NormalizeContext = { sessionIds: [sessionId, String(headerOf(child).id)], cwd }
|
||||
const normalizedParent = scrubRequestHeaders(normalizeSessionLog(parent, context))
|
||||
const normalizedChild = scrubRequestHeaders(normalizeSessionLog(child, context))
|
||||
|
||||
@@ -59,6 +59,8 @@ interface SdkScenario {
|
||||
expectedFiles?: Readonly<Record<string, string>>
|
||||
/** Assembled model-facing tool names and required argument keys. */
|
||||
expectedTools?: Readonly<Record<string, readonly string[]>>
|
||||
/** Stable policy-context clauses the real assembled request must include or omit. */
|
||||
policyContext?: { includes: readonly string[]; excludes: readonly string[] }
|
||||
}
|
||||
|
||||
const SCENARIOS: SdkScenario[] = [
|
||||
@@ -88,6 +90,10 @@ const SCENARIOS: SdkScenario[] = [
|
||||
configs: { live: persistentToolsLiveConfig, replay: persistentToolsReplayConfig },
|
||||
expectedFiles: { 'note.txt': 'target:\n\tnew\n' },
|
||||
expectedTools: { bash: ['command'], str_replace_editor: ['command', 'path'] },
|
||||
policyContext: {
|
||||
includes: ['Current DSH file policy: danger-full-access.', 'file modifications by available operations'],
|
||||
excludes: ['write and edit tools', 'terminal sessions', 'one-shot bash commands'],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
@@ -117,7 +123,7 @@ async function persistedLogs(sessionsRoot: string): Promise<PersistedLog[]> {
|
||||
|
||||
interface LoggedRequestHeader {
|
||||
type?: string
|
||||
data?: { header?: { tools?: Array<{ name: string; parameters: { required?: string[] } }> } }
|
||||
data?: { header?: { system?: unknown; tools?: Array<{ name: string; parameters: { required?: string[] } }> } }
|
||||
}
|
||||
|
||||
function assembledToolRequirements(log: PersistedLog): Record<string, string[]> {
|
||||
@@ -129,6 +135,30 @@ function assembledToolRequirements(log: PersistedLog): Record<string, string[]>
|
||||
return Object.fromEntries(tools.map(tool => [tool.name, tool.parameters.required ?? []]))
|
||||
}
|
||||
|
||||
function assembledSystem(log: PersistedLog): string {
|
||||
const event = log.content.trimEnd().split('\n')
|
||||
.map(line => JSON.parse(line) as LoggedRequestHeader)
|
||||
.find(candidate => candidate.type === 'request/header')
|
||||
const system = event?.data?.header?.system
|
||||
if (typeof system !== 'string') throw new Error('session log has no request/header system')
|
||||
return system
|
||||
}
|
||||
|
||||
function assembledPolicyContext(log: PersistedLog): string {
|
||||
const contexts = log.content.trimEnd().split('\n').flatMap((line) => {
|
||||
const event = JSON.parse(line) as {
|
||||
type?: string
|
||||
data?: { source?: { kind?: string; plugin?: string }; content?: Array<{ type?: string; text?: unknown }> }
|
||||
}
|
||||
if (event.type !== 'user/message'
|
||||
|| event.data?.source?.kind !== 'plugin'
|
||||
|| event.data.source.plugin !== '@deepseek-ai/dsh-system-prompt') return []
|
||||
return event.data.content?.flatMap(block => block.type === 'text' && typeof block.text === 'string' ? [block.text] : []) ?? []
|
||||
})
|
||||
if (contexts.length !== 1) throw new Error(`session log has ${String(contexts.length)} runtime-context snapshots; expected one`)
|
||||
return contexts[0] as string
|
||||
}
|
||||
|
||||
function contextOf(logs: readonly { content: string; header: Record<string, unknown> }[], cwd: string): NormalizeContext {
|
||||
return {
|
||||
sessionIds: logs.flatMap(log => typeof log.header.id === 'string' ? [log.header.id] : []),
|
||||
@@ -360,6 +390,15 @@ describe('TypeScript SDK snapshots over the jsonrpc runtime', () => {
|
||||
if (parent === undefined) throw new Error(`${scenario.name} has no parent session log`)
|
||||
expect(assembledToolRequirements(parent)).toEqual(scenario.expectedTools)
|
||||
}
|
||||
if (scenario.policyContext !== undefined) {
|
||||
const parent = ordered[0]
|
||||
if (parent === undefined) throw new Error(`${scenario.name} has no parent session log`)
|
||||
const context = assembledPolicyContext(parent)
|
||||
for (const clause of scenario.policyContext.includes) expect(context).toContain(clause)
|
||||
for (const clause of scenario.policyContext.excludes) expect(context).not.toContain(clause)
|
||||
const system = assembledSystem(parent)
|
||||
for (const clause of scenario.policyContext.includes) expect(system).not.toContain(clause)
|
||||
}
|
||||
if (scenario.children > 0) {
|
||||
expect(notifications.some(n => n.method === 'subagent.started')).toBe(true)
|
||||
expect(notifications.some(n => n.method === 'subagent.finished')).toBe(true)
|
||||
|
||||
6
examples/mcp-memory/README.i18n.yaml
Normal file
6
examples/mcp-memory/README.i18n.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
||||
# 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: 1249ae40bb344fc81836cb49d71dd5656457b1b3
|
||||
113
examples/mcp-memory/README.md
Normal file
113
examples/mcp-memory/README.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# Third-party memory MCP examples
|
||||
|
||||
English | [中文](README.zh.md)
|
||||
|
||||
These three **default-off reference configurations** connect one memory system to DSH through [`@deepseek-ai/dsh-mcp-client`](../../packages/mcp/mcp-client/README.md). Pick one, or copy the same generic MCP row for another server.
|
||||
|
||||
These third-party configurations are provided as interoperability examples only. Their inclusion does not imply endorsement, recommendation, partnership, or ongoing support by DeepSeek.
|
||||
|
||||
## What DSH does
|
||||
|
||||
DSH parses the selected Cordis overlay, starts a configured stdio command or connects to a configured Streamable HTTP URL, discovers MCP tools, and exposes them as `mcp__<serverName>__<tool>`. DSH does **not** download the server, initialize its database, choose its model or embedding provider, create a cloud account, migrate vendor data, or supervise a separate HTTP service. For stdio, the generic client launches and stops the child with the DSH plugin lifecycle; for HTTP, the upstream service must already be running.
|
||||
|
||||
The stdio bridge deliberately removes ambient credential-shaped and `DSH_*` variables before launching a child; other ambient variables remain inherited. Each example adds only the baseline override it needs. If an optional upstream feature needs another secret, add that variable to the row's `config.env` instead of putting the secret directly in YAML.
|
||||
|
||||
## Choose one
|
||||
|
||||
| System | Tested pin | Transport | Upstream prerequisite |
|
||||
|---|---:|---|---|
|
||||
| [Memorix](https://github.com/AVIDS2/memorix) | `memorix@1.3.0` (`500792cad3144142293bfbb20acb4841c9f7fcfa`) | stdio | Node 22.18+ and `npm install --global memorix@1.3.0` |
|
||||
| [MCP Reference Memory](https://github.com/modelcontextprotocol/servers/tree/main/src/memory) | `@modelcontextprotocol/server-memory@2026.7.4` (`6dd0a683e198783e30feabf7abaf42f925bd18b1`) | stdio | `npm install --global @modelcontextprotocol/server-memory@2026.7.4` |
|
||||
| [Engram](https://github.com/Gentleman-Programming/engram) | `v1.20.0` (`ba9e46ced152c37a7cb9e576153c41995873e2fc`) | stdio | Go 1.25.10+ and `go install github.com/Gentleman-Programming/engram/cmd/engram@v1.20.0`, or the matching release binary |
|
||||
|
||||
## Enable one
|
||||
|
||||
Pass one overlay to DSH:
|
||||
|
||||
```sh
|
||||
dsh --config "$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.
|
||||
|
||||
Without a repository checkout, download the selected overlay directly:
|
||||
|
||||
```sh
|
||||
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"
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
## Provider setup
|
||||
|
||||
### Memorix
|
||||
|
||||
```sh
|
||||
npm install --global memorix@1.3.0
|
||||
dsh --config "$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.
|
||||
|
||||
### MCP Reference Memory
|
||||
|
||||
```sh
|
||||
npm install --global @modelcontextprotocol/server-memory@2026.7.4
|
||||
dsh --config "$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.
|
||||
|
||||
Search is case-insensitive substring matching over entity names, types, and observations, not semantic retrieval. The server does not add embeddings, automatic summarization, conflict resolution, or a forgetting policy.
|
||||
|
||||
### Engram
|
||||
|
||||
```sh
|
||||
go install github.com/Gentleman-Programming/engram/cmd/engram@v1.20.0
|
||||
dsh --config "$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.
|
||||
|
||||
## Optional shared model instruction
|
||||
|
||||
Add this short, vendor-neutral instruction to your existing model instructions if the server's tool descriptions do not trigger memory use reliably:
|
||||
|
||||
> When the user asks you to remember something, call a memory write tool. When historical information may be relevant, search memory and use relevant results.
|
||||
|
||||
This is additive guidance only. The examples do not replace DSH's system-prompt persona.
|
||||
|
||||
## Verify write, fresh-session recall, and use
|
||||
|
||||
Use one unique value and keep the provider's storage scope unchanged throughout:
|
||||
|
||||
1. In DSH session A, ask: `Remember that my validation drink is lapsang-<unique suffix>.` Confirm the model called the provider's write tool and the tool returned success.
|
||||
2. Create DSH session B in the same running Host. Do not copy session A's conversation. Ask: `What is my validation drink? Check memory.` Confirm the model called the provider's search or recall tool and returned the value.
|
||||
3. Still in session B, ask: `Use that preference to suggest one drink for the meeting.` Confirm the answer uses the recalled value.
|
||||
|
||||
A new DSH session is required; a Host restart is not. Restart or HMR is needed only after an MCP child crashes because the current generic client does not auto-reconnect; its tool registrations remain until plugin disposal or a successful re-sync, and calls can fail against the closed transport. Initial discovery is asynchronous, so wait for the provider's `mcp__...` tools before sending the first validation prompt.
|
||||
|
||||
## Bring another MCP server
|
||||
|
||||
Copy the same generic shape and use a unique `id` and `serverName`:
|
||||
|
||||
```yaml
|
||||
- insert:
|
||||
- id: memory-my-server
|
||||
name: '@deepseek-ai/dsh-mcp-client'
|
||||
config:
|
||||
serverName: my-memory
|
||||
transport: stdio
|
||||
command: my-memory-mcp
|
||||
args: []
|
||||
env: {}
|
||||
cwd: !!js process.cwd()
|
||||
```
|
||||
|
||||
For a remote server, use `transport: streamable-http`, `url`, and `headers` instead. Provider-specific installation, identity, authentication, models, embeddings, persistence, and licensing remain the provider's responsibility.
|
||||
113
examples/mcp-memory/README.zh.md
Normal file
113
examples/mcp-memory/README.zh.md
Normal file
@@ -0,0 +1,113 @@
|
||||
# 第三方记忆 MCP 示例
|
||||
|
||||
[English](README.md) | 中文
|
||||
|
||||
这三份**默认关闭的参考配置** 通过 [`@deepseek-ai/dsh-mcp-client`](../../packages/mcp/mcp-client/README.md) 将一个记忆系统连接到 DSH。请选择其中一份,或复制相同的通用 MCP 配置项来连接其他服务器。
|
||||
|
||||
这些第三方配置仅作为互操作参考;收录不代表 DeepSeek 的认可、推荐、合作关系或持续支持承诺。
|
||||
|
||||
## DSH 负责什么
|
||||
|
||||
DSH 解析选中的 Cordis overlay,启动已配置的 stdio 命令或连接已配置的 Streamable HTTP URL,发现 MCP 工具,并以 `mcp__<serverName>__<tool>` 的形式公开这些工具。DSH **不负责** 下载服务器、初始化其数据库、选择模型或 embedding 提供方、创建云端账户、迁移提供方数据,也不监管独立的 HTTP 服务。对于 stdio,通用客户端会随 DSH 插件生命周期启动和停止子进程;对于 HTTP,上游服务必须已经运行。
|
||||
|
||||
stdio 桥接器在启动子进程前会主动移除环境中名称类似凭据的变量和 `DSH_*` 变量;其余环境变量仍会继承。每份示例仅添加其基线所需的覆盖项。如果某个可选的上游功能还需要其他密钥,请将该变量添加到配置项的 `config.env`,不要把密钥直接写进 YAML。
|
||||
|
||||
## 选择一个
|
||||
|
||||
| 系统 | 已测试版本 | 传输方式 | 上游前置条件 |
|
||||
|---|---:|---|---|
|
||||
| [Memorix](https://github.com/AVIDS2/memorix) | `memorix@1.3.0`(`500792cad3144142293bfbb20acb4841c9f7fcfa`) | stdio | Node 22.18+,并执行 `npm install --global memorix@1.3.0` |
|
||||
| [MCP Reference Memory](https://github.com/modelcontextprotocol/servers/tree/main/src/memory) | `@modelcontextprotocol/server-memory@2026.7.4`(`6dd0a683e198783e30feabf7abaf42f925bd18b1`) | stdio | `npm install --global @modelcontextprotocol/server-memory@2026.7.4` |
|
||||
| [Engram](https://github.com/Gentleman-Programming/engram) | `v1.20.0`(`ba9e46ced152c37a7cb9e576153c41995873e2fc`) | stdio | Go 1.25.10+,并执行 `go install github.com/Gentleman-Programming/engram/cmd/engram@v1.20.0`,或安装匹配的发布版二进制文件 |
|
||||
|
||||
## 启用一个
|
||||
|
||||
将一份 overlay 传给 DSH:
|
||||
|
||||
```sh
|
||||
dsh --config "$PWD/examples/mcp-memory/memorix.cordis.yml"
|
||||
```
|
||||
|
||||
请将文件名替换为 `mcp-reference-memory.cordis.yml` 或 `engram.cordis.yml`。该路径可以指向磁盘任意位置的一份复制文件。交付组合不包含任何记忆服务器,因此不传 `--config` 就会让这三项全部保持关闭。
|
||||
|
||||
如果本地没有仓库 checkout,可直接下载所选 overlay:
|
||||
|
||||
```sh
|
||||
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"
|
||||
```
|
||||
|
||||
若要选择另外任一配置,请将 URL 中的 `memorix.cordis.yml` 替换为对应文件名。运行下载的 overlay 前,请先审阅其内容:Cordis 配置可以包含可执行的 `!!js` 表达式。
|
||||
|
||||
如果要把所选配置保存在个人配置中,请将对应文件中的单个 `insert` patch 合并到 `$DSH_HOME/config.yaml`(通常是 `~/.dsh/config.yaml`)。不要覆盖已有文件,其中可能已经包含无关的个人 patch。
|
||||
|
||||
## 提供方设置
|
||||
|
||||
### Memorix
|
||||
|
||||
```sh
|
||||
npm install --global memorix@1.3.0
|
||||
dsh --config "$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`。
|
||||
|
||||
### MCP Reference Memory
|
||||
|
||||
```sh
|
||||
npm install --global @modelcontextprotocol/server-memory@2026.7.4
|
||||
dsh --config "$PWD/examples/mcp-memory/mcp-reference-memory.cordis.yml"
|
||||
```
|
||||
|
||||
该参考服务器存储本地知识图谱,并公开实体、关系、观察、读取、搜索和打开工具。它不需要模型或 embedding 服务。该示例将 JSONL 存储在 `$HOME/.dsh-mcp-reference-memory.jsonl`,而不是已安装的 npm 包(package)目录中。若要覆盖该路径,请在启动 DSH 前设置 `MEMORY_FILE_PATH`。
|
||||
|
||||
搜索只对实体名称、类型和 observation 进行不区分大小写的子字符串匹配,不是语义检索。该服务器不提供 embedding、自动摘要、冲突消解或遗忘策略。
|
||||
|
||||
### Engram
|
||||
|
||||
```sh
|
||||
go install github.com/Gentleman-Programming/engram/cmd/engram@v1.20.0
|
||||
dsh --config "$PWD/examples/mcp-memory/engram.cordis.yml"
|
||||
```
|
||||
|
||||
Engram 负责存储和项目选择:它默认使用 `~/.engram`,从 DSH 工作目录检测 Git 项目,并接受 `ENGRAM_DATA_DIR` 或 `ENGRAM_PROJECT` 作为环境覆盖项。
|
||||
|
||||
## 可选的共用模型指令
|
||||
|
||||
如果服务器的工具描述无法可靠触发记忆使用,请将以下简短、与提供方无关的指令添加到你现有的模型指令中:
|
||||
|
||||
> 用户要求记住时调用写入工具;涉及历史信息时,主动检索并使用相关记忆。
|
||||
|
||||
这只是附加指导。示例不会替换 DSH 系统提示词中的 persona。
|
||||
|
||||
## 验证写入、新会话召回和使用
|
||||
|
||||
请在整个过程中使用一个唯一值,并保持提供方的存储范围不变:
|
||||
|
||||
1. 在 DSH 会话 A 中提出:`Remember that my validation drink is lapsang-<unique suffix>.`。确认模型调用了提供方的写入工具,并且工具返回成功。
|
||||
2. 在同一个仍在运行的 Host 中创建 DSH 会话 B。不要复制会话 A 的对话。提出:`What is my validation drink? Check memory.`。确认模型调用了提供方的搜索或召回工具,并返回该值。
|
||||
3. 继续在会话 B 中提出:`Use that preference to suggest one drink for the meeting.`。确认回答使用了召回的值。
|
||||
|
||||
必须新建 DSH 会话,但不需要重启 Host。只有 MCP 子进程崩溃后才需要重启或执行 HMR(热模块替换),因为当前的通用客户端不会自动重连;其工具注册会一直保留到插件完成资源释放或成功重新同步,针对已关闭传输的调用可能失败。初始发现过程是异步的,因此发送第一条验证提示词前,请等待提供方的 `mcp__...` 工具出现。
|
||||
|
||||
## 接入其他 MCP 服务器
|
||||
|
||||
复制相同的通用结构,并使用唯一的 `id` 和 `serverName`:
|
||||
|
||||
```yaml
|
||||
- insert:
|
||||
- id: memory-my-server
|
||||
name: '@deepseek-ai/dsh-mcp-client'
|
||||
config:
|
||||
serverName: my-memory
|
||||
transport: stdio
|
||||
command: my-memory-mcp
|
||||
args: []
|
||||
env: {}
|
||||
cwd: !!js process.cwd()
|
||||
```
|
||||
|
||||
对于远程服务器,请改用 `transport: streamable-http`、`url` 和 `headers`。提供方专属的安装、身份、认证、模型、embedding、持久化和许可仍由提供方负责。
|
||||
11
examples/mcp-memory/engram.cordis.yml
Normal file
11
examples/mcp-memory/engram.cordis.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
# Opt-in reference for Engram 1.20.0. Install the pinned `engram` executable
|
||||
# first; storage and project selection remain Engram-owned.
|
||||
- insert:
|
||||
- id: memory-engram
|
||||
name: '@deepseek-ai/dsh-mcp-client'
|
||||
config:
|
||||
serverName: engram
|
||||
transport: stdio
|
||||
command: engram
|
||||
args: [mcp]
|
||||
cwd: !!js process.cwd()
|
||||
13
examples/mcp-memory/mcp-reference-memory.cordis.yml
Normal file
13
examples/mcp-memory/mcp-reference-memory.cordis.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
# Opt-in reference for @modelcontextprotocol/server-memory 2026.7.4. Install
|
||||
# the pinned executable first; DSH starts it but does not run a package manager.
|
||||
- insert:
|
||||
- id: memory-mcp-reference
|
||||
name: '@deepseek-ai/dsh-mcp-client'
|
||||
config:
|
||||
serverName: reference_memory
|
||||
transport: stdio
|
||||
command: mcp-server-memory
|
||||
cwd: !!js process.cwd()
|
||||
env:
|
||||
MEMORY_FILE_PATH: !!js >-
|
||||
process.env.MEMORY_FILE_PATH?.trim() || process.getBuiltinModule('node:path').join(process.getBuiltinModule('node:os').homedir(), '.dsh-mcp-reference-memory.jsonl')
|
||||
11
examples/mcp-memory/memorix.cordis.yml
Normal file
11
examples/mcp-memory/memorix.cordis.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
# Opt-in reference for Memorix 1.3.0. Install the pinned `memorix` executable
|
||||
# first; DSH starts it but does not run a package manager.
|
||||
- insert:
|
||||
- id: memory-memorix
|
||||
name: '@deepseek-ai/dsh-mcp-client'
|
||||
config:
|
||||
serverName: memorix
|
||||
transport: stdio
|
||||
command: memorix
|
||||
args: [serve]
|
||||
cwd: !!js process.cwd()
|
||||
@@ -12,7 +12,10 @@
|
||||
config:
|
||||
host: 127.0.0.1
|
||||
port: 3081
|
||||
distIndex: !!js "new URL('./apps/web/dist/index.html', 'file://' + process.cwd() + '/').pathname"
|
||||
# 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