Skip to content

Commit 723dec0

Browse files
samzongfrankekn
andauthored
[Feat] Gateway: add commands.list RPC method (openclaw#62656)
Merged via squash. Co-authored-by: samzong <samzong.lu@gmail.com> Co-authored-by: Frank Yang <frank.ekn@gmail.com> Reviewed-by: @frankekn
1 parent 4bf94aa commit 723dec0

16 files changed

Lines changed: 855 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Docs: https://docs.openclaw.ai
1313
- Gateway: split startup and runtime seams so gateway lifecycle sequencing, reload state, and shutdown behavior stay easier to maintain without changing observed behavior. (#63975) Thanks @gumadeiras.
1414
- CLI/exec policy: add a local `openclaw exec-policy` command with `show`, `preset`, and `set` subcommands for synchronizing requested `tools.exec.*` config with the local exec approvals file, plus follow-up hardening for node-host rejection, rollback safety, and sync conflict detection.
1515
- Models/providers: add per-provider `models.providers.*.request.allowPrivateNetwork` for trusted self-hosted OpenAI-compatible endpoints, keep the opt-in scoped to model request surfaces, and refresh cached WebSocket managers when request transport overrides change. (#63671) Thanks @qas.
16+
- Gateway: add a `commands.list` RPC so remote gateway clients can discover runtime-native, text, skill, and plugin commands with surface-aware naming and serialized argument metadata. (#62656) Thanks @samzong.
1617

1718
### Fixes
1819

apps/macos/Sources/OpenClawProtocol/GatewayModels.swift

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2883,6 +2883,92 @@ public struct ModelsListResult: Codable, Sendable {
28832883
}
28842884
}
28852885

2886+
public struct CommandEntry: Codable, Sendable {
2887+
public let name: String
2888+
public let nativename: String?
2889+
public let textaliases: [String]?
2890+
public let description: String
2891+
public let category: AnyCodable?
2892+
public let source: AnyCodable
2893+
public let scope: AnyCodable
2894+
public let acceptsargs: Bool
2895+
public let args: [[String: AnyCodable]]?
2896+
2897+
public init(
2898+
name: String,
2899+
nativename: String?,
2900+
textaliases: [String]?,
2901+
description: String,
2902+
category: AnyCodable?,
2903+
source: AnyCodable,
2904+
scope: AnyCodable,
2905+
acceptsargs: Bool,
2906+
args: [[String: AnyCodable]]?)
2907+
{
2908+
self.name = name
2909+
self.nativename = nativename
2910+
self.textaliases = textaliases
2911+
self.description = description
2912+
self.category = category
2913+
self.source = source
2914+
self.scope = scope
2915+
self.acceptsargs = acceptsargs
2916+
self.args = args
2917+
}
2918+
2919+
private enum CodingKeys: String, CodingKey {
2920+
case name
2921+
case nativename = "nativeName"
2922+
case textaliases = "textAliases"
2923+
case description
2924+
case category
2925+
case source
2926+
case scope
2927+
case acceptsargs = "acceptsArgs"
2928+
case args
2929+
}
2930+
}
2931+
2932+
public struct CommandsListParams: Codable, Sendable {
2933+
public let agentid: String?
2934+
public let provider: String?
2935+
public let scope: AnyCodable?
2936+
public let includeargs: Bool?
2937+
2938+
public init(
2939+
agentid: String?,
2940+
provider: String?,
2941+
scope: AnyCodable?,
2942+
includeargs: Bool?)
2943+
{
2944+
self.agentid = agentid
2945+
self.provider = provider
2946+
self.scope = scope
2947+
self.includeargs = includeargs
2948+
}
2949+
2950+
private enum CodingKeys: String, CodingKey {
2951+
case agentid = "agentId"
2952+
case provider
2953+
case scope
2954+
case includeargs = "includeArgs"
2955+
}
2956+
}
2957+
2958+
public struct CommandsListResult: Codable, Sendable {
2959+
public let commands: [CommandEntry]
2960+
2961+
public init(
2962+
commands: [CommandEntry])
2963+
{
2964+
self.commands = commands
2965+
}
2966+
2967+
private enum CodingKeys: String, CodingKey {
2968+
case commands
2969+
}
2970+
}
2971+
28862972
public struct SkillsStatusParams: Codable, Sendable {
28872973
public let agentid: String?
28882974

apps/shared/OpenClawKit/Sources/OpenClawProtocol/GatewayModels.swift

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2883,6 +2883,92 @@ public struct ModelsListResult: Codable, Sendable {
28832883
}
28842884
}
28852885

2886+
public struct CommandEntry: Codable, Sendable {
2887+
public let name: String
2888+
public let nativename: String?
2889+
public let textaliases: [String]?
2890+
public let description: String
2891+
public let category: AnyCodable?
2892+
public let source: AnyCodable
2893+
public let scope: AnyCodable
2894+
public let acceptsargs: Bool
2895+
public let args: [[String: AnyCodable]]?
2896+
2897+
public init(
2898+
name: String,
2899+
nativename: String?,
2900+
textaliases: [String]?,
2901+
description: String,
2902+
category: AnyCodable?,
2903+
source: AnyCodable,
2904+
scope: AnyCodable,
2905+
acceptsargs: Bool,
2906+
args: [[String: AnyCodable]]?)
2907+
{
2908+
self.name = name
2909+
self.nativename = nativename
2910+
self.textaliases = textaliases
2911+
self.description = description
2912+
self.category = category
2913+
self.source = source
2914+
self.scope = scope
2915+
self.acceptsargs = acceptsargs
2916+
self.args = args
2917+
}
2918+
2919+
private enum CodingKeys: String, CodingKey {
2920+
case name
2921+
case nativename = "nativeName"
2922+
case textaliases = "textAliases"
2923+
case description
2924+
case category
2925+
case source
2926+
case scope
2927+
case acceptsargs = "acceptsArgs"
2928+
case args
2929+
}
2930+
}
2931+
2932+
public struct CommandsListParams: Codable, Sendable {
2933+
public let agentid: String?
2934+
public let provider: String?
2935+
public let scope: AnyCodable?
2936+
public let includeargs: Bool?
2937+
2938+
public init(
2939+
agentid: String?,
2940+
provider: String?,
2941+
scope: AnyCodable?,
2942+
includeargs: Bool?)
2943+
{
2944+
self.agentid = agentid
2945+
self.provider = provider
2946+
self.scope = scope
2947+
self.includeargs = includeargs
2948+
}
2949+
2950+
private enum CodingKeys: String, CodingKey {
2951+
case agentid = "agentId"
2952+
case provider
2953+
case scope
2954+
case includeargs = "includeArgs"
2955+
}
2956+
}
2957+
2958+
public struct CommandsListResult: Codable, Sendable {
2959+
public let commands: [CommandEntry]
2960+
2961+
public init(
2962+
commands: [CommandEntry])
2963+
{
2964+
self.commands = commands
2965+
}
2966+
2967+
private enum CodingKeys: String, CodingKey {
2968+
case commands
2969+
}
2970+
}
2971+
28862972
public struct SkillsStatusParams: Codable, Sendable {
28872973
public let agentid: String?
28882974

docs/gateway/protocol.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ implemented in `src/gateway/server-methods/*.ts`.
400400
- `wake` schedules an immediate or next-heartbeat wake text injection
401401
- `cron.list`, `cron.status`, `cron.add`, `cron.update`, `cron.remove`,
402402
`cron.run`, `cron.runs`
403-
- skills/tools: `skills.*`, `tools.catalog`, `tools.effective`
403+
- skills/tools: `commands.list`, `skills.*`, `tools.catalog`, `tools.effective`
404404

405405
### Common event families
406406

@@ -431,6 +431,18 @@ implemented in `src/gateway/server-methods/*.ts`.
431431

432432
### Operator helper methods
433433

434+
- Operators may call `commands.list` (`operator.read`) to fetch the runtime
435+
command inventory for an agent.
436+
- `agentId` is optional; omit it to read the default agent workspace.
437+
- `scope` controls which surface the primary `name` targets:
438+
- `text` returns the primary text command token without the leading `/`
439+
- `native` and the default `both` path return provider-aware native names
440+
when available
441+
- `textAliases` carries exact slash aliases such as `/model` and `/m`.
442+
- `nativeName` carries the provider-aware native command name when one exists.
443+
- `provider` is optional and only affects native naming plus native plugin
444+
command availability.
445+
- `includeArgs=false` omits serialized argument metadata from the response.
434446
- Operators may call `tools.catalog` (`operator.read`) to fetch the runtime tool catalog for an
435447
agent. The response includes grouped tools and provenance metadata:
436448
- `source`: `core` or `plugin`

src/gateway/method-scopes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ const METHOD_SCOPE_GROUPS: Record<OperatorScope, readonly string[]> = {
7676
"usage.cost",
7777
"tts.status",
7878
"tts.providers",
79+
"commands.list",
7980
"models.list",
8081
"tools.catalog",
8182
"tools.effective",

src/gateway/protocol/index.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ import {
5656
ChannelsStatusParamsSchema,
5757
type ChannelsStatusResult,
5858
ChannelsStatusResultSchema,
59+
type CommandEntry,
60+
type CommandsListParams,
61+
CommandsListParamsSchema,
62+
type CommandsListResult,
63+
CommandsListResultSchema,
5964
type ChatAbortParams,
6065
ChatAbortParamsSchema,
6166
type ChatEvent,
@@ -295,6 +300,7 @@ const ajv = new (AjvPkg as unknown as new (opts?: object) => import("ajv").defau
295300
removeAdditional: false,
296301
});
297302

303+
export const validateCommandsListParams = ajv.compile<CommandsListParams>(CommandsListParamsSchema);
298304
export const validateConnectParams = ajv.compile<ConnectParams>(ConnectParamsSchema);
299305
export const validateRequestFrame = ajv.compile<RequestFrame>(RequestFrameSchema);
300306
export const validateResponseFrame = ajv.compile<ResponseFrame>(ResponseFrameSchema);
@@ -624,6 +630,8 @@ export {
624630
AgentsFilesSetResultSchema,
625631
AgentsListParamsSchema,
626632
AgentsListResultSchema,
633+
CommandsListParamsSchema,
634+
CommandsListResultSchema,
627635
ModelsListParamsSchema,
628636
SkillsStatusParamsSchema,
629637
ToolsCatalogParamsSchema,
@@ -726,6 +734,9 @@ export type {
726734
AgentsFilesSetResult,
727735
AgentsListParams,
728736
AgentsListResult,
737+
CommandsListParams,
738+
CommandsListResult,
739+
CommandEntry,
729740
SkillsStatusParams,
730741
ToolsCatalogParams,
731742
ToolsCatalogResult,

src/gateway/protocol/schema.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export * from "./schema/agent.js";
22
export * from "./schema/agents-models-skills.js";
33
export * from "./schema/channels.js";
4+
export * from "./schema/commands.js";
45
export * from "./schema/config.js";
56
export * from "./schema/cron.js";
67
export * from "./schema/error-codes.js";
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { Type } from "@sinclair/typebox";
2+
import { NonEmptyString } from "./primitives.js";
3+
4+
export const CommandSourceSchema = Type.Union([
5+
Type.Literal("native"),
6+
Type.Literal("skill"),
7+
Type.Literal("plugin"),
8+
]);
9+
10+
export const CommandScopeSchema = Type.Union([
11+
Type.Literal("text"),
12+
Type.Literal("native"),
13+
Type.Literal("both"),
14+
]);
15+
16+
export const CommandCategorySchema = Type.Union([
17+
Type.Literal("session"),
18+
Type.Literal("options"),
19+
Type.Literal("status"),
20+
Type.Literal("management"),
21+
Type.Literal("media"),
22+
Type.Literal("tools"),
23+
Type.Literal("docks"),
24+
]);
25+
26+
export const CommandArgChoiceSchema = Type.Object(
27+
{
28+
value: Type.String(),
29+
label: Type.String(),
30+
},
31+
{ additionalProperties: false },
32+
);
33+
34+
export const CommandArgSchema = Type.Object(
35+
{
36+
name: NonEmptyString,
37+
description: Type.String(),
38+
type: Type.Union([Type.Literal("string"), Type.Literal("number"), Type.Literal("boolean")]),
39+
required: Type.Optional(Type.Boolean()),
40+
choices: Type.Optional(Type.Array(CommandArgChoiceSchema)),
41+
dynamic: Type.Optional(Type.Boolean()),
42+
},
43+
{ additionalProperties: false },
44+
);
45+
46+
export const CommandEntrySchema = Type.Object(
47+
{
48+
name: NonEmptyString,
49+
nativeName: Type.Optional(NonEmptyString),
50+
textAliases: Type.Optional(Type.Array(NonEmptyString)),
51+
description: Type.String(),
52+
category: Type.Optional(CommandCategorySchema),
53+
source: CommandSourceSchema,
54+
scope: CommandScopeSchema,
55+
acceptsArgs: Type.Boolean(),
56+
args: Type.Optional(Type.Array(CommandArgSchema)),
57+
},
58+
{ additionalProperties: false },
59+
);
60+
61+
export const CommandsListParamsSchema = Type.Object(
62+
{
63+
agentId: Type.Optional(NonEmptyString),
64+
provider: Type.Optional(NonEmptyString),
65+
scope: Type.Optional(CommandScopeSchema),
66+
includeArgs: Type.Optional(Type.Boolean()),
67+
},
68+
{ additionalProperties: false },
69+
);
70+
71+
export const CommandsListResultSchema = Type.Object(
72+
{
73+
commands: Type.Array(CommandEntrySchema),
74+
},
75+
{ additionalProperties: false },
76+
);

src/gateway/protocol/schema/protocol-schemas.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@ import {
6060
WebLoginStartParamsSchema,
6161
WebLoginWaitParamsSchema,
6262
} from "./channels.js";
63+
import {
64+
CommandEntrySchema,
65+
CommandsListParamsSchema,
66+
CommandsListResultSchema,
67+
} from "./commands.js";
6368
import {
6469
ConfigApplyParamsSchema,
6570
ConfigGetParamsSchema,
@@ -297,6 +302,9 @@ export const ProtocolSchemas = {
297302
ModelChoice: ModelChoiceSchema,
298303
ModelsListParams: ModelsListParamsSchema,
299304
ModelsListResult: ModelsListResultSchema,
305+
CommandEntry: CommandEntrySchema,
306+
CommandsListParams: CommandsListParamsSchema,
307+
CommandsListResult: CommandsListResultSchema,
300308
SkillsStatusParams: SkillsStatusParamsSchema,
301309
ToolsCatalogParams: ToolsCatalogParamsSchema,
302310
ToolCatalogProfile: ToolCatalogProfileSchema,

src/gateway/protocol/schema/types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ export type AgentsListResult = SchemaType<"AgentsListResult">;
105105
export type ModelChoice = SchemaType<"ModelChoice">;
106106
export type ModelsListParams = SchemaType<"ModelsListParams">;
107107
export type ModelsListResult = SchemaType<"ModelsListResult">;
108+
export type CommandEntry = SchemaType<"CommandEntry">;
109+
export type CommandsListParams = SchemaType<"CommandsListParams">;
110+
export type CommandsListResult = SchemaType<"CommandsListResult">;
108111
export type SkillsStatusParams = SchemaType<"SkillsStatusParams">;
109112
export type ToolsCatalogParams = SchemaType<"ToolsCatalogParams">;
110113
export type ToolCatalogProfile = SchemaType<"ToolCatalogProfile">;

0 commit comments

Comments
 (0)