diff --git a/tools/ai-cli-dispatch/src/execute.ts b/tools/ai-cli-dispatch/src/execute.ts index b443e6a..f79be5b 100644 --- a/tools/ai-cli-dispatch/src/execute.ts +++ b/tools/ai-cli-dispatch/src/execute.ts @@ -1,8 +1,6 @@ -import type { ChildProcess } from "node:child_process"; import { spawn as defaultSpawn } from "node:child_process"; -import type { PathLike } from "node:fs"; import { existsSync as defaultExistsSync } from "node:fs"; -import type { ClientName, ExecResult, DebugInfo } from "./types.js"; +import type { ClientName, ExecResult, DebugInfo, ExecuteOptions } from "./types.js"; import { ClientNotFoundError, ExecError } from "./types.js"; const CLIENT_ARGS: Record string[]> = { @@ -11,15 +9,6 @@ const CLIENT_ARGS: Record string[]> = { opencode: (p) => ["run", "--dangerously-skip-permissions", p], }; -export interface ExecuteOptions { - clientPath?: string; - timeoutMs?: number; - debug?: boolean; - onDebug?: (info: DebugInfo) => void; - spawn?: (command: string, args: string[], options?: { shell?: boolean }) => ChildProcess; - existsSync?: (path: PathLike) => boolean; -} - export async function executePrompt( client: ClientName, prompt: string, diff --git a/tools/ai-cli-dispatch/src/types.ts b/tools/ai-cli-dispatch/src/types.ts index 0bf167d..fd0f2fe 100644 --- a/tools/ai-cli-dispatch/src/types.ts +++ b/tools/ai-cli-dispatch/src/types.ts @@ -1,3 +1,6 @@ +import type { ChildProcess } from "node:child_process"; +import type { PathLike } from "node:fs"; + export type ClientName = "codex" | "claude" | "opencode"; export interface ClientInfo { @@ -27,6 +30,42 @@ export interface DebugInfo { noisySuccess: boolean; } +export interface ExecuteOptions { + clientPath?: string; + timeoutMs?: number; + debug?: boolean; + onDebug?: (info: DebugInfo) => void; + spawn?: (command: string, args: string[], options?: { shell?: boolean }) => ChildProcess; + existsSync?: (path: PathLike) => boolean; +} + +export type JobStatus = "running" | "completed" | "failed" | "timed_out" | "cancelled"; + +export interface Job { + id: string; + client: ClientName; + prompt: string; + status: JobStatus; + result?: ExecResult; + error?: string; + startedAt: string; + completedAt?: string; + pid?: number; +} + +/** + * On-disk storage contract for job files under + * ~/.openclaw/ai-cli-dispatch/jobs/.json + */ +export interface JobRecord extends Job { + stdout: string; + stderr: string; +} + +export interface JobStartOptions extends ExecuteOptions { + jobDir?: string; +} + export class ClientNotFoundError extends Error { constructor(client: string) { super(`Client "${client}" not found or not installed.`); @@ -43,3 +82,17 @@ export class ExecError extends Error { this.result = result; } } + +export class JobNotFoundError extends Error { + constructor(jobId: string) { + super(`Job "${jobId}" not found.`); + this.name = "JobNotFoundError"; + } +} + +export class JobResultUnavailableError extends Error { + constructor(jobId: string, status: JobStatus) { + super(`Job "${jobId}" result is not available (status: ${status}).`); + this.name = "JobResultUnavailableError"; + } +}