mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-15 07:04:48 +00:00
chore: sync workspace changes
This commit is contained in:
parent
d24f983e2c
commit
bf58891edf
139 changed files with 5454 additions and 8986 deletions
|
|
@ -8,8 +8,7 @@
|
|||
"url": "https://github.com/rivet-dev/sandbox-agent"
|
||||
},
|
||||
"bin": {
|
||||
"sandbox-agent": "bin/sandbox-agent",
|
||||
"sandbox-daemon": "bin/sandbox-agent"
|
||||
"sandbox-agent": "bin/sandbox-agent"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "vitest run"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,4 @@
|
|||
import type {
|
||||
SandboxDaemonSpawnHandle,
|
||||
SandboxDaemonSpawnOptions,
|
||||
} from "./spawn.ts";
|
||||
import type { SandboxAgentSpawnHandle, SandboxAgentSpawnOptions } from "./spawn.ts";
|
||||
import type {
|
||||
AgentInstallRequest,
|
||||
AgentListResponse,
|
||||
|
|
@ -21,29 +18,27 @@ import type {
|
|||
|
||||
const API_PREFIX = "/v1";
|
||||
|
||||
export interface SandboxDaemonClientOptions {
|
||||
export interface SandboxAgentConnectOptions {
|
||||
baseUrl: string;
|
||||
token?: string;
|
||||
fetch?: typeof fetch;
|
||||
headers?: HeadersInit;
|
||||
}
|
||||
|
||||
export interface SandboxDaemonConnectOptions {
|
||||
baseUrl?: string;
|
||||
token?: string;
|
||||
export interface SandboxAgentStartOptions {
|
||||
spawn?: SandboxAgentSpawnOptions | boolean;
|
||||
fetch?: typeof fetch;
|
||||
headers?: HeadersInit;
|
||||
spawn?: SandboxDaemonSpawnOptions | boolean;
|
||||
}
|
||||
|
||||
export class SandboxDaemonError extends Error {
|
||||
export class SandboxAgentError extends Error {
|
||||
readonly status: number;
|
||||
readonly problem?: ProblemDetails;
|
||||
readonly response: Response;
|
||||
|
||||
constructor(status: number, problem: ProblemDetails | undefined, response: Response) {
|
||||
super(problem?.title ?? `Request failed with status ${status}`);
|
||||
this.name = "SandboxDaemonError";
|
||||
this.name = "SandboxAgentError";
|
||||
this.status = status;
|
||||
this.problem = problem;
|
||||
this.response = response;
|
||||
|
|
@ -60,14 +55,14 @@ type RequestOptions = {
|
|||
signal?: AbortSignal;
|
||||
};
|
||||
|
||||
export class SandboxDaemonClient {
|
||||
export class SandboxAgent {
|
||||
private readonly baseUrl: string;
|
||||
private readonly token?: string;
|
||||
private readonly fetcher: typeof fetch;
|
||||
private readonly defaultHeaders?: HeadersInit;
|
||||
private spawnHandle?: SandboxDaemonSpawnHandle;
|
||||
private spawnHandle?: SandboxAgentSpawnHandle;
|
||||
|
||||
constructor(options: SandboxDaemonClientOptions) {
|
||||
private constructor(options: SandboxAgentConnectOptions) {
|
||||
this.baseUrl = options.baseUrl.replace(/\/$/, "");
|
||||
this.token = options.token;
|
||||
this.fetcher = options.fetch ?? globalThis.fetch;
|
||||
|
|
@ -78,23 +73,18 @@ export class SandboxDaemonClient {
|
|||
}
|
||||
}
|
||||
|
||||
static async connect(options: SandboxDaemonConnectOptions): Promise<SandboxDaemonClient> {
|
||||
const spawnOptions = normalizeSpawnOptions(options.spawn, !options.baseUrl);
|
||||
if (!spawnOptions.enabled) {
|
||||
if (!options.baseUrl) {
|
||||
throw new Error("baseUrl is required when autospawn is disabled.");
|
||||
}
|
||||
return new SandboxDaemonClient({
|
||||
baseUrl: options.baseUrl,
|
||||
token: options.token,
|
||||
fetch: options.fetch,
|
||||
headers: options.headers,
|
||||
});
|
||||
}
|
||||
static async connect(options: SandboxAgentConnectOptions): Promise<SandboxAgent> {
|
||||
return new SandboxAgent(options);
|
||||
}
|
||||
|
||||
const { spawnSandboxDaemon } = await import("./spawn.js");
|
||||
const handle = await spawnSandboxDaemon(spawnOptions, options.fetch ?? globalThis.fetch);
|
||||
const client = new SandboxDaemonClient({
|
||||
static async start(options: SandboxAgentStartOptions = {}): Promise<SandboxAgent> {
|
||||
const spawnOptions = normalizeSpawnOptions(options.spawn, true);
|
||||
if (!spawnOptions.enabled) {
|
||||
throw new Error("SandboxAgent.start requires spawn to be enabled.");
|
||||
}
|
||||
const { spawnSandboxAgent } = await import("./spawn.js");
|
||||
const handle = await spawnSandboxAgent(spawnOptions, options.fetch ?? globalThis.fetch);
|
||||
const client = new SandboxAgent({
|
||||
baseUrl: handle.baseUrl,
|
||||
token: handle.token,
|
||||
fetch: options.fetch,
|
||||
|
|
@ -277,7 +267,7 @@ export class SandboxDaemonClient {
|
|||
const response = await this.fetcher(url, init);
|
||||
if (!response.ok) {
|
||||
const problem = await this.readProblem(response);
|
||||
throw new SandboxDaemonError(response.status, problem, response);
|
||||
throw new SandboxAgentError(response.status, problem, response);
|
||||
}
|
||||
|
||||
return response;
|
||||
|
|
@ -309,20 +299,10 @@ export class SandboxDaemonClient {
|
|||
}
|
||||
}
|
||||
|
||||
export const createSandboxDaemonClient = (options: SandboxDaemonClientOptions): SandboxDaemonClient => {
|
||||
return new SandboxDaemonClient(options);
|
||||
};
|
||||
|
||||
export const connectSandboxDaemonClient = (
|
||||
options: SandboxDaemonConnectOptions,
|
||||
): Promise<SandboxDaemonClient> => {
|
||||
return SandboxDaemonClient.connect(options);
|
||||
};
|
||||
|
||||
const normalizeSpawnOptions = (
|
||||
spawn: SandboxDaemonSpawnOptions | boolean | undefined,
|
||||
spawn: SandboxAgentSpawnOptions | boolean | undefined,
|
||||
defaultEnabled: boolean,
|
||||
): SandboxDaemonSpawnOptions => {
|
||||
): SandboxAgentSpawnOptions => {
|
||||
if (typeof spawn === "boolean") {
|
||||
return { enabled: spawn };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,10 +51,21 @@ export type webhooks = Record<string, never>;
|
|||
export interface components {
|
||||
schemas: {
|
||||
AgentCapabilities: {
|
||||
commandExecution: boolean;
|
||||
errorEvents: boolean;
|
||||
fileAttachments: boolean;
|
||||
fileChanges: boolean;
|
||||
images: boolean;
|
||||
mcpTools: boolean;
|
||||
permissions: boolean;
|
||||
planMode: boolean;
|
||||
questions: boolean;
|
||||
reasoning: boolean;
|
||||
sessionLifecycle: boolean;
|
||||
streamingDeltas: boolean;
|
||||
textMessages: boolean;
|
||||
toolCalls: boolean;
|
||||
toolResults: boolean;
|
||||
};
|
||||
AgentError: {
|
||||
agent?: string | null;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,7 @@
|
|||
export {
|
||||
SandboxDaemonClient,
|
||||
SandboxDaemonError,
|
||||
connectSandboxDaemonClient,
|
||||
createSandboxDaemonClient,
|
||||
} from "./client.ts";
|
||||
export { SandboxAgent, SandboxAgentError } from "./client.ts";
|
||||
export type {
|
||||
SandboxDaemonClientOptions,
|
||||
SandboxDaemonConnectOptions,
|
||||
SandboxAgentConnectOptions,
|
||||
SandboxAgentStartOptions,
|
||||
} from "./client.ts";
|
||||
export type {
|
||||
AgentCapabilities,
|
||||
|
|
@ -52,4 +47,4 @@ export type {
|
|||
UniversalItem,
|
||||
} from "./types.ts";
|
||||
export type { components, paths } from "./generated/openapi.ts";
|
||||
export type { SandboxDaemonSpawnOptions, SandboxDaemonSpawnLogMode } from "./spawn.ts";
|
||||
export type { SandboxAgentSpawnOptions, SandboxAgentSpawnLogMode } from "./spawn.ts";
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
import type { ChildProcess } from "node:child_process";
|
||||
import type { AddressInfo } from "node:net";
|
||||
|
||||
export type SandboxDaemonSpawnLogMode = "inherit" | "pipe" | "silent";
|
||||
export type SandboxAgentSpawnLogMode = "inherit" | "pipe" | "silent";
|
||||
|
||||
export type SandboxDaemonSpawnOptions = {
|
||||
export type SandboxAgentSpawnOptions = {
|
||||
enabled?: boolean;
|
||||
host?: string;
|
||||
port?: number;
|
||||
token?: string;
|
||||
binaryPath?: string;
|
||||
timeoutMs?: number;
|
||||
log?: SandboxDaemonSpawnLogMode;
|
||||
log?: SandboxAgentSpawnLogMode;
|
||||
env?: Record<string, string>;
|
||||
};
|
||||
|
||||
export type SandboxDaemonSpawnHandle = {
|
||||
export type SandboxAgentSpawnHandle = {
|
||||
baseUrl: string;
|
||||
token: string;
|
||||
child: ChildProcess;
|
||||
|
|
@ -32,10 +32,10 @@ export function isNodeRuntime(): boolean {
|
|||
return typeof process !== "undefined" && !!process.versions?.node;
|
||||
}
|
||||
|
||||
export async function spawnSandboxDaemon(
|
||||
options: SandboxDaemonSpawnOptions,
|
||||
export async function spawnSandboxAgent(
|
||||
options: SandboxAgentSpawnOptions,
|
||||
fetcher?: typeof fetch,
|
||||
): Promise<SandboxDaemonSpawnHandle> {
|
||||
): Promise<SandboxAgentSpawnHandle> {
|
||||
if (!isNodeRuntime()) {
|
||||
throw new Error("Autospawn requires a Node.js runtime.");
|
||||
}
|
||||
|
|
@ -54,7 +54,7 @@ export async function spawnSandboxDaemon(
|
|||
const connectHost = bindHost === "0.0.0.0" || bindHost === "::" ? "127.0.0.1" : bindHost;
|
||||
const token = options.token ?? crypto.randomBytes(24).toString("hex");
|
||||
const timeoutMs = options.timeoutMs ?? 15_000;
|
||||
const logMode: SandboxDaemonSpawnLogMode = options.log ?? "inherit";
|
||||
const logMode: SandboxAgentSpawnLogMode = options.log ?? "inherit";
|
||||
|
||||
const binaryPath =
|
||||
options.binaryPath ??
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { describe, it, expect, vi, type Mock } from "vitest";
|
||||
import { SandboxDaemonClient, SandboxDaemonError } from "../src/client.ts";
|
||||
import { SandboxAgent, SandboxAgentError } from "../src/client.ts";
|
||||
|
||||
function createMockFetch(
|
||||
response: unknown,
|
||||
|
|
@ -23,18 +23,18 @@ function createMockFetchError(status: number, problem: unknown): Mock<typeof fet
|
|||
);
|
||||
}
|
||||
|
||||
describe("SandboxDaemonClient", () => {
|
||||
describe("constructor", () => {
|
||||
it("creates client with baseUrl", () => {
|
||||
const client = new SandboxDaemonClient({
|
||||
describe("SandboxAgent", () => {
|
||||
describe("connect", () => {
|
||||
it("creates client with baseUrl", async () => {
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl: "http://localhost:8080",
|
||||
});
|
||||
expect(client).toBeInstanceOf(SandboxDaemonClient);
|
||||
expect(client).toBeInstanceOf(SandboxAgent);
|
||||
});
|
||||
|
||||
it("strips trailing slash from baseUrl", async () => {
|
||||
const mockFetch = createMockFetch({ status: "ok" });
|
||||
const client = new SandboxDaemonClient({
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl: "http://localhost:8080/",
|
||||
fetch: mockFetch,
|
||||
});
|
||||
|
|
@ -47,41 +47,33 @@ describe("SandboxDaemonClient", () => {
|
|||
);
|
||||
});
|
||||
|
||||
it("throws if fetch is not available", () => {
|
||||
it("throws if fetch is not available", async () => {
|
||||
const originalFetch = globalThis.fetch;
|
||||
// @ts-expect-error - testing missing fetch
|
||||
globalThis.fetch = undefined;
|
||||
|
||||
expect(() => {
|
||||
new SandboxDaemonClient({
|
||||
await expect(
|
||||
SandboxAgent.connect({
|
||||
baseUrl: "http://localhost:8080",
|
||||
});
|
||||
}).toThrow("Fetch API is not available");
|
||||
})
|
||||
).rejects.toThrow("Fetch API is not available");
|
||||
|
||||
globalThis.fetch = originalFetch;
|
||||
});
|
||||
});
|
||||
|
||||
describe("connect", () => {
|
||||
it("creates client without spawn when baseUrl provided", async () => {
|
||||
const client = await SandboxDaemonClient.connect({
|
||||
baseUrl: "http://localhost:8080",
|
||||
spawn: false,
|
||||
});
|
||||
expect(client).toBeInstanceOf(SandboxDaemonClient);
|
||||
});
|
||||
|
||||
it("throws when no baseUrl and spawn disabled", async () => {
|
||||
await expect(
|
||||
SandboxDaemonClient.connect({ spawn: false })
|
||||
).rejects.toThrow("baseUrl is required when autospawn is disabled");
|
||||
describe("start", () => {
|
||||
it("rejects when spawn disabled", async () => {
|
||||
await expect(SandboxAgent.start({ spawn: false })).rejects.toThrow(
|
||||
"SandboxAgent.start requires spawn to be enabled."
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getHealth", () => {
|
||||
it("returns health response", async () => {
|
||||
const mockFetch = createMockFetch({ status: "ok" });
|
||||
const client = new SandboxDaemonClient({
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl: "http://localhost:8080",
|
||||
fetch: mockFetch,
|
||||
});
|
||||
|
|
@ -100,7 +92,7 @@ describe("SandboxDaemonClient", () => {
|
|||
it("returns agent list", async () => {
|
||||
const agents = { agents: [{ id: "claude", installed: true }] };
|
||||
const mockFetch = createMockFetch(agents);
|
||||
const client = new SandboxDaemonClient({
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl: "http://localhost:8080",
|
||||
fetch: mockFetch,
|
||||
});
|
||||
|
|
@ -115,7 +107,7 @@ describe("SandboxDaemonClient", () => {
|
|||
it("creates session with agent", async () => {
|
||||
const response = { healthy: true, agentSessionId: "abc123" };
|
||||
const mockFetch = createMockFetch(response);
|
||||
const client = new SandboxDaemonClient({
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl: "http://localhost:8080",
|
||||
fetch: mockFetch,
|
||||
});
|
||||
|
|
@ -136,7 +128,7 @@ describe("SandboxDaemonClient", () => {
|
|||
|
||||
it("encodes session ID in URL", async () => {
|
||||
const mockFetch = createMockFetch({ healthy: true });
|
||||
const client = new SandboxDaemonClient({
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl: "http://localhost:8080",
|
||||
fetch: mockFetch,
|
||||
});
|
||||
|
|
@ -155,7 +147,7 @@ describe("SandboxDaemonClient", () => {
|
|||
const mockFetch = vi.fn().mockResolvedValue(
|
||||
new Response(null, { status: 204 })
|
||||
);
|
||||
const client = new SandboxDaemonClient({
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl: "http://localhost:8080",
|
||||
fetch: mockFetch,
|
||||
});
|
||||
|
|
@ -176,7 +168,7 @@ describe("SandboxDaemonClient", () => {
|
|||
it("returns events", async () => {
|
||||
const events = { events: [], hasMore: false };
|
||||
const mockFetch = createMockFetch(events);
|
||||
const client = new SandboxDaemonClient({
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl: "http://localhost:8080",
|
||||
fetch: mockFetch,
|
||||
});
|
||||
|
|
@ -188,7 +180,7 @@ describe("SandboxDaemonClient", () => {
|
|||
|
||||
it("passes query parameters", async () => {
|
||||
const mockFetch = createMockFetch({ events: [], hasMore: false });
|
||||
const client = new SandboxDaemonClient({
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl: "http://localhost:8080",
|
||||
fetch: mockFetch,
|
||||
});
|
||||
|
|
@ -205,7 +197,7 @@ describe("SandboxDaemonClient", () => {
|
|||
describe("authentication", () => {
|
||||
it("includes authorization header when token provided", async () => {
|
||||
const mockFetch = createMockFetch({ status: "ok" });
|
||||
const client = new SandboxDaemonClient({
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl: "http://localhost:8080",
|
||||
token: "test-token",
|
||||
fetch: mockFetch,
|
||||
|
|
@ -227,7 +219,7 @@ describe("SandboxDaemonClient", () => {
|
|||
});
|
||||
|
||||
describe("error handling", () => {
|
||||
it("throws SandboxDaemonError on non-ok response", async () => {
|
||||
it("throws SandboxAgentError on non-ok response", async () => {
|
||||
const problem = {
|
||||
type: "error",
|
||||
title: "Not Found",
|
||||
|
|
@ -235,20 +227,20 @@ describe("SandboxDaemonClient", () => {
|
|||
detail: "Session not found",
|
||||
};
|
||||
const mockFetch = createMockFetchError(404, problem);
|
||||
const client = new SandboxDaemonClient({
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl: "http://localhost:8080",
|
||||
fetch: mockFetch,
|
||||
});
|
||||
|
||||
await expect(client.getEvents("nonexistent")).rejects.toThrow(
|
||||
SandboxDaemonError
|
||||
SandboxAgentError
|
||||
);
|
||||
|
||||
try {
|
||||
await client.getEvents("nonexistent");
|
||||
} catch (e) {
|
||||
expect(e).toBeInstanceOf(SandboxDaemonError);
|
||||
const error = e as SandboxDaemonError;
|
||||
expect(e).toBeInstanceOf(SandboxAgentError);
|
||||
const error = e as SandboxAgentError;
|
||||
expect(error.status).toBe(404);
|
||||
expect(error.problem?.title).toBe("Not Found");
|
||||
}
|
||||
|
|
@ -260,7 +252,7 @@ describe("SandboxDaemonClient", () => {
|
|||
const mockFetch = vi.fn().mockResolvedValue(
|
||||
new Response(null, { status: 204 })
|
||||
);
|
||||
const client = new SandboxDaemonClient({
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl: "http://localhost:8080",
|
||||
fetch: mockFetch,
|
||||
});
|
||||
|
|
@ -284,7 +276,7 @@ describe("SandboxDaemonClient", () => {
|
|||
const mockFetch = vi.fn().mockResolvedValue(
|
||||
new Response(null, { status: 204 })
|
||||
);
|
||||
const client = new SandboxDaemonClient({
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl: "http://localhost:8080",
|
||||
fetch: mockFetch,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ import { existsSync } from "node:fs";
|
|||
import { dirname, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { type ChildProcess } from "node:child_process";
|
||||
import { SandboxDaemonClient } from "../src/client.ts";
|
||||
import { spawnSandboxDaemon, isNodeRuntime } from "../src/spawn.ts";
|
||||
import { SandboxAgent } from "../src/client.ts";
|
||||
import { spawnSandboxAgent, isNodeRuntime } from "../src/spawn.ts";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
|
|
@ -38,8 +38,8 @@ if (BINARY_PATH && !process.env.SANDBOX_AGENT_BIN) {
|
|||
}
|
||||
|
||||
describe.skipIf(SKIP_INTEGRATION)("Integration: spawn (local mode)", () => {
|
||||
it("spawns daemon and connects", async () => {
|
||||
const handle = await spawnSandboxDaemon({
|
||||
it("spawns server and connects", async () => {
|
||||
const handle = await spawnSandboxAgent({
|
||||
enabled: true,
|
||||
log: "silent",
|
||||
timeoutMs: 30000,
|
||||
|
|
@ -49,7 +49,7 @@ describe.skipIf(SKIP_INTEGRATION)("Integration: spawn (local mode)", () => {
|
|||
expect(handle.baseUrl).toMatch(/^http:\/\/127\.0\.0\.1:\d+$/);
|
||||
expect(handle.token).toBeTruthy();
|
||||
|
||||
const client = new SandboxDaemonClient({
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl: handle.baseUrl,
|
||||
token: handle.token,
|
||||
});
|
||||
|
|
@ -61,8 +61,8 @@ describe.skipIf(SKIP_INTEGRATION)("Integration: spawn (local mode)", () => {
|
|||
}
|
||||
});
|
||||
|
||||
it("SandboxDaemonClient.connect spawns automatically", async () => {
|
||||
const client = await SandboxDaemonClient.connect({
|
||||
it("SandboxAgent.start spawns automatically", async () => {
|
||||
const client = await SandboxAgent.start({
|
||||
spawn: { log: "silent", timeoutMs: 30000 },
|
||||
});
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ describe.skipIf(SKIP_INTEGRATION)("Integration: spawn (local mode)", () => {
|
|||
});
|
||||
|
||||
it("lists available agents", async () => {
|
||||
const client = await SandboxDaemonClient.connect({
|
||||
const client = await SandboxAgent.start({
|
||||
spawn: { log: "silent", timeoutMs: 30000 },
|
||||
});
|
||||
|
||||
|
|
@ -95,31 +95,31 @@ describe.skipIf(SKIP_INTEGRATION)("Integration: spawn (local mode)", () => {
|
|||
});
|
||||
|
||||
describe.skipIf(SKIP_INTEGRATION)("Integration: connect (remote mode)", () => {
|
||||
let daemonProcess: ChildProcess;
|
||||
let serverProcess: ChildProcess;
|
||||
let baseUrl: string;
|
||||
let token: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
// Start daemon manually to simulate remote server
|
||||
const handle = await spawnSandboxDaemon({
|
||||
// Start server manually to simulate remote server
|
||||
const handle = await spawnSandboxAgent({
|
||||
enabled: true,
|
||||
log: "silent",
|
||||
timeoutMs: 30000,
|
||||
});
|
||||
daemonProcess = handle.child;
|
||||
serverProcess = handle.child;
|
||||
baseUrl = handle.baseUrl;
|
||||
token = handle.token;
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
if (daemonProcess && daemonProcess.exitCode === null) {
|
||||
daemonProcess.kill("SIGTERM");
|
||||
if (serverProcess && serverProcess.exitCode === null) {
|
||||
serverProcess.kill("SIGTERM");
|
||||
await new Promise<void>((resolve) => {
|
||||
const timeout = setTimeout(() => {
|
||||
daemonProcess.kill("SIGKILL");
|
||||
serverProcess.kill("SIGKILL");
|
||||
resolve();
|
||||
}, 5000);
|
||||
daemonProcess.once("exit", () => {
|
||||
serverProcess.once("exit", () => {
|
||||
clearTimeout(timeout);
|
||||
resolve();
|
||||
});
|
||||
|
|
@ -128,26 +128,17 @@ describe.skipIf(SKIP_INTEGRATION)("Integration: connect (remote mode)", () => {
|
|||
});
|
||||
|
||||
it("connects to remote server", async () => {
|
||||
const client = await SandboxDaemonClient.connect({
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl,
|
||||
token,
|
||||
spawn: false,
|
||||
});
|
||||
|
||||
const health = await client.getHealth();
|
||||
expect(health.status).toBe("ok");
|
||||
});
|
||||
|
||||
it("creates client directly without spawn", () => {
|
||||
const client = new SandboxDaemonClient({
|
||||
baseUrl,
|
||||
token,
|
||||
});
|
||||
expect(client).toBeInstanceOf(SandboxDaemonClient);
|
||||
});
|
||||
|
||||
it("handles authentication", async () => {
|
||||
const client = new SandboxDaemonClient({
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl,
|
||||
token,
|
||||
});
|
||||
|
|
@ -157,7 +148,7 @@ describe.skipIf(SKIP_INTEGRATION)("Integration: connect (remote mode)", () => {
|
|||
});
|
||||
|
||||
it("rejects invalid token on protected endpoints", async () => {
|
||||
const client = new SandboxDaemonClient({
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl,
|
||||
token: "invalid-token",
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { describe, it, expect, vi, type Mock } from "vitest";
|
||||
import { SandboxDaemonClient } from "../src/client.ts";
|
||||
import { SandboxAgent } from "../src/client.ts";
|
||||
import type { UniversalEvent } from "../src/types.ts";
|
||||
|
||||
function createMockResponse(chunks: string[]): Response {
|
||||
|
|
@ -51,7 +51,7 @@ describe("SSE Parser", () => {
|
|||
const event = createEvent(1);
|
||||
const mockFetch = createMockFetch([`data: ${JSON.stringify(event)}\n\n`]);
|
||||
|
||||
const client = new SandboxDaemonClient({
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl: "http://localhost:8080",
|
||||
fetch: mockFetch,
|
||||
});
|
||||
|
|
@ -73,7 +73,7 @@ describe("SSE Parser", () => {
|
|||
`data: ${JSON.stringify(event2)}\n\n`,
|
||||
]);
|
||||
|
||||
const client = new SandboxDaemonClient({
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl: "http://localhost:8080",
|
||||
fetch: mockFetch,
|
||||
});
|
||||
|
|
@ -97,7 +97,7 @@ describe("SSE Parser", () => {
|
|||
fullMessage.slice(10),
|
||||
]);
|
||||
|
||||
const client = new SandboxDaemonClient({
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl: "http://localhost:8080",
|
||||
fetch: mockFetch,
|
||||
});
|
||||
|
|
@ -118,7 +118,7 @@ describe("SSE Parser", () => {
|
|||
`data: ${JSON.stringify(event1)}\n\ndata: ${JSON.stringify(event2)}\n\n`,
|
||||
]);
|
||||
|
||||
const client = new SandboxDaemonClient({
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl: "http://localhost:8080",
|
||||
fetch: mockFetch,
|
||||
});
|
||||
|
|
@ -139,7 +139,7 @@ describe("SSE Parser", () => {
|
|||
`data: ${JSON.stringify(event)}\n\n`,
|
||||
]);
|
||||
|
||||
const client = new SandboxDaemonClient({
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl: "http://localhost:8080",
|
||||
fetch: mockFetch,
|
||||
});
|
||||
|
|
@ -158,7 +158,7 @@ describe("SSE Parser", () => {
|
|||
`data: ${JSON.stringify(event)}\r\n\r\n`,
|
||||
]);
|
||||
|
||||
const client = new SandboxDaemonClient({
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl: "http://localhost:8080",
|
||||
fetch: mockFetch,
|
||||
});
|
||||
|
|
@ -174,7 +174,7 @@ describe("SSE Parser", () => {
|
|||
it("handles empty stream", async () => {
|
||||
const mockFetch = createMockFetch([]);
|
||||
|
||||
const client = new SandboxDaemonClient({
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl: "http://localhost:8080",
|
||||
fetch: mockFetch,
|
||||
});
|
||||
|
|
@ -190,7 +190,7 @@ describe("SSE Parser", () => {
|
|||
it("passes query parameters", async () => {
|
||||
const mockFetch = createMockFetch([]);
|
||||
|
||||
const client = new SandboxDaemonClient({
|
||||
const client = await SandboxAgent.connect({
|
||||
baseUrl: "http://localhost:8080",
|
||||
fetch: mockFetch,
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue