Skip to content

feat: sessions start and message each other - #239

Merged
GoDiao merged 3 commits into
mainfrom
feat/session-links
Nov 6, 2026
Merged

GoDiao merged 3 commits into
mainfrom
feat/session-links

Conversation

@GoDiao

@GoDiao GoDiao commented Nov 5, 2026 •

Copy link
Copy Markdown
Owner

What

Sessions can now start other sessions and talk to each other, and the sidebar shows which session came from which.

  • Tools for the agent (enabled when the CLI runs under the DreamCoder server):
    • StartSession: start a child session, fresh with a brief or as a fork of the current conversation, optionally in a new git worktree. Always asks the user, whatever the permission mode (a safetyCheck ask that bypass and auto mode cannot skip). Subagents cannot use it.
    • SendMessage to session:<id>, across projects. mode: "message" wakes the receiver; mode: "report" is a progress update to the caller's parent: delivered at once if the parent is mid-turn, otherwise queued in the parent's transcript and delivered with its next turn. summary is optional for sessions (first line of the body).
    • ListSessions, and RenameSession for the agent's own session. A session has one display name, its title.
  • Origin: the server stamps who sent each session message from the SDK connection, never from the request body or the client socket. The CLI wraps the body in <cross-session-message> (forged tags escaped, titles sanitized) with a note that it carries no user authority and that text replies do not reach the sender.
  • Fork mid-turn: a forked child gets the caller's open tool calls closed with a note that the running turn belongs to the parent, so it does only its brief.
  • User messages during a turn now wait for the next turn (CLI queue priority later) instead of being slipped into the running turn. They are listed above the composer and can be withdrawn or sent now (interrupts the turn); Stop does the same while something is queued. Queued messages are held and resent when a model or permission change restarts the CLI at turn end.
  • Mid-turn messages are persisted: queued_command attachments were dropped from transcripts by the upstream isLoggableMessage filter, so messages that reached a session mid-turn vanished on reload and on resume. They are now written and shown in history; fork and rewind resolve them by their client id.
  • Desktop: sessions nest under their parent (spawned and forked, collapsible with a child count), session messages render as one-line collapsible rows, plus a pending-reports bar and a queued-messages bar. i18n in en and zh.
  • Removed the inherited UDS / bridge peer messaging stubs (ListPeers, /peers, udsMessaging, peerSessions, …).
  • Server layering: the queue and report delivery logic lives in services/turnQueueService.ts; the ws handler only calls it.
  • Docs: reorganized into docs/general and docs/features/<feature>; added docs/features/session-links/tech-design.md (Chinese). The outdated glossary was removed.

Related to #162.

Why

Agent teams need sessions that can delegate to and coordinate with other full sessions. The CLI had only stubs for this (UDS_INBOX behind a disabled flag), and session messages must be distinguishable from human messages, which text tags cannot guarantee.

How it was tested

  • bun test: 2461 pass, 0 fail.
  • bun test --randomize over the touched files: 224 pass; after the review fixes, the queue, session-links and batching test files again: 119 pass. The new server test files were also run 6 at a time in parallel (72 runs) with no failures after fixing shared ids between tests.
  • Desktop: bun run lint clean, bun run test -- --run 2678 pass.
  • Every new test was checked to fail with its change reverted.
  • In the Electron dev app with a real model: fresh, fork and fork-in-worktree children; a mid-turn fork doing only its brief; reports queued for an idle parent and delivered with its next message; reports delivered at once to a working parent; messages to a stopped session restarting its CLI; mid-turn messages surviving a history reload and a CLI resume; queued user messages, withdraw and send now; a session renaming itself on request and its new title shown as the sender; no fabricated replies after the prompt changes.

Not covered by hand: a real CLI restart at turn end with queued messages (covered by a unit test through the no-restart path), and light/dark screenshots.

- StartSession (fresh, fork, fork in a new worktree), always user-approved;
  SendMessage to session:<id> across projects with message and report modes;
  ListSessions; RenameSession for the agent's own session.
- The server stamps the origin of every session message from the SDK
  connection; envelopes escape forged tags and sanitize display titles.
- Reports to an idle parent are queued in its transcript and delivered with
  its next turn; a working parent gets them at once.
- User messages sent during a turn wait for the next turn (CLI priority
  later), can be withdrawn or sent now, and survive a restart at turn end.
- Messages that reach a session mid-turn are persisted and shown in history.
- Sidebar nests spawned and forked sessions; session messages render as
  collapsible rows; pending reports and queued messages bars.
- Remove the inherited UDS/bridge peer messaging stubs.
- Reorganize docs into docs/general and docs/features/<feature>; add the
  session-links tech design.
…e duplicates

- Queue, withdraw, send-now, restart hold/resend and report queue/claim/delivery
  now live in services/turnQueueService.ts; the ws handler only calls it.
- Reuse errorMessage, escapeXmlAttr, openSessionTab, Button link variant and one
  localStorage string-list pair; share the bar frame and the parent kind type.
- Keep the sidebar sort order for child sessions; show origin.summary as is.
- Do not rename the session or clear finished tasks for a queued message.
- Drop the unused pid-file bridge id and its helpers.
- Tests: inherited mode and model, queue and report error paths, batch merge,
  relative time; docs updated for the queue bar and session state fields.
@GoDiao
GoDiao merged commit b4ee8b3 into main Nov 6, 2026
4 checks passed
@GoDiao
GoDiao deleted the feat/session-links branch November 6, 2026 01:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant