DSH HUB
HomePlugin StorePlugin PacksCommunityRankingsResourcesPublish Guide
Plugin source
Back to catalog

Weiyang742 /

Weiyang742/dsh-cross-session-messaging

Verified

Cross-session relay for DeepSeek Harness: peer discovery and text delivery between independent dsh processes.

★ 1 Stars0 Forks0 IssuesN/A Community rating0 Confirmed installs
View on GitHub
READMESource: main@0af18721

DSH Cross-Session Relay

English | 中文

License: MIT CI

Lets multiple independent DeepSeek Harness (dsh) sessions discover each other and exchange text messages peer-to-peer.

The problem

dsh ships two built-in "cross-session" capabilities, neither of which is peer-to-peer messaging between processes:

  • subagents are parent/child: the parent agent spawns a subagent that lives in its context and stays under its control — not an independent peer.
  • @session mentions in the Web UI are one-way, read-only recall: you can reference another session's history, but cannot send it a message.

In practice, though, two sessions often need to send each other messages. Take a "database assistant" and a "frontend assistant" split into two independent sessions, each in the environment that suits it:

  • the database assistant runs on an intranet machine with database access and context;
  • the frontend assistant runs on a dev machine and owns the UI.

When the frontend assistant needs the CREATE TABLE SQL for a users table, it has no database context or credentials of its own, so it has to message the database assistant; the database assistant looks it up and replies. This peer-to-peer ask/reply across different specialties, permissions, or machines is exactly what subagents' parent/child structure and @session's read-only recall cannot cover. This plugin adds that peer-to-peer, two-way channel.

What this plugin does

A peer-to-peer, centerless, cross-process (optionally cross-machine) message channel:

  • Model-driven: the agent itself calls cross_session_list_agents to discover peers and cross_session_send_message to send; no human relays anything.
  • Relay injection, never authorization: messages arrive as form: 'relay' text and never approve a tool call on the user's behalf — the receiver's own approval still applies.
  • Reliable delivery: sender-side spool + exponential backoff + dead-letter; receiver persists before ack; at-least-once with content dedup.
  • Local and cross-machine: Unix sockets locally, TCP+TLS (fail-closed, static peers) across machines.
  • Centerless: the on-disk registry is the source of truth; there is no central server.

How it differs from dsh's built-ins

subagent @session mention this plugin
Relationship parent/child one-way, read-only peer-to-peer
Can send messages parent → child control no yes, both ways
Cross-process / cross-machine same process same process yes
Injection form subagent context history snapshot relay text, no authorization

Installation

Prerequisites: Node.js >= 24.11 and a working dsh (DeepSeek Harness) environment.

When installing from source, build the artifacts first (lib/ is not distributed):

npm install
npm run build

Then add the plugin to a profile:

dsh plugin --profile demo add ./cross-session-messaging
dsh --profile demo --dump-config   # verify it is wired in

The plugin is inserted into the profile at the bundle layer via cordis.patch.yml; any fields not listed fall back to schema defaults.

Usage

Open two dsh sessions (for example, two "New Session" in the Web UI) and, in one of them, ask in natural language:

List the other sessions currently running, then send one of them a message: hello.

The model calls cross_session_list_agents to discover the peer and cross_session_send_message to send; the other session receives the message as form: 'relay'. The human only writes a natural-language request and names no tool.

See Quick start for the full end-to-end walkthrough.

Configuration

Configuration lives in the plugin's cordis.patch.yml under config: (already used to wire it in during installation); any field not listed falls back to its schema default. Local use normally needs no customization beyond name and the inbound policy:

- insert:
    - id: cross-session-messaging
      name: '@wy/dsh-cross-session-messaging'
      config:
        dirs:
          baseDir: ~/.dsh/cross-session   # data root; registry/socket/spool derive from it
        inbound:
          rules: []                        # inbound rules, see below
          defaultDecision: auto            # fallback when no rule matches
        name: ''                           # session name, defaults to the shortId
        # Cross-machine (optional, see "Cross-machine"):
        # remote:
        #   listen: { host, port, identity, secret }
        #   tls: { key, cert }
        #   peers:
        #     - { name, host, port, secret, tls, tlsCa/tlsFingerprint }
  • dirs.baseDir: root of all data directories (registry / socket / spool / credential / deadletter / audit), default ~/.dsh/cross-session; each of the six can be overridden.
  • inbound.rules: accept | hold | refuse rules matched by receiver (local session id/name) and sender (sender sessionId); omitting either means "all local sessions" / "default rule".
  • inbound.defaultDecision: fallback when no rule matches; auto (default) consults the receiver's DSH_PERMISSION_MODE (danger-full-access → hold, otherwise accept), or set accept | hold | refuse explicitly.
  • name: the session's readable name, used for addressing by cross_session_send_message.

Cross-machine

Cross-machine delivery needs remote (omit it for local-only use):

  • remote.listen: the TCP listener when this machine receives (host / port / identity / secret); identity is how this machine appears to peers and is stamped onto inbound from.
  • remote.tls: listener certificate (key / cert); omit to auto-generate a self-signed cert under spool/tls, with its fingerprint written to spool/tls/fingerprint.
  • remote.peers: the static peer list when this machine sends (name / host / port / secret / tls / tlsCa or tlsFingerprint). tls defaults to true; cross-machine TLS requires tlsCa or tlsFingerprint, otherwise the connection is refused.

Capacity and retry (tuning)

limits.* (queue caps, message size, rate limit, dedup window), delivery.* (retry/backoff), metricsIntervalMs, and auditMaxBytes have conservative defaults and rarely need changing; adjust by field name when you do.

Tools

  • cross_session_list_agents: list reachable peer sessions (sessionId / name / shortId / cwd / pid).
  • cross_session_send_message: send text to a session by sessionId, shortId, or name.
  • cross_session_inbox_review: review held messages awaiting accept/refuse.
  • cross_session_inbox_resolve: accept or refuse a held message.

Permission semantics

  • Peer messages are injected with source.form = 'relay', enter the model as text only, and never approve any tool call on the user's behalf; the receiving tools still go through their own approval (fail-closed by default).
  • The from identity is overwritten by server-side authentication (local = sessionId, cross-machine = listen.identity), never trusted from the sender; tool names this session's permission system rejected are remembered, so send_message will not forward text asking another session to run one of them.

Hooks / child-process replies

The plugin injects the current socket / sessionId / handshake token into shell child processes via dsh's ctx.shellEnv registry (DSH_CROSS_SESSION_SOCKET / DSH_CROSS_SESSION_ID / DSH_CROSS_SESSION_TOKEN). A long-running child process or hook can connect to that socket and send back text, or call the exported sendToCurrentSession(text).

Testing

npm test          # unit + integration (real sockets)
npm run check     # lint + typecheck + build + test

Test layering, the cross-machine stress matrix, and CI policy are in docs/testing.md.

Limitations

  • Cross-machine discovery is static peers config (requires restart), with no central registry and no public NAT traversal; real public two-host transport/service layers are verified (stable at low frequency, occasional ping failures at high frequency), but the host end-to-end where the model proactively calls the tool is not yet verified.
  • TLS certificates are auto-generated (openssl self-signed) but not rotated/revoked; cross-machine TLS requires tlsCa / tlsFingerprint (fail-closed).
  • Delivery is at-least-once with content dedup (across restarts), not strict exactly-once: duplicates are possible outside the window or for different content.
  • Both accepted and held are persisted (recovered on restart); accepted messages are marked after injection and re-delivered if not injected, with a minimal crash window.
  • Cross-machine identity is single-peer: listen.identity is a single value (two-machine assumption); future multi-peer needs an allowed list.
  • Forward protection is heuristic (best-effort); the real security boundary is relay-does-not-authorize + the default inbound policy.
  • Peer messages are injected with form: 'relay' and carry no user authorization; receiving tools still use their own approval (fail-closed by default).
—/ 5

No ratings yet

Verified DSH bundle

Commit 0af18721fcfc

Community comments

No comments yet. Be the first to write one.

DSH HUB

A community index for DSH plugins. Not an official GitHub or DeepSeek AI product.

CommunityResourcesAPIAbout