Skip to content

feat(rpc): multi-session mode for the plain-RPC protocol#312

Merged
code-yeongyu merged 16 commits into
mainfrom
feat/multi-session-rpc
Jul 23, 2026
Merged

feat(rpc): multi-session mode for the plain-RPC protocol#312
code-yeongyu merged 16 commits into
mainfrom
feat/multi-session-rpc

Conversation

@code-yeongyu

@code-yeongyu code-yeongyu commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Summary

Adds a multi-session mode to senpi's plain-RPC protocol so one senpi process can host many concurrent AgentSessions over stdio, each fully isolated. This is the senpi half of omo-desktop-app's single-shared-process cutover (companion PR in code-yeongyu/omo-desktop-app). Classic single-session --mode rpc stays byte-identical.

What's new

  • --multi-session flag: no default session is constructed; the process hosts a session registry. Classic mode is unchanged except the additive, side-effect-free get_protocol_info command.
  • Wire protocol: open_session / close_session / list_sessions / get_protocol_info, a sessionId routing envelope on session-scoped commands, sessionId tagging on session-owned output, and stable machine-matchable error codes (unknown_session, session_closing, session_path_in_use, missing_session_id, multi_session_disabled, invalid_path, open_failed). Two identities: an ephemeral per-epoch routing handle vs the durable JSONL session id.
  • Session-scoped state isolation (mutation-proven): pi-ai provider registry resolves session overlay → immutable builtins via a node-only @earendil-works/pi-ai/node/provider-scope subpath (root/compat stay browser-safe); session-owned MCP service / elicitation / instructions / prompts; session-keyed config-reload handoff. Includes a shared-state audit of the agent core.
  • Lifecycle: per-session state machine (opening|open|closing|closed) with path reservation, synchronous closing transition, and atomic rollback on open failure; immutable per-open launch profile (permissionPreset/model/thinkingLevel/cwd) applied on create, restored on resume.
  • Output: per-session FIFO with a fair round-robin record writer (no cross-session batch coalescing).

Non-goals

No app-server/ACP changes. No per-connection multi-tenant key isolation (that stays the neo daemon's job). Full rich-event vocabulary preserved — only the additive sessionId key.

Verification

  • Per-package vitest --run green; npm run check green (incl. neo Go build/vet/tests — neo behavior unchanged, bridge exhaustiveness maintained).
  • Classic-compat characterization pins + all neo-daemon suites green (byte-identical classic behavior).
  • Isolation battery driven through the real routing stack with mutation proofs: provider-overlay swap, real config-reload-while-peer-streaming, MCP session ownership.
  • Built binary answers the multi-session capability probe; drives the companion omo E2E.

Plan: .omo/plans/senpi-single-rpc-process.md (in the omo-desktop-app repo).

🤖 Generated with senpi


Summary by cubic

Adds a multi-session mode for the plain-RPC protocol so one senpi --mode rpc process can host many isolated sessions over a single stdio stream. Classic mode stays byte-identical; get_protocol_info is the only additive command.

  • New Features

    • --multi-session RPC host with no default session; sessions are created on demand.
    • D1 wire protocol: get_protocol_info, open_session, close_session, list_sessions; session-scoped commands are routed by sessionId.
    • Stable error codes for routing and lifecycle (unknown_session, session_closing, session_path_in_use, missing_session_id, multi_session_disabled, invalid_path, open_failed).
    • Session-scoped provider resolution via @earendil-works/pi-ai/node/provider-scope (ALS-backed overlay) with handler binding for EventEmitter callbacks.
    • Session-owned MCP and config-reload state (per-session artifacts cleanup, auth flow guard, elicitation UI provider, and instructions injection).
    • Immutable launch profile applied on create/resume (cwd, permissionPreset, model, thinkingLevel), with path reservation and atomic rollback on open failure.
    • Per-session FIFO output with a fair round-robin writer; every record is tagged with sessionId.
  • Migration

    • To host multiple sessions: senpi --mode rpc --multi-session.
    • Probe with get_protocol_info. Then use open_session/close_session/list_sessions. Include sessionId on all session-scoped commands; events include sessionId.
    • Classic --mode rpc needs no changes and remains wire-identical.
    • In multi-session mode, HTTP proxy and the Undici dispatcher are process-global and fixed at startup.

Written for commit 63b69d8. Summary will update on new commits.

Review in cubic

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