mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-15 19:21:08 +00:00
fix(agents): split sandbox backend handle types
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import fsPromises from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import type {
|
||||
SandboxContext,
|
||||
SandboxFsBridge,
|
||||
SandboxFsStat,
|
||||
SandboxResolvedPath,
|
||||
@@ -10,6 +9,10 @@ import { createWritableRenameTargetResolver } from "openclaw/plugin-sdk/sandbox"
|
||||
import type { OpenShellSandboxBackend } from "./backend.js";
|
||||
import { movePathWithCopyFallback } from "./mirror.js";
|
||||
|
||||
type OpenShellFsBridgeContext = Parameters<
|
||||
NonNullable<OpenShellSandboxBackend["createFsBridge"]>
|
||||
>[0]["sandbox"];
|
||||
|
||||
type ResolvedMountPath = SandboxResolvedPath & {
|
||||
mountHostRoot: string;
|
||||
writable: boolean;
|
||||
@@ -17,7 +20,7 @@ type ResolvedMountPath = SandboxResolvedPath & {
|
||||
};
|
||||
|
||||
export function createOpenShellFsBridge(params: {
|
||||
sandbox: SandboxContext;
|
||||
sandbox: OpenShellFsBridgeContext;
|
||||
backend: OpenShellSandboxBackend;
|
||||
}): SandboxFsBridge {
|
||||
return new OpenShellFsBridge(params.sandbox, params.backend);
|
||||
@@ -30,7 +33,7 @@ class OpenShellFsBridge implements SandboxFsBridge {
|
||||
);
|
||||
|
||||
constructor(
|
||||
private readonly sandbox: SandboxContext,
|
||||
private readonly sandbox: OpenShellFsBridgeContext,
|
||||
private readonly backend: OpenShellSandboxBackend,
|
||||
) {}
|
||||
|
||||
|
||||
65
src/agents/sandbox/backend-handle.types.ts
Normal file
65
src/agents/sandbox/backend-handle.types.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import type { SandboxFsBridge } from "./fs-bridge.types.js";
|
||||
|
||||
export type SandboxBackendId = string;
|
||||
|
||||
export type SandboxBackendExecSpec = {
|
||||
argv: string[];
|
||||
env: NodeJS.ProcessEnv;
|
||||
stdinMode: "pipe-open" | "pipe-closed";
|
||||
finalizeToken?: unknown;
|
||||
};
|
||||
|
||||
export type SandboxBackendCommandParams = {
|
||||
script: string;
|
||||
args?: string[];
|
||||
stdin?: Buffer | string;
|
||||
allowFailure?: boolean;
|
||||
signal?: AbortSignal;
|
||||
};
|
||||
|
||||
export type SandboxBackendCommandResult = {
|
||||
stdout: Buffer;
|
||||
stderr: Buffer;
|
||||
code: number;
|
||||
};
|
||||
|
||||
export type SandboxFsBridgeContext = {
|
||||
workspaceDir: string;
|
||||
agentWorkspaceDir: string;
|
||||
workspaceAccess: "none" | "ro" | "rw";
|
||||
containerName: string;
|
||||
containerWorkdir: string;
|
||||
docker: {
|
||||
binds?: string[];
|
||||
};
|
||||
backend?: {
|
||||
runShellCommand(params: SandboxBackendCommandParams): Promise<SandboxBackendCommandResult>;
|
||||
};
|
||||
};
|
||||
|
||||
export type SandboxBackendHandle = {
|
||||
id: SandboxBackendId;
|
||||
runtimeId: string;
|
||||
runtimeLabel: string;
|
||||
workdir: string;
|
||||
env?: Record<string, string>;
|
||||
configLabel?: string;
|
||||
configLabelKind?: string;
|
||||
capabilities?: {
|
||||
browser?: boolean;
|
||||
};
|
||||
buildExecSpec(params: {
|
||||
command: string;
|
||||
workdir?: string;
|
||||
env: Record<string, string>;
|
||||
usePty: boolean;
|
||||
}): Promise<SandboxBackendExecSpec>;
|
||||
finalizeExec?: (params: {
|
||||
status: "completed" | "failed";
|
||||
exitCode: number | null;
|
||||
timedOut: boolean;
|
||||
token?: unknown;
|
||||
}) => Promise<void>;
|
||||
runShellCommand(params: SandboxBackendCommandParams): Promise<SandboxBackendCommandResult>;
|
||||
createFsBridge?: (params: { sandbox: SandboxFsBridgeContext }) => SandboxFsBridge;
|
||||
};
|
||||
@@ -1,58 +1,17 @@
|
||||
import type { OpenClawConfig } from "../../config/config.js";
|
||||
import { normalizeOptionalLowercaseString } from "../../shared/string-coerce.js";
|
||||
import type { SandboxFsBridge } from "./fs-bridge.types.js";
|
||||
import type { SandboxBackendHandle, SandboxBackendId } from "./backend-handle.types.js";
|
||||
import type { SandboxRegistryEntry } from "./registry.js";
|
||||
import type { SandboxConfig, SandboxContext } from "./types.js";
|
||||
import type { SandboxConfig } from "./types.js";
|
||||
|
||||
export type SandboxBackendId = string;
|
||||
|
||||
export type SandboxBackendExecSpec = {
|
||||
argv: string[];
|
||||
env: NodeJS.ProcessEnv;
|
||||
stdinMode: "pipe-open" | "pipe-closed";
|
||||
finalizeToken?: unknown;
|
||||
};
|
||||
|
||||
export type SandboxBackendCommandParams = {
|
||||
script: string;
|
||||
args?: string[];
|
||||
stdin?: Buffer | string;
|
||||
allowFailure?: boolean;
|
||||
signal?: AbortSignal;
|
||||
};
|
||||
|
||||
export type SandboxBackendCommandResult = {
|
||||
stdout: Buffer;
|
||||
stderr: Buffer;
|
||||
code: number;
|
||||
};
|
||||
|
||||
export type SandboxBackendHandle = {
|
||||
id: SandboxBackendId;
|
||||
runtimeId: string;
|
||||
runtimeLabel: string;
|
||||
workdir: string;
|
||||
env?: Record<string, string>;
|
||||
configLabel?: string;
|
||||
configLabelKind?: string;
|
||||
capabilities?: {
|
||||
browser?: boolean;
|
||||
};
|
||||
buildExecSpec(params: {
|
||||
command: string;
|
||||
workdir?: string;
|
||||
env: Record<string, string>;
|
||||
usePty: boolean;
|
||||
}): Promise<SandboxBackendExecSpec>;
|
||||
finalizeExec?: (params: {
|
||||
status: "completed" | "failed";
|
||||
exitCode: number | null;
|
||||
timedOut: boolean;
|
||||
token?: unknown;
|
||||
}) => Promise<void>;
|
||||
runShellCommand(params: SandboxBackendCommandParams): Promise<SandboxBackendCommandResult>;
|
||||
createFsBridge?: (params: { sandbox: SandboxContext }) => SandboxFsBridge;
|
||||
};
|
||||
export type {
|
||||
SandboxBackendCommandParams,
|
||||
SandboxBackendCommandResult,
|
||||
SandboxBackendExecSpec,
|
||||
SandboxBackendHandle,
|
||||
SandboxBackendId,
|
||||
SandboxFsBridgeContext,
|
||||
} from "./backend-handle.types.js";
|
||||
|
||||
export type SandboxBackendRuntimeInfo = {
|
||||
running: boolean;
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import fs from "node:fs";
|
||||
import { normalizeOptionalLowercaseString } from "../../shared/string-coerce.js";
|
||||
import type { SandboxBackendCommandResult } from "./backend.js";
|
||||
import type {
|
||||
SandboxBackendCommandResult,
|
||||
SandboxFsBridgeContext,
|
||||
} from "./backend-handle.types.js";
|
||||
import { runDockerSandboxShellCommand } from "./docker-backend.js";
|
||||
import {
|
||||
buildPinnedMkdirpPlan,
|
||||
@@ -16,7 +19,7 @@ import {
|
||||
resolveSandboxFsPathWithMounts,
|
||||
type SandboxResolvedFsPath,
|
||||
} from "./fs-paths.js";
|
||||
import type { SandboxContext, SandboxWorkspaceAccess } from "./types.js";
|
||||
import type { SandboxWorkspaceAccess } from "./types.js";
|
||||
|
||||
type RunCommandOptions = {
|
||||
args?: string[];
|
||||
@@ -27,16 +30,18 @@ type RunCommandOptions = {
|
||||
|
||||
export type { SandboxFsBridge, SandboxFsStat, SandboxResolvedPath } from "./fs-bridge.types.js";
|
||||
|
||||
export function createSandboxFsBridge(params: { sandbox: SandboxContext }): SandboxFsBridge {
|
||||
export function createSandboxFsBridge(params: {
|
||||
sandbox: SandboxFsBridgeContext;
|
||||
}): SandboxFsBridge {
|
||||
return new SandboxFsBridgeImpl(params.sandbox);
|
||||
}
|
||||
|
||||
class SandboxFsBridgeImpl implements SandboxFsBridge {
|
||||
private readonly sandbox: SandboxContext;
|
||||
private readonly sandbox: SandboxFsBridgeContext;
|
||||
private readonly mounts: ReturnType<typeof buildSandboxFsMounts>;
|
||||
private readonly pathGuard: SandboxFsPathGuard;
|
||||
|
||||
constructor(sandbox: SandboxContext) {
|
||||
constructor(sandbox: SandboxFsBridgeContext) {
|
||||
this.sandbox = sandbox;
|
||||
this.mounts = buildSandboxFsMounts(sandbox);
|
||||
const mountsByContainer = [...this.mounts].toSorted(
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import path from "node:path";
|
||||
import { normalizeOptionalLowercaseString } from "../../shared/string-coerce.js";
|
||||
import { resolveSandboxInputPath, resolveSandboxPath } from "../sandbox-paths.js";
|
||||
import type { SandboxFsBridgeContext } from "./backend-handle.types.js";
|
||||
import { splitSandboxBindSpec } from "./bind-spec.js";
|
||||
import { SANDBOX_AGENT_WORKSPACE_MOUNT } from "./constants.js";
|
||||
import { resolveSandboxHostPathViaExistingAncestor } from "./host-paths.js";
|
||||
import { isPathInsideContainerRoot, normalizeContainerPath } from "./path-utils.js";
|
||||
import type { SandboxContext } from "./types.js";
|
||||
|
||||
export type SandboxFsMount = {
|
||||
hostRoot: string;
|
||||
@@ -58,7 +58,7 @@ export function parseSandboxBindMount(spec: string): ParsedBindMount | null {
|
||||
};
|
||||
}
|
||||
|
||||
export function buildSandboxFsMounts(sandbox: SandboxContext): SandboxFsMount[] {
|
||||
export function buildSandboxFsMounts(sandbox: SandboxFsBridgeContext): SandboxFsMount[] {
|
||||
const mounts: SandboxFsMount[] = [
|
||||
{
|
||||
hostRoot: path.resolve(sandbox.workspaceDir),
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
import path from "node:path";
|
||||
import { isPathInside } from "../../infra/path-guards.js";
|
||||
import type { SandboxBackendCommandParams, SandboxBackendCommandResult } from "./backend.js";
|
||||
import type {
|
||||
SandboxBackendCommandParams,
|
||||
SandboxBackendCommandResult,
|
||||
SandboxFsBridgeContext,
|
||||
} from "./backend-handle.types.js";
|
||||
import { SANDBOX_PINNED_MUTATION_PYTHON } from "./fs-bridge-mutation-helper.js";
|
||||
import { createWritableRenameTargetResolver } from "./fs-bridge-rename-targets.js";
|
||||
import type { SandboxFsBridge, SandboxFsStat, SandboxResolvedPath } from "./fs-bridge.types.js";
|
||||
@@ -8,7 +12,6 @@ import {
|
||||
isPathInsideContainerRoot,
|
||||
normalizeContainerPath as normalizeSandboxContainerPath,
|
||||
} from "./path-utils.js";
|
||||
import type { SandboxContext } from "./types.js";
|
||||
|
||||
type ResolvedRemotePath = SandboxResolvedPath & {
|
||||
writable: boolean;
|
||||
@@ -29,7 +32,7 @@ export type RemoteShellSandboxHandle = {
|
||||
};
|
||||
|
||||
export function createRemoteShellSandboxFsBridge(params: {
|
||||
sandbox: SandboxContext;
|
||||
sandbox: SandboxFsBridgeContext;
|
||||
runtime: RemoteShellSandboxHandle;
|
||||
}): SandboxFsBridge {
|
||||
return new RemoteShellSandboxFsBridge(params.sandbox, params.runtime);
|
||||
@@ -42,7 +45,7 @@ class RemoteShellSandboxFsBridge implements SandboxFsBridge {
|
||||
);
|
||||
|
||||
constructor(
|
||||
private readonly sandbox: SandboxContext,
|
||||
private readonly sandbox: SandboxFsBridgeContext,
|
||||
private readonly runtime: RemoteShellSandboxHandle,
|
||||
) {}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { SandboxBackendHandle, SandboxBackendId } from "./backend.js";
|
||||
import type { SandboxBackendHandle, SandboxBackendId } from "./backend-handle.types.js";
|
||||
import type { SandboxFsBridge } from "./fs-bridge.types.js";
|
||||
import type { SandboxDockerConfig } from "./types.docker.js";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user