evOo-local/packages/adapters/src/testing/cursor-cloud-agent-emulator.ts
cynarAI 6c7eed7580 Initial clean evOo-local from f00577b
Fresh history cut from cynarAI/evoo antigravity-handoff/project-timeline
(Voice First + project timeline). Brand docs/titles as evOo; keep @rakazo/*
packages as tech debt. Excludes node_modules, caches, secrets, voice blobs.
2026-09-20 17:15:16 +02:00

111 lines
4.3 KiB
TypeScript

import type { AdapterContext, CloudAgentSnapshot } from "@rakazo/adapter-kit";
import { CloudAgentRequestRejected } from "@rakazo/adapter-kit";
import { EmulatorCloudAgentProvider } from "../cloud-agent-emulator.js";
/** In-process Cursor v1 HTTP server substitute, including post-commit transport faults. */
export class CursorCloudAgentEmulator {
readonly provider = new EmulatorCloudAgentProvider({ autoFinishAfterGets: null });
readonly ids = new Map<string, string>();
readonly requests: Array<{ method: string; path: string; body?: Record<string, unknown> }> = [];
staleLatestRunId: string | undefined;
loseNextLaunchResponse = false;
loseNextReplyResponse = false;
failNextRequest: number | undefined;
cancelPending = false;
readonly fetch: typeof fetch = async (input, init) => {
const url = new URL(String(input));
if (url.origin !== "https://api.cursor.com") throw new Error("Unexpected emulator origin");
if (new Headers(init?.headers).get("authorization") !== "Bearer fake-key")
return new Response(null, { status: 401 });
const method = init?.method ?? "GET";
const body = init?.body ? JSON.parse(String(init.body)) : undefined;
this.requests.push({ method, path: url.pathname, body });
if (this.failNextRequest) {
const status = this.failNextRequest;
this.failNextRequest = undefined;
return new Response("fake-key must never be exposed", { status });
}
const context: AdapterContext = {
operationId: "wire-test",
traceId: "wire-test",
spaceId: "test-space",
userId: "test-user",
signal: init?.signal ?? new AbortController().signal,
};
if (url.pathname === "/v1/agents" && method === "POST") {
if (this.ids.has(body.agentId)) return new Response(null, { status: 409 });
const launched = await this.provider.launch(
{
idempotencyKey: body.agentId,
prompt: body.prompt.text,
images: body.prompt.images,
repository: body.repos?.[0]?.url,
openPr: body.autoCreatePR,
},
context,
);
this.ids.set(body.agentId, launched.id);
if (this.loseNextLaunchResponse) {
this.loseNextLaunchResponse = false;
throw new Error("Connection lost after create");
}
return Response.json({ agent: this.agent(body.agentId), run: this.run(launched) });
}
const match = /^\/v1\/agents\/([^/]+)(?:\/runs(?:\/([^/]+)(\/cancel)?)?)?$/.exec(url.pathname);
if (!match) return new Response(null, { status: 404 });
const id = decodeURIComponent(match[1]!);
const internalId = this.ids.get(id);
if (!internalId) return new Response(null, { status: 404 });
try {
if (method === "GET" && !url.pathname.includes("/runs")) return Response.json(this.agent(id));
if (method === "GET")
return Response.json(this.run(await this.provider.get(internalId, context, match[2])));
if (match[3]) {
if (!this.cancelPending) await this.provider.cancel(internalId, context, match[2]);
return new Response(null, { status: 204 });
}
const reply = await this.provider.reply(
internalId,
{ prompt: body.prompt.text, images: body.prompt.images },
context,
);
if (this.loseNextReplyResponse) {
this.loseNextReplyResponse = false;
throw new Error("Connection lost after reply");
}
return Response.json({ run: this.run(reply) });
} catch (error) {
if (error instanceof CloudAgentRequestRejected) return new Response(null, { status: 409 });
throw error;
}
};
complete(id: string, options: { failed?: boolean; prUrl?: string } = {}) {
return this.provider.complete(this.ids.get(id)!, options);
}
private agent(id: string) {
const agent = this.provider.agents.get(this.ids.get(id)!)!;
return {
id,
name: agent.title,
status: "ACTIVE",
url: `https://cursor.com/agents/${id}`,
latestRunId: this.staleLatestRunId ?? agent.latestRunId,
};
}
private run(snapshot: CloudAgentSnapshot) {
return {
id: snapshot.latestRunId,
status: { running: "RUNNING", finished: "FINISHED", failed: "ERROR", cancelled: "CANCELLED" }[
snapshot.status
],
git: {
branches: snapshot.branch ? [{ branch: snapshot.branch, prUrl: snapshot.prUrl }] : [],
},
};
}
}