qwen-code/docs/developers
qqqys af4dece3a7
feat(sdk): add a peer endpoint so a program outside Qwen Code can join cross-session messaging (#11560)
* feat(sdk): add a peer endpoint so a program outside Qwen Code can join cross-session messaging

`@qwen-code/sdk/peer` is an implementation of the cross-session protocol
for a program that is not itself a Qwen Code session — a voice
front-end, a relay, a build watcher. `PeerEndpoint.start({ name })`
binds an inbox and publishes a session record, so the program is listed
by `qwen sessions ps` and by every session's `list_agents`; `list()` and
`send()` address sessions by name; `onMessage` receives what they send;
receipts are applied as state transitions and can be awaited.

It is written from the protocol page with Node's own modules alone and
shares no code with Qwen Code. That makes it the page's first
independent implementation, and a conformance suite runs it against
Qwen Code's own registry, inbox, directory and send path in both
directions: listing and reaching each other, frames parsed and answered
each way, a folded drop receipt settling a burst, a user-minted
controller token recognised and a forged one not, identical verdicts on
hostile lines, record files and names, and every published limit pinned
to Qwen Code's constants.

The endpoint takes the shared `<pid>.json` when it is free and a minted
`<pid>-<8 hex>.json` when it is held, never replacing a record it cannot
prove dead. Its inbox accepts only its own token, it never deletes
records or sockets other processes wrote, and trust comes only from a
controller token. On Linux it refuses to publish a record without a
start token and PID namespace.

Implementing the page found two rules it left implicit, now stated in
"Writing your own record": `procStart` and `pidNs` are required on
Linux, and a held `<pid>.json` means writing the minted name instead.

Separate Node-only subpath, kept out of the browser-bundled entries;
the build checks its size and that it carries no runtime dependency.

* fix(sdk): present the controller token only on sends marked controller

Review follow-ups on the peer endpoint.

The controller token was presented on every send, so any process that
published a record under a name the program then addressed read the
plaintext of a credential Qwen Code only ever stores hashed. A send now
presents it only when marked `controller: true`; unmarked sends — from an
endpoint holding a token too — present the recipient's own token. On a
marked send, two records for one session id and name are ambiguous rather
than collapsed to the newer, so a copied record cannot take the grant. A
malformed `controllerToken` (empty, no `qpc_` prefix) is rejected at start
with `invalid-controller-token`, as is a marked send without one.

Other fixes:
- Two `start()` calls in one process raced for `<pid>.json` and one
  record was lost; registrations inside a process now run one at a time.
- `send()` checks `closed` again after the directory read, so a send
  overlapping `close()` rejects instead of writing a dead reply address.
- `ambiguous.matches` holds only addresses that select one session.
- Receipt `reason` is flattened and bounded like every other label.
- The local concurrent-send ceiling is marked `local` and described as
  this program's limit, not as a busy peer.
- An explicit `socketPath` no longer re-permissions a directory the call
  did not create.
- `probePeerSocket` is renamed `probePeerSocketVerdict`, matching core;
  the status list is the single source of the status type.
- `flattenPeerLabel` matches control and format characters by Unicode
  category and caps in code points, in core as well, so the two
  implementations still agree.
- The build checks every emitted peer declaration, from a module with
  tests of its own; the surface test is compiled by the typecheck and
  matches imports as path segments.

Docs: `list_agents` and `send_message` need `agents.crossSessionMessaging`
on the receiving session; delivery without review also follows a matching
`fromMode`, and `agents.crossSessionInbound` outranks a controller grant;
a controller send to another endpoint is dropped unread; the endpoint's
inbox applies none of the protocol page's §6; the `socketPath` sibling
fallback; and the protocol page gives separate reasons for `pidNs` and
`procStart`. The design doc no longer says the default entry ships to
browsers.

Tests pin each of these, plus the paths the first round left unexercised:
ledger and answered-id eviction past their bounds, start rollback, the
Linux identity guard, registry directory tightening and read errors, the
over-long line with the default deadline, the symlinked and over-long
socket paths, prompt close, Windows, and a live PID with a mismatched
start token.
2026-09-10 22:13:39 +00:00
..
daemon fix(serve): restore configured channels after restart (#11472) 2026-09-10 15:40:24 +00:00
daemon-client-adapters refactor!: retire @qwen-code/webui (#9812) 2026-09-05 09:13:54 +00:00
daemon-ui feat(web-shell): make the product name and logo configurable (#11244) 2026-09-10 04:54:45 +00:00
development fix(cli): restore OpenTUI banner, footer, and loading states; fix the OSS mirror flavor (#11437) 2026-09-09 09:26:07 +00:00
examples docs(serve): state what --no-web actually removes (#11446) 2026-09-09 07:01:52 +00:00
tools feat(core): enable the built-in web_search by default on ModelStudio Standard/Token Plan (#11348) 2026-09-09 04:08:29 +00:00
_meta.ts docs(daemon): add a REST integration entry point, guarded against the route surface (#11477) 2026-09-10 06:49:42 +00:00
architecture.md refactor!: retire @qwen-code/webui (#9812) 2026-09-05 09:13:54 +00:00
channel-plugins.md refactor(channels): remove obsolete block streaming (#11381) 2026-09-09 04:41:31 +00:00
contributing.md docs: require bilingual design documents (#11419) 2026-09-09 03:41:56 +00:00
qwen-serve-protocol.md fix(serve): restore configured channels after restart (#11472) 2026-09-10 15:40:24 +00:00
rest-api-integration.md docs(daemon): add a REST integration entry point, guarded against the route surface (#11477) 2026-09-10 06:49:42 +00:00
roadmap.md feat(core): enable the built-in web_search by default on ModelStudio Standard/Token Plan (#11348) 2026-09-09 04:08:29 +00:00
sdk-java.md fix(java): make SDK worker threads daemon (#9925) 2026-09-01 18:06:25 +00:00
sdk-python.md fix(sdk): support "auto" permission mode (#9003) 2026-08-22 14:25:40 +00:00
sdk-typescript.md feat(sdk): add a peer endpoint so a program outside Qwen Code can join cross-session messaging (#11560) 2026-09-10 22:13:39 +00:00