Files
next-tjwater-agent/tests/routes/promptSuggestions.test.ts
T
jiang 6a49d2209e feat(agent): unify MCP tools and adopt Responses delivery
Move project and host queries into native MCP with host-owned OAuth/context,
while retaining memory, skills, actions and publication plugins. Add nearby-model
queries and explicit chat/task/learning model defaults.

Adopt Responses HTTP/SSE and native steer/queue inbox delivery, preserving scoped
session ownership, pending input edits and investigation communication.

Disable local-provider discovery: Server /health allowed native vLLM to probe
/v1/models on port 8000. A native before/after regression prevents recurrence.

Validation: 170 focused Bun tests; service/plugin typechecks; native discovery,
provider-discovery and input-inbox smoke checks; no paid model inference.
2026-10-19 18:46:58 +08:00

45 lines
2.6 KiB
TypeScript

import { afterEach, expect, test } from "bun:test";
import express from "express";
import type { Server } from "node:http";
import { buildChatRouter } from "../../src/routes/chat.js";
const originalFetch = globalThis.fetch;
let server: Server | undefined;
afterEach(async () => {
globalThis.fetch = originalFetch;
if (server) await new Promise<void>((resolve) => server!.close(() => resolve()));
server = undefined;
});
test("suggestions inherit verified identity and project scope and reject unsupported requests before inference", async () => {
globalThis.fetch = (async (_input, init) => {
const headers = new Headers(init?.headers);
if (headers.get("Authorization") === "Bearer denied") return Response.json({ detail: "denied" }, { status: 403 });
return Response.json({ user_id: headers.get("Authorization") === "Bearer user-a" ? "user-a" : "user-b", project_id: headers.get("X-Project-Id"), network: "supply" });
}) as typeof fetch;
let generations = 0;
const app = express();
app.use(express.json());
app.use("/api/v1", buildChatRouter({
runtime: { generateText: async () => { generations += 1; return '{"suggestions":[{"question":"核对供水监测数据的完整性","activity_id":null}]}'; } },
frontendActionCoordinator: {}, learningOrchestrator: {}, memoryStore: {}, sessionBridge: {}, sessionMetadataStore: {}, sessionTranscriptStore: {}, sessionUiStateStore: {},
} as never));
server = app.listen(0, "127.0.0.1");
await new Promise<void>((resolve) => server!.once("listening", resolve));
const address = server.address();
if (!address || typeof address === "string") throw new Error("missing test server address");
const post = (user: string, project = "10000000-0000-4000-8000-000000000001", body: unknown = { activities: [] }) => originalFetch(`http://127.0.0.1:${address.port}/api/v1/suggestions`, {
method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${user}`, "X-Project-Id": project, Connection: "close" }, body: JSON.stringify(body),
});
expect((await post("user-a")).status).toBe(200);
expect((await post("user-a")).status).toBe(200);
expect(generations).toBe(1);
expect((await post("user-b")).status).toBe(200);
expect((await post("user-a", "10000000-0000-4000-8000-000000000002")).status).toBe(200);
expect(generations).toBe(3);
expect((await post("denied")).status).toBe(403);
expect((await post("user-a", undefined, { activities: [], model: "unknown/model" })).status).toBe(400);
expect((await post("user-a", undefined, { activities: [], unexpected: "field" })).status).toBe(400);
expect(generations).toBe(3);
});