feat(runtime): add synchronous useAgent() over the request store (#95) - #402
Conversation
🦋 Changeset detectedLatest commit: 99fb862 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
commit: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2c91fc992d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| Component or utility that cannot `await` calls `useAgent()` instead; it | ||
| returns the identical handle under the same lease rules and never suspends. |
There was a problem hiding this comment.
Update the runtime README for the shipped API
The package README still states that useAgent() “arrive[s] later” at packages/rsc-runtime/README.md:66, directly contradicting this newly documented and exported API. Package users consulting the published README may therefore conclude that useAgent() is unavailable; update that section as part of this release.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in bf7c0ab: the package README now documents the shipped useAgent() (same handle, same lease rules) and the provider-populated providers slot instead of saying they arrive later; only state and notices remain reserved.
There was a problem hiding this comment.
Acknowledged — the runtime README still says useAgent() arrives later. This PR is still open, so the fix belongs on feat/95-use-agent (the #95 useAgent lane) rather than a follow-up on main: update packages/rsc-runtime/README.md alongside the docs/framework-mode.md change before merge. Tracked by the late-review sweep; not fixed on main.
|
@codex review |
|
Codex Review: Didn't find any major issues. Hooray! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
useAgent() returns the identical request handle await agent() resolves, from the same realm-singleton store under the same lease rules (outside-invocation, request-closed), so synchronous Server Components and utilities can read request context without suspending. Route-unit and request-store tests pin identity and lease behavior; docs record the convenience beside agent().
|
@codex review |
bf7c0ab to
eafe997
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: eafe997772
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| returns the identical handle from the same store under the same lease rules | ||
| (`outside-invocation` before a request, `request-closed` after it). `providers` |
There was a problem hiding this comment.
Distinguish post-request calls from captured handles
Calling useAgent() after awaiting runAgentRequest() does not produce request-closed: AsyncLocalStorage.run has restored the caller's context, so currentLease() throws outside-invocation, exactly as the added test verifies. Only accessing a captured handle—or calling from an escaped continuation that retained the closed lease—produces request-closed. Because these are public typed error codes, document those scenarios separately rather than promising request-closed for every call after a request.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Correct — fixed in 99fb862. The README, the useAgent() docblock, and the changeset now state the two scenarios separately: a call with no request in its async context (before a request, or after runAgentRequest has settled) throws outside-invocation; a handle captured inside the request (or a continuation that retained its lease) throws request-closed once the request completes. The runtime test now asserts both codes explicitly (outside-invocation on the fresh call, request-closed on the captured handle).
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d2cfd472fa
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| @@ -0,0 +1,5 @@ | |||
| --- | |||
| "@agent-bundle/runtime": patch | |||
There was a problem hiding this comment.
Mark the new public export as a minor change
When Changesets produces the release, this declares only a patch even though the commit adds and documents a new public useAgent() export. That ships an additive API without the expected minor-version signal for consumers and release tooling; the existing request-store API introduction is also classified as minor in .changeset/request-store-agent.md, so this entry should use minor as well.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Not a defect: patch is the repository's pre-1.0 convention, adopted on main in #403. AGENTS.md ("Pre-1.0 semver: minor = breaking, patch = everything else (features included). No major before 1.0.") and .changeset/README.md ("Semver before 1.0: minor = breaking change …; patch = everything else") both classify an additive export such as useAgent() as patch. The older request-store-agent.md entry predates that convention; the changeset here was deliberately switched from minor to patch in d2cfd47 to follow it.
|
@codex review |
|
Codex Review: Didn't find any major issues. Swish! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Summary
Closes the last #95 delivery step still owned here — "Add
agent()and synchronoususeAgent()" — which the #96 closing audit explicitly handed back to #95 ("useAgent(): not shipped; tracked as a migration step on the open #95").@agent-bundle/runtimeexportsuseAgent(): AgentRequestContext: the synchronous convenience overawait agent(). It returns the identical handle (useAgent() === await agent()within one invocation) from the same realm-singletonAsyncLocalStoragestore, so every lease rule holds unchanged —outside-invocationoutside a real request,request-closedthrough a captured handle after completion.use()would only add a suspend/retry cycle for a value that is synchronously available. The core request store stays React-independent, as Add typed Agent request context and pluggable context providers #95 requires.docs/framework-mode.mdanddocs/entry-conventions.mdrecorduseAgent()besideagent()(async components should still preferawait agent()). Changeset:@agent-bundle/runtimeminor.Evidence
packages/rsc-runtime/tests/agent-request.test.ts— new "returns the identical handle synchronously through useAgent() under the same lease rules" (same object asawait agent(), stable acrossawait,outside-invocationoutside a request, captured handlerequest-closedafterward) plus the plugin-entry re-export pin. 15/15.packages/agent-bundle/tests/route-unit/render-route.test.ts— new "serves useAgent() synchronously inside a rendered Server Component": a synchronous component rendered through the real Flight renderer observes invocation kind, injected workspace, and provider fixtures viauseAgent(). Route-unit pool 37/37.pnpm typecheckgreen,pnpm lint0/0,pnpm test:projection63/63, integrationpublic-api+state-packaging14/14.Test plan