feat: cross-session send (split view button + send_to_session MCP tool) - #5819
feat: cross-session send (split view button + send_to_session MCP tool)#5819alonzazo wants to merge 1 commit into
Conversation
Add dashboard.cross_session_send (default false, Settings > Chat) and the send_to_session MCP tool: route a composed message from one chat session to another via the existing /api/chat slot routing. Double gate: the UI button is hidden and the tool rejects server-side without the flag. Hardening: LLM output redaction (exfil URLs + credentials) before injection, deny-by-default origin resolution restricted to dashboard sessions, namespace-aware self-target guard (feedback-loop prevention), anchored slot-key schema pattern, target-session existence probe before the workspace check, workspace isolation mirroring the chat-history read paths, and SEL audit events on denied/error/success paths. Frontend: send-to-session listbox dropdown in split view pane headers (keyboard-operable, portaled, focus-restoring), per-cause failure indicator preserving the composer text, Settings > Chat toggle. 17 new backend tests; website tsc -b and vite build clean.
|
🤖 Kiro Crew [operator: bolichen97#bb3ad1ca]: This PR has been inactive for 7+ days with failing CI. I've assessed the blockers and they appear resolvable — I'll push fixes directly to this branch as a co-author. Assessment: Merge conflict from base drift plus mechanical CI failures: black formatting on the PR's two backend files, two i18n literal-string lint errors in ChatPane.tsx, and one new error response in files.py missing the machine-readable If you'd prefer I don't touch this PR, add the |
Audit note — part of this has already landed; the rest has notThis PR is not a duplicate and is not finished by anything on Already landed
Which parts
|
Open PR relationship auditThis is a consolidated, point-in-time code-level audit note. It compares complete merge-base diffs and current/merged code; it does not treat a shared topic as duplication or partial coverage as completion. Relationship findings
No PR, Issue, label, branch, or review state was changed by the relationship-note portion of this audit. |
|
@alonzazo Thanks for this, and please keep it open: the split-view half is genuinely uncovered work. Already on main. The agent-facing half landed as Still missing. Main has no browser path for cross-session send: Overlap with #8947 (cc @CrysisDeu): mechanical only. Both insert a prop at the same Posted from the 2026-09-08 open-PR relationship audit (read-only, one auditor per PR); reply here if any of this is wrong. |
Problem / Motivation
Sessions are fully isolated — there is no way for a user in split view (session grid) to route a composed message to another visible session, nor for an agent to hand context to a sibling session. Coordinating parallel sessions today requires copy-paste between panes.
Why it matters
Split view (
dashboard.session_grid) makes running parallel sessions a first-class workflow, but without a message path between panes the grid is view-only coordination. Cross-session send closes that loop: draft in one pane, dispatch to another; or let an agent delegate follow-up work to a sibling session — with explicit user opt-in.What changed (motivation → approach → change)
Goal: a message path between sessions that (a) cannot be used by an agent without the user's explicit opt-in, and (b) cannot become a feedback loop or a cross-workspace leak.
Approach: no new endpoint —
/api/chatalready routes by slot and queues when the target is busy, so the tool POSTs there. A single feature flag (dashboard.cross_session_send, defaultfalse) gates both surfaces: the UI button does not render without it, and the MCP tool rejects server-side, so an agent cannot move messages between sessions unless the user enabled it in Settings > Chat.Backend (
src/kiro_crew/):send_to_session(slot, message)inmcp_tools/messaging.py(descriptor + handler, registered inHANDLERSandMCP_CORE_SCHEMAS).[Cross-session message from <origin>]provenance prefix.redact_exfiltration_urls+redact_credentials) before injection into another session.dashboard:origins so cron/hook callers cannot bypass the self-target guard.^chat-\d+-\d+$) rejecting namespaced or path-like values.has_log) before the workspace comparison — a missing session has empty metadata that buckets to the default workspace and would otherwise pass the check open, and/api/chatwould then silently create a session for the typo'd slot._caller_workspace/_ws_bucket).dashboard.cross_session_sendflag: dataclass field, loader parse, PUT validation + GET exposure in the dashboard config handler,config-baseline.jsonregenerated.Frontend (
website/src/):SendHorizontal) in split view pane headers with a keyboard-operable listbox dropdown (useListboxKeyboard: focus-on-open, arrow nav, Escape-to-trigger, ARIA roles, roving tabindex, outside-click dismissal), portaled todocument.bodyso it is not clipped by pane overflow.SessionGridViewpasses the other visible grid sessions as send targets, flag-gated.settingsRegistry.gen.tsregenerated viascripts/gen-settings-registry.mjs.Known limitation (documented in code):
_caller_workspacefalls back to the default bucket for sessions whose metadata has not been written yet — same limitation as the existing chat-history read paths.Tests
17 new tests in
test/test_send_to_session.py:/api/chat?ws=1with the target slot.schemas()and dispatchable viaHANDLERS; config flag defaults tofalse.Regression:
test_config_loader.py+test_mcp_tool_registry.py(474 passed, 5 skipped).Manual verification
Validated end-to-end in the internal (pre-fork) codebase this is ported from, in an isolated gateway with both flags enabled: UI button send between grid panes and agent-initiated
send_to_sessionboth worked, including the busy-target queueing path. Websitetsc -bandvite buildclean on this branch.Screenshots / video
N/A — happy to add a short clip if reviewers want one; the UI surface is a small header button + dropdown in split view.