|
1 | 1 | import { defineConfig } from "vitepress"; |
| 2 | +import path from "path"; |
| 3 | +import fs from "fs"; |
| 4 | +import { google } from "@ai-sdk/google"; |
| 5 | +import { streamText } from "ai"; |
| 6 | +import dotenv from "dotenv"; |
| 7 | +import { globSync } from "glob"; |
| 8 | + |
| 9 | +dotenv.config(); |
2 | 10 |
|
3 | 11 | export default defineConfig({ |
4 | 12 | base: "/user_docs/", |
@@ -179,4 +187,113 @@ export default defineConfig({ |
179 | 187 | message: "Released under the GPL 3.0 License as of 2025.", |
180 | 188 | }, |
181 | 189 | }, |
| 190 | + vite: { |
| 191 | + resolve: { |
| 192 | + alias: { |
| 193 | + "zod/v3": "zod", |
| 194 | + "zod/v4": "zod", |
| 195 | + }, |
| 196 | + }, |
| 197 | + plugins: [ |
| 198 | + { |
| 199 | + name: "handle-chat-api", |
| 200 | + configureServer(server) { |
| 201 | + server.middlewares.use(async (req, res, next) => { |
| 202 | + if (req.url === "/api/chat" && req.method === "POST") { |
| 203 | + let body = ""; |
| 204 | + req.on("data", (chunk) => { |
| 205 | + body += chunk.toString(); |
| 206 | + }); |
| 207 | + req.on("end", async () => { |
| 208 | + try { |
| 209 | + const { messages } = JSON.parse(body); |
| 210 | + |
| 211 | + if ( |
| 212 | + !process.env |
| 213 | + .GOOGLE_GENERATIVE_AI_API_KEY |
| 214 | + ) { |
| 215 | + throw new Error( |
| 216 | + "Missing GOOGLE_GENERATIVE_AI_API_KEY in .env file", |
| 217 | + ); |
| 218 | + } |
| 219 | + |
| 220 | + let docsContext = ""; |
| 221 | + let systemPrompt = ""; |
| 222 | + |
| 223 | + const includeDocs = process.env.INCLUDE_DOCS_CONTEXT === "true"; |
| 224 | + |
| 225 | + if (includeDocs) { |
| 226 | + const docsPath = path.resolve(process.cwd()); |
| 227 | + const mdFiles = globSync("**/*.md", { |
| 228 | + cwd: docsPath, |
| 229 | + ignore: ["node_modules/**"] |
| 230 | + }); |
| 231 | + |
| 232 | + for (const file of mdFiles) { |
| 233 | + const fullPath = path.join(docsPath, file); |
| 234 | + const content = fs.readFileSync(fullPath, "utf-8"); |
| 235 | + docsContext += `\n--- FILE: ${file} ---\n${content}\n`; |
| 236 | + } |
| 237 | + |
| 238 | + systemPrompt = `You are the EvOC AI Assistant. Your PRIMARY goal is to provide accurate information based EXCLUSIVELY on the project's documentation provided below. |
| 239 | +
|
| 240 | +DOCUMENTATION CONTEXT: |
| 241 | +${docsContext} |
| 242 | +
|
| 243 | +INSTRUCTIONS: |
| 244 | +1. Strict Grounding: Use ONLY the documentation provided above. If the answer is not in the documentation, state that you don't have that information. |
| 245 | +2. Identity: EvOC is a GUI-based framework for Evolutionary Algorithms using Python/DEAP. |
| 246 | +3. Markdown: Use rich markdown (headers, bold, lists, code blocks). |
| 247 | +4. Professionalism: Be helpful, concise, and professional.`; |
| 248 | + |
| 249 | + |
| 250 | + } else { |
| 251 | + // less token prompt |
| 252 | + systemPrompt = `You are the EvOC AI Assistant, a specialized technical guide for the Evolve On Click (EvOC) framework. Your PRIMARY goal is to provide accurate information based on the project's documentation. |
| 253 | +
|
| 254 | +IDENTITY: |
| 255 | +EvOC (Evolutionary Algorithms On Click) is a user-friendly framework for designing, executing, and analyzing Evolutionary Algorithms (EA) without writing code. It uses Python and the **DEAP library** under the hood. |
| 256 | +
|
| 257 | +INSTRUCTIONS: |
| 258 | +1. Guidance: Answer questions about EvOC's features, algorithms (GA, GP, PSO, DE), and usage. |
| 259 | +2. Markdown: Use rich markdown (headers, bold, lists). |
| 260 | +3. Professionalism: Be helpful, concise, and professional. |
| 261 | +4. Note: Full documentation context is currently disabled. Answer based on general knowledge of the framework.`; |
| 262 | + } |
| 263 | + |
| 264 | + const result = await streamText({ |
| 265 | + model: google("gemini-flash-latest"), |
| 266 | + system: systemPrompt, |
| 267 | + messages, |
| 268 | + }); |
| 269 | + |
| 270 | + res.setHeader( |
| 271 | + "Content-Type", |
| 272 | + "text/plain; charset=utf-8", |
| 273 | + ); |
| 274 | + res.setHeader("x-vercel-ai-data-stream", "v1"); |
| 275 | + |
| 276 | + for await (const textPart of result.textStream) { |
| 277 | + res.write(`0:${JSON.stringify(textPart)}\n`); |
| 278 | + } |
| 279 | + res.end(); |
| 280 | + } catch (error) { |
| 281 | + console.error("--- Chat API ERROR ---"); |
| 282 | + console.error(error); |
| 283 | + res.statusCode = 500; |
| 284 | + res.end( |
| 285 | + JSON.stringify({ |
| 286 | + error: error.message, |
| 287 | + }), |
| 288 | + ); |
| 289 | + } |
| 290 | + }); |
| 291 | + } else { |
| 292 | + next(); |
| 293 | + } |
| 294 | + }); |
| 295 | + }, |
| 296 | + }, |
| 297 | + ], |
| 298 | + }, |
182 | 299 | }); |
0 commit comments