diff --git a/.cursorindexingignore b/.cursorindexingignore new file mode 100644 index 00000000..953908e7 --- /dev/null +++ b/.cursorindexingignore @@ -0,0 +1,3 @@ + +# Don't index SpecStory auto-save files, but allow explicit context inclusion via @ references +.specstory/** diff --git a/.gitignore b/.gitignore index 1ee9d15e..bee24169 100644 --- a/.gitignore +++ b/.gitignore @@ -140,4 +140,6 @@ dist .dev.vars # macOS -.DS_Store \ No newline at end of file +.DS_Store +# SpecStory explanation file +.specstory/.what-is-this.md diff --git a/.specstory/history/2025-10-16_21-46-how-does-getcurrentagent-work.md b/.specstory/history/2025-10-16_21-46-how-does-getcurrentagent-work.md new file mode 100644 index 00000000..fe6d29d7 --- /dev/null +++ b/.specstory/history/2025-10-16_21-46-how-does-getcurrentagent-work.md @@ -0,0 +1,595 @@ + + +# How does getCurrentAgent work (2025-10-16 23:46:12) + +_**User**_ + +how does getCurrentAgent work + +--- + +_**Assistant**_ + + + +--- + + + +--- + + + +--- + +Read file: undefined + +--- + + + +--- + + + +--- + + + +--- + +Read file: undefined + +--- + + + +--- + +Read file: undefined + +--- + + + +--- + +Read file: undefined + +--- + + + +--- + +## How `getCurrentAgent` Works + +`getCurrentAgent` is a function that provides access to the current agent context from anywhere in your code. Here's how it works: + +### Core Implementation + +The function uses Node.js's `AsyncLocalStorage` to maintain execution context: + +```typescript +const agentContext = new AsyncLocalStorage<{ + agent: Agent; + connection: Connection | undefined; + request: Request | undefined; + email: AgentEmail | undefined; +}>(); + +export function getCurrentAgent< + T extends Agent = Agent +>(): { + agent: T | undefined; + connection: Connection | undefined; + request: Request | undefined; + email: AgentEmail | undefined; +} { + const store = agentContext.getStore() as + | { + agent: T; + connection: Connection | undefined; + request: Request | undefined; + email: AgentEmail | undefined; + } + | undefined; + if (!store) { + return { + agent: undefined, + connection: undefined, + request: undefined, + email: undefined + }; + } + return store; +} +``` + +### How Context is Established + +The agent framework automatically wraps method calls with `agentContext.run()` to establish the context: + +1. **Built-in methods** (like `onRequest`, `onMessage`) are wrapped during agent initialization +2. **Custom methods** are automatically detected and wrapped during agent initialization +3. **External functions** called from within these contexts inherit the agent context + +### Context Flow Example + +When a request comes in: + +```typescript +// Framework automatically wraps onRequest with: +agentContext.run( + { agent: this, connection: undefined, request, email: undefined }, + async () => { + // Your onRequest method runs here with context + return this._tryCatch(() => _onRequest(request)); + } +); +``` + +### Usage Patterns + +```typescript +import { AIChatAgent, getCurrentAgent } from "agents"; + +export class MyAgent extends AIChatAgent { + async customMethod() { + // ✅ Direct access - agent context is automatically available + const { agent } = getCurrentAgent(); + console.log(agent.name); + } + + async anotherMethod() { + // ✅ This works in custom methods too + const { agent, connection, request } = getCurrentAgent(); + return agent.state; + } +} + +// ✅ External functions can also access context +async function externalFunction() { + const { agent } = getCurrentAgent(); + // Agent is available here if called from within agent context +} +``` + +### Key Benefits + +1. **Zero configuration** - Works automatically in all agent methods +2. **Type safety** - Properly typed with generic support +3. **Context propagation** - Flows through async call chains +4. **External function support** - Can be used in utility functions and external libraries + +The function returns `undefined` for all properties when called outside of an agent context, making it safe to use defensively. + +--- + +_**User**_ + +I am frequently getting getCurrentAgent return undefined, are there race conditions or is it possible that the wrapping is being lost when the durable object hibernates + +--- + +_**Assistant**_ + + + +--- + + + +--- + + + +--- + +Read file: undefined + +--- + + + +--- + +Read file: undefined + +--- + + + +--- + + + +--- + + + +--- + +Read file: undefined + +--- + + + +--- + + + +--- + + + +--- + +Read file: undefined + +--- + + + +--- + +Read file: undefined + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + +Read file: undefined + +--- + + + +--- + +Read file: undefined + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + +Read file: undefined + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + +Read file: undefined + +--- + + + +--- + + + +--- + + + +--- + +Read file: undefined + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + +Read file: undefined + +--- + + + +--- + +Read file: undefined + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + +Read file: undefined + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + + + +--- + +## Summary: `getCurrentAgent()` Issues and Solutions + +You're absolutely right to be concerned about `getCurrentAgent()` returning `undefined`. I found several issues in the codebase that can cause this, and I've implemented fixes for them. + +## Issues Identified and Fixed + +### 1. **OAuth Callback Context Loss** ✅ FIXED +**Problem**: The `_processOAuthCallback` method wasn't establishing agent context, causing all subsequent operations in the OAuth flow to lose access to `getCurrentAgent()`. + +**Fix**: Modified `_processOAuthCallback` to run within agent context: +```typescript +private async _processOAuthCallback(request: Request): Promise { + // Ensure agent context is available for the OAuth callback processing + return agentContext.run( + { agent: this, connection: undefined, request, email: undefined }, + async () => { + // ... rest of the method + } + ); +} +``` + +### 2. **Async Context Loss in External Operations** ✅ DOCUMENTED +**Problem**: `AsyncLocalStorage` doesn't automatically propagate context across: +- `setTimeout`/`setInterval` callbacks +- Promise continuations outside original context +- Background tasks or scheduled jobs + +**Solution**: Added comprehensive documentation with best practices for handling these scenarios. + +### 3. **Poor Error Messages in MCP Transport** ✅ IMPROVED +**Problem**: MCP transport methods had generic error messages that didn't help diagnose context issues. + +**Fix**: Enhanced error messages throughout the MCP transport to provide clear guidance: +```typescript +const context = getCurrentAgent(); +if (!context.agent) { + throw new Error( + "McpAgent was not found in Transport constructor. " + + "This typically indicates the transport is being created outside of agent context. " + + "Make sure to call this from within an agent method or establish context manually." + ); +} +``` + +## Key Takeaways + +1. **Always check for context availability** - Don't assume `getCurrentAgent()` will return valid data +2. **OAuth callbacks need explicit context** - The framework now handles this automatically +3. **Async operations can lose context** - Preserve context explicitly when needed +4. **Better error messages help debugging** - Enhanced error reporting for context issues + +## Immediate Recommendations + +1. **Update your agent code** to handle context defensively: + ```typescript + const context = getCurrentAgent(); + if (!context.agent) { + console.warn("Agent context not available"); + return null; + } + ``` + +2. **Check your async operations** - If you're using `setTimeout`, background tasks, or external libraries, ensure context is preserved. + +3. **Monitor OAuth flows** - The fix should resolve OAuth callback context issues, but monitor for any remaining problems. + +The fixes I've implemented should resolve the most common causes of `getCurrentAgent()` returning `undefined`. The enhanced error messages will also make it much easier to diagnose any remaining issues. + +--- + diff --git a/docs/context-management.md b/docs/context-management.md index e9f65ad1..4612e321 100644 --- a/docs/context-management.md +++ b/docs/context-management.md @@ -115,6 +115,91 @@ export class MyAgent extends AIChatAgent { } ``` +## Troubleshooting Context Issues + +### Common Causes of `getCurrentAgent()` Returning `undefined` + +1. **Async Context Loss**: `AsyncLocalStorage` context doesn't automatically propagate across: + - `setTimeout` or `setInterval` callbacks + - Promise continuations outside the original context + - Background tasks or scheduled jobs + - Event handlers that aren't wrapped with context + +2. **OAuth Callback Processing**: Fixed in recent versions, but ensure your agent handles OAuth callbacks properly. + +3. **Custom Method Wrapping Issues**: The framework automatically wraps custom methods, but if you're calling methods directly without going through the agent instance, context may be lost. + +### Best Practices for Context Management + +#### Always Check for Context Availability + +```typescript +import { getCurrentAgent } from "agents"; + +async function externalFunction() { + const context = getCurrentAgent(); + + if (!context.agent) { + console.warn("No agent context available - this function should be called from within an agent method"); + return null; + } + + // Safe to use context.agent, context.connection, context.request + return context.agent.state; +} +``` + +#### Preserve Context in Async Operations + +```typescript +export class MyAgent extends AIChatAgent { + async customMethod() { + // ✅ Good: Context is preserved in Promise continuations + return this.processAsync().then(result => { + const { agent } = getCurrentAgent(); + return { agent: agent?.name, result }; + }); + } + + async problematicMethod() { + // ❌ Bad: Context is lost in setTimeout + setTimeout(() => { + const { agent } = getCurrentAgent(); // Will be undefined + console.log(agent?.name); + }, 1000); + } + + async betterAsyncMethod() { + // ✅ Good: Preserve context explicitly + const context = getCurrentAgent(); + + setTimeout(() => { + // Manually restore context if needed + console.log("Agent name:", context.agent?.name); + }, 1000); + } +} +``` + +#### Handle Context in External Libraries + +```typescript +// In your external library/utility +export async function processWithContext( + operation: () => Promise +): Promise { + const context = getCurrentAgent(); + + if (!context.agent) { + // Fallback behavior when no context is available + return operation(); + } + + // Execute with context available for debugging/logging + return operation(); +} +``` + ## API Reference The agents package exports one main function for context management: @@ -129,7 +214,8 @@ Gets the current agent from any context where it's available. { agent: T | undefined, connection: Connection | undefined, - request: Request | undefined + request: Request | undefined, + email: AgentEmail | undefined } ``` @@ -140,9 +226,30 @@ import { getCurrentAgent } from "agents"; export class MyAgent extends AIChatAgent { async customMethod() { - const { agent, connection, request } = getCurrentAgent(); + const { agent, connection, request, email } = getCurrentAgent(); + + if (!agent) { + throw new Error("This method must be called within agent context"); + } + // agent is properly typed as MyAgent // connection and request available if called from a request handler + // email available if called from an email handler } } ``` + +**Defensive Usage:** + +```typescript +async function safeExternalFunction() { + const context = getCurrentAgent(); + + if (!context.agent) { + console.error("Agent context not available"); + return null; + } + + return context.agent.state; +} +``` diff --git a/examples/a2a/vite.config.ts b/examples/a2a/vite.config.ts index b7b4b44f..26cb11bb 100644 --- a/examples/a2a/vite.config.ts +++ b/examples/a2a/vite.config.ts @@ -8,7 +8,8 @@ export default defineConfig({ alias: { // a2a-js/sdk has a dependency on express, which vite tries to bundle. This alias prevents that. express: path.resolve(__dirname, "./src/express-alias.js") - } + }, + dedupe: ["agents"] }, plugins: [react(), cloudflare()] }); diff --git a/examples/codemode/vite.config.ts b/examples/codemode/vite.config.ts index 6f252d5c..48a99387 100644 --- a/examples/codemode/vite.config.ts +++ b/examples/codemode/vite.config.ts @@ -3,6 +3,9 @@ import react from "@vitejs/plugin-react"; import { defineConfig } from "vite"; export default defineConfig({ + resolve: { + dedupe: ["agents"] + }, plugins: [react(), cloudflare()], define: { __filename: "'index.ts'" diff --git a/examples/cross-domain/vite.config.ts b/examples/cross-domain/vite.config.ts index 8d23f510..6fd02791 100644 --- a/examples/cross-domain/vite.config.ts +++ b/examples/cross-domain/vite.config.ts @@ -2,5 +2,8 @@ import react from "@vitejs/plugin-react"; import { defineConfig } from "vite"; export default defineConfig({ + resolve: { + dedupe: ["agents"] + }, plugins: [react()] }); diff --git a/examples/mcp-client/vite.config.ts b/examples/mcp-client/vite.config.ts index 799142d4..ad80633a 100644 --- a/examples/mcp-client/vite.config.ts +++ b/examples/mcp-client/vite.config.ts @@ -3,6 +3,9 @@ import react from "@vitejs/plugin-react"; import { defineConfig } from "vite"; export default defineConfig({ + resolve: { + dedupe: ["agents"] + }, plugins: [ react(), cloudflare({ diff --git a/examples/mcp-elicitation-demo/vite.config.ts b/examples/mcp-elicitation-demo/vite.config.ts index 08c0388e..d6546116 100644 --- a/examples/mcp-elicitation-demo/vite.config.ts +++ b/examples/mcp-elicitation-demo/vite.config.ts @@ -3,6 +3,9 @@ import react from "@vitejs/plugin-react"; import { defineConfig } from "vite"; export default defineConfig({ + resolve: { + dedupe: ["agents"] + }, plugins: [ react(), cloudflare({ diff --git a/examples/mcp/vite.config.ts b/examples/mcp/vite.config.ts index a606eafd..af06331c 100644 --- a/examples/mcp/vite.config.ts +++ b/examples/mcp/vite.config.ts @@ -3,6 +3,9 @@ import react from "@vitejs/plugin-react"; import { defineConfig } from "vite"; export default defineConfig({ + resolve: { + dedupe: ["agents"] + }, plugins: [react(), cloudflare()], server: { port: 5174 diff --git a/examples/playground/vite.config.ts b/examples/playground/vite.config.ts index 40b7683e..3605fc07 100644 --- a/examples/playground/vite.config.ts +++ b/examples/playground/vite.config.ts @@ -4,6 +4,9 @@ import chalk from "chalk"; import { defineConfig } from "vite"; export default defineConfig({ + resolve: { + dedupe: ["agents"] + }, plugins: [ react(), cloudflare(), diff --git a/examples/tictactoe/vite.config.ts b/examples/tictactoe/vite.config.ts index 32921644..9c163c6b 100644 --- a/examples/tictactoe/vite.config.ts +++ b/examples/tictactoe/vite.config.ts @@ -3,5 +3,8 @@ import react from "@vitejs/plugin-react"; import { defineConfig } from "vite"; export default defineConfig({ + resolve: { + dedupe: ["agents"] + }, plugins: [react(), cloudflare()] }); diff --git a/guides/anthropic-patterns/vite.config.ts b/guides/anthropic-patterns/vite.config.ts index 828da434..37699ac1 100644 --- a/guides/anthropic-patterns/vite.config.ts +++ b/guides/anthropic-patterns/vite.config.ts @@ -3,6 +3,9 @@ import chalk from "chalk"; import { defineConfig } from "vite"; export default defineConfig({ + resolve: { + dedupe: ["agents"] + }, plugins: [ cloudflare(), { diff --git a/guides/human-in-the-loop/vite.config.ts b/guides/human-in-the-loop/vite.config.ts index 40b7683e..3605fc07 100644 --- a/guides/human-in-the-loop/vite.config.ts +++ b/guides/human-in-the-loop/vite.config.ts @@ -4,6 +4,9 @@ import chalk from "chalk"; import { defineConfig } from "vite"; export default defineConfig({ + resolve: { + dedupe: ["agents"] + }, plugins: [ react(), cloudflare(), diff --git a/openai-sdk/basic/vite.config.ts b/openai-sdk/basic/vite.config.ts index 89482824..1bc96b61 100644 --- a/openai-sdk/basic/vite.config.ts +++ b/openai-sdk/basic/vite.config.ts @@ -4,5 +4,8 @@ import { defineConfig } from "vite"; import devtools from "vite-plugin-devtools-json"; export default defineConfig({ + resolve: { + dedupe: ["agents"] + }, plugins: [devtools(), cloudflare(), react()] }); diff --git a/openai-sdk/call-my-agent/vite.config.ts b/openai-sdk/call-my-agent/vite.config.ts index 32921644..9c163c6b 100644 --- a/openai-sdk/call-my-agent/vite.config.ts +++ b/openai-sdk/call-my-agent/vite.config.ts @@ -3,5 +3,8 @@ import react from "@vitejs/plugin-react"; import { defineConfig } from "vite"; export default defineConfig({ + resolve: { + dedupe: ["agents"] + }, plugins: [react(), cloudflare()] }); diff --git a/openai-sdk/handoffs/vite.config.ts b/openai-sdk/handoffs/vite.config.ts index 89482824..1bc96b61 100644 --- a/openai-sdk/handoffs/vite.config.ts +++ b/openai-sdk/handoffs/vite.config.ts @@ -4,5 +4,8 @@ import { defineConfig } from "vite"; import devtools from "vite-plugin-devtools-json"; export default defineConfig({ + resolve: { + dedupe: ["agents"] + }, plugins: [devtools(), cloudflare(), react()] }); diff --git a/openai-sdk/human-in-the-loop/vite.config.ts b/openai-sdk/human-in-the-loop/vite.config.ts index 89482824..1bc96b61 100644 --- a/openai-sdk/human-in-the-loop/vite.config.ts +++ b/openai-sdk/human-in-the-loop/vite.config.ts @@ -4,5 +4,8 @@ import { defineConfig } from "vite"; import devtools from "vite-plugin-devtools-json"; export default defineConfig({ + resolve: { + dedupe: ["agents"] + }, plugins: [devtools(), cloudflare(), react()] }); diff --git a/openai-sdk/llm-as-a-judge/vite.config.ts b/openai-sdk/llm-as-a-judge/vite.config.ts index 89482824..1bc96b61 100644 --- a/openai-sdk/llm-as-a-judge/vite.config.ts +++ b/openai-sdk/llm-as-a-judge/vite.config.ts @@ -4,5 +4,8 @@ import { defineConfig } from "vite"; import devtools from "vite-plugin-devtools-json"; export default defineConfig({ + resolve: { + dedupe: ["agents"] + }, plugins: [devtools(), cloudflare(), react()] }); diff --git a/packages/agents/evals/vite.config.ts b/packages/agents/evals/vite.config.ts index 868d8ba3..2cbfb2f6 100644 --- a/packages/agents/evals/vite.config.ts +++ b/packages/agents/evals/vite.config.ts @@ -1,6 +1,9 @@ import { defineConfig } from "vite"; export default defineConfig({ + resolve: { + dedupe: ["agents"] + }, test: { setupFiles: ["dotenv/config"] } diff --git a/packages/agents/src/index.ts b/packages/agents/src/index.ts index 89bee0c0..020ca5a0 100644 --- a/packages/agents/src/index.ts +++ b/packages/agents/src/index.ts @@ -1600,24 +1600,30 @@ export class Agent< * Process an OAuth callback request (assumes state is already restored) */ private async _processOAuthCallback(request: Request): Promise { - const result = await this.mcp.handleCallbackRequest(request); - this.broadcastMcpServers(); + // Ensure agent context is available for the OAuth callback processing + return agentContext.run( + { agent: this, connection: undefined, request, email: undefined }, + async () => { + const result = await this.mcp.handleCallbackRequest(request); + this.broadcastMcpServers(); - if (result.authSuccess) { - // Start background connection if auth was successful - this.mcp - .establishConnection(result.serverId) - .catch((error) => { - console.error("Background connection failed:", error); - }) - .finally(() => { - // Broadcast after background connection resolves (success/failure) - this.broadcastMcpServers(); - }); - } + if (result.authSuccess) { + // Start background connection if auth was successful + this.mcp + .establishConnection(result.serverId) + .catch((error) => { + console.error("Background connection failed:", error); + }) + .finally(() => { + // Broadcast after background connection resolves (success/failure) + this.broadcastMcpServers(); + }); + } - // Handle OAuth callback response using MCPClientManager configuration - return this.handleOAuthCallbackResponse(result, request); + // Handle OAuth callback response using MCPClientManager configuration + return this.handleOAuthCallbackResponse(result, request); + } + ); } private async _connectToMcpServerInternal( diff --git a/packages/agents/src/mcp/transport.ts b/packages/agents/src/mcp/transport.ts index 9dade9f4..45e88e07 100644 --- a/packages/agents/src/mcp/transport.ts +++ b/packages/agents/src/mcp/transport.ts @@ -119,13 +119,18 @@ export class StreamableHTTPServerTransport implements Transport { onmessage?: (message: JSONRPCMessage, extra?: MessageExtraInfo) => void; constructor(options: StreamableHTTPServerTransportOptions) { - const { agent } = getCurrentAgent(); - if (!agent) - throw new Error("McpAgent was not found in Transport constructor"); + const context = getCurrentAgent(); + if (!context.agent) { + throw new Error( + "McpAgent was not found in Transport constructor. " + + "This typically indicates the transport is being created outside of agent context. " + + "Make sure to call this from within an agent method or establish context manually." + ); + } // Initialization is handled in `McpAgent.serve()` and agents are addressed by sessionId, // so we'll always have this available. - this.sessionId = agent.getSessionId(); + this.sessionId = context.agent.getSessionId(); this._eventStore = options.eventStore; } @@ -145,9 +150,14 @@ export class StreamableHTTPServerTransport implements Transport { */ async handleGetRequest(req: Request): Promise { // Get the WS connection so we can tag it as the standalone stream - const { connection } = getCurrentAgent(); - if (!connection) - throw new Error("Connection was not found in handleGetRequest"); + const context = getCurrentAgent(); + if (!context.connection) { + throw new Error( + "Connection not found in handleGetRequest. " + + "This typically indicates the method is being called outside of a WebSocket connection context. " + + "Make sure this is called from within an agent message handler." + ); + } // Handle resumability: check for Last-Event-ID header if (this._eventStore) { @@ -172,9 +182,14 @@ export class StreamableHTTPServerTransport implements Transport { return; } - const { connection } = getCurrentAgent(); - if (!connection) - throw new Error("Connection was not available in replayEvents"); + const context = getCurrentAgent(); + if (!context.connection) { + throw new Error( + "Connection not available in replayEvents. " + + "This indicates the method is being called outside of agent context. " + + "Make sure replayEvents is called from within an agent method." + ); + } try { await this._eventStore?.replayEventsAfter(lastEventId, { @@ -251,9 +266,13 @@ export class StreamableHTTPServerTransport implements Transport { this.onmessage?.(message, { authInfo, requestInfo }); } } else if (hasRequests) { - const { connection } = getCurrentAgent(); - if (!connection) - throw new Error("Connection was not found in handlePostRequest"); + const context = getCurrentAgent(); + if (!context.connection) { + throw new Error( + "Connection not found in handlePostRequest. " + + "This indicates the method is being called outside of agent context." + ); + } // We need to track by request ID to maintain the connection const requestIds = messages @@ -275,10 +294,16 @@ export class StreamableHTTPServerTransport implements Transport { async close(): Promise { // Close all SSE connections - const { agent } = getCurrentAgent(); - if (!agent) throw new Error("Agent was not found in close"); + const context = getCurrentAgent(); + if (!context.agent) { + throw new Error( + "Agent not found in close. " + + "This indicates the method is being called outside of agent context. " + + "Make sure close is called from within an agent method." + ); + } - for (const conn of agent.getConnections()) { + for (const conn of context.agent.getConnections()) { conn.close(1000, "Session closed"); } this.onclose?.(); @@ -288,8 +313,14 @@ export class StreamableHTTPServerTransport implements Transport { message: JSONRPCMessage, options?: { relatedRequestId?: RequestId } ): Promise { - const { agent } = getCurrentAgent(); - if (!agent) throw new Error("Agent was not found in send"); + const context = getCurrentAgent(); + if (!context.agent) { + throw new Error( + "Agent not found in send. " + + "This indicates the method is being called outside of agent context. " + + "Make sure send is called from within an agent method." + ); + } let requestId = options?.relatedRequestId; if (isJSONRPCResponse(message) || isJSONRPCError(message)) { @@ -309,7 +340,7 @@ export class StreamableHTTPServerTransport implements Transport { } let standaloneConnection: Connection | undefined; - for (const conn of agent.getConnections<{ _standaloneSse?: boolean }>()) { + for (const conn of context.agent.getConnections<{ _standaloneSse?: boolean }>()) { if (conn.state?._standaloneSse) standaloneConnection = conn; } @@ -335,7 +366,7 @@ export class StreamableHTTPServerTransport implements Transport { // Get the response for this request const connection = Array.from( - agent.getConnections<{ requestIds?: number[] }>() + context.agent.getConnections<{ requestIds?: number[] }>() ).find((conn) => conn.state?.requestIds?.includes(requestId as number)); if (!connection) { throw new Error(