mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-15 17:01:02 +00:00
feat: add process management API (#203)
* feat: add process management API Introduces a complete Process Management API for Sandbox Agent with process lifecycle management (start, stop, kill, delete), one-shot command execution, log streaming via SSE and WebSocket, stdin input, and PTY/terminal support. Includes new process_runtime module for managing process state, HTTP route handlers, OpenAPI documentation, and integration tests. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> * fix: address review issues in process management API - Add doc comments to all 13 new #[utoipa::path] handlers (CLAUDE.md compliance) - Fix send_signal ESRCH check: use raw_os_error() == Some(libc::ESRCH) instead of ErrorKind::NotFound - Add max_input_bytes_per_request enforcement in WebSocket terminal handler - URL-decode access_token query parameter for WebSocket auth - Replace fragile string prefix matching with proper SandboxError::NotFound variant Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> * feat: add TypeScript SDK support for process management Add process CRUD operations (create, get, list, update, delete) and event streaming to the TypeScript SDK. Includes integration tests, mock agent updates, and test environment fixes for cross-platform home directory handling. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: provide WebSocket impl for process terminal test on Node 20 Node 20 lacks globalThis.WebSocket. Add ws as a devDependency and pass it to connectProcessTerminalWebSocket in the integration test so CI no longer fails. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
fba06d3304
commit
4335ef6af6
23 changed files with 5571 additions and 181 deletions
|
|
@ -39,6 +39,20 @@ import {
|
|||
type McpConfigQuery,
|
||||
type McpServerConfig,
|
||||
type ProblemDetails,
|
||||
type ProcessConfig,
|
||||
type ProcessCreateRequest,
|
||||
type ProcessInfo,
|
||||
type ProcessInputRequest,
|
||||
type ProcessInputResponse,
|
||||
type ProcessListResponse,
|
||||
type ProcessLogEntry,
|
||||
type ProcessLogsQuery,
|
||||
type ProcessLogsResponse,
|
||||
type ProcessRunRequest,
|
||||
type ProcessRunResponse,
|
||||
type ProcessSignalQuery,
|
||||
type ProcessTerminalResizeRequest,
|
||||
type ProcessTerminalResizeResponse,
|
||||
type SessionEvent,
|
||||
type SessionPersistDriver,
|
||||
type SessionRecord,
|
||||
|
|
@ -98,6 +112,27 @@ export interface SessionSendOptions {
|
|||
}
|
||||
|
||||
export type SessionEventListener = (event: SessionEvent) => void;
|
||||
export type ProcessLogListener = (entry: ProcessLogEntry) => void;
|
||||
export type ProcessLogFollowQuery = Omit<ProcessLogsQuery, "follow">;
|
||||
|
||||
export interface AgentQueryOptions {
|
||||
config?: boolean;
|
||||
noCache?: boolean;
|
||||
}
|
||||
|
||||
export interface ProcessLogSubscription {
|
||||
close(): void;
|
||||
closed: Promise<void>;
|
||||
}
|
||||
|
||||
export interface ProcessTerminalWebSocketUrlOptions {
|
||||
accessToken?: string;
|
||||
}
|
||||
|
||||
export interface ProcessTerminalConnectOptions extends ProcessTerminalWebSocketUrlOptions {
|
||||
protocols?: string | string[];
|
||||
WebSocket?: typeof WebSocket;
|
||||
}
|
||||
|
||||
export class SandboxAgentError extends Error {
|
||||
readonly status: number;
|
||||
|
|
@ -674,15 +709,15 @@ export class SandboxAgent {
|
|||
return this.requestJson("GET", `${API_PREFIX}/health`);
|
||||
}
|
||||
|
||||
async listAgents(options?: { config?: boolean }): Promise<AgentListResponse> {
|
||||
async listAgents(options?: AgentQueryOptions): Promise<AgentListResponse> {
|
||||
return this.requestJson("GET", `${API_PREFIX}/agents`, {
|
||||
query: options?.config ? { config: "true" } : undefined,
|
||||
query: toAgentQuery(options),
|
||||
});
|
||||
}
|
||||
|
||||
async getAgent(agent: string, options?: { config?: boolean }): Promise<AgentInfo> {
|
||||
async getAgent(agent: string, options?: AgentQueryOptions): Promise<AgentInfo> {
|
||||
return this.requestJson("GET", `${API_PREFIX}/agents/${encodeURIComponent(agent)}`, {
|
||||
query: options?.config ? { config: "true" } : undefined,
|
||||
query: toAgentQuery(options),
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -771,6 +806,134 @@ export class SandboxAgent {
|
|||
await this.requestRaw("DELETE", `${API_PREFIX}/config/skills`, { query });
|
||||
}
|
||||
|
||||
async getProcessConfig(): Promise<ProcessConfig> {
|
||||
return this.requestJson("GET", `${API_PREFIX}/processes/config`);
|
||||
}
|
||||
|
||||
async setProcessConfig(config: ProcessConfig): Promise<ProcessConfig> {
|
||||
return this.requestJson("POST", `${API_PREFIX}/processes/config`, {
|
||||
body: config,
|
||||
});
|
||||
}
|
||||
|
||||
async createProcess(request: ProcessCreateRequest): Promise<ProcessInfo> {
|
||||
return this.requestJson("POST", `${API_PREFIX}/processes`, {
|
||||
body: request,
|
||||
});
|
||||
}
|
||||
|
||||
async runProcess(request: ProcessRunRequest): Promise<ProcessRunResponse> {
|
||||
return this.requestJson("POST", `${API_PREFIX}/processes/run`, {
|
||||
body: request,
|
||||
});
|
||||
}
|
||||
|
||||
async listProcesses(): Promise<ProcessListResponse> {
|
||||
return this.requestJson("GET", `${API_PREFIX}/processes`);
|
||||
}
|
||||
|
||||
async getProcess(id: string): Promise<ProcessInfo> {
|
||||
return this.requestJson("GET", `${API_PREFIX}/processes/${encodeURIComponent(id)}`);
|
||||
}
|
||||
|
||||
async stopProcess(id: string, query?: ProcessSignalQuery): Promise<ProcessInfo> {
|
||||
return this.requestJson("POST", `${API_PREFIX}/processes/${encodeURIComponent(id)}/stop`, {
|
||||
query,
|
||||
});
|
||||
}
|
||||
|
||||
async killProcess(id: string, query?: ProcessSignalQuery): Promise<ProcessInfo> {
|
||||
return this.requestJson("POST", `${API_PREFIX}/processes/${encodeURIComponent(id)}/kill`, {
|
||||
query,
|
||||
});
|
||||
}
|
||||
|
||||
async deleteProcess(id: string): Promise<void> {
|
||||
await this.requestRaw("DELETE", `${API_PREFIX}/processes/${encodeURIComponent(id)}`);
|
||||
}
|
||||
|
||||
async getProcessLogs(id: string, query: ProcessLogFollowQuery = {}): Promise<ProcessLogsResponse> {
|
||||
return this.requestJson("GET", `${API_PREFIX}/processes/${encodeURIComponent(id)}/logs`, {
|
||||
query,
|
||||
});
|
||||
}
|
||||
|
||||
async followProcessLogs(
|
||||
id: string,
|
||||
listener: ProcessLogListener,
|
||||
query: ProcessLogFollowQuery = {},
|
||||
): Promise<ProcessLogSubscription> {
|
||||
const abortController = new AbortController();
|
||||
const response = await this.requestRaw(
|
||||
"GET",
|
||||
`${API_PREFIX}/processes/${encodeURIComponent(id)}/logs`,
|
||||
{
|
||||
query: { ...query, follow: true },
|
||||
accept: "text/event-stream",
|
||||
signal: abortController.signal,
|
||||
},
|
||||
);
|
||||
|
||||
if (!response.body) {
|
||||
abortController.abort();
|
||||
throw new Error("SSE stream is not readable in this environment.");
|
||||
}
|
||||
|
||||
const closed = consumeProcessLogSse(response.body, listener, abortController.signal);
|
||||
|
||||
return {
|
||||
close: () => abortController.abort(),
|
||||
closed,
|
||||
};
|
||||
}
|
||||
|
||||
async sendProcessInput(id: string, request: ProcessInputRequest): Promise<ProcessInputResponse> {
|
||||
return this.requestJson("POST", `${API_PREFIX}/processes/${encodeURIComponent(id)}/input`, {
|
||||
body: request,
|
||||
});
|
||||
}
|
||||
|
||||
async resizeProcessTerminal(
|
||||
id: string,
|
||||
request: ProcessTerminalResizeRequest,
|
||||
): Promise<ProcessTerminalResizeResponse> {
|
||||
return this.requestJson(
|
||||
"POST",
|
||||
`${API_PREFIX}/processes/${encodeURIComponent(id)}/terminal/resize`,
|
||||
{
|
||||
body: request,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
buildProcessTerminalWebSocketUrl(
|
||||
id: string,
|
||||
options: ProcessTerminalWebSocketUrlOptions = {},
|
||||
): string {
|
||||
return toWebSocketUrl(
|
||||
this.buildUrl(`${API_PREFIX}/processes/${encodeURIComponent(id)}/terminal/ws`, {
|
||||
access_token: options.accessToken ?? this.token,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
connectProcessTerminalWebSocket(
|
||||
id: string,
|
||||
options: ProcessTerminalConnectOptions = {},
|
||||
): WebSocket {
|
||||
const WebSocketCtor = options.WebSocket ?? globalThis.WebSocket;
|
||||
if (!WebSocketCtor) {
|
||||
throw new Error("WebSocket API is not available; provide a WebSocket implementation.");
|
||||
}
|
||||
|
||||
return new WebSocketCtor(
|
||||
this.buildProcessTerminalWebSocketUrl(id, {
|
||||
accessToken: options.accessToken,
|
||||
}),
|
||||
options.protocols,
|
||||
);
|
||||
}
|
||||
|
||||
private async getLiveConnection(agent: string): Promise<LiveAcpConnection> {
|
||||
const existing = this.liveConnections.get(agent);
|
||||
if (existing) {
|
||||
|
|
@ -1068,6 +1231,17 @@ async function autoAuthenticate(acp: AcpHttpClient, methods: AuthMethod[]): Prom
|
|||
}
|
||||
}
|
||||
|
||||
function toAgentQuery(options: AgentQueryOptions | undefined): Record<string, QueryValue> | undefined {
|
||||
if (!options) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
config: options.config,
|
||||
no_cache: options.noCache,
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeSessionInit(
|
||||
value: Omit<NewSessionRequest, "_meta"> | undefined,
|
||||
): Omit<NewSessionRequest, "_meta"> {
|
||||
|
|
@ -1230,3 +1404,93 @@ async function readProblem(response: Response): Promise<ProblemDetails | undefin
|
|||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
async function consumeProcessLogSse(
|
||||
body: ReadableStream<Uint8Array>,
|
||||
listener: ProcessLogListener,
|
||||
signal: AbortSignal,
|
||||
): Promise<void> {
|
||||
const reader = body.getReader();
|
||||
const decoder = new TextDecoder();
|
||||
let buffer = "";
|
||||
|
||||
try {
|
||||
while (!signal.aborted) {
|
||||
const { done, value } = await reader.read();
|
||||
if (done) {
|
||||
return;
|
||||
}
|
||||
|
||||
buffer += decoder.decode(value, { stream: true }).replace(/\r\n/g, "\n");
|
||||
|
||||
let separatorIndex = buffer.indexOf("\n\n");
|
||||
while (separatorIndex !== -1) {
|
||||
const chunk = buffer.slice(0, separatorIndex);
|
||||
buffer = buffer.slice(separatorIndex + 2);
|
||||
|
||||
const entry = parseProcessLogSseChunk(chunk);
|
||||
if (entry) {
|
||||
listener(entry);
|
||||
}
|
||||
|
||||
separatorIndex = buffer.indexOf("\n\n");
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
if (signal.aborted || isAbortError(error)) {
|
||||
return;
|
||||
}
|
||||
throw error;
|
||||
} finally {
|
||||
reader.releaseLock();
|
||||
}
|
||||
}
|
||||
|
||||
function parseProcessLogSseChunk(chunk: string): ProcessLogEntry | null {
|
||||
if (!chunk.trim()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let eventName = "message";
|
||||
const dataLines: string[] = [];
|
||||
|
||||
for (const line of chunk.split("\n")) {
|
||||
if (!line || line.startsWith(":")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.startsWith("event:")) {
|
||||
eventName = line.slice(6).trim();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.startsWith("data:")) {
|
||||
dataLines.push(line.slice(5).trimStart());
|
||||
}
|
||||
}
|
||||
|
||||
if (eventName !== "log") {
|
||||
return null;
|
||||
}
|
||||
|
||||
const data = dataLines.join("\n");
|
||||
if (!data.trim()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return JSON.parse(data) as ProcessLogEntry;
|
||||
}
|
||||
|
||||
function toWebSocketUrl(url: string): string {
|
||||
const parsed = new URL(url);
|
||||
if (parsed.protocol === "http:") {
|
||||
parsed.protocol = "ws:";
|
||||
} else if (parsed.protocol === "https:") {
|
||||
parsed.protocol = "wss:";
|
||||
}
|
||||
return parsed.toString();
|
||||
}
|
||||
|
||||
function isAbortError(error: unknown): boolean {
|
||||
return error instanceof Error && error.name === "AbortError";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,39 @@ export interface paths {
|
|||
"/v1/health": {
|
||||
get: operations["get_v1_health"];
|
||||
};
|
||||
"/v1/processes": {
|
||||
get: operations["get_v1_processes"];
|
||||
post: operations["post_v1_processes"];
|
||||
};
|
||||
"/v1/processes/config": {
|
||||
get: operations["get_v1_processes_config"];
|
||||
post: operations["post_v1_processes_config"];
|
||||
};
|
||||
"/v1/processes/run": {
|
||||
post: operations["post_v1_processes_run"];
|
||||
};
|
||||
"/v1/processes/{id}": {
|
||||
get: operations["get_v1_process"];
|
||||
delete: operations["delete_v1_process"];
|
||||
};
|
||||
"/v1/processes/{id}/input": {
|
||||
post: operations["post_v1_process_input"];
|
||||
};
|
||||
"/v1/processes/{id}/kill": {
|
||||
post: operations["post_v1_process_kill"];
|
||||
};
|
||||
"/v1/processes/{id}/logs": {
|
||||
get: operations["get_v1_process_logs"];
|
||||
};
|
||||
"/v1/processes/{id}/stop": {
|
||||
post: operations["post_v1_process_stop"];
|
||||
};
|
||||
"/v1/processes/{id}/terminal/resize": {
|
||||
post: operations["post_v1_process_terminal_resize"];
|
||||
};
|
||||
"/v1/processes/{id}/terminal/ws": {
|
||||
get: operations["get_v1_process_terminal_ws"];
|
||||
};
|
||||
}
|
||||
|
||||
export type webhooks = Record<string, never>;
|
||||
|
|
@ -230,6 +263,116 @@ export interface components {
|
|||
type: string;
|
||||
[key: string]: unknown;
|
||||
};
|
||||
ProcessConfig: {
|
||||
/** Format: int64 */
|
||||
defaultRunTimeoutMs: number;
|
||||
maxConcurrentProcesses: number;
|
||||
maxInputBytesPerRequest: number;
|
||||
maxLogBytesPerProcess: number;
|
||||
maxOutputBytes: number;
|
||||
/** Format: int64 */
|
||||
maxRunTimeoutMs: number;
|
||||
};
|
||||
ProcessCreateRequest: {
|
||||
args?: string[];
|
||||
command: string;
|
||||
cwd?: string | null;
|
||||
env?: {
|
||||
[key: string]: string;
|
||||
};
|
||||
interactive?: boolean;
|
||||
tty?: boolean;
|
||||
};
|
||||
ProcessInfo: {
|
||||
args: string[];
|
||||
command: string;
|
||||
/** Format: int64 */
|
||||
createdAtMs: number;
|
||||
cwd?: string | null;
|
||||
/** Format: int32 */
|
||||
exitCode?: number | null;
|
||||
/** Format: int64 */
|
||||
exitedAtMs?: number | null;
|
||||
id: string;
|
||||
interactive: boolean;
|
||||
/** Format: int32 */
|
||||
pid?: number | null;
|
||||
status: components["schemas"]["ProcessState"];
|
||||
tty: boolean;
|
||||
};
|
||||
ProcessInputRequest: {
|
||||
data: string;
|
||||
encoding?: string | null;
|
||||
};
|
||||
ProcessInputResponse: {
|
||||
bytesWritten: number;
|
||||
};
|
||||
ProcessListResponse: {
|
||||
processes: components["schemas"]["ProcessInfo"][];
|
||||
};
|
||||
ProcessLogEntry: {
|
||||
data: string;
|
||||
encoding: string;
|
||||
/** Format: int64 */
|
||||
sequence: number;
|
||||
stream: components["schemas"]["ProcessLogsStream"];
|
||||
/** Format: int64 */
|
||||
timestampMs: number;
|
||||
};
|
||||
ProcessLogsQuery: {
|
||||
follow?: boolean | null;
|
||||
/** Format: int64 */
|
||||
since?: number | null;
|
||||
stream?: components["schemas"]["ProcessLogsStream"] | null;
|
||||
tail?: number | null;
|
||||
};
|
||||
ProcessLogsResponse: {
|
||||
entries: components["schemas"]["ProcessLogEntry"][];
|
||||
processId: string;
|
||||
stream: components["schemas"]["ProcessLogsStream"];
|
||||
};
|
||||
/** @enum {string} */
|
||||
ProcessLogsStream: "stdout" | "stderr" | "combined" | "pty";
|
||||
ProcessRunRequest: {
|
||||
args?: string[];
|
||||
command: string;
|
||||
cwd?: string | null;
|
||||
env?: {
|
||||
[key: string]: string;
|
||||
};
|
||||
maxOutputBytes?: number | null;
|
||||
/** Format: int64 */
|
||||
timeoutMs?: number | null;
|
||||
};
|
||||
ProcessRunResponse: {
|
||||
/** Format: int64 */
|
||||
durationMs: number;
|
||||
/** Format: int32 */
|
||||
exitCode?: number | null;
|
||||
stderr: string;
|
||||
stderrTruncated: boolean;
|
||||
stdout: string;
|
||||
stdoutTruncated: boolean;
|
||||
timedOut: boolean;
|
||||
};
|
||||
ProcessSignalQuery: {
|
||||
/** Format: int64 */
|
||||
waitMs?: number | null;
|
||||
};
|
||||
/** @enum {string} */
|
||||
ProcessState: "running" | "exited";
|
||||
ProcessTerminalResizeRequest: {
|
||||
/** Format: int32 */
|
||||
cols: number;
|
||||
/** Format: int32 */
|
||||
rows: number;
|
||||
};
|
||||
ProcessTerminalResizeResponse: {
|
||||
/** Format: int32 */
|
||||
cols: number;
|
||||
/** Format: int32 */
|
||||
rows: number;
|
||||
};
|
||||
/** @enum {string} */
|
||||
ServerStatus: "running" | "stopped";
|
||||
ServerStatusInfo: {
|
||||
|
|
@ -748,4 +891,417 @@ export interface operations {
|
|||
};
|
||||
};
|
||||
};
|
||||
get_v1_processes: {
|
||||
responses: {
|
||||
/** @description List processes */
|
||||
200: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProcessListResponse"];
|
||||
};
|
||||
};
|
||||
/** @description Process API unsupported on this platform */
|
||||
501: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
post_v1_processes: {
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProcessCreateRequest"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Started process */
|
||||
200: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProcessInfo"];
|
||||
};
|
||||
};
|
||||
/** @description Invalid request */
|
||||
400: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
/** @description Process limit or state conflict */
|
||||
409: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
/** @description Process API unsupported on this platform */
|
||||
501: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
get_v1_processes_config: {
|
||||
responses: {
|
||||
/** @description Current runtime process config */
|
||||
200: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProcessConfig"];
|
||||
};
|
||||
};
|
||||
/** @description Process API unsupported on this platform */
|
||||
501: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
post_v1_processes_config: {
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProcessConfig"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Updated runtime process config */
|
||||
200: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProcessConfig"];
|
||||
};
|
||||
};
|
||||
/** @description Invalid config */
|
||||
400: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
/** @description Process API unsupported on this platform */
|
||||
501: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
post_v1_processes_run: {
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProcessRunRequest"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description One-off command result */
|
||||
200: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProcessRunResponse"];
|
||||
};
|
||||
};
|
||||
/** @description Invalid request */
|
||||
400: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
/** @description Process API unsupported on this platform */
|
||||
501: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
get_v1_process: {
|
||||
parameters: {
|
||||
path: {
|
||||
/** @description Process ID */
|
||||
id: string;
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Process details */
|
||||
200: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProcessInfo"];
|
||||
};
|
||||
};
|
||||
/** @description Unknown process */
|
||||
404: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
/** @description Process API unsupported on this platform */
|
||||
501: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
delete_v1_process: {
|
||||
parameters: {
|
||||
path: {
|
||||
/** @description Process ID */
|
||||
id: string;
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Process deleted */
|
||||
204: {
|
||||
content: never;
|
||||
};
|
||||
/** @description Unknown process */
|
||||
404: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
/** @description Process is still running */
|
||||
409: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
/** @description Process API unsupported on this platform */
|
||||
501: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
post_v1_process_input: {
|
||||
parameters: {
|
||||
path: {
|
||||
/** @description Process ID */
|
||||
id: string;
|
||||
};
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProcessInputRequest"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Input accepted */
|
||||
200: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProcessInputResponse"];
|
||||
};
|
||||
};
|
||||
/** @description Invalid request */
|
||||
400: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
/** @description Process not writable */
|
||||
409: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
/** @description Input exceeds configured limit */
|
||||
413: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
/** @description Process API unsupported on this platform */
|
||||
501: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
post_v1_process_kill: {
|
||||
parameters: {
|
||||
query?: {
|
||||
/** @description Wait up to N ms for process to exit */
|
||||
waitMs?: number | null;
|
||||
};
|
||||
path: {
|
||||
/** @description Process ID */
|
||||
id: string;
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Kill signal sent */
|
||||
200: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProcessInfo"];
|
||||
};
|
||||
};
|
||||
/** @description Unknown process */
|
||||
404: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
/** @description Process API unsupported on this platform */
|
||||
501: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
get_v1_process_logs: {
|
||||
parameters: {
|
||||
query?: {
|
||||
/** @description stdout|stderr|combined|pty */
|
||||
stream?: components["schemas"]["ProcessLogsStream"] | null;
|
||||
/** @description Tail N entries */
|
||||
tail?: number | null;
|
||||
/** @description Follow via SSE */
|
||||
follow?: boolean | null;
|
||||
/** @description Only entries with sequence greater than this */
|
||||
since?: number | null;
|
||||
};
|
||||
path: {
|
||||
/** @description Process ID */
|
||||
id: string;
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Process logs */
|
||||
200: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProcessLogsResponse"];
|
||||
};
|
||||
};
|
||||
/** @description Unknown process */
|
||||
404: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
/** @description Process API unsupported on this platform */
|
||||
501: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
post_v1_process_stop: {
|
||||
parameters: {
|
||||
query?: {
|
||||
/** @description Wait up to N ms for process to exit */
|
||||
waitMs?: number | null;
|
||||
};
|
||||
path: {
|
||||
/** @description Process ID */
|
||||
id: string;
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Stop signal sent */
|
||||
200: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProcessInfo"];
|
||||
};
|
||||
};
|
||||
/** @description Unknown process */
|
||||
404: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
/** @description Process API unsupported on this platform */
|
||||
501: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
post_v1_process_terminal_resize: {
|
||||
parameters: {
|
||||
path: {
|
||||
/** @description Process ID */
|
||||
id: string;
|
||||
};
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProcessTerminalResizeRequest"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Resize accepted */
|
||||
200: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProcessTerminalResizeResponse"];
|
||||
};
|
||||
};
|
||||
/** @description Invalid request */
|
||||
400: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
/** @description Unknown process */
|
||||
404: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
/** @description Not a terminal process */
|
||||
409: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
/** @description Process API unsupported on this platform */
|
||||
501: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
get_v1_process_terminal_ws: {
|
||||
parameters: {
|
||||
query?: {
|
||||
/** @description Bearer token alternative for WS auth */
|
||||
access_token?: string | null;
|
||||
};
|
||||
path: {
|
||||
/** @description Process ID */
|
||||
id: string;
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description WebSocket upgraded */
|
||||
101: {
|
||||
content: never;
|
||||
};
|
||||
/** @description Invalid websocket frame or upgrade request */
|
||||
400: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
/** @description Unknown process */
|
||||
404: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
/** @description Not a terminal process */
|
||||
409: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
/** @description Process API unsupported on this platform */
|
||||
501: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["ProblemDetails"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,12 @@ export { AcpRpcError } from "acp-http-client";
|
|||
export { buildInspectorUrl } from "./inspector.ts";
|
||||
|
||||
export type {
|
||||
AgentQueryOptions,
|
||||
ProcessLogFollowQuery,
|
||||
ProcessLogListener,
|
||||
ProcessLogSubscription,
|
||||
ProcessTerminalConnectOptions,
|
||||
ProcessTerminalWebSocketUrlOptions,
|
||||
SandboxAgentConnectOptions,
|
||||
SandboxAgentStartOptions,
|
||||
SessionCreateRequest,
|
||||
|
|
@ -29,6 +35,7 @@ export type {
|
|||
AcpServerInfo,
|
||||
AcpServerListResponse,
|
||||
AgentInfo,
|
||||
AgentQuery,
|
||||
AgentInstallRequest,
|
||||
AgentInstallResponse,
|
||||
AgentListResponse,
|
||||
|
|
@ -51,6 +58,27 @@ export type {
|
|||
McpConfigQuery,
|
||||
McpServerConfig,
|
||||
ProblemDetails,
|
||||
ProcessConfig,
|
||||
ProcessCreateRequest,
|
||||
ProcessInfo,
|
||||
ProcessInputRequest,
|
||||
ProcessInputResponse,
|
||||
ProcessListResponse,
|
||||
ProcessLogEntry,
|
||||
ProcessLogsQuery,
|
||||
ProcessLogsResponse,
|
||||
ProcessLogsStream,
|
||||
ProcessRunRequest,
|
||||
ProcessRunResponse,
|
||||
ProcessSignalQuery,
|
||||
ProcessState,
|
||||
ProcessTerminalClientFrame,
|
||||
ProcessTerminalErrorFrame,
|
||||
ProcessTerminalExitFrame,
|
||||
ProcessTerminalReadyFrame,
|
||||
ProcessTerminalResizeRequest,
|
||||
ProcessTerminalResizeResponse,
|
||||
ProcessTerminalServerFrame,
|
||||
SessionEvent,
|
||||
SessionPersistDriver,
|
||||
SessionRecord,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ export type ProblemDetails = components["schemas"]["ProblemDetails"];
|
|||
export type HealthResponse = JsonResponse<operations["get_v1_health"], 200>;
|
||||
export type AgentListResponse = JsonResponse<operations["get_v1_agents"], 200>;
|
||||
export type AgentInfo = components["schemas"]["AgentInfo"];
|
||||
export type AgentQuery = QueryParams<operations["get_v1_agents"]>;
|
||||
export type AgentInstallRequest = JsonRequestBody<operations["post_v1_agent_install"]>;
|
||||
export type AgentInstallResponse = JsonResponse<operations["post_v1_agent_install"], 200>;
|
||||
|
||||
|
|
@ -31,6 +32,58 @@ export type McpServerConfig = components["schemas"]["McpServerConfig"];
|
|||
export type SkillsConfigQuery = QueryParams<operations["get_v1_config_skills"]>;
|
||||
export type SkillsConfig = components["schemas"]["SkillsConfig"];
|
||||
|
||||
export type ProcessConfig = JsonResponse<operations["get_v1_processes_config"], 200>;
|
||||
export type ProcessCreateRequest = JsonRequestBody<operations["post_v1_processes"]>;
|
||||
export type ProcessInfo = components["schemas"]["ProcessInfo"];
|
||||
export type ProcessInputRequest = JsonRequestBody<operations["post_v1_process_input"]>;
|
||||
export type ProcessInputResponse = JsonResponse<operations["post_v1_process_input"], 200>;
|
||||
export type ProcessListResponse = JsonResponse<operations["get_v1_processes"], 200>;
|
||||
export type ProcessLogEntry = components["schemas"]["ProcessLogEntry"];
|
||||
export type ProcessLogsQuery = QueryParams<operations["get_v1_process_logs"]>;
|
||||
export type ProcessLogsResponse = JsonResponse<operations["get_v1_process_logs"], 200>;
|
||||
export type ProcessLogsStream = components["schemas"]["ProcessLogsStream"];
|
||||
export type ProcessRunRequest = JsonRequestBody<operations["post_v1_processes_run"]>;
|
||||
export type ProcessRunResponse = JsonResponse<operations["post_v1_processes_run"], 200>;
|
||||
export type ProcessSignalQuery = QueryParams<operations["post_v1_process_stop"]>;
|
||||
export type ProcessState = components["schemas"]["ProcessState"];
|
||||
export type ProcessTerminalResizeRequest = JsonRequestBody<operations["post_v1_process_terminal_resize"]>;
|
||||
export type ProcessTerminalResizeResponse = JsonResponse<operations["post_v1_process_terminal_resize"], 200>;
|
||||
|
||||
export type ProcessTerminalClientFrame =
|
||||
| {
|
||||
type: "input";
|
||||
data: string;
|
||||
encoding?: string;
|
||||
}
|
||||
| {
|
||||
type: "resize";
|
||||
cols: number;
|
||||
rows: number;
|
||||
}
|
||||
| {
|
||||
type: "close";
|
||||
};
|
||||
|
||||
export interface ProcessTerminalReadyFrame {
|
||||
type: "ready";
|
||||
processId: string;
|
||||
}
|
||||
|
||||
export interface ProcessTerminalExitFrame {
|
||||
type: "exit";
|
||||
exitCode?: number | null;
|
||||
}
|
||||
|
||||
export interface ProcessTerminalErrorFrame {
|
||||
type: "error";
|
||||
message: string;
|
||||
}
|
||||
|
||||
export type ProcessTerminalServerFrame =
|
||||
| ProcessTerminalReadyFrame
|
||||
| ProcessTerminalExitFrame
|
||||
| ProcessTerminalErrorFrame;
|
||||
|
||||
export interface SessionRecord {
|
||||
id: string;
|
||||
agent: string;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue