Files
openwork/evals/drivers/cloud-connect-services-mock.mjs

630 lines
21 KiB
JavaScript

#!/usr/bin/env node
import { createServer } from "node:http";
import { pathToFileURL } from "node:url";
export const MOCK_MICROSOFT_ACCESS_TOKEN = "mock-microsoft-access-token";
export const MOCK_MICROSOFT_REFRESH_TOKEN = "mock-microsoft-refresh-token";
export const MOCK_WORKER_HOST_TOKEN = "mock-worker-host-token";
export const MOCK_WORKER_CLIENT_TOKEN = "mock-worker-client-token";
const MICROSOFT_SCOPES = [
"openid",
"profile",
"email",
"offline_access",
"User.Read",
"Mail.Read",
"Calendars.Read",
"Files.Read",
];
const MICROSOFT_MESSAGES = [
{
id: "message-launch-readiness",
subject: "Launch readiness",
receivedDateTime: "2026-07-09T16:00:00Z",
bodyPreview: "The launch checklist is complete. The only remaining item is the final support handoff.",
body: {
contentType: "text",
content: "The launch checklist is complete. The only remaining item is the final support handoff.",
},
from: { emailAddress: { name: "Ada Lovelace", address: "ada@example.test" } },
toRecipients: [{ emailAddress: { name: "OpenWork Tester", address: "tester@example.test" } }],
webLink: "https://outlook.office.test/mail/message-launch-readiness",
},
{
id: "message-q3-budget",
subject: "Q3 budget approved",
receivedDateTime: "2026-07-09T15:00:00Z",
bodyPreview: "Finance approved the Q3 budget with no changes.",
body: { contentType: "text", content: "Finance approved the Q3 budget with no changes." },
from: { emailAddress: { name: "Grace Hopper", address: "grace@example.test" } },
toRecipients: [{ emailAddress: { name: "OpenWork Tester", address: "tester@example.test" } }],
webLink: "https://outlook.office.test/mail/message-q3-budget",
},
{
id: "message-customer-feedback",
subject: "Customer feedback summary",
receivedDateTime: "2026-07-09T14:00:00Z",
bodyPreview: "Pilot customers highlighted faster setup and asked for clearer connection health.",
body: {
contentType: "text",
content: "Pilot customers highlighted faster setup and asked for clearer connection health.",
},
from: { emailAddress: { name: "Katherine Johnson", address: "katherine@example.test" } },
toRecipients: [{ emailAddress: { name: "OpenWork Tester", address: "tester@example.test" } }],
webLink: "https://outlook.office.test/mail/message-customer-feedback",
},
];
const MICROSOFT_EVENTS = [
{
id: "event-launch-review",
subject: "Launch review",
bodyPreview: "Review launch status and support handoff.",
start: { dateTime: "2026-07-10T09:00:00", timeZone: "America/Los_Angeles" },
end: { dateTime: "2026-07-10T09:30:00", timeZone: "America/Los_Angeles" },
organizer: { emailAddress: { name: "Ada Lovelace", address: "ada@example.test" } },
attendees: [],
location: { displayName: "OpenWork Room" },
isCancelled: false,
webLink: "https://outlook.office.test/calendar/event-launch-review",
},
{
id: "event-q3-planning",
subject: "Q3 planning",
bodyPreview: "Confirm Q3 milestones and owners.",
start: { dateTime: "2026-07-10T11:00:00", timeZone: "America/Los_Angeles" },
end: { dateTime: "2026-07-10T12:00:00", timeZone: "America/Los_Angeles" },
organizer: { emailAddress: { name: "Grace Hopper", address: "grace@example.test" } },
attendees: [],
location: { displayName: "Microsoft Teams" },
isCancelled: false,
webLink: "https://outlook.office.test/calendar/event-q3-planning",
},
];
const MICROSOFT_Q3_FILE = {
id: "file-q3-plan",
name: "Q3 Plan.txt",
size: 128,
lastModifiedDateTime: "2026-07-09T13:00:00Z",
webUrl: "https://onedrive.office.test/files/file-q3-plan",
file: { mimeType: "text/plain", hashes: { quickXorHash: "mock-hash" } },
parentReference: { driveId: "drive-openwork-test", path: "/drive/root:" },
};
const Q3_FILE_CONTENT = [
"Q3 Plan",
"",
"1. Ship cloud connections.",
"2. Improve connection health and audit history.",
"3. Complete the support handoff.",
].join("\n");
function sendJson(response, status, body, headers = {}) {
response.writeHead(status, {
"access-control-allow-origin": "*",
"access-control-allow-methods": "GET,POST,DELETE,OPTIONS",
"access-control-allow-headers": "authorization,content-type,x-openwork-host-token",
"content-type": "application/json; charset=utf-8",
...headers,
});
response.end(JSON.stringify(body));
}
function sendText(response, status, body, contentType = "text/plain; charset=utf-8", headers = {}) {
response.writeHead(status, {
"access-control-allow-origin": "*",
"content-type": contentType,
...headers,
});
response.end(body);
}
function sendEmpty(response, status = 204) {
response.writeHead(status, { "access-control-allow-origin": "*" });
response.end();
}
function readBody(request) {
return new Promise((resolve, reject) => {
let raw = "";
request.setEncoding("utf8");
request.on("data", (chunk) => {
raw += chunk;
if (raw.length > 1_000_000) request.destroy(new Error("request_too_large"));
});
request.on("end", () => resolve(raw));
request.on("error", reject);
});
}
function parseJson(raw) {
if (!raw.trim()) return {};
return JSON.parse(raw);
}
function requestHeaders(request) {
return Object.fromEntries(
Object.entries(request.headers).map(([name, value]) => [name, Array.isArray(value) ? value.join(", ") : value ?? ""]),
);
}
function recordRequest(state, request, url, rawBody) {
const contentType = request.headers["content-type"] ?? "";
let body = rawBody;
if (rawBody && contentType.includes("application/json")) {
try {
body = JSON.parse(rawBody);
} catch {
body = rawBody;
}
} else if (rawBody && contentType.includes("application/x-www-form-urlencoded")) {
body = Object.fromEntries(new URLSearchParams(rawBody));
}
state.requests.push({
id: state.requests.length + 1,
method: request.method ?? "GET",
path: url.pathname,
search: url.search,
headers: requestHeaders(request),
body,
});
}
function initialState() {
return {
requests: [],
worker: {
nextSessionId: 1,
sessions: new Map(),
},
};
}
function resetState(state) {
const fresh = initialState();
state.requests = fresh.requests;
state.worker = fresh.worker;
}
function handleMicrosoftOAuth(request, response, url, rawBody) {
const match = url.pathname.match(/^\/entra\/([^/]+)\/oauth2\/v2\.0\/(authorize|token)$/);
if (!match) return false;
const operation = match[2];
if (operation === "authorize" && request.method === "GET") {
const redirectUri = url.searchParams.get("redirect_uri");
if (!redirectUri) {
sendJson(response, 400, { error: "invalid_request", error_description: "redirect_uri is required" });
return true;
}
const callback = new URL(redirectUri);
const requestedScopes = url.searchParams.get("scope") ?? MICROSOFT_SCOPES.join(" ");
const encodedScopes = Buffer.from(requestedScopes, "utf8").toString("base64url");
callback.searchParams.set("code", `mock-microsoft-authorization-code.${encodedScopes}`);
const state = url.searchParams.get("state");
if (state) callback.searchParams.set("state", state);
response.writeHead(302, { location: callback.toString() });
response.end();
return true;
}
if (operation === "token" && request.method === "POST") {
const form = new URLSearchParams(rawBody);
const grantType = form.get("grant_type");
if (grantType !== "authorization_code" && grantType !== "refresh_token") {
sendJson(response, 400, { error: "unsupported_grant_type" });
return true;
}
const authorizationCode = form.get("code") ?? "";
const encodedScopes = authorizationCode.startsWith("mock-microsoft-authorization-code.")
? authorizationCode.slice("mock-microsoft-authorization-code.".length)
: "";
let authorizedScopes = form.get("scope") ?? MICROSOFT_SCOPES.join(" ");
if (encodedScopes) {
try {
authorizedScopes = Buffer.from(encodedScopes, "base64url").toString("utf8");
} catch {
sendJson(response, 400, { error: "invalid_grant", error_description: "The mock authorization code is malformed." });
return true;
}
}
sendJson(response, 200, {
token_type: "Bearer",
scope: authorizedScopes,
expires_in: 3600,
access_token: MOCK_MICROSOFT_ACCESS_TOKEN,
refresh_token: MOCK_MICROSOFT_REFRESH_TOKEN,
});
return true;
}
sendJson(response, 405, { error: "method_not_allowed" });
return true;
}
function hasMicrosoftBearer(request) {
return request.headers.authorization === `Bearer ${MOCK_MICROSOFT_ACCESS_TOKEN}`;
}
function graphEnvelope(value) {
return {
"@odata.context": "https://graph.microsoft.test/v1.0/$metadata#mock",
value,
};
}
function handleMicrosoftGraph(request, response, url) {
if (!url.pathname.startsWith("/graph/v1.0/")) return false;
if (!hasMicrosoftBearer(request)) {
sendJson(response, 401, { error: { code: "InvalidAuthenticationToken", message: "Access token is missing or invalid." } });
return true;
}
if (url.pathname === "/graph/v1.0/me" && request.method === "GET") {
sendJson(response, 200, {
id: "microsoft-user-openwork-test",
displayName: "OpenWork Tester",
givenName: "OpenWork",
surname: "Tester",
mail: "tester@example.test",
userPrincipalName: "tester@example.test",
});
return true;
}
if (url.pathname === "/graph/v1.0/me/messages" && request.method === "GET") {
const top = Number(url.searchParams.get("$top") ?? MICROSOFT_MESSAGES.length);
sendJson(response, 200, graphEnvelope(MICROSOFT_MESSAGES.slice(0, Number.isFinite(top) ? top : MICROSOFT_MESSAGES.length)));
return true;
}
if (url.pathname === "/graph/v1.0/me/messages" && request.method === "POST") {
sendJson(response, 201, {
id: "draft-openwork-test",
subject: "OpenWork permission parity draft",
bodyPreview: "Drafted by the deterministic Microsoft Graph mock.",
webLink: "https://outlook.office.test/mail/draft-openwork-test",
isDraft: true,
});
return true;
}
const messageMatch = url.pathname.match(/^\/graph\/v1\.0\/me\/messages\/([^/]+)$/);
if (messageMatch && request.method === "GET") {
const message = MICROSOFT_MESSAGES.find((item) => item.id === decodeURIComponent(messageMatch[1]));
if (!message) {
sendJson(response, 404, { error: { code: "ErrorItemNotFound", message: "The message was not found." } });
return true;
}
sendJson(response, 200, message);
return true;
}
if (
(url.pathname === "/graph/v1.0/me/calendarView" || url.pathname === "/graph/v1.0/me/events")
&& request.method === "GET"
) {
sendJson(response, 200, graphEnvelope(MICROSOFT_EVENTS));
return true;
}
if (url.pathname === "/graph/v1.0/me/events" && request.method === "POST") {
sendJson(response, 201, {
id: "event-openwork-test",
subject: "OpenWork permission parity review",
start: { dateTime: "2026-07-13T10:00:00Z", timeZone: "UTC" },
end: { dateTime: "2026-07-13T10:30:00Z", timeZone: "UTC" },
webLink: "https://outlook.office.test/calendar/event-openwork-test",
});
return true;
}
if (
(url.pathname === "/graph/v1.0/me/drive/root/children" || url.pathname.startsWith("/graph/v1.0/me/drive/root/search"))
&& request.method === "GET"
) {
sendJson(response, 200, graphEnvelope([MICROSOFT_Q3_FILE]));
return true;
}
if (url.pathname === "/graph/v1.0/me/drive/items/file-q3-plan" && request.method === "GET") {
sendJson(response, 200, MICROSOFT_Q3_FILE);
return true;
}
if (url.pathname === "/graph/v1.0/me/drive/items/file-q3-plan/content" && request.method === "GET") {
sendText(response, 200, Q3_FILE_CONTENT);
return true;
}
if (url.pathname === "/graph/v1.0/me/drive/root:/OpenWork/permission-parity.txt:/content" && request.method === "PUT") {
sendJson(response, 201, {
id: "file-permission-parity",
name: "permission-parity.txt",
size: 37,
webUrl: "https://onedrive.office.test/files/file-permission-parity",
file: { mimeType: "text/plain" },
});
return true;
}
if (url.pathname === "/graph/v1.0/me/chats" && request.method === "GET") {
sendJson(response, 200, graphEnvelope([{
id: "chat-openwork-test",
topic: "OpenWork launch",
chatType: "group",
webUrl: "https://teams.office.test/chats/chat-openwork-test",
lastUpdatedDateTime: "2026-07-13T09:00:00Z",
}]));
return true;
}
if (url.pathname === "/graph/v1.0/chats/chat-openwork-test/messages" && request.method === "GET") {
sendJson(response, 200, graphEnvelope([{
id: "teams-message-existing",
createdDateTime: "2026-07-13T09:05:00Z",
body: { contentType: "text", content: "Ready for the permission review." },
from: { user: { id: "microsoft-user-openwork-test", displayName: "OpenWork Tester" } },
webUrl: "https://teams.office.test/messages/teams-message-existing",
}]));
return true;
}
if (url.pathname === "/graph/v1.0/chats/chat-openwork-test/messages" && request.method === "POST") {
sendJson(response, 201, {
id: "teams-message-sent",
createdDateTime: "2026-07-13T09:10:00Z",
body: { contentType: "text", content: "Permission parity verified." },
from: { user: { id: "microsoft-user-openwork-test", displayName: "OpenWork Tester" } },
webUrl: "https://teams.office.test/messages/teams-message-sent",
});
return true;
}
sendJson(response, 404, { error: { code: "Request_ResourceNotFound", message: `Unhandled mock Graph route: ${url.pathname}` } });
return true;
}
function hasWorkerDualAuth(request) {
return request.headers["x-openwork-host-token"] === MOCK_WORKER_HOST_TOKEN
&& request.headers.authorization === `Bearer ${MOCK_WORKER_CLIENT_TOKEN}`;
}
function workerUnauthorized(response) {
sendJson(response, 401, {
error: "worker_mock_unauthorized",
message: "Both the OpenWork host token and client bearer token are required.",
});
}
function workerMessage(session, role, id, text, parentID = null) {
return {
info: { id, sessionID: session.id, role, ...(parentID ? { parentID } : {}), time: { created: 1783612800000 } },
parts: [{ id: `${id}-part`, messageID: id, sessionID: session.id, type: "text", text }],
};
}
function workerMessages(session, includeReply) {
const messages = [];
if (session.prompt) {
messages.push(workerMessage(session, "user", session.messageId, session.prompt));
}
if (includeReply && session.prompt) {
messages.push(workerMessage(session, "assistant", `${session.messageId}-assistant`, `OpenWork worker reply: ${session.prompt}`, session.messageId));
}
return messages;
}
function handleWorker(state, request, response, url, rawBody) {
if (!url.pathname.startsWith("/worker/")) return false;
if (!hasWorkerDualAuth(request)) {
workerUnauthorized(response);
return true;
}
if (url.pathname === "/worker/workspaces" && request.method === "GET") {
sendJson(response, 200, {
activeId: "ws_mock_cloud",
items: [{ id: "ws_mock_cloud", name: "Mock cloud workspace", path: "/workspace" }],
});
return true;
}
if (url.pathname === "/worker/workspace/ws_mock_cloud/opencode/session" && request.method === "POST") {
let body;
try {
body = parseJson(rawBody);
} catch {
sendJson(response, 400, { error: "invalid_json" });
return true;
}
const id = `ses_mock_${state.worker.nextSessionId++}`;
const session = { id, title: typeof body.title === "string" ? body.title : "Cloud connect session", prompt: null, messageId: null, polls: 0 };
state.worker.sessions.set(id, session);
sendJson(response, 200, { id, title: session.title, directory: "/workspace" });
return true;
}
const promptMatch = url.pathname.match(
/^\/worker\/workspace\/ws_mock_cloud\/opencode\/session\/([^/]+)\/prompt_async$/,
);
if (promptMatch && request.method === "POST") {
const session = state.worker.sessions.get(decodeURIComponent(promptMatch[1]));
if (!session) {
sendJson(response, 404, { error: "session_not_found" });
return true;
}
let body;
try {
body = parseJson(rawBody);
} catch {
sendJson(response, 400, { error: "invalid_json" });
return true;
}
const textPart = Array.isArray(body.parts)
? body.parts.find((part) => part && part.type === "text" && typeof part.text === "string")
: null;
if (!textPart) {
sendJson(response, 400, { error: "text_part_required" });
return true;
}
session.prompt = textPart.text;
session.messageId = typeof body.messageID === "string" ? body.messageID : `${session.id}-user`;
session.polls = 0;
sendEmpty(response);
return true;
}
if (url.pathname === "/worker/workspace/ws_mock_cloud/opencode/session/status" && request.method === "GET") {
const statuses = {};
for (const session of state.worker.sessions.values()) {
statuses[session.id] = { type: session.polls++ === 0 ? "busy" : "idle" };
}
sendJson(response, 200, statuses);
return true;
}
const sessionMatch = url.pathname.match(
/^\/worker\/workspace\/ws_mock_cloud\/opencode\/session\/([^/]+)(?:\/(message|todo))?$/,
);
if (sessionMatch && request.method === "GET") {
const session = state.worker.sessions.get(decodeURIComponent(sessionMatch[1]));
if (!session) {
sendJson(response, 404, { error: "session_not_found" });
return true;
}
if (sessionMatch[2] === "message") {
sendJson(response, 200, workerMessages(session, session.polls > 0));
} else if (sessionMatch[2] === "todo") {
sendJson(response, 200, []);
} else {
sendJson(response, 200, {
id: session.id,
title: session.title,
directory: "/workspace",
time: { created: 1783612800000, updated: 1783612801000 },
});
}
return true;
}
sendJson(response, 404, { error: "worker_mock_not_found", path: url.pathname });
return true;
}
function stateView(state, origin) {
return {
endpoints: {
microsoftAuthorizeUrl: `${origin}/entra/{tenantId}/oauth2/v2.0/authorize`,
microsoftTokenUrl: `${origin}/entra/{tenantId}/oauth2/v2.0/token`,
microsoftGraphBaseUrl: `${origin}/graph/v1.0`,
workerBaseUrl: `${origin}/worker`,
},
credentials: {
microsoftAccessToken: MOCK_MICROSOFT_ACCESS_TOKEN,
workerHostToken: MOCK_WORKER_HOST_TOKEN,
workerClientToken: MOCK_WORKER_CLIENT_TOKEN,
},
worker: {
sessions: Array.from(state.worker.sessions.values()),
},
};
}
export function createCloudConnectMockServer(options = {}) {
const hostname = options.hostname ?? "127.0.0.1";
const port = options.port ?? 0;
const state = initialState();
const server = createServer(async (request, response) => {
const origin = `http://${request.headers.host ?? `${hostname}:${port}`}`;
const url = new URL(request.url ?? "/", origin);
const method = request.method ?? "GET";
if (method === "OPTIONS") {
sendEmpty(response);
return;
}
let rawBody = "";
try {
rawBody = method === "GET" || method === "HEAD" ? "" : await readBody(request);
} catch (error) {
sendJson(response, 400, { error: error instanceof Error ? error.message : "invalid_request" });
return;
}
recordRequest(state, request, url, rawBody);
if (url.pathname === "/health" && method === "GET") {
sendJson(response, 200, { ok: true, service: "cloud-connect-services-mock", ...stateView(state, origin) });
return;
}
if (url.pathname === "/__mock/state" && method === "GET") {
sendJson(response, 200, stateView(state, origin));
return;
}
if (url.pathname === "/__mock/requests" && method === "GET") {
sendJson(response, 200, { requests: state.requests });
return;
}
if (url.pathname === "/__mock/reset" && method === "POST") {
resetState(state);
sendJson(response, 200, { ok: true });
return;
}
if (handleMicrosoftOAuth(request, response, url, rawBody)) return;
if (handleMicrosoftGraph(request, response, url)) return;
if (handleWorker(state, request, response, url, rawBody)) return;
sendJson(response, 404, { error: "not_found", path: url.pathname });
});
return {
state,
async start() {
await new Promise((resolve, reject) => {
server.once("error", reject);
server.listen(port, hostname, resolve);
});
const address = server.address();
if (!address || typeof address === "string") throw new Error("mock_server_address_unavailable");
return {
origin: `http://${hostname}:${address.port}`,
port: address.port,
};
},
async stop() {
if (!server.listening) return;
await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
},
};
}
function cliPort() {
const index = process.argv.indexOf("--port");
const raw = index === -1 ? process.env.PORT : process.argv[index + 1];
const port = Number(raw ?? 3979);
if (!Number.isInteger(port) || port <= 0) throw new Error(`Invalid port: ${raw}`);
return port;
}
const isMain = process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href;
if (isMain) {
const mock = createCloudConnectMockServer({
hostname: process.env.HOST ?? "127.0.0.1",
port: cliPort(),
});
const started = await mock.start();
console.log(`Cloud connection services mock listening at ${started.origin}`);
console.log(`Inspect endpoints and credentials at ${started.origin}/health`);
}