Spaces:
Running
Running
| import http from "node:http"; | |
| import { readFile } from "node:fs/promises"; | |
| import path from "node:path"; | |
| const appBaseUrl = process.env.APP_BASE_URL || "http://127.0.0.1:3000"; | |
| const seedPath = path.join( | |
| process.cwd(), | |
| "agentic_pm_demo_codex_plans/data/work-packages.seed.json", | |
| ); | |
| function assert(condition, message) { | |
| if (!condition) { | |
| throw new Error(message); | |
| } | |
| } | |
| function buildFakeLlmResponse(joinedMessages) { | |
| if (joinedMessages.includes("Connection test.")) { | |
| return "Connected to the configured model."; | |
| } | |
| if (joinedMessages.includes('"mode": "ask"')) { | |
| return "Verification method explains how the requirement will be checked, such as by test, inspection, or analysis."; | |
| } | |
| if (joinedMessages.includes('"mode": "plan"')) { | |
| return "Please break this package into review tasks."; | |
| } | |
| if (joinedMessages.includes('"mode": "change"')) { | |
| return "Please update the objective to include cybersecurity acceptance criteria."; | |
| } | |
| return JSON.stringify({ | |
| choices: [ | |
| { | |
| message: { | |
| content: JSON.stringify({ | |
| assistantMessage: "Fallback JSON response.", | |
| boardAction: { type: "none", workPackageId: null }, | |
| }), | |
| }, | |
| }, | |
| ], | |
| }); | |
| } | |
| async function startFakeLlmServer() { | |
| const server = http.createServer((req, res) => { | |
| let body = ""; | |
| req.on("data", (chunk) => { | |
| body += chunk; | |
| }); | |
| req.on("end", () => { | |
| let payload = {}; | |
| try { | |
| payload = JSON.parse(body || "{}"); | |
| } catch { | |
| payload = {}; | |
| } | |
| const joinedMessages = Array.isArray(payload.messages) | |
| ? payload.messages.map((message) => String(message?.content || "")).join("\n\n") | |
| : ""; | |
| res.writeHead(200, { "content-type": "text/plain" }); | |
| res.end(buildFakeLlmResponse(joinedMessages)); | |
| }); | |
| }); | |
| await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve)); | |
| const address = server.address(); | |
| if (!address || typeof address === "string") { | |
| throw new Error("Could not determine fake LLM server address."); | |
| } | |
| return { | |
| server, | |
| baseUrl: `http://127.0.0.1:${address.port}/v1`, | |
| }; | |
| } | |
| async function postJson(url, body) { | |
| const response = await fetch(url, { | |
| method: "POST", | |
| headers: { "content-type": "application/json" }, | |
| body: JSON.stringify(body), | |
| }); | |
| const payload = await response.json(); | |
| if (!response.ok) { | |
| throw new Error(`Request failed (${response.status}): ${JSON.stringify(payload)}`); | |
| } | |
| return payload; | |
| } | |
| async function main() { | |
| const seed = JSON.parse(await readFile(seedPath, "utf8")); | |
| const { server, baseUrl } = await startFakeLlmServer(); | |
| try { | |
| console.log(`Smoke target: ${appBaseUrl}`); | |
| console.log(`Fake LLM: ${baseUrl}`); | |
| const llmConfig = { | |
| apiKey: "live-key", | |
| baseUrl, | |
| model: "fake-model", | |
| }; | |
| const connection = await postJson(`${appBaseUrl}/api/test-connection`, { | |
| llmConfig, | |
| }); | |
| assert(connection.ok === true, "Connection test did not succeed."); | |
| assert( | |
| connection.message === "Connected to the configured model.", | |
| "Connection test message mismatch.", | |
| ); | |
| console.log("PASS connection"); | |
| const ask = await postJson(`${appBaseUrl}/api/chat`, { | |
| messages: [{ role: "user", content: "@SRS ask What does verification method mean?" }], | |
| workPackages: seed, | |
| selectedWorkPackageId: "wp-srs", | |
| parsedCommand: { | |
| referencedPackageName: "System Requirements Specification", | |
| mode: "ask", | |
| instruction: "What does verification method mean?", | |
| }, | |
| llmConfig, | |
| }); | |
| assert( | |
| typeof ask.assistantMessage === "string" && | |
| ask.assistantMessage.includes("Verification method explains"), | |
| "Ask response was not human-readable.", | |
| ); | |
| assert( | |
| !ask.assistantMessage.includes("Network or parsing error"), | |
| "Ask response fell back to network/parsing error.", | |
| ); | |
| assert(ask.boardAction?.type === "none", "Ask response changed the board."); | |
| console.log("PASS ask"); | |
| const plan = await postJson(`${appBaseUrl}/api/chat`, { | |
| messages: [{ role: "user", content: "@SRS plan Break this into review tasks." }], | |
| workPackages: seed, | |
| selectedWorkPackageId: "wp-srs", | |
| parsedCommand: { | |
| referencedPackageName: "System Requirements Specification", | |
| mode: "plan", | |
| instruction: "Break this into review tasks.", | |
| }, | |
| llmConfig, | |
| }); | |
| assert( | |
| typeof plan.assistantMessage === "string" && | |
| plan.assistantMessage.includes("Planned next steps for SRS"), | |
| "Plan response message mismatch.", | |
| ); | |
| assert(plan.boardAction?.type === "update", "Plan did not return an update."); | |
| assert(plan.boardAction?.workPackageId === "wp-srs", "Plan updated the wrong package."); | |
| assert( | |
| Array.isArray(plan.boardAction?.fields?.tasks) && | |
| plan.boardAction.fields.tasks.length > 0, | |
| "Plan did not provide tasks.", | |
| ); | |
| console.log("PASS plan"); | |
| const change = await postJson(`${appBaseUrl}/api/chat`, { | |
| messages: [ | |
| { role: "user", content: "@SRS change Add cybersecurity acceptance criteria." }, | |
| ], | |
| workPackages: seed, | |
| selectedWorkPackageId: "wp-srs", | |
| parsedCommand: { | |
| referencedPackageName: "System Requirements Specification", | |
| mode: "change", | |
| instruction: "Add cybersecurity acceptance criteria.", | |
| }, | |
| llmConfig, | |
| }); | |
| assert( | |
| typeof change.assistantMessage === "string" && | |
| change.assistantMessage.includes("Updated SRS"), | |
| "Change response message mismatch.", | |
| ); | |
| assert(change.boardAction?.type === "update", "Change did not return an update."); | |
| assert( | |
| change.boardAction?.workPackageId === "wp-srs", | |
| "Change updated the wrong package.", | |
| ); | |
| assert( | |
| String(change.boardAction?.fields?.objective || "").includes( | |
| "Add cybersecurity acceptance criteria.", | |
| ), | |
| "Change response did not update the objective.", | |
| ); | |
| console.log("PASS change"); | |
| console.log("Smoke test complete."); | |
| } finally { | |
| await new Promise((resolve, reject) => { | |
| server.close((error) => { | |
| if (error) { | |
| reject(error); | |
| return; | |
| } | |
| resolve(); | |
| }); | |
| }); | |
| } | |
| } | |
| main().catch((error) => { | |
| console.error(error instanceof Error ? error.message : String(error)); | |
| process.exitCode = 1; | |
| }); | |