import type { BackendDriver, DaytonaClientLike, DaytonaDriver, GitDriver, GithubDriver, StackDriver, SandboxAgentDriver, SandboxAgentClientLike, TmuxDriver, } from "../../src/driver.js"; import type { ListEventsRequest, ListPage, ListPageRequest, ProcessInfo, ProcessLogsResponse, SessionEvent, SessionRecord } from "sandbox-agent"; export function createTestDriver(overrides?: Partial): BackendDriver { return { git: overrides?.git ?? createTestGitDriver(), stack: overrides?.stack ?? createTestStackDriver(), github: overrides?.github ?? createTestGithubDriver(), sandboxAgent: overrides?.sandboxAgent ?? createTestSandboxAgentDriver(), daytona: overrides?.daytona ?? createTestDaytonaDriver(), tmux: overrides?.tmux ?? createTestTmuxDriver(), }; } export function createTestGitDriver(overrides?: Partial): GitDriver { return { validateRemote: async () => {}, ensureCloned: async () => {}, fetch: async () => {}, listRemoteBranches: async () => [], remoteDefaultBaseRef: async () => "origin/main", revParse: async () => "abc1234567890", ensureRemoteBranch: async () => {}, diffStatForBranch: async () => "+0/-0", conflictsWithMain: async () => false, ...overrides, }; } export function createTestStackDriver(overrides?: Partial): StackDriver { return { available: async () => false, listStack: async () => [], syncRepo: async () => {}, restackRepo: async () => {}, restackSubtree: async () => {}, rebaseBranch: async () => {}, reparentBranch: async () => {}, trackBranch: async () => {}, ...overrides, }; } export function createTestGithubDriver(overrides?: Partial): GithubDriver { return { listPullRequests: async () => [], createPr: async (_repoPath, _headBranch, _title) => ({ number: 1, url: `https://github.com/test/repo/pull/1`, }), starRepository: async () => {}, ...overrides, }; } export function createTestSandboxAgentDriver(overrides?: Partial): SandboxAgentDriver { return { createClient: (_opts) => createTestSandboxAgentClient(), ...overrides, }; } export function createTestSandboxAgentClient(overrides?: Partial): SandboxAgentClientLike { const defaultProcess: ProcessInfo = { id: "process-1", command: "bash", args: ["-lc", "echo test"], createdAtMs: Date.now(), cwd: "/workspace", exitCode: null, exitedAtMs: null, interactive: true, pid: 123, status: "running", tty: true, }; const defaultLogs: ProcessLogsResponse = { processId: defaultProcess.id, stream: "combined", entries: [], }; return { createSession: async (_prompt) => ({ id: "test-session-1", status: "running" }), sessionStatus: async (sessionId) => ({ id: sessionId, status: "running" }), listSessions: async (_request?: ListPageRequest): Promise> => ({ items: [], nextCursor: undefined, }), listEvents: async (_request: ListEventsRequest): Promise> => ({ items: [], nextCursor: undefined, }), createProcess: async () => defaultProcess, listProcesses: async () => ({ processes: [defaultProcess] }), getProcessLogs: async () => defaultLogs, stopProcess: async () => ({ ...defaultProcess, status: "exited", exitCode: 0, exitedAtMs: Date.now() }), killProcess: async () => ({ ...defaultProcess, status: "exited", exitCode: 137, exitedAtMs: Date.now() }), deleteProcess: async () => {}, sendPrompt: async (_request) => {}, cancelSession: async (_sessionId) => {}, destroySession: async (_sessionId) => {}, ...overrides, }; } export function createTestDaytonaDriver(overrides?: Partial): DaytonaDriver { return { createClient: (_opts) => createTestDaytonaClient(), ...overrides, }; } export function createTestDaytonaClient(overrides?: Partial): DaytonaClientLike { return { createSandbox: async () => ({ id: "sandbox-test-1", state: "started" }), getSandbox: async (sandboxId) => ({ id: sandboxId, state: "started" }), startSandbox: async () => {}, stopSandbox: async () => {}, deleteSandbox: async () => {}, executeCommand: async () => ({ exitCode: 0, result: "" }), getPreviewEndpoint: async (sandboxId, port) => ({ url: `https://preview.example/sandbox/${sandboxId}/port/${port}`, token: "preview-token", }), ...overrides, }; } export function createTestTmuxDriver(overrides?: Partial): TmuxDriver { return { setWindowStatus: () => 0, ...overrides, }; }