diff --git a/packages/opencode/test/fixture/skills/agents-sdk/SKILL.md b/packages/opencode/test/fixture/skills/agents-sdk/SKILL.md index 3da4d32f0..d01d3013f 100644 --- a/packages/opencode/test/fixture/skills/agents-sdk/SKILL.md +++ b/packages/opencode/test/fixture/skills/agents-sdk/SKILL.md @@ -11,21 +11,21 @@ description: Build AI agents on Cloudflare Workers using the Agents SDK. Load wh Fetch current docs from `https://github.com/cloudflare/agents/tree/main/docs` before implementing. -| Topic | Doc | Use for | -|-------|-----|---------| -| Getting started | `docs/getting-started.md` | First agent, project setup | -| State | `docs/state.md` | `setState`, `validateStateChange`, persistence | -| Routing | `docs/routing.md` | URL patterns, `routeAgentRequest`, `basePath` | -| Callable methods | `docs/callable-methods.md` | `@callable`, RPC, streaming, timeouts | -| Scheduling | `docs/scheduling.md` | `schedule()`, `scheduleEvery()`, cron | -| Workflows | `docs/workflows.md` | `AgentWorkflow`, durable multi-step tasks | -| HTTP/WebSockets | `docs/http-websockets.md` | Lifecycle hooks, hibernation | -| Email | `docs/email.md` | Email routing, secure reply resolver | -| MCP client | `docs/mcp-client.md` | Connecting to MCP servers | -| MCP server | `docs/mcp-servers.md` | Building MCP servers with `McpAgent` | -| Client SDK | `docs/client-sdk.md` | `useAgent`, `useAgentChat`, React hooks | -| Human-in-the-loop | `docs/human-in-the-loop.md` | Approval flows, pausing workflows | -| Resumable streaming | `docs/resumable-streaming.md` | Stream recovery on disconnect | +| Topic | Doc | Use for | +| ------------------- | ----------------------------- | ---------------------------------------------- | +| Getting started | `docs/getting-started.md` | First agent, project setup | +| State | `docs/state.md` | `setState`, `validateStateChange`, persistence | +| Routing | `docs/routing.md` | URL patterns, `routeAgentRequest`, `basePath` | +| Callable methods | `docs/callable-methods.md` | `@callable`, RPC, streaming, timeouts | +| Scheduling | `docs/scheduling.md` | `schedule()`, `scheduleEvery()`, cron | +| Workflows | `docs/workflows.md` | `AgentWorkflow`, durable multi-step tasks | +| HTTP/WebSockets | `docs/http-websockets.md` | Lifecycle hooks, hibernation | +| Email | `docs/email.md` | Email routing, secure reply resolver | +| MCP client | `docs/mcp-client.md` | Connecting to MCP servers | +| MCP server | `docs/mcp-servers.md` | Building MCP servers with `McpAgent` | +| Client SDK | `docs/client-sdk.md` | `useAgent`, `useAgentChat`, React hooks | +| Human-in-the-loop | `docs/human-in-the-loop.md` | Approval flows, pausing workflows | +| Resumable streaming | `docs/resumable-streaming.md` | Stream recovery on disconnect | Cloudflare docs: https://developers.cloudflare.com/agents/ @@ -49,6 +49,7 @@ npm ls agents # Should show agents package ``` If not installed: + ```bash npm install agents ``` @@ -58,89 +59,85 @@ npm install agents ```jsonc { "durable_objects": { - "bindings": [{ "name": "MyAgent", "class_name": "MyAgent" }] + "bindings": [{ "name": "MyAgent", "class_name": "MyAgent" }], }, - "migrations": [{ "tag": "v1", "new_sqlite_classes": ["MyAgent"] }] + "migrations": [{ "tag": "v1", "new_sqlite_classes": ["MyAgent"] }], } ``` ## Agent Class ```typescript -import { Agent, routeAgentRequest, callable } from "agents"; +import { Agent, routeAgentRequest, callable } from "agents" -type State = { count: number }; +type State = { count: number } export class Counter extends Agent { - initialState = { count: 0 }; + initialState = { count: 0 } // Validation hook - runs before state persists (sync, throwing rejects the update) validateStateChange(nextState: State, source: Connection | "server") { - if (nextState.count < 0) throw new Error("Count cannot be negative"); + if (nextState.count < 0) throw new Error("Count cannot be negative") } // Notification hook - runs after state persists (async, non-blocking) onStateUpdate(state: State, source: Connection | "server") { - console.log("State updated:", state); + console.log("State updated:", state) } @callable() increment() { - this.setState({ count: this.state.count + 1 }); - return this.state.count; + this.setState({ count: this.state.count + 1 }) + return this.state.count } } export default { - fetch: (req, env) => routeAgentRequest(req, env) ?? new Response("Not found", { status: 404 }) -}; + fetch: (req, env) => routeAgentRequest(req, env) ?? new Response("Not found", { status: 404 }), +} ``` ## Routing Requests route to `/agents/{agent-name}/{instance-name}`: -| Class | URL | -|-------|-----| -| `Counter` | `/agents/counter/user-123` | -| `ChatRoom` | `/agents/chat-room/lobby` | +| Class | URL | +| ---------- | -------------------------- | +| `Counter` | `/agents/counter/user-123` | +| `ChatRoom` | `/agents/chat-room/lobby` | Client: `useAgent({ agent: "Counter", name: "user-123" })` ## Core APIs -| Task | API | -|------|-----| -| Read state | `this.state.count` | -| Write state | `this.setState({ count: 1 })` | -| SQL query | `` this.sql`SELECT * FROM users WHERE id = ${id}` `` | -| Schedule (delay) | `await this.schedule(60, "task", payload)` | -| Schedule (cron) | `await this.schedule("0 * * * *", "task", payload)` | -| Schedule (interval) | `await this.scheduleEvery(30, "poll")` | -| RPC method | `@callable() myMethod() { ... }` | -| Streaming RPC | `@callable({ streaming: true }) stream(res) { ... }` | -| Start workflow | `await this.runWorkflow("ProcessingWorkflow", params)` | +| Task | API | +| ------------------- | ------------------------------------------------------ | +| Read state | `this.state.count` | +| Write state | `this.setState({ count: 1 })` | +| SQL query | `` this.sql`SELECT * FROM users WHERE id = ${id}` `` | +| Schedule (delay) | `await this.schedule(60, "task", payload)` | +| Schedule (cron) | `await this.schedule("0 * * * *", "task", payload)` | +| Schedule (interval) | `await this.scheduleEvery(30, "poll")` | +| RPC method | `@callable() myMethod() { ... }` | +| Streaming RPC | `@callable({ streaming: true }) stream(res) { ... }` | +| Start workflow | `await this.runWorkflow("ProcessingWorkflow", params)` | ## React Client ```tsx -import { useAgent } from "agents/react"; +import { useAgent } from "agents/react" function App() { - const [state, setLocalState] = useState({ count: 0 }); + const [state, setLocalState] = useState({ count: 0 }) const agent = useAgent({ agent: "Counter", name: "my-instance", onStateUpdate: (newState) => setLocalState(newState), - onIdentity: (name, agentType) => console.log(`Connected to ${name}`) - }); + onIdentity: (name, agentType) => console.log(`Connected to ${name}`), + }) - return ( - - ); + return } ``` diff --git a/packages/opencode/test/fixture/skills/agents-sdk/references/callable.md b/packages/opencode/test/fixture/skills/agents-sdk/references/callable.md index 241d30cf9..164150c98 100644 --- a/packages/opencode/test/fixture/skills/agents-sdk/references/callable.md +++ b/packages/opencode/test/fixture/skills/agents-sdk/references/callable.md @@ -7,18 +7,18 @@ Fetch `docs/callable-methods.md` from `https://github.com/cloudflare/agents/tree `@callable()` exposes agent methods to clients via WebSocket RPC. ```typescript -import { Agent, callable } from "agents"; +import { Agent, callable } from "agents" export class MyAgent extends Agent { @callable() async greet(name: string): Promise { - return `Hello, ${name}!`; + return `Hello, ${name}!` } @callable() async processData(data: unknown): Promise { // Long-running work - return result; + return result } } ``` @@ -27,26 +27,26 @@ export class MyAgent extends Agent { ```typescript // Basic call -const greeting = await agent.call("greet", ["World"]); +const greeting = await agent.call("greet", ["World"]) // With timeout const result = await agent.call("processData", [data], { - timeout: 5000 // 5 second timeout -}); + timeout: 5000, // 5 second timeout +}) ``` ## Streaming Responses ```typescript -import { Agent, callable, StreamingResponse } from "agents"; +import { Agent, callable, StreamingResponse } from "agents" export class MyAgent extends Agent { @callable({ streaming: true }) async streamResults(stream: StreamingResponse, query: string) { for await (const item of fetchResults(query)) { - stream.send(JSON.stringify(item)); + stream.send(JSON.stringify(item)) } - stream.close(); + stream.close() } @callable({ streaming: true }) @@ -54,10 +54,10 @@ export class MyAgent extends Agent { try { // ... work } catch (error) { - stream.error(error.message); // Signal error to client - return; + stream.error(error.message) // Signal error to client + return } - stream.close(); + stream.close() } } ``` @@ -69,24 +69,24 @@ await agent.call("streamResults", ["search term"], { stream: { onChunk: (data) => console.log("Chunk:", data), onDone: () => console.log("Complete"), - onError: (error) => console.error("Error:", error) - } -}); + onError: (error) => console.error("Error:", error), + }, +}) ``` ## Introspection ```typescript // Get list of callable methods on an agent -const methods = await agent.call("getCallableMethods", []); +const methods = await agent.call("getCallableMethods", []) // Returns: ["greet", "processData", "streamResults", ...] ``` ## When to Use -| Scenario | Use | -|----------|-----| -| Browser/mobile calling agent | `@callable()` | -| External service calling agent | `@callable()` | -| Worker calling agent (same codebase) | DO RPC directly | -| Agent calling another agent | `getAgentByName()` + DO RPC | +| Scenario | Use | +| ------------------------------------ | --------------------------- | +| Browser/mobile calling agent | `@callable()` | +| External service calling agent | `@callable()` | +| Worker calling agent (same codebase) | DO RPC directly | +| Agent calling another agent | `getAgentByName()` + DO RPC | diff --git a/packages/opencode/test/fixture/skills/cloudflare/SKILL.md b/packages/opencode/test/fixture/skills/cloudflare/SKILL.md index 9fe05d014..3512838ec 100644 --- a/packages/opencode/test/fixture/skills/cloudflare/SKILL.md +++ b/packages/opencode/test/fixture/skills/cloudflare/SKILL.md @@ -101,101 +101,111 @@ Need IaC? → pulumi/ (Pulumi), terraform/ (Terraform), or api/ (REST API) ## Product Index ### Compute & Runtime -| Product | Reference | -|---------|-----------| -| Workers | `references/workers/` | -| Pages | `references/pages/` | -| Pages Functions | `references/pages-functions/` | -| Durable Objects | `references/durable-objects/` | -| Workflows | `references/workflows/` | -| Containers | `references/containers/` | + +| Product | Reference | +| --------------------- | ----------------------------------- | +| Workers | `references/workers/` | +| Pages | `references/pages/` | +| Pages Functions | `references/pages-functions/` | +| Durable Objects | `references/durable-objects/` | +| Workflows | `references/workflows/` | +| Containers | `references/containers/` | | Workers for Platforms | `references/workers-for-platforms/` | -| Cron Triggers | `references/cron-triggers/` | -| Tail Workers | `references/tail-workers/` | -| Snippets | `references/snippets/` | -| Smart Placement | `references/smart-placement/` | +| Cron Triggers | `references/cron-triggers/` | +| Tail Workers | `references/tail-workers/` | +| Snippets | `references/snippets/` | +| Smart Placement | `references/smart-placement/` | ### Storage & Data -| Product | Reference | -|---------|-----------| -| KV | `references/kv/` | -| D1 | `references/d1/` | -| R2 | `references/r2/` | -| Queues | `references/queues/` | -| Hyperdrive | `references/hyperdrive/` | -| DO Storage | `references/do-storage/` | -| Secrets Store | `references/secrets-store/` | -| Pipelines | `references/pipelines/` | + +| Product | Reference | +| --------------- | ----------------------------- | +| KV | `references/kv/` | +| D1 | `references/d1/` | +| R2 | `references/r2/` | +| Queues | `references/queues/` | +| Hyperdrive | `references/hyperdrive/` | +| DO Storage | `references/do-storage/` | +| Secrets Store | `references/secrets-store/` | +| Pipelines | `references/pipelines/` | | R2 Data Catalog | `references/r2-data-catalog/` | -| R2 SQL | `references/r2-sql/` | +| R2 SQL | `references/r2-sql/` | ### AI & Machine Learning -| Product | Reference | -|---------|-----------| + +| Product | Reference | +| ---------- | ------------------------ | | Workers AI | `references/workers-ai/` | -| Vectorize | `references/vectorize/` | +| Vectorize | `references/vectorize/` | | Agents SDK | `references/agents-sdk/` | | AI Gateway | `references/ai-gateway/` | -| AI Search | `references/ai-search/` | +| AI Search | `references/ai-search/` | ### Networking & Connectivity -| Product | Reference | -|---------|-----------| -| Tunnel | `references/tunnel/` | -| Spectrum | `references/spectrum/` | -| TURN | `references/turn/` | + +| Product | Reference | +| -------------------- | ---------------------------------- | +| Tunnel | `references/tunnel/` | +| Spectrum | `references/spectrum/` | +| TURN | `references/turn/` | | Network Interconnect | `references/network-interconnect/` | -| Argo Smart Routing | `references/argo-smart-routing/` | -| Workers VPC | `references/workers-vpc/` | +| Argo Smart Routing | `references/argo-smart-routing/` | +| Workers VPC | `references/workers-vpc/` | ### Security -| Product | Reference | -|---------|-----------| -| WAF | `references/waf/` | -| DDoS Protection | `references/ddos/` | -| Bot Management | `references/bot-management/` | -| API Shield | `references/api-shield/` | -| Turnstile | `references/turnstile/` | + +| Product | Reference | +| --------------- | ---------------------------- | +| WAF | `references/waf/` | +| DDoS Protection | `references/ddos/` | +| Bot Management | `references/bot-management/` | +| API Shield | `references/api-shield/` | +| Turnstile | `references/turnstile/` | ### Media & Content -| Product | Reference | -|---------|-----------| -| Images | `references/images/` | -| Stream | `references/stream/` | + +| Product | Reference | +| ----------------- | ------------------------------- | +| Images | `references/images/` | +| Stream | `references/stream/` | | Browser Rendering | `references/browser-rendering/` | -| Zaraz | `references/zaraz/` | +| Zaraz | `references/zaraz/` | ### Real-Time Communication -| Product | Reference | -|---------|-----------| -| RealtimeKit | `references/realtimekit/` | + +| Product | Reference | +| ------------ | -------------------------- | +| RealtimeKit | `references/realtimekit/` | | Realtime SFU | `references/realtime-sfu/` | ### Developer Tools -| Product | Reference | -|---------|-----------| -| Wrangler | `references/wrangler/` | -| Miniflare | `references/miniflare/` | -| C3 | `references/c3/` | -| Observability | `references/observability/` | -| Analytics Engine | `references/analytics-engine/` | -| Web Analytics | `references/web-analytics/` | -| Sandbox | `references/sandbox/` | -| Workerd | `references/workerd/` | + +| Product | Reference | +| ------------------ | -------------------------------- | +| Wrangler | `references/wrangler/` | +| Miniflare | `references/miniflare/` | +| C3 | `references/c3/` | +| Observability | `references/observability/` | +| Analytics Engine | `references/analytics-engine/` | +| Web Analytics | `references/web-analytics/` | +| Sandbox | `references/sandbox/` | +| Workerd | `references/workerd/` | | Workers Playground | `references/workers-playground/` | ### Infrastructure as Code -| Product | Reference | -|---------|-----------| -| Pulumi | `references/pulumi/` | + +| Product | Reference | +| --------- | ----------------------- | +| Pulumi | `references/pulumi/` | | Terraform | `references/terraform/` | -| API | `references/api/` | +| API | `references/api/` | ### Other Services -| Product | Reference | -|---------|-----------| + +| Product | Reference | +| ------------- | --------------------------- | | Email Routing | `references/email-routing/` | | Email Workers | `references/email-workers/` | | Static Assets | `references/static-assets/` | -| Bindings | `references/bindings/` | +| Bindings | `references/bindings/` | | Cache Reserve | `references/cache-reserve/` |