branch:
server.ts
4212 bytesRaw
import { Agent, type RunResult, RunState, run, tool } from "@openai/agents";
import { Agent as CFAgent, callable, routeAgentRequest } from "agents";
import { z } from "zod";
const getWeatherTool = tool({
description: "Get the weather for a given city",
execute: async ({ location }) => {
console.log(`[getWeatherTool] Executing weather lookup for: ${location}`);
const result = `The weather in ${location} is sunny`;
console.log(`[getWeatherTool] Returning result: ${result}`);
return result;
},
name: "get_weather",
needsApproval: async (_context, { location }) => {
console.log(
`[getWeatherTool] Checking if approval needed for location: ${location}`
);
// forces approval to look up the weather in San Francisco
const needsApproval = location === "San Francisco";
console.log(`[getWeatherTool] Approval needed: ${needsApproval}`);
return needsApproval;
},
parameters: z.object({
location: z.string()
})
});
export type AgentState = {
serialisedRunState: string | null;
};
export class MyAgent extends CFAgent<Env, AgentState> {
initialState: AgentState = {
serialisedRunState: null
};
// oxlint-disable-next-line @typescript-eslint/no-explicit-any -- OpenAI SDK type compatibility
result: RunResult<unknown, Agent<unknown, any>> | null = null;
agent = new Agent({
instructions: "You are a helpful assistant",
name: "Assistant",
tools: [getWeatherTool]
});
async onStart() {
console.log("[MyAgent] onStart called");
console.log("[MyAgent] Current state:", this.state);
if (this.state.serialisedRunState) {
console.log("[MyAgent] Restoring from serialised state");
const runState = await RunState.fromString(
this.agent,
this.state.serialisedRunState
);
console.log("[MyAgent] RunState restored:", runState);
this.result = await run(this.agent, runState);
console.log("[MyAgent] Agent run completed with result:", this.result);
} else {
console.log("[MyAgent] No serialised state found, starting fresh");
}
}
@callable()
async ask(question: string) {
console.log(`[MyAgent] ask method called with question: "${question}"`);
console.log("[MyAgent] Starting agent run...");
this.result = await run(this.agent, question);
console.log("[MyAgent] Agent run completed");
console.log("[MyAgent] Result:", this.result);
console.log("[MyAgent] Result state:", this.result.state);
const serialisedState = JSON.stringify(this.result.state, null, 2);
console.log("[MyAgent] Serialising state:", serialisedState);
this.setState({
serialisedRunState: serialisedState
});
console.log("[MyAgent] State updated, serialisedRunState saved");
}
@callable()
async proceed(id: string, approval: boolean) {
console.log(
`[MyAgent] proceed method called with id: ${id}, approval: ${approval}`
);
const runState = await RunState.fromString(
this.agent,
this.state.serialisedRunState!
);
const interruption = this.result?.interruptions?.find(
(i) => "callId" in i.rawItem && i.rawItem.callId === id
);
if (interruption) {
if (approval) {
runState.approve(interruption);
} else {
runState.reject(interruption);
}
this.result = await run(this.agent, runState);
const serialisedState = JSON.stringify(this.result.state, null, 2);
console.log("[MyAgent] Serialising state:", serialisedState);
this.setState({
serialisedRunState: serialisedState
});
} else {
throw new Error(`[MyAgent] No interruption found with id: ${id}`);
}
}
}
export default {
async fetch(request: Request, env: Env, _ctx: ExecutionContext) {
console.log(`[Server] Handling request: ${request.method} ${request.url}`);
const response = await routeAgentRequest(request, env);
if (response) {
console.log(
`[Server] Agent request routed successfully, status: ${response.status}`
);
return response;
}
console.log("[Server] No agent route matched, returning 404");
return new Response("Not found", { status: 404 });
}
};