(_onFinish: unknown, options?: OnChatMessageOptions)
| 42 | maxPersistedMessages = 200; |
| 43 | |
| 44 | async onChatMessage(_onFinish: unknown, options?: OnChatMessageOptions) { |
| 45 | const workersai = createWorkersAI({ binding: this.env.AI }); |
| 46 | |
| 47 | const result = streamText({ |
| 48 | abortSignal: options?.abortSignal, |
| 49 | model: workersai("@cf/moonshotai/kimi-k2.6", { |
| 50 | sessionAffinity: this.sessionAffinity |
| 51 | }), |
| 52 | system: [ |
| 53 | "You are a helpful coding assistant with access to a persistent virtual filesystem and git.", |
| 54 | "You have direct tools for simple file operations (readFile, writeFile, listDirectory, deleteFile, mkdir, glob).", |
| 55 | "You have direct tools for git operations (gitInit, gitStatus, gitAdd, gitCommit, gitLog, gitDiff).", |
| 56 | "For multi-file refactors, coordinated edits, search/replace, edit planning, or any transactional update, use the `runStateCode` tool.", |
| 57 | "The `runStateCode` sandbox also has `git.*` available (git.clone, git.push, git.pull, git.fetch, git.branch, git.checkout, git.remote, etc.).", |
| 58 | "There is no bash tool.", |
| 59 | "When the user asks you to create files or projects, use the tools to actually do it.", |
| 60 | "When showing file contents, prefer reading them with the readFile tool rather than guessing.", |
| 61 | "After making changes, briefly summarize what you did.", |
| 62 | "", |
| 63 | STATE_SYSTEM_PROMPT.replace("{{types}}", STATE_TYPES) |
| 64 | ].join("\n"), |
| 65 | messages: pruneMessages({ |
| 66 | messages: await convertToModelMessages(this.messages), |
| 67 | toolCalls: "before-last-2-messages", |
| 68 | reasoning: "before-last-message" |
| 69 | }), |
| 70 | tools: { |
| 71 | readFile: tool({ |
| 72 | description: "Read the contents of a file at the given path", |
| 73 | inputSchema: z.object({ |
| 74 | path: z.string().describe("Absolute file path, e.g. /src/index.ts") |
| 75 | }), |
| 76 | execute: async ({ path }) => { |
| 77 | const content = await this.workspace.readFile(path); |
| 78 | if (content === null) { |
| 79 | return { error: `File not found: ${path}` }; |
| 80 | } |
| 81 | return { path, content }; |
| 82 | } |
| 83 | }), |
| 84 | |
| 85 | writeFile: tool({ |
| 86 | description: |
| 87 | "Write content to a file. Creates the file and parent directories if they don't exist.", |
| 88 | inputSchema: z.object({ |
| 89 | path: z.string().describe("Absolute file path, e.g. /src/index.ts"), |
| 90 | content: z.string().describe("File content to write") |
| 91 | }), |
| 92 | execute: async ({ path, content }) => { |
| 93 | await this.workspace.writeFile(path, content); |
| 94 | return { path, bytesWritten: content.length }; |
| 95 | } |
| 96 | }), |
| 97 | |
| 98 | listDirectory: tool({ |
| 99 | description: |
| 100 | "List all files and directories at the given path. Returns name, type, and size for each entry.", |
| 101 | inputSchema: z.object({ |
nothing calls this directly
no test coverage detected