| 86 | |
| 87 | // Agent executor that calls Workers AI |
| 88 | class AIAgentExecutor implements AgentExecutor { |
| 89 | constructor(private getEnv: () => Env) {} |
| 90 | |
| 91 | async execute( |
| 92 | requestContext: RequestContext, |
| 93 | eventBus: ExecutionEventBus |
| 94 | ): Promise<void> { |
| 95 | const { taskId, contextId, userMessage, task } = requestContext; |
| 96 | |
| 97 | // Publish initial task if new |
| 98 | if (!task) { |
| 99 | const initialTask: Task = { |
| 100 | contextId, |
| 101 | history: [userMessage], |
| 102 | id: taskId, |
| 103 | kind: "task", |
| 104 | status: { |
| 105 | state: "submitted", |
| 106 | timestamp: new Date().toISOString() |
| 107 | } |
| 108 | }; |
| 109 | eventBus.publish(initialTask); |
| 110 | } |
| 111 | |
| 112 | // Working status |
| 113 | eventBus.publish({ |
| 114 | contextId, |
| 115 | final: false, |
| 116 | kind: "status-update", |
| 117 | status: { |
| 118 | state: "working", |
| 119 | timestamp: new Date().toISOString() |
| 120 | }, |
| 121 | taskId |
| 122 | } as TaskStatusUpdateEvent); |
| 123 | |
| 124 | // Extract user text |
| 125 | const userText = userMessage.parts |
| 126 | .filter((p) => p.kind === "text") |
| 127 | .map((p) => (p as { kind: "text"; text: string }).text) |
| 128 | .join(""); |
| 129 | |
| 130 | // Call Workers AI |
| 131 | const workersai = createWorkersAI({ binding: this.getEnv().AI }); |
| 132 | const result = await generateText({ |
| 133 | model: workersai("@cf/moonshotai/kimi-k2.6"), |
| 134 | system: |
| 135 | "You are a helpful AI assistant. Keep responses concise and clear.", |
| 136 | messages: [{ role: "user", content: userText }] |
| 137 | }); |
| 138 | |
| 139 | // Publish agent response |
| 140 | const responseMessage: Message = { |
| 141 | contextId, |
| 142 | kind: "message", |
| 143 | messageId: crypto.randomUUID(), |
| 144 | parts: [{ kind: "text", text: result.text }], |
| 145 | role: "agent", |
nothing calls this directly
no outgoing calls
no test coverage detected