Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244export { Sandbox } from "../../worker/sandbox";
import runtime from "../../worker/index";import { Conversation as BaseConversation } from "./think-worker";import { getAgentByName } from "agents";import { PersonalAgent as BasePersonalAgent } from "./think-worker";import { Conversation as RuntimeConversation } from "../../worker/conversation";import { MockLanguageModelV3 } from "ai/test";import { tool, type UIMessage } from "ai";import { z } from "zod";import type { Env } from "../../worker/personal-agent";
export class PersonalAgent extends BasePersonalAgent { fixturePreviousModel() { this .sql`UPDATE flarebot_model_settings SET configuration = ${JSON.stringify({ provider: "openrouter", model: "openai/gpt-5-mini", })} WHERE singleton = 1`; this.fixtureEnableOpenRouter(); }
async seedChat(id: string, count: number) { const conversation = await this.subAgent(RuntimeConversation, id); await (conversation as unknown as Conversation).seedHistory(count); }}
const rich = `## Research result\n\nThis is **clear** and *readable* with \`inline code\`.\n\n- First item\n- Second item\n\n> Quoted evidence\n\n\`\`\`javascript\nconst answer = "<script>window.chatXss = true</script>";\nconsole.log(answer);\n\`\`\`\n\n| Topic | Result |\n| --- | --- |\n| Native | Working |\n\n[Documentation](https://developers.cloudflare.com/agents/)\n\n<script>window.chatXss = true</script>\n\n[unsafe](javascript:alert(1))  [data](data:text/html,bad) [relative](//evil.invalid/)\n`;type Chunk = Awaited< ReturnType<MockLanguageModelV3["doStream"]> >["stream"] extends ReadableStream<infer C> ? C : never;export class Conversation extends BaseConversation { protected createModel() { return new MockLanguageModelV3({ doStream: async ({ prompt, abortSignal }) => { const user = prompt.findLast( (message) => message.role === "user" && message.content.some( (part) => part.type === "text" && part.text.startsWith("chat:"), ), ); const text = user?.role === "user" ? user.content .filter((part) => part.type === "text") .map((part) => part.text) .join("") .slice(5) : "default"; const continuing = prompt.some( (message) => message.role === "user" && message.content.some( (part) => part.type === "text" && part.text === "Continue your previous response from exactly where it left off. Do not repeat any of it.", ), ); if (text === "error") throw new Error("Fixture unavailable"); if (text === "pending") await new Promise((resolve) => setTimeout(resolve, 2500)); const resource = text.startsWith("resource:") ? (JSON.parse(text.slice("resource:".length)) as { toolName: string; input: unknown; }) : undefined; const calls = (text === "rich" || resource) && prompt.at(-1)?.role !== "tool"; const tokens = text === "restart" && continuing ? ["Recovered remaining response."] : resource ? ["Resource saved."] : text === "rich" ? [rich] : [ "Starting ", ...Array.from({ length: 20 }, (_, i) => `${text}-${i} `), "finished.", ]; return { stream: new ReadableStream<Chunk>({ async start(controller) { const emit = (value: Chunk) => controller.enqueue(value); emit({ type: "stream-start", warnings: [] }); if (calls) { for (const call of resource ? [resource] : [false, true].map((fail) => ({ toolName: "fixtureSources", input: { fail }, }))) emit({ type: "tool-call", toolCallId: crypto.randomUUID(), toolName: call.toolName, input: JSON.stringify(call.input), }); } else { emit({ type: "text-start", id: "text" }); for (const token of tokens) { if (abortSignal?.aborted) { controller.close(); return; } emit({ type: "text-delta", id: "text", delta: token }); if (text !== "rich" && text !== "fast") await new Promise<void>((resolve) => { const timer = setTimeout( resolve, text === "restart" ? 1500 : 150, ); abortSignal?.addEventListener( "abort", () => { clearTimeout(timer); resolve(); }, { once: true }, ); }); } emit({ type: "text-end", id: "text" }); } emit({ type: "finish", finishReason: { unified: calls ? "tool-calls" : "stop", raw: undefined, }, usage: { inputTokens: { total: 1, noCache: 1, cacheRead: 0, cacheWrite: 0, }, outputTokens: { total: 1, text: 1, reasoning: 0 }, }, }); controller.close(); }, }), }; }, }); } protected getToolActivityDescriptors() { return { ...super.getToolActivityDescriptors(), fixtureSources: { kind: "web" as const, label: "Read evidence", outcome: (output: unknown) => (output as { ok: boolean }).ok ? ("succeeded" as const) : ("failed" as const), outputSummary: (output: unknown) => (output as { ok: boolean }).ok ? "Evidence read" : "Page could not be read", }, }; } getTools() { return { ...super.getTools(), fixtureSources: tool({ description: "Fixture source evidence", inputSchema: z.object({ fail: z.boolean() }), execute: async ({ fail }) => { await new Promise((resolve) => setTimeout(resolve, 1500)); return fail ? { ok: false, message: "Safe tool failure <img src=x onerror=window.chatXss=true>", } : { ok: true, sources: [ { id: "fixture-source", title: "Agents documentation", requestedUrl: "https://developers.cloudflare.com/agents/", finalUrl: "https://developers.cloudflare.com/agents/", fetchedAt: new Date().toISOString(), sourceKind: "page", content: "Native evidence", truncated: false, }, ], }; }, }), }; } async seedHistory(count: number) { const messages: UIMessage[] = Array.from({ length: count }, (_, index) => ({ id: `seed-${index}`, role: index % 2 ? "assistant" : "user", parts: [ { type: "text", text: `Saved message ${index}\n\n${"Long conversation content. ".repeat(12)}`, }, ], })); await this.saveMessages(messages); }}export default { async fetch(request, env, ctx) { if (new URL(request.url).pathname === "/__chat/previous-model") { const owner = await getAgentByName( env.PersonalAgent as unknown as DurableObjectNamespace<PersonalAgent>, "personal", ); await owner.fixturePreviousModel(); return Response.json({ ok: true }); } if (new URL(request.url).pathname === "/__chat/seed") { const { id, count } = (await request.json()) as { id: string; count: number; }; const owner = await getAgentByName( env.PersonalAgent as unknown as DurableObjectNamespace<PersonalAgent>, "personal", ); await owner.seedChat(id, count); return Response.json({ ok: true }); } return runtime.fetch(request, env, ctx); },} satisfies ExportedHandler<Env>;