mirror of
https://github.com/ksyasuda/dotfiles.git
synced 2026-03-21 06:11:27 -07:00
update skills
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
# Patterns & Use Cases
|
||||
|
||||
## AI Chat w/Tools
|
||||
|
||||
**Server (AIChatAgent):**
|
||||
|
||||
```ts
|
||||
import { AIChatAgent } from "agents";
|
||||
import { openai } from "@ai-sdk/openai";
|
||||
import { tool } from "ai";
|
||||
import { z } from "zod";
|
||||
|
||||
export class ChatAgent extends AIChatAgent<Env> {
|
||||
async onChatMessage(onFinish) {
|
||||
return this.streamText({
|
||||
model: openai("gpt-4"),
|
||||
messages: this.messages, // Auto-managed
|
||||
tools: {
|
||||
getWeather: tool({
|
||||
description: "Get current weather",
|
||||
parameters: z.object({ city: z.string() }),
|
||||
execute: async ({ city }) => `Weather in ${city}: Sunny, 72°F`
|
||||
}),
|
||||
searchDocs: tool({
|
||||
description: "Search documentation",
|
||||
parameters: z.object({ query: z.string() }),
|
||||
execute: async ({ query }) => JSON.stringify(
|
||||
this.sql<{title, content}>`SELECT title, content FROM docs WHERE content LIKE ${'%' + query + '%'}`
|
||||
)
|
||||
})
|
||||
},
|
||||
onFinish,
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Client (React):**
|
||||
|
||||
```tsx
|
||||
import { useAgent } from "agents/react";
|
||||
import { useAgentChat } from "agents/ai-react";
|
||||
|
||||
function ChatUI() {
|
||||
const agent = useAgent({ agent: "ChatAgent" });
|
||||
const { messages, input, handleInputChange, handleSubmit, isLoading } = useAgentChat({ agent });
|
||||
|
||||
return (
|
||||
<div>
|
||||
{messages.map(m => <div key={m.id}>{m.role}: {m.content}</div>)}
|
||||
<form onSubmit={handleSubmit}>
|
||||
<input value={input} onChange={handleInputChange} disabled={isLoading} />
|
||||
<button disabled={isLoading}>Send</button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Human-in-the-Loop (Client Tools)
|
||||
|
||||
Server defines tool, client executes:
|
||||
|
||||
```ts
|
||||
// Server
|
||||
export class ChatAgent extends AIChatAgent<Env> {
|
||||
async onChatMessage(onFinish) {
|
||||
return this.streamText({
|
||||
model: openai("gpt-4"),
|
||||
messages: this.messages,
|
||||
tools: {
|
||||
confirmAction: tool({
|
||||
description: "Ask user to confirm",
|
||||
parameters: z.object({ action: z.string() }),
|
||||
execute: "client", // Client-side execution
|
||||
})
|
||||
},
|
||||
onFinish,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Client
|
||||
const { messages } = useAgentChat({
|
||||
agent,
|
||||
onToolCall: async (toolCall) => {
|
||||
if (toolCall.toolName === "confirmAction") {
|
||||
return { confirmed: window.confirm(`Confirm: ${toolCall.args.action}?`) };
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Task Queue & Scheduled Processing
|
||||
|
||||
```ts
|
||||
export class TaskAgent extends Agent<Env> {
|
||||
onStart() {
|
||||
this.schedule("*/5 * * * *", "processQueue", {}); // Every 5 min
|
||||
this.schedule("0 0 * * *", "dailyCleanup", {}); // Daily
|
||||
}
|
||||
|
||||
async onRequest(req: Request) {
|
||||
await this.queue("processVideo", { videoId: (await req.json()).videoId });
|
||||
return Response.json({ queued: true });
|
||||
}
|
||||
|
||||
async processQueue() {
|
||||
const tasks = await this.dequeue(10);
|
||||
for (const task of tasks) {
|
||||
if (task.name === "processVideo") await this.processVideo(task.data.videoId);
|
||||
}
|
||||
}
|
||||
|
||||
async dailyCleanup() {
|
||||
this.sql`DELETE FROM logs WHERE created_at < ${Date.now() - 86400000}`;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Manual WebSocket Chat
|
||||
|
||||
Custom protocols (non-AI):
|
||||
|
||||
```ts
|
||||
export class ChatAgent extends Agent<Env> {
|
||||
async onConnect(conn: Connection, ctx: ConnectionContext) {
|
||||
conn.accept();
|
||||
conn.setState({userId: ctx.request.headers.get("X-User-ID") || "anon"});
|
||||
conn.send(JSON.stringify({type: "history", messages: this.state.messages}));
|
||||
}
|
||||
|
||||
async onMessage(conn: Connection, msg: WSMessage) {
|
||||
const newMsg = {userId: conn.state.userId, text: JSON.parse(msg as string).text, timestamp: Date.now()};
|
||||
this.setState({messages: [...this.state.messages, newMsg]});
|
||||
this.connections.forEach(c => c.send(JSON.stringify(newMsg)));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Email Processing w/AI
|
||||
|
||||
```ts
|
||||
export class EmailAgent extends Agent<Env> {
|
||||
async onEmail(email: AgentEmail) {
|
||||
const [text, from, subject] = [await email.text(), email.from, email.headers.get("subject") || ""];
|
||||
this.sql`INSERT INTO emails (from_addr, subject, body) VALUES (${from}, ${subject}, ${text})`;
|
||||
|
||||
const { text: summary } = await generateText({
|
||||
model: openai("gpt-4o-mini"), prompt: `Summarize: ${subject}\n\n${text}`
|
||||
});
|
||||
|
||||
this.connections.forEach(c => c.send(JSON.stringify({type: "new_email", from, summary})));
|
||||
if (summary.includes("urgent")) await this.schedule(0, "sendAutoReply", { to: from });
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Real-time Collaboration
|
||||
|
||||
```ts
|
||||
export class GameAgent extends Agent<Env> {
|
||||
initialState = { players: [], gameStarted: false };
|
||||
|
||||
async onConnect(conn: Connection, ctx: ConnectionContext) {
|
||||
conn.accept();
|
||||
const playerId = ctx.request.headers.get("X-Player-ID") || crypto.randomUUID();
|
||||
conn.setState({ playerId });
|
||||
|
||||
const newPlayer = { id: playerId, score: 0 };
|
||||
this.setState({...this.state, players: [...this.state.players, newPlayer]});
|
||||
this.connections.forEach(c => c.send(JSON.stringify({type: "player_joined", player: newPlayer})));
|
||||
}
|
||||
|
||||
async onMessage(conn: Connection, msg: WSMessage) {
|
||||
const m = JSON.parse(msg as string);
|
||||
|
||||
if (m.type === "move") {
|
||||
this.setState({
|
||||
...this.state,
|
||||
players: this.state.players.map(p => p.id === conn.state.playerId ? {...p, score: p.score + m.points} : p)
|
||||
});
|
||||
this.connections.forEach(c => c.send(JSON.stringify({type: "player_moved", playerId: conn.state.playerId})));
|
||||
}
|
||||
|
||||
if (m.type === "start" && this.state.players.length >= 2) {
|
||||
this.setState({...this.state, gameStarted: true});
|
||||
this.connections.forEach(c => c.send(JSON.stringify({type: "game_started"})));
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user