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.
40 lines
2.4 KiB
TypeScript
40 lines
2.4 KiB
TypeScript
import { describe, expect, it } from "bun:test";
|
|
import express from "express";
|
|
import { registerTaskAgentBridge } from "../../src/routes/task-agent-bridge.js";
|
|
import { registerTaskPublicationBridge } from "../../src/routes/task-publication-bridge.js";
|
|
import { removeRuntimeSessionContext, setRuntimeSessionContext } from "../../src/runtime/sessionContext.js";
|
|
import { TASK_AGENT, TASK_READER_AGENT } from "../../src/runtime/task-agent-policy.js";
|
|
|
|
describe("task reader bridge", () => {
|
|
it("uses parent identity only for reads, revokes on run end and forbids child publication", async () => {
|
|
const id = "bridge-task-parent";
|
|
setRuntimeSessionContext({ sessionId: id, clientSessionId: id, actorKey: "a", projectKey: "p",
|
|
projectId: "project-1", taskId: "task-1", traceId: "test", purpose: "task_execution" });
|
|
let active = true;
|
|
const app = express(); app.use(express.json());
|
|
const reader = registerTaskAgentBridge(app, { internalToken: "TEST_ONLY", hasActiveRun: () => active,
|
|
getSession: async (sessionId) => ({ id: sessionId, parentID: sessionId === id ? undefined : id,
|
|
agent: sessionId === id ? TASK_AGENT : TASK_READER_AGENT, location: { directory: "/workspace" } }),
|
|
});
|
|
registerTaskPublicationBridge(app, { internalToken: "TEST_ONLY" });
|
|
const server = app.listen(0, "127.0.0.1");
|
|
await new Promise<void>((resolve) => server.once("listening", resolve));
|
|
const base = `http://127.0.0.1:${(server.address() as { port: number }).port}`;
|
|
const post = (path: string, token = "TEST_ONLY") => fetch(`${base}/internal/operational-task/${path}`, {
|
|
method: "POST", headers: { "Content-Type": "application/json", "x-agent-internal-token": token }, body: JSON.stringify({ session_id: "child" }),
|
|
});
|
|
try {
|
|
expect(await (await post("agent-policy")).json()).toEqual({ role: "reader" });
|
|
expect((await post("agent-policy", "wrong")).status).toBe(403);
|
|
expect((await reader("child"))?.runtimeSessionId).toBe(id);
|
|
for (const kind of ["artifacts", "presentation"]) expect((await post(kind)).status).toBe(403);
|
|
active = false;
|
|
expect(await reader("child")).toBeNull();
|
|
expect(await (await post("agent-policy")).json()).toEqual({ role: "denied" });
|
|
} finally {
|
|
removeRuntimeSessionContext(id);
|
|
await new Promise<void>((resolve) => server.close(() => resolve()));
|
|
}
|
|
});
|
|
});
|