feat(gateway): add SDK environment discovery RPCs (#74867) thanks @ai-hpc

Co-authored-by: ai-hpc <183861985+ai-hpc@users.noreply.github.com>
Co-authored-by: BunsDev <68980965+BunsDev@users.noreply.github.com>
This commit is contained in:
NVIDIAN
2026-05-05 06:59:03 -07:00
committed by GitHub
parent 9f4a3932ed
commit 63de304102
21 changed files with 631 additions and 38 deletions

View File

@@ -8,6 +8,8 @@ import type {
ArtifactsDownloadResult,
ArtifactsGetResult,
ArtifactsListResult,
EnvironmentSummary,
EnvironmentsListResult,
GatewayEvent,
GatewayRequestOptions,
OpenClawEvent,
@@ -819,9 +821,8 @@ export class EnvironmentsNamespace extends RpcNamespace {
super(client, "environments");
}
async list(params?: unknown): Promise<unknown> {
void params;
return unsupportedGatewayApi("oc.environments.list");
async list(params?: unknown): Promise<EnvironmentsListResult> {
return await this.call("list", params ?? {});
}
async create(params?: unknown): Promise<unknown> {
@@ -829,9 +830,8 @@ export class EnvironmentsNamespace extends RpcNamespace {
return unsupportedGatewayApi("oc.environments.create");
}
async status(environmentId: string): Promise<unknown> {
void environmentId;
return unsupportedGatewayApi("oc.environments.status");
async status(environmentId: string): Promise<EnvironmentSummary> {
return await this.call("status", { environmentId });
}
async delete(environmentId: string): Promise<unknown> {

View File

@@ -335,15 +335,9 @@ describe("OpenClaw SDK", () => {
await expect(oc.tasks.cancel("task_123")).rejects.toThrow(
"oc.tasks.cancel is not supported by the current OpenClaw Gateway yet",
);
await expect(oc.environments.list()).rejects.toThrow(
"oc.environments.list is not supported by the current OpenClaw Gateway yet",
);
await expect(oc.environments.create({ provider: "testbox" })).rejects.toThrow(
"oc.environments.create is not supported by the current OpenClaw Gateway yet",
);
await expect(oc.environments.status("environment_123")).rejects.toThrow(
"oc.environments.status is not supported by the current OpenClaw Gateway yet",
);
await expect(oc.environments.delete("environment_123")).rejects.toThrow(
"oc.environments.delete is not supported by the current OpenClaw Gateway yet",
);
@@ -379,6 +373,36 @@ describe("OpenClaw SDK", () => {
]);
});
it("lists and reads environment status through current Gateway methods", async () => {
const gatewayEnvironment = {
id: "gateway",
type: "local",
label: "Gateway local",
status: "available",
capabilities: ["agent.run"],
};
const transport = new FakeTransport({
"environments.list": { environments: [gatewayEnvironment] },
"environments.status": gatewayEnvironment,
});
const oc = new OpenClaw({ transport });
await expect(oc.environments.list()).resolves.toEqual({
environments: [gatewayEnvironment],
});
await expect(oc.environments.status("gateway")).resolves.toEqual(gatewayEnvironment);
await expect(oc.environments.create({ provider: "testbox" })).rejects.toThrow(
"oc.environments.create is not supported by the current OpenClaw Gateway yet",
);
await expect(oc.environments.delete("gateway")).rejects.toThrow(
"oc.environments.delete is not supported by the current OpenClaw Gateway yet",
);
expect(transport.calls).toEqual([
{ method: "environments.list", params: {}, options: undefined },
{ method: "environments.status", params: { environmentId: "gateway" }, options: undefined },
]);
});
it("cancels runs and checks model auth status through current Gateway methods", async () => {
const transport = new FakeTransport({
agent: { status: "accepted", runId: "run_without_session" },

View File

@@ -27,6 +27,8 @@ export type {
ArtifactsListResult,
ConnectableOpenClawTransport,
EnvironmentSelection,
EnvironmentSummary,
EnvironmentsListResult,
GatewayEvent,
GatewayRequestOptions,
JsonObject,

View File

@@ -40,6 +40,18 @@ export type EnvironmentSelection =
| { type: "managed"; provider: string; repo?: string; ref?: string }
| { type: "ephemeral"; provider: string; repo?: string; ref?: string };
export type EnvironmentSummary = {
id: string;
type: "local" | "gateway" | "node" | "managed" | "ephemeral" | (string & {});
label?: string;
status: "available" | "unavailable" | "starting" | "stopping" | "error";
capabilities?: string[];
};
export type EnvironmentsListResult = {
environments: EnvironmentSummary[];
};
export type WorkspaceSelection = {
cwd?: string;
repo?: string;