dsh-agent-relay

DSH PLUGIN工具与能力

仓库 lyuwen/dsh-agent-relay

工具与能力 未标注验证等级 安全审查:未标注 可信度:未标注 可安装插件
安装这个插件

dsh-agent-relay 是 lyuwen 维护的 工具与能力 类 DSH 可安装插件, 仓库为 lyuwen/dsh-agent-relay。 下面按「装什么、怎么装、验没验过、跑起来要注意什么」逐项列出。

一句话选型结论

按资料字段整理

dsh-agent-relay 是工具与能力类的 DSH 可安装插件,未做沙盒验证,暂无安全审查结论,有可直接复制的安装命令。验证通过不等于安全:插件会读写文件、执行命令或联网,装前先到仓库确认它做了什么;涉及密钥或系统权限的,建议先在隔离环境试装。

分类工具与能力 收录类型可安装插件 验证等级未标注验证等级 安全审查未标注
验证等级 UNKNOWN 未标注验证等级
GitHub 星标 0 复刻 0 · 未关闭 issue 0
最近更新 2026-10-28 创建于 2026-10-23
README 26.7 KB 正文体量,越大说明说明书写得越细

安装

可安装插件
在 DSH 里执行,装完用 dsh plugin list 确认已挂上;标了 L4 / L5 的命令已在沙盒里真实跑通
dsh plugin --profile web add github:lyuwen/dsh-agent-relay
  1. 1
    确认版本与运行环境

    仓库没有标注兼容版本与 Node.js 要求,先确认你的 DSH 版本能装,再继续。

  2. 2
    执行安装命令

    在 DSH 里执行上面的命令;多包仓库要注意区分具体子包名,别装错包。

  3. 3
    确认已挂载

    用 dsh plugin list 查看列表里是否出现这个插件,出现即挂载成功。

  4. 4
    试跑并检查权限

    加载后跑一个最小用例,确认它能正常工作;同时看它申请了哪些文件、命令或网络权限。

兼容 DSH 版本未标注版本不匹配时安装会报错
Node.js 要求未标注来自仓库 package.json 的 engines 字段
前置依赖无需要同时安装的同级依赖
npm 包名未发布到 npm可用 npm view 查看包信息

能做什么

工具与能力
字段来自项目仓库与公开索引,中文说明由本站标注

上游标签

dsh-plugin

验证等级与安全审查

未标注验证等级
自动化流程结论,不是人工审核
验证等级未标注验证等级上游未给出验证结论,安装前请自行确认
安全审查未标注静态分析结论,未标注不代表已通过审查
仓库健康度未标注按仓库活跃度与最近更新时间给出
可信度未标注综合仓库活跃度与验证结果

选择建议

装之前先看这几条
按条目字段给出的判断,不替你决定用不用

值得选的地方

  • 有可直接复制的安装命令,不用自己翻文档找入口。

先想清楚的地方

  • 安全审查还没结论,装之前先看仓库改了什么、要什么权限。
  • 没有声明 Node.js 版本要求,版本不匹配可能装不上。
  • 验证通过不等于安全:插件会读写文件、执行命令或联网,装前先到仓库确认它做了什么。

更适合

  • 需要在工具与能力场景里给 DSH 补能力的人。
  • 能接受在本地装依赖、愿意自己确认权限的人。

不太适合

  • 只使用 DSH 官方内置能力、不接受第三方插件的人。

同类对比

6 个同类
同分类里挑最接近的几条,字段以各自详情页为准
插件验证等级安全审查星标兼容版本安装命令
dsh-agent-relay当前 未做沙盒验证 未标注 0 未标注 有
huashu-design 未做沙盒验证 未标注 3.0 万 未标注 有
loopx 未做沙盒验证 未标注 6,233 未标注 无
agy-staff 未做沙盒验证 未标注 870 未标注 有
dsh-startup-screen 未做沙盒验证 未标注 633 未标注 有
minara-skills L4 · 沙盒安装通过 中风险 360 未标注 有

仓库档案

工具与能力
字段来自项目仓库与公开索引,中文说明由本站标注
作者 / 维护方lyuwen仓库 dsh-agent-relay · 默认分支 main
分类工具与能力agent-workflow
收录类型可安装插件声明了 dsh.bundle、可用 dsh plugin add 安装的条目
开发语言未标注仓库主语言
许可证未标注商用或二次分发前请确认条款原文
星标 / 复刻 / issue0 / 0 / 0收录时的数值,非实时
创建 / 更新2026-10-23 · 2026-10-28最后推送 2026-10-23
本站收录2026-10-30首次进入本站目录的时间

README 全文

26.7 KB
作者原文,中文版优先;只做安全转义,不改内容

Agent Relay

Durable, bidirectional messaging between native agent sessions, shipped as a
DeepSeek Harness bundle (dsh-agent-relay-plugin): DSH sessions and Codex threads
exchange messages with push delivery, thread discovery, and delegated work that
returns to the conversation that asked.

A live DSH agent (a real DSH Web session) and a persistent native Codex thread
exchange durable messages. Each side reaches the relay the way that harness is
supposed to be reached: DSH through a registered relay_send tool whose sender
is taken from exec.agent, and Codex through a member-bound stdio MCP companion
whose sender is taken from its bearer credential.

Install

Agent Relay is a DSH bundle. Installing it adds a disabled Host row to a
profile; enabling that row in the profile's user layer starts the relay with every
boot of the profile.

# prebuilt tarball: no build-time scripts, no extra network
dsh plugin --profile web add ./dsh-agent-relay-plugin-0.1.0.tgz
# or from a checkout:
dsh plugin --profile web add /path/to/dsh-agent-relay
# or once published:
dsh plugin --profile web add dsh-agent-relay-plugin

Add the enable block to $DSH_HOME/profiles/web/cordis.patch.yml (a top-level
YAML array). A later layer replaces a row's whole config, so repeat every key:

- id: agent-relay
disabled: false
config:
codexProxy: ~/.codex/app-server-control/app-server-control.sock
codexExecutable: /path/to/codex
allowSessionCreation: true
externalMembers:
- id: codex-tui
tokenFile: $DSH_HOME/agent-relay/codex-tui.token

Defaults: teamId: relay, bridgePort: 33120, journal at
$DSH_HOME/agent-relay/journal.jsonl, status/log beside it, and lazy attachment
to the default Codex daemon socket when no transport is configured. Restart the
profile: the relay starts with it and attaches to Codex whenever the daemon
appears, even if that is after the host booted.

Codex side

Codex reaches the relay through the bundled MCP companion. Add to
~/.codex/config.toml, using the same token as the external member:

[mcp_servers.agent-relay]
command = "/path/to/node"
args = ["$DSH_HOME/profiles/web/node_modules/dsh-agent-relay-plugin/dist/mcp.mjs"]
default_tools_approval_mode = "approve"

[mcp_servers.agent-relay.env]
AGENT_RELAY_URL = "http://127.0.0.1:33120/relay"
AGENT_RELAY_TOKEN = ""

Create the member token file and install the skill into both harnesses:

mkdir -p "$DSH_HOME/agent-relay" && chmod 700 "$DSH_HOME/agent-relay"
printf '%s\n' "$TOKEN" > "$DSH_HOME/agent-relay/codex-tui.token"
chmod 600 "$DSH_HOME/agent-relay/codex-tui.token"
node "$DSH_HOME/profiles/web/node_modules/dsh-agent-relay-plugin/tools/install-skill.mjs" \
--dsh-home "$DSH_HOME" --codex-home "$HOME/.codex" --agents-home "$HOME/.agents"

Check that the layer composed without booting, then restart the profile:

dsh --profile web --dump-config | grep -A4 'id: agent-relay'

Uninstall: dsh plugin --profile web remove dsh-agent-relay-plugin.

Compatibility and verification

Component Verified against
DeepSeek Harness 0.2.0-rc.2; engines.dsh is >=0.2.0-rc.2 <0.3.0
Codex CLI 0.163.0 — stdio app-server, WebSocket app-server, and the shared daemon's unix WebSocket endpoint; the protocol was first probed on 0.162.1
Node >=22

Verified end to end inside a real web profile: push delivery in both
directions, relay_threads discovery, lazy attach when the Codex daemon starts
after the host, delegated work returning to the originating Codex conversation,
and the relay's own ephemeral thread staying out of the user's history. See
Evidence.

How it is wired (and what stays untouched)

The development profile relay-dev is created from the shipped web template
inside a separate DSH home ($PWD/.relay-home/dsh), and the plugin is added
as an extra patch overlay for that boot only:

# once: create the isolated development home and profile
mkdir -p .relay-home/dsh
ln -s ~/.dsh/.credentials.yaml .relay-home/dsh/.credentials.yaml   # read-only reuse
DSH_HOME=$PWD/.relay-home/dsh dsh --profile relay-dev --from-default-profile web --help

# every boot
DSH_HOME=$PWD/.relay-home/dsh dsh --profile relay-dev \
--patch "$PWD/dev/relay-dev.patch.yml" --no-open --port 3099

The user's real ~/.dsh profile, sessions and credentials are never modified:
the isolated home borrows the credentials file by symlink and the overlay lives
in this workspace. cordis.patch.yml is the same plugin as a proper bundle
layer, with its row disabled by default so installing the bundle alone
changes nothing until an operator enables it with a config.

Using it with the real environment (web-relay)

A second instance runs inside the user's own ~/.dsh, so it uses their real
credentials, models and session history. It is a new profile created from the
shipped web template plus a copy of their own patch layer; their web profile
is untouched.

# once: create the profile and mirror their bundle list + patch layer
DSH_HOME=~/.dsh dsh --profile web-relay --from-default-profile web --help
cp ~/.dsh/profiles/web/cordis.patch.yml ~/.dsh/profiles/web-relay/cordis.patch.yml
#   (package.json: copy theirs, rename "name" to the new profile)

# every boot
DSH_HOME=~/.dsh dsh --profile web-relay \
--patch "$PWD/dev/web-relay.patch.yml" --no-open --port 3100

Notes for that instance:

  • It keeps its own journal and Codex home (relay-personal, codex-personal),
    so it never contends with the isolated relay-dev instance.
  • It shares ~/.dsh/storages and ~/.dsh/sessions with any other running host
    on the same home. Two hosts are fine for reading history; keep heavy
    workspace/registry edits in one host at a time.
  • dev/web-relay.patch.yml pins agent-default-model to a reachable model
    because the profile's own selection (pai, 127.0.0.1:30808) was not
    reachable when it was booted. Remove that block or switch model in the GUI
    once that endpoint is up.
  • Only sessions live in that host can be borrowed as members; sessions from
    the other host appear in its history and can be resumed there.

Connecting a Codex you run yourself (pull path)

The relay drives its own managed Codex. A Codex you run — your TUI, your IDE
session, your daemon — is reached the other way round: it pulls.

# dev/web-relay.patch.yml
bridgePort: 33120                     # pin it: the member config must survive restarts
externalMembers:
- id: codex-tui                     # stable member identity
token: <64 hex random string>     # operator-supplied; same value in that Codex's env

Then give that Codex the relay MCP server (its own ~/.codex/config.toml):

[mcp_servers.agent-relay]
command = "/usr/bin/node"
args = ["/path/to/dsh-agent-relay/dist/mcp.mjs"]
default_tools_approval_mode = "approve"

[mcp_servers.agent-relay.env]
AGENT_RELAY_URL = "http://127.0.0.1:33120/relay"
AGENT_RELAY_TOKEN = ""

Restart that Codex (or reload its config) and it gains relay_send,
relay_inbox, relay_members, relay_status. Semantics:

  • Messages addressed to the external member stay queued — nothing is
    injected into a process the relay does not own — and they survive relay
    restarts.
  • relay_inbox hands them over exactly once; the relay then records
    accepted with receipt.deliveredBy: "pull".
  • Recipients are resolved, not required verbatim: relay_members lists every
    member with an alias, its title and cwd (for DSH sessions), and to accepts an
    alias, any unique id prefix, or the full member id. Ambiguity and unknown names
    fail with the candidate list instead of guessing.
  • Members can create new sessions when the operator enables it
    (allowSessionCreation, capped by maxSpawnedMembers): relay_create_session
    opens a fresh root DSH session in a chosen directory, or an additional
    persistent Codex thread, and can hand it its first task through the ordinary
    relay path. DSH sessions are created through the host's session controller, so
    preset and model resolve before the first turn; dshAgentPreset overrides the
    preset.
  • The external Codex can relay_send to any member; the DSH side is woken
    normally.
  • Push into a thread another Codex process is currently holding is not
    supported; that needs the still-unimplemented daemon/control-socket attachment.

Verified end to end: evidence/unmanaged-codex-pull.txt, reproducible with
node tools/unmanaged-codex-pull.mjs --url --token.
Copy-paste prompts for the Codex side (TUI and codex exec) are in
examples/from-codex.md.

Skill: teach the agents the protocol

skills/agent-relay/ is one skill bundle both harnesses understand — a
SKILL.md with name/description frontmatter plus a references/operations.md
that is loaded only when needed. It tells an agent to find members with
relay_members instead of inventing ids, how to address by alias/title/prefix,
when to drain with relay_inbox, how requestIds make retries safe, and what each
delivery state means.

node tools/install-skill.mjs --dry-run                  # preview
node tools/install-skill.mjs \
--codex-home ~/.codex --dsh-home ~/.dsh --agents-home ~/.agents

It symlinks the repository bundle into each root, so edits here are live:

harness root discovery
Codex $CODEX_HOME/skills/agent-relay/ on start
DSH /skills/agent-relay/ (rank 400) watched; appears without restart
other agents ~/.agents/skills/agent-relay/ (DSH rank 500) watched

Verified on this machine: the skill is listed in a live DSH session's catalog and
in Codex's rendered prompt input (codex debug prompt-input).

Run

Requires Node >= 22.

npm install
node tools/link-host-packages.mjs    # point @deepseek-ai/* at the installed DSH packages
npm run build                        # tsc -> dist/index.js, plus the runtime .mjs modules
npm test                             # 7 core/bridge/MCP tests
npm run check                        # typecheck + syntax check, no emit required

# two-round acceptance run against a booted dev host (see above)
node tools/round-trip.mjs

tools/link-host-packages.mjs exists because the bundle's own module lives in
this workspace: linking the @deepseek-ai/* dependencies to the installation
guarantees the plugin is compiled and executed against exactly the host modules
that are running, instead of a second copy from the registry.

Attaching your own Codex (true push)

The relay can own the Codex App Server over WebSocket instead of a private stdio
pipe. A Codex TUI then attaches to the same conversation, so turns the relay
pushes from DSH appear live in the session you are looking at, and turns you type
are visible to the relay.

# dev/web-relay.patch.yml / operator config
codexListen: ws://127.0.0.1:18799

The plugin spawns codex app-server --listen --ws-auth capability-token --ws-token-file .codex-ws-token (0600, loopback only), connects itself,
and publishes the attach command in its log and status file:

export AGENT_RELAY_CODEX_TOKEN=$(cat .relay-home/relay-personal/journal.jsonl.codex-ws-token)
codex --remote ws://127.0.0.1:18799 --remote-auth-token-env AGENT_RELAY_CODEX_TOKEN

Verified with a recording client in place of the TUI: a DSH message to codex
appeared as turn/started → userMessage → mcpToolCall → turn/completed in
the attached session, and Codex's reply woke the DSH session — no polling on
either side (evidence/codex-attach-demo.txt, evidence/codex-ws-multiclient-probe.txt).

Threads you open in that attached TUI get the relay's MCP tools too: in
WebSocket mode the plugin gives the whole app-server the MCP server at process
level, and adopts whichever thread you are in as the push member
codex-attached (resumed conversations included — adoption triggers on any
notification, not just thread/started). So relay_members from a DSH session
shows codex-attached, and messages to it run as turns in the session you are
looking at; its replies come back addressed to the sender. One attached
conversation is represented by that member at a time; opening another rebinds it.
Evidence: evidence/codex-attached-thread-fix.txt.
A second client can also resume the thread and submit turns; a turn submitted
while another is active merges into it, so the relay still drains only at idle
boundaries.

Attaching the relay to a server you own (codexAttach)

The opposite split is also supported: you start the app-server (your CODEX_HOME,
your config, your skills) and the relay attaches as a client instead of spawning
one.

codexAttach: ws://127.0.0.1:18899
codexAttachTokenFile: /path/to/that-servers-capability-token
# you run this, in your terminal / supervisor:
CODEX_HOME=~/.codex codex app-server --listen ws://127.0.0.1:18899 \
--ws-auth capability-token --ws-token-file ~/.codex/relay-ws-token

# your TUI joins the same server (both clients see the same threads):
codex --remote ws://127.0.0.1:18899 --remote-auth-token-env AGENT_RELAY_CODEX_TOKEN

The relay creates its own thread on that server and supplies the relay MCP server
through per-thread config (verified end to end: two-round run passed, and
stopping the relay left the external server healthy — evidence/codex-attach-external-server.txt).
The relay's own Codex thread on that server is ephemeral: it runs turns and
carries the relay MCP server, but it is not written into the user's history and
leaves no rollout (a non-ephemeral thread there would show up as an unattachable
"task" in their TUI). It is replaced on every relay start.

The relay never stops a server it does not own. Two consequences:

  • Threads that other clients create on that server get the relay tools only if
    the server itself was launched with process-level
    -c mcp_servers.agent-relay.… (relay-owned mode adds that automatically).
  • Restarting the external server drops the relay's connection; it does not
    reconnect automatically, and deliveries around that moment are uncertain.

Attaching to the daemon your TUI already uses (codexProxy)

A plain codex TUI joins a shared background app-server when one is running
(codex --no-daemon opts out), and its control socket is
/app-server-control/app-server-control.sock. The relay can join that
same daemon instead of creating its own server:

codexProxy: ~/.codex/app-server-control/app-server-control.sock

The plugin runs codex app-server proxy --sock and speaks stdio JSON-RPC
through it. Consequences: the relay's thread lives in your real ~/.codex history,
the conversation your TUI has open is discovered (via thread/list polling plus
notifications) and adopted as the push member — by default the first configured
external member, i.e. the identity your Codex config authenticates as — and the
daemon is never stopped on unload. Startup command (run from the terminal that
shares the daemon's /tmp):

cd /path/to/dsh-agent-relay
DSH_HOME=~/.dsh dsh --profile web-relay \
--patch "$PWD/dev/web-relay-daemon.patch.yml" --no-open --port 3102

Status: working. The control socket is a WebSocket server at path /, and the
plugin talks to it directly (UnixWebSocket in src/codex.mjs) — the ws
library's socketPath option is ignored and codex app-server proxy did not
answer, which is what blocked earlier attempts. Verified end to end against a real
unix app-server: attach, thread/start, a completed turn, 23 notifications, and
the server outliving the client (evidence/codex-shared-daemon-attach.txt).
Start the host from the same session as the daemon:

cd /path/to/dsh-agent-relay
DSH_HOME=~/.dsh dsh --profile web-relay \
--patch "$PWD/dev/web-relay-daemon.patch.yml" --no-open --port 3102

Caveats: the proxy host must run in the same session as the daemon (its socket
lives in that session's /tmp); a daemon started before the current
binary/config was installed keeps that older state until restarted; and the relay
does not auto-reconnect if the daemon restarts.

Development install (linked checkout)

For iterating on the plugin itself, install the checkout as a link so rebuilt
dist/ files are picked up on the next host start:

npm install && npm run build
dsh plugin --profile web add /path/to/dsh-agent-relay

The enable block and Codex-side setup are the same as in Install.
Rebuild and restart the profile to pick up changes; npm test runs the full
suite and dsh --profile web --dump-config shows the composed layers.

Thread discovery and addressing specific conversations

relay_threads (DSH tool and MCP tool) lists both sides: open Codex conversations
with thread ids and the member that addresses each (codex-<8hex>), the attached
conversation (codex-tui), the relay-owned thread (codex), and DSH sessions with
session id, title, cwd and live. Every persisted thread the app-server reports as
loaded becomes a push member, so a message can be written into a specific existing
Codex conversation instead of only the attached one. Ephemeral threads and threads
without a rollout are never exposed. See evidence/thread-discovery.txt.

Inspecting the relay

Three surfaces, all usable without a Codex or DSH session:

# read-only journal (no credentials): members, messages, state counts
node tools/relay-cli.mjs states
node tools/relay-cli.mjs members --journal .relay-home/relay-personal/journal.jsonl
node tools/relay-cli.mjs messages --state queued --limit 20

# the bridge is loopback HTTP: every method is POST /relay with a member token
curl -s -X POST http://127.0.0.1:33120/relay -H "Authorization: Bearer $TOKEN" \
-H 'content-type: application/json' -d '{"method":"members","params":{}}'
#   methods: members | status | send | inbox | drain | discard | create
#   (no token -> 401; GET -> 404)

# settle mail that nobody will drain (scoped: a member can only discard its own)
node tools/relay-cli.mjs discard --all --reason "stale" --token "$TOKEN"
node tools/relay-cli.mjs discard  --token "$TOKEN"

# the MCP companion is stdio JSON-RPC, not HTTP: pipe frames into it
node tools/relay-cli.mjs mcp --token "$TOKEN" --call relay_members
printf '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}\n' | \
AGENT_RELAY_URL=http://127.0.0.1:33120/relay AGENT_RELAY_TOKEN="$TOKEN" node dist/mcp.mjs

node tools/relay-cli.mjs curl prints all of the above with the current paths
filled in. From the Codex side, codex mcp get agent-relay shows how that Codex
sees the server.

Contents

Path Purpose
src/index.ts Host plugin: borrows live DSH agents, owns the Codex thread, registers tools, compiles to dist/index.js
src/core.mjs Exclusive journal owner: durable messages, request dedup, generation pinning, serialized delivery
src/bridge.mjs Loopback HTTP API; each bearer credential binds one member generation
src/codex.mjs Codex App Server client verified against codex-cli 0.162.1
src/mcp.mjs Member-bound stdio MCP companion (relay_send, relay_members, relay_status)
dev/relay-dev.patch.yml Development overlay that wires the compiled plugin into relay-dev
cordis.patch.yml Bundle patch layer (row disabled until configured)
tools/round-trip.mjs Two-round acceptance harness (creates its own DSH Web session)
tools/dsh-web-client.mjs Token exchange + /api RPC client used to drive a real Web session
tools/codex-mcp-approval-probe.mjs Probe that established which MCP approval configuration Codex accepts
skills/agent-relay/ One SKILL.md bundle both harnesses read: addressing, sending, draining, states
tools/install-skill.mjs Installs that skill into Codex, DSH and ~/.agents skill roots
tools/relay-cli.mjs Inspect members/messages from the journal, the HTTP bridge, or the stdio MCP server
tools/unmanaged-codex-pull.mjs Drives an unmanaged Codex through the pull path (relay_inbox -> relay_send)
tools/codex-account-check.mjs Isolates home/auth/network from app-server daemon state when a Codex TUI bootstrap fails
dev/web-relay.patch.yml Real-home overlay for the web-relay profile (own journal + Codex home)
research/dsh-plugin-api.md Every DSH seam used, quoted from the installed .d.ts / lib
research/codex-api.md, research/codex-probe-output.txt Codex App Server protocol reference and raw probe transcript

Verified host behavior the design depends on

DeepSeek Harness 0.2.0-rc.2 (details and quotes in research/dsh-plugin-api.md):

  • A plugin is an ES module with name, inject = ['tools', 'agents'],
    Config (Schemastery) and apply(ctx, config); no export default.
  • ctx.tools.register(defineTool({...})) accepts the definition; exec.agent
    is the calling Agent, and agent.session.id is the live session id.
  • agent.followup(message) queues an ordinary next turn and wakes the driver;
    it never steers a running step. agent.status (idle/running) plus the
    agent/status event are the idle-boundary signal.
  • ctx.agents.roots() is how an already-open Web session is borrowed rather
    than recreated.
  • A user-role message requires an explicit source.kind. The relay declares its
    own agent-relay kind instead of user, because kind: 'user' is the
    host-attested human marker that grants goal-completion authority.

Codex CLI 0.162.1 (details in research/codex-api.md):

  • thread/start / thread/resume accept an unconstrained config object that
    carries per-thread MCP servers: config.mcp_servers..{command,args,env}.
  • Threads persist across app-server restarts; thread/resume restores the same
    conversation (verified with a fresh process answering about an earlier turn).
  • turn/start is not a mutual-exclusion primitive. A second turn/start
    on an active thread is accepted and its input is merged into the active turn
    instead of returning an error. The relay therefore treats accepted as
    "the harness admitted this input", drains only at idle boundaries, and never
    claims turn exclusivity.
  • MCP tool calls need an explicit approval mode. With
    approvalPolicy: 'never', an unconfigured MCP server fails the model's tool
    call with MCP tool call requires approval, but approval policy is never.
    default_tools_approval_mode accepts auto | prompt | writes | approve; only
    approve makes the call succeed (verified at both the -c and per-thread
    config level; auto and writes still fail). The relay sets approve for
    its own MCP server only and documents it as an operator decision.
  • Server-to-client approval/user-input/elicitation requests are answered with a
    refusal and recorded; the relay never grants one.
  • Codex injects a minimal environment into stdio MCP servers — HOME LANG LOGNAME PATH SHELL TERM USER plus that server's configured env (verified with a dump
    server) — so a member derived from an MCP credential identifies the member,
    never the Codex thread that called it. Thread-level provenance exists only where
    the relay owns the app-server and can read thread/start / turn/completed.

Delivery guarantees

A send acknowledges journal persistence, not model execution. An accepted
delivery means the harness accepted the input. It does not mean consumed,
understood or done. The core records uncertain BEFORE submission; ambiguous
submissions are never retried automatically. Inspect native history and
reconcile it before redelivery. Already accepted messages do not replay.

Task IDs and kinds are routing metadata; there is no task scheduler or
completion engine. kind: 'complete' is a message from one agent, not a
verified task outcome.

Idle-boundary delivery: messages queued for a member are delivered when that
member reaches an idle boundary (Codex turn/completed, DSH agent/status →
idle), or immediately when a send is made. A busy DSH session receives the
callback as a queued follow-up turn, never as mid-step steering.

Current limits

  • Approvals. Codex sandbox/file-change/exec approval requests are refused,
    not routed to a DSH user surface. Until that exists, a Codex task that needs a
    sandbox approval will not complete; the refusal is recorded, and no permission
    is silently granted. research/codex-api.md documents the exact decision
    payloads a real approval surface must answer.
  • One process owns the journal. A second owner is refused while the recorded
    heartbeat is fresh; a lock whose heartbeat stopped for
    LOCK_STALE_MS (10s) is reclaimed automatically. A torn journal still fails
    closed and needs operator repair.
  • Delivery is globally serialized in one process, and drain() walks queued
    messages in order. No daemon proxy attachment, remote transport, artifact
    transfer or dashboard.
  • A recovered uncertain message is never retried automatically. Reconcile
    it against native history first.
  • Queued mail for a member nobody runs never expires. Settle it explicitly
    with discard (the journal records who/why); it is never dropped silently.
  • Existing Codex daemon attachment is not supported: the plugin spawns its
    own codex app-server (managed mode) under a per-member CODEX_HOME.
  • The plugin borrows only root DSH agents; subagents and owned children are
    not members.

Evidence

  • research/dsh-plugin-api.md — every DSH API used, quoted from the installed
    .d.ts / built lib/*.js.
  • research/codex-api.md and research/codex-probe-output.txt — Codex App
    Server reference and a real protocol transcript (raw frames), including the
    busy-thread, persistence, MCP-config and approval findings.
  • tools/codex-mcp-approval-probe.mjs — reproduces the approval-mode matrix;
    captured in evidence/codex-mcp-approval-matrix.txt (approve works, auto
    and writes fail under approvalPolicy: never).
  • tools/round-trip.mjs — the acceptance run: two rounds, same DSH session,
    same Codex thread, DSH session wakes after each MCP callback; captured in
    evidence/round-trip-acceptance.json (isolated home) and
    evidence/round-trip-real-home.json (the user's real ~/.dsh).
  • evidence/unmanaged-codex-pull.txt — a Codex the relay does not own pulls
    queued work with relay_inbox and answers back, waking the DSH session.
  • evidence/busy-session-gate.txt — a callback queued against a mid-turn DSH
    session (queuedWhileRunning: true) and two DSH sessions exchanging messages
    by addressed member id.
  • evidence/relay-plugin-lifecycle.log and evidence/relay-status-final.json —
    the dev host's plugin lifecycle lines and final status snapshot (no
    credentials). The live copies stay under .relay-home/run/.

常见问题

4 问
答案由本站依据条目字段整理,不引用上游原文
dsh-agent-relay 怎么安装?

在 DSH 里执行 `dsh plugin --profile web add github:lyuwen/dsh-agent-relay` 即可。

dsh-agent-relay 的验证等级是什么意思?

未标注验证等级。上游未给出验证结论,安装前请自行确认

dsh-agent-relay 安全吗?

未标注。

dsh-agent-relay 装之前要先确认什么?

先看它会读写哪些文件、执行哪些命令、连接哪些网络地址;验证等级只说明装得上、跑得起来,不等于安全。涉及密钥或系统权限的,建议先在隔离环境试装。

同名或近似条目

1 条
不同作者的仓库分开列,请确认你要装的是哪一个
工具与能力
按星标排序,可作替代方案

huashu-design

huashu-design

在 DeepSeek Harness 里说一句话,就能拿回可交付的设计:网页、App 原型、可编辑 PPTX、动画与信息图,自带 84 种风

未标注验证等级 3.0 万 星

loopx

loopx

LoopX 是面向长周期 Agent 的本地优先控制平面,作为 DSH plugin 为 DeepSeek Harness 提供持久目标、证

未标注验证等级 6,233 星

agy-staff

agy-staff

把 Google Antigravity CLI 作为快速 Gemini 员工接入 DSH,提供子代理侧边栏、编排模式与多种角色技能。

未标注验证等级 870 星

dsh-startup-screen

dsh-startup-screen

DeepSeek Harness 的启动界面与启动动画插件。

未标注验证等级 633 星

dsh-blender-plugin

dsh-blender-plugin

让 AI 模型通过直连 TCP 通道实时驱动 Blender 的 DSH plugin:15 个工具覆盖视口取帧、任意角度渲染、内循环搜索、

未标注验证等级 211 星

lyuwen 的其它插件

5 个

插件的元信息来自作者仓库;分类、验证等级与安全结论的中文说明为中文整理,最近核验 —。