Repository navigation
feat(sdk): add scoped direct Session handles - #45988
Closed
kitlangton wants to merge 3 commits into
Closed
kitlangton wants to merge 3 commits into
kitlangton wants to merge 3 commits into
Conversation
Contributor
|
This is great |
Contributor
|
Automated PR Cleanup Thank you for contributing to opencode. Due to the high volume of PRs from users and AI agents, we periodically close older PRs using automated criteria so maintainers can focus review time on the most active and community-supported contributions. This PR was closed because it matched the following cleanup criteria:
PRs created within the last month are not affected by this cleanup. If you believe this PR was closed incorrectly, or if you are still actively working on it, please leave a comment explaining why it should be reopened. A maintainer can review and reopen it if appropriate. Thanks again for taking the time to contribute. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Applications that keep one conversation per thread need to choose that conversation's live tools and plugins without building an embedded HTTP gateway. Location-based instance sharing also cannot give two conversations at the same directory independently configured capabilities.
The existing embedded SDK remains available. This adds a direct Effect entrypoint whose handles retain their instances through preparation, execution, child work, observation, and shutdown.
What Changes
@opencode-ai/sdk/direct/effectexportsSession.createandShared.layer. Provide shared infrastructure once and acquire private, ready Session handles inside that scope. Handles exposeid,prompt,resume,interrupt,wait, and liveevents.subscribe.resume: falseSession.AlreadyBoundError, never replace its live instanceSession.ClosedErrorDirect construction defaults to
discovery: false; opt in to filesystem discovery explicitly. Runtime plugins/options are not serialized into Session metadata. Explicit relative database paths are resolved against the application's working directory.flowchart LR Shared[Shared.layer] --> Backing[Shared Database and Bus/projectors] Shared --> Execution[One SessionExecution coordinator] A[Private Session A] --> Execution B[Private Session B at the same directory] --> Execution Execution -->|Session A binding| RunnerA[A's runner and capabilities] Execution -->|Session B binding| RunnerB[B's runner and capabilities] RunnerA --> Backing RunnerB --> BackingBound Execution
Core's
SessionInstanceboundary separates instance selection from the existing Session algorithms. The server adapter still uses its originalLocationServiceMap; direct bindings retain already-built contexts and resolve children through their bound ancestor. Both adapters use the same durable prompt work and shared coordinator, not separate model loops.Instance.composerequires explicit shared infrastructure and freshens only local services. Shared cleanup directly groups the existing Shell and ToolOutput cleanup nodes; no new graph-discard transform is needed. Captured Bus views isolate existing instance-local ephemeral inventory notifications through plugin context trimming while preserving shared credentials, placement/path events, and Session-event semantics. Durable publication, projector transactions, event schemas, and replay are unchanged.Shutdown marks the entire bound execution chain before signaling any fibers. Bound runtime admission is closed before interruption, so background child completion cannot consume a recoverable notification ID with a teardown cancellation. Foreground cleanup cannot reclassify a shutdown child as user-cancelled.
Each private graph is a child of the Shared layer's acquisition scope and also closes with its caller's scope. This keeps private cleanup ahead of backing disposal even when the caller's scope outlives an
Effect.provide(Shared.layer(...))block.Observation fibers attach to the caller with
Fiber.runInand detach automatically on completion. Their own Scope still owns the eager subscription and callback resources, avoiding accumulated caller finalizers when observations are repeatedly stopped.Scope
This PR owns the map-free direct Effect slice and the Core binding/composition needed to support it. The server keeps its existing location cache, and the shipped embedded/Workerd SDK entrypoints remain unchanged. Movable placement, custom server assignment, replay-cursor observation, exactly-once outbound delivery, and a direct Promise facade are follow-ups.
Direct
resume()drains the selected Session; it does not run the server's automatic restart/background-Job recovery sweep. Automatic background Job restoration after reopening handles remains a follow-up, with the durable recovery markers preserved by shutdown.Verification
1383222327, before the simplification pass. The new direct entrypoint constructs two co-located handles, commits real admission, and receives its already-acquired Session observation from packed packages. Existing imports, the Workerd dry-run bundle and boot/health check passed. SDK packed contents and emitted direct declarations were inspected.The initial SDK run against ambient home configuration timed out in seven existing embedded fixtures after loading configured MCP servers. The full isolated rerun passed without changing those fixtures. Formatting passes for the new source/tests and changed runtime surfaces; the existing
session-prompt.test.tshas a baseline formatting warning, with only a no-op shutdown fixture field added here.During simplification verification, a parallel SDK run timed out in the existing five-second contract-generation test. The full SDK suite passed when rerun alone, without changing its timeout or fixture.