Skip to content

Expose local cross-session discovery and delivery - #2616

Closed
dfrysinger wants to merge 9 commits into
mainfrom
dfrysinger/cross-session-runtime-admission
Closed

dfrysinger wants to merge 9 commits into
mainfrom
dfrysinger/cross-session-runtime-admission

Conversation

@dfrysinger

@dfrysinger dfrysinger commented Sep 11, 2026 •

Copy link
Copy Markdown

Summary

  • add source-bound Node and Rust APIs for listing active local messageable sessions
  • add exact-target cross-session delivery with typed refused, not-delivered, and ambiguous terminal errors
  • keep authenticated recipient admission inside the runtime rather than exposing caller-controlled provenance through the SDK
  • ensure generated session-scoped TypeScript calls always overwrite any caller-provided source session ID

Runtime dependency

This SDK surface consumes the local transport, provenance, target-claim, and recipient-admission contract in github/copilot-agent-runtime#19586. The runtime owns wire security and recipient admission. The SDK exposes only source-bound discovery and delivery so CLI and App consumers do not implement separate local protocols. Same-computer discovery and delivery do not require remote control or remote export.

The unreleased discovery and delivery wire types live in the hand-written SDK facades until the runtime schema reaches the SDK pinned CLI release. Generated files remain reproducible from that pinned release.

Companion integration

Validation

  • Node typecheck and formatting
  • 70 focused Node tests for discovery, delivery, event types, and source identity
  • Rust compile check
  • 2 Rust discovery tests
  • 4 Rust delivery tests
  • deterministic pinned-schema generation and whitespace checks

dfrysinger and others added 3 commits September 1, 2026 21:22
Add a hand-written typed `Session::admit_authenticated_cross_session_input`
for the runtime's private direct-host-only
`session.lifecycle.admitAuthenticatedCrossSessionInput` method. The public
request types carry only caller-variable fields; the wire `version`, `kind`,
`origin`, and `integrity` discriminators are stamped by private wire types
during request conversion.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5b6a7c90-1ad5-47e3-83a3-a87b895fb13c
Add session-bound Node and Rust SDK operations for listing active local peers and sending an exact-ID message through the runtime contract. Preserve typed refused, not-delivered, and ambiguous outcomes without retrying an uncertain delivery.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: ea23a388-a87d-436d-8110-4f7f543141d6
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: ea23a388-a87d-436d-8110-4f7f543141d6
Copilot AI balanced review requested due to automatic review settings September 11, 2026 00:21
@dfrysinger
dfrysinger requested a review from a team as a code owner September 11, 2026 00:21
Comment thread nodejs/test/session-list-messageable-sessions.test.ts Fixed
Comment thread nodejs/test/session-send-session-message.test.ts Fixed
@github-actions

This comment has been minimized.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generated by SDK Consistency Review Agent for #2616 · copilot · sonnet50 · 110.6 AIC · ⌖ 13.3 AIC · ⊞ 8.3K

Comment thread rust/src/session.rs Outdated
/// [`Client::call`](crate::Client::call)). If the caller's future is
/// dropped after the frame is enqueued, the admission still lands and
/// the runtime processes it normally.
pub async fn admit_authenticated_cross_session_input(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cross-SDK consistency: admit_authenticated_cross_session_input (backed by session.lifecycle.admitAuthenticatedCrossSessionInput, plus the new CrossSessionInput/CrossSessionPresentation/CrossSessionRecipientContext types) is added only to the Rust SDK. Since this is documented as usable by "a host embedding the SDK in-process (or over the direct local transport)", Node.js hosts embedding the SDK in-process would plausibly want the same capability, but no equivalent was added to nodejs/src/session.ts in this PR. If this omission is intentional (e.g., Node hosts don't embed the runtime the same way), consider noting that in the PR description; otherwise this looks like a parity gap worth tracking for the Node SDK, and eventually Python/Go/.NET/Java if this capability becomes broadly useful.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Unresolved critical code-generation, compatibility, re-export, and API-boundary issues remain.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review tier: Lite
Findings: 2 High severity

New issues introduced by this change (2)
Severity Finding
High severity rust/​src/​session.rs — Keep the private admission producer out of the public API
High severity rust/​src/​types.rs — Preserve the public rpc type import path
What changed in this PR

Adds local cross-session discovery and exact-target delivery APIs for Node and Rust, with source binding, typed delivery errors, and authenticated admission.

Changes:

  • Adds generated and high-level discovery/delivery APIs.
  • Adds authenticated admission models and typed terminal errors.
  • Updates bindings, exports, code generation, and focused tests.
File Summary / review notes
scripts/​codegen/​typescript.ts Ensures bound source session IDs override caller parameters.
rust/​tests/​session_test.rs Tests admission, discovery, delivery, and failure outcomes.
rust/​src/​types.rs Adds admission models and wire conversion. Critical (1 vote): preserve the public github_copilot_sdk::rpc::PermissionDecisionSource facade. Nit (1 vote): use an explicit named conversion instead of From.
rust/​src/​session.rs Adds Rust discovery, delivery, and admission APIs. Critical (2 votes): keep authenticated admission behind an internal host adapter. Nit (1 vote): add experimental notices to the public methods.
rust/​src/​lib.rs Preserves structured RPC error data.
rust/​src/​generated/​session_events.rs Adds cross-session event types and fields. Critical (1 vote each): preserve the stable permission-source re-export and apply compatibility protection such as #[non_exhaustive] to extended public event structs.
rust/​src/​generated/​rpc.rs Adds generated Rust RPC methods.
rust/​src/​generated/​api_types.rs Adds generated request and result types.
rust/​src/​errors.rs Adds typed delivery error variants.
nodejs/​tsconfig.test.json Updates test TypeScript configuration.
nodejs/​test/​session-send-session-message.test.ts Tests delivery and terminal error behavior.
nodejs/​test/​session-list-messageable-sessions.test.ts Tests discovery and source binding.
nodejs/​src/​types.ts Exposes cross-session types.
nodejs/​src/​session.ts Adds Node discovery, delivery, and typed errors. Nit (1 vote): document targetSessionId explicitly.
nodejs/​src/​index.ts Exports new public Node APIs.
nodejs/​src/​generated/​session-events.ts Adds generated cross-session event types.
nodejs/​src/​generated/​rpc.ts Adds generated cross-session RPC bindings. Critical (1 vote): regenerate all schema-derived language outputs or explicitly change the generation contract, since the shared codegen check currently lacks corresponding Python, Go, and .NET definitions.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread rust/src/session.rs Outdated
Comment on lines +759 to +762
pub async fn admit_authenticated_cross_session_input(
&self,
request: AdmitAuthenticatedCrossSessionInputRequest,
) -> Result<(), Error> {
Comment thread rust/src/types.rs Outdated
PermissionDecisionReject, PermissionDecisionSurface, PermissionDecisionUserNotAvailable,
PermissionResponseCapability,
};
pub use crate::generated::session_events::PermissionDecisionSource;
Define unreleased discovery and delivery wire types in the SDK facade while leaving generated bindings reproducible from the pinned CLI schema. Replace unreachable compile assertions with callable type checks.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: ea23a388-a87d-436d-8110-4f7f543141d6
@github-actions

This comment has been minimized.

@dfrysinger

Copy link
Copy Markdown
Author

The official GitHub Copilot App consumer is now open: https://github.com/github/github-app/pull/15507\n\nThese PRs align Runtime, SDK, and App on one public local cross-session messaging protocol. The App vendors SDK commit d8aaeed and proves bidirectional local App/CLI delivery without remote control or remote session export.

@SteveSandersonMS

Copy link
Copy Markdown
Contributor

Thanks for iterating on this. Three things to resolve before this is ready for review:

  1. Capability gating: cross-session-messaging is hardcoded to client_kind == "cli" in the runtime rather than using the existing enable_<feature> + ClientMode-default pattern already used for mcp-apps/session-store (default off in Empty mode, on in CopilotCli mode, always caller-overridable). Please make this an explicit opt-in/opt-out flag like the others, not a categorical client-kind exclusion.
  2. Cross-language consistency: this only lands in Node and Rust. Please add it consistently across all SDK languages.
  3. Real E2E coverage: today's tests only assert JSON-RPC serialization/types; none exercise the actual runtime behavior (discovery, delivery, tool-level cross-session messaging) against a real running runtime. Please add E2E tests that drive this through an actual agent turn once the runtime supports it, not just mocked RPC calls.

I'm moving this to draft until the runtime dependency lands and the SDK surface (and its tests) can be built against real runtime behavior. Please mark it ready for review once that's true.

@SteveSandersonMS
SteveSandersonMS marked this pull request as draft September 11, 2026 10:29
Fake Copilot added 2 commits September 17, 2026 14:00
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: ea23a388-a87d-436d-8110-4f7f543141d6
Preserve the Node and Rust cross-session messaging APIs while adopting current SDK main, including the new Runtime host and model allowlist coverage. Remove a stale source-text assertion after upstream moved session wrappers out of generated RPC code; behavioral source-binding coverage remains.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: ea23a388-a87d-436d-8110-4f7f543141d6
@github-actions

This comment has been minimized.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: ea23a388-a87d-436d-8110-4f7f543141d6
@github-actions

This comment has been minimized.

Preserve session-bound cross-session messaging APIs while adopting the current generated SDK surfaces and generalized Rust RPC error data.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: ea23a388-a87d-436d-8110-4f7f543141d6
@github-actions

This comment has been minimized.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generated by SDK Consistency Review Agent for #2616 · copilot · sonnet50 · 38.3 AIC · ⌖ 11.8 AIC · ⊞ 8.1K

Comment thread nodejs/src/types.ts
Comment on lines 2949 to +2955
*/
enableSessionStore?: boolean;

/**
* Whether this session participates in local cross-session messaging
* discovery and delivery. Defaults to true when omitted.
*/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New enableCrossSessionMessaging config option is added here (and in Rust's SessionConfig/ResumeSessionConfig), but not in Python, Go, .NET, or Java. If this feature is intended for all SDKs, consider adding the equivalent option (enable_cross_session_messaging in Python, EnableCrossSessionMessaging in Go/.NET, enableCrossSessionMessaging in Java) to keep config surfaces in parity, similar to the existing enableSessionStore option present in all six SDKs.

Comment thread nodejs/src/session.ts
Comment on lines 1271 to +1315
return (response as { messageId: string }).messageId;
}

/**
* Lists active local sessions that this bound session can select by exact
* ID for cross-session messaging. The result grants no delivery authority;
* call {@link sendSessionMessage} with a selected `sessionId`.
*
* @experimental
*/
async listMessageableSessions(
params: ListMessageableSessionsRequest = {}
): Promise<ListMessageableSessionsResult> {
return this.connection.sendRequest("session.listMessageableSessions", {
...params,
sessionId: this.sessionId,
});
}

/**
* Sends one authenticated non-user message from this bound session to an
* exact active local session.
*
* Success reports recipient admission, not completion of delegated work.
* An ambiguous error means delivery may have started and is never retried.
*
* @experimental
*/
async sendSessionMessage(params: SendSessionMessageRequest): Promise<SendSessionMessageResult> {
try {
return await this.connection.sendRequest("session.sendSessionMessage", {
...params,
sessionId: this.sessionId,
});
} catch (error) {
if (error instanceof ResponseError) {
const translated = parseSendSessionMessageErrorData(error.data);
if (translated) {
throw new SendSessionMessageError(
translated.code,
error.message,
translated.messageId
);
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New listMessageableSessions() / sendSessionMessage() methods (mirrored in Rust's Session::list_messageable_sessions / Session::send_session_message) introduce a new cross-session-messaging API surface. This is not yet present in Python, Go, .NET, or Java. Consider tracking follow-up work to add equivalent methods (list_messageable_sessions/send_session_message for Python/Rust conventions, ListMessageableSessions/SendSessionMessage for Go/.NET, listMessageableSessions/sendSessionMessage for Java) with the same request/result shapes and SendSessionMessageError (refused/not-delivered/ambiguous) error taxonomy for full feature parity.

@dfrysinger
dfrysinger marked this pull request as ready for review September 24, 2026 01:48
@github-actions

Copy link
Copy Markdown
Contributor

SDK Consistency Review — PR #2616

This PR adds a new cross-session messaging feature (session-to-session message delivery and discovery) plus its supporting enableCrossSessionMessaging session config flag. The changes are scoped to two SDKs only:

  • Node.js/TypeScript (nodejs/src/session.ts, client.ts, types.ts, index.ts, generated/rpc.ts): adds CopilotSession.listMessageableSessions(), CopilotSession.sendSessionMessage(), SendSessionMessageError, related request/result types, and SessionConfigBase.enableCrossSessionMessaging.
  • Rust (rust/src/session.rs, rpc.rs, errors.rs, types.rs, wire.rs): adds Session::list_messageable_sessions(), Session::send_session_message(), SendSessionMessageErrorCode, matching request/result structs, and SessionConfig::enable_cross_session_messaging / ResumeSessionConfig::enable_cross_session_messaging.

I confirmed (via repo-wide search) that no equivalent APIs or config flag exist yet in Python, Go, .NET, or Java — no enable_session_store-style sibling flag for cross-session messaging, and no sendSessionMessage/listMessageableSessions equivalents. This repo's convention (confirmed by the parallel enableSessionStore flag, which is implemented in all six languages) is that session-config options and session-scoped RPC-backed methods land in parity across languages, generally in the same PR or a fast follow.

Suggested follow-ups

  1. Python (python/copilot/client.py, python/copilot/session.py if applicable): add enable_cross_session_messaging to session-create/resume config, and list_messageable_sessions() / send_session_message() methods on the session object, mirroring the send/send_messages snake_case pattern already used there.
  2. Go (go/ session config + session methods): add EnableCrossSessionMessaging field to the session config struct(s) (see mode_empty.go pattern for EnableSessionStore), and ListMessageableSessions / SendSessionMessage exported methods.
  3. .NET (dotnet/src/): add EnableCrossSessionMessaging property to the session config classes and ListMessageableSessionsAsync / SendSessionMessageAsync methods, following existing async/Result conventions.
  4. Java (java/sdk/src/main/java/): add enableCrossSessionMessaging fluent setter to session config, and listMessageableSessions / sendSessionMessage methods returning CompletableFuture, matching the Node.js API shape (SendSessionMessageError → a checked/runtime exception with a stable error-code enum).

If cross-session messaging is intentionally being rolled out CLI-first or Node/Rust-first (e.g., behind an experimental flag, as the @experimental JSDoc/doc comments in this PR indicate), it may be fine to defer the other four SDKs to a follow-up PR — but please confirm that's the plan so the remaining SDKs aren't left permanently out of parity.

Everything else in this PR (the sessionId field-ordering fix in nodejs/src/generated/rpc.ts, generated-file/codegen changes) is internal-only and doesn't require cross-SDK mirroring.

Generated by SDK Consistency Review Agent for #2616 · copilot · sonnet50 · 45 AIC · ⌖ 12 AIC · ⊞ 8.1K · ◷

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generated by SDK Consistency Review Agent for #2616 · copilot · sonnet50 · 45 AIC · ⌖ 12 AIC · ⊞ 8.1K

Comment thread nodejs/src/session.ts
*
* @experimental
*/
async listMessageableSessions(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New cross-session messaging API (listMessageableSessions / sendSessionMessage) is added here for Node.js and mirrored in Rust (rust/src/session.rs), but I could not find equivalent methods in Python, Go, .NET, or Java. If this feature should have parity across all six SDKs (as enableSessionStore and other session-scoped methods do), please add list_messageable_sessions/send_session_message-style methods to those SDKs, or note that this is an intentional Node/Rust-first rollout.

Comment thread nodejs/src/types.ts
* Whether this session participates in local cross-session messaging
* discovery and delivery. Defaults to true when omitted.
*/
enableCrossSessionMessaging?: boolean;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enableCrossSessionMessaging is added to the Node.js session config and mirrored in Rust (SessionConfig::enable_cross_session_messaging / ResumeSessionConfig::enable_cross_session_messaging), but no equivalent flag exists yet in Python, Go, .NET, or Java session configs. Consider adding it to the remaining SDKs for parity, similar to how enableSessionStore is implemented everywhere.

Comment thread rust/src/session.rs
/// The runtime derives the source identity from this bound session. Pass
/// `None` to list all messageable sessions or a request containing an
/// exact-name filter. Discovery grants no delivery authority.
pub async fn list_messageable_sessions(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rust adds list_messageable_sessions/send_session_message here, matching the new Node.js API in nodejs/src/session.ts. This new cross-session messaging feature (and its enable_cross_session_messaging config flag) currently only exists in Node.js and Rust — Python, Go, .NET, and Java don't have equivalents yet. Worth tracking as a follow-up for the other four SDKs if this isn't an intentional staged rollout.

@dfrysinger

Copy link
Copy Markdown
Author

Superseded by https://github.com/github/copilot-agent-runtime/pull/19586. Runtime now owns the canonical src/sdk source tree and includes the reviewed high-level Node and Rust cross-session messaging facades, generated bindings, and closure fixes. The companion App integration remains at https://github.com/github/github-app/pull/15507.

@dfrysinger dfrysinger closed this Sep 24, 2026
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.

4 participants