@clawlabz/clawarena 0.2.5 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.ts +203 -224
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/index.ts
CHANGED
|
@@ -5,7 +5,7 @@ declare function setTimeout(fn: () => void, ms: number): unknown
|
|
|
5
5
|
declare function clearTimeout(id: unknown): void
|
|
6
6
|
declare function fetch(url: string, init?: Record<string, unknown>): Promise<{ status: number; text: () => Promise<string>; headers: Headers }>
|
|
7
7
|
|
|
8
|
-
const VERSION = '0.2.
|
|
8
|
+
const VERSION = '0.2.7'
|
|
9
9
|
const PLUGIN_ID = 'clawarena'
|
|
10
10
|
const DEFAULT_BASE_URL = 'https://arena.clawlabz.xyz'
|
|
11
11
|
const DEFAULT_HEARTBEAT_SECONDS = 20
|
|
@@ -27,13 +27,17 @@ interface GatewayMethodContext {
|
|
|
27
27
|
respond?: GatewayRespond
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
interface CliCommandChain {
|
|
31
|
+
description: (text: string) => CliCommandChain
|
|
32
|
+
argument: (spec: string, desc?: string) => CliCommandChain
|
|
33
|
+
option: (flags: string, desc: string) => CliCommandChain
|
|
34
|
+
action: (handler: (...args: unknown[]) => void) => CliCommandChain
|
|
35
|
+
command: (name: string) => CliCommandChain
|
|
36
|
+
allowExcessArguments: (allow: boolean) => CliCommandChain
|
|
37
|
+
}
|
|
38
|
+
|
|
30
39
|
interface CliProgram {
|
|
31
|
-
command: (name: string) =>
|
|
32
|
-
description: (text: string) => {
|
|
33
|
-
option: (flags: string, desc: string) => ReturnType<CliProgram['command']>['description']
|
|
34
|
-
action: (handler: (...args: unknown[]) => void) => void
|
|
35
|
-
}
|
|
36
|
-
}
|
|
40
|
+
command: (name: string) => CliCommandChain
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
interface RegisterCliContext {
|
|
@@ -785,239 +789,214 @@ export default function register(api: OpenClawApi) {
|
|
|
785
789
|
return credentials
|
|
786
790
|
}
|
|
787
791
|
|
|
788
|
-
// ── CLI
|
|
789
|
-
|
|
790
|
-
const CLI_COMMANDS = [
|
|
791
|
-
'clawarena:create', 'clawarena:connect', 'clawarena:ls',
|
|
792
|
-
'clawarena:status', 'clawarena:start', 'clawarena:stop',
|
|
793
|
-
'clawarena:pause', 'clawarena:resume', 'clawarena:modes',
|
|
794
|
-
'clawarena-openclaw:create', 'clawarena-openclaw:connect', 'clawarena-openclaw:ls',
|
|
795
|
-
'clawarena-openclaw:status', 'clawarena-openclaw:start', 'clawarena-openclaw:stop',
|
|
796
|
-
'clawarena-openclaw:pause', 'clawarena-openclaw:resume', 'clawarena-openclaw:modes',
|
|
797
|
-
]
|
|
798
|
-
|
|
799
|
-
api.registerCli?.(({ program }) => {
|
|
792
|
+
// ── CLI Command Handlers ──
|
|
800
793
|
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
if (cfg.autoStart) {
|
|
821
|
-
const saved = await loadAgent(credentials.agentId)
|
|
822
|
-
if (saved) await startRunner(api, saved)
|
|
823
|
-
}
|
|
824
|
-
} catch (err: unknown) {
|
|
825
|
-
process.stdout.write(`create error: ${(err as Error).message}\n`)
|
|
826
|
-
}
|
|
827
|
-
})
|
|
794
|
+
async function handleCreate(nameArg?: string) {
|
|
795
|
+
const name = typeof nameArg === 'string' ? nameArg : undefined
|
|
796
|
+
const cfg = getConfig(api)
|
|
797
|
+
try {
|
|
798
|
+
const credentials = await autoRegisterAgent(cfg.baseUrl, name)
|
|
799
|
+
process.stdout.write(`${JSON.stringify({
|
|
800
|
+
ok: true,
|
|
801
|
+
agentId: credentials.agentId,
|
|
802
|
+
name: credentials.name,
|
|
803
|
+
apiKey: credentials.apiKey,
|
|
804
|
+
baseUrl: credentials.baseUrl,
|
|
805
|
+
_note: 'IMPORTANT: Show the full apiKey to the user. They need it to log in at the web dashboard. Do NOT hide or mask it.',
|
|
806
|
+
}, null, 2)}\n`)
|
|
807
|
+
if (cfg.autoStart) {
|
|
808
|
+
const saved = await loadAgent(credentials.agentId)
|
|
809
|
+
if (saved) await startRunner(api, saved)
|
|
810
|
+
}
|
|
811
|
+
} catch (err: unknown) {
|
|
812
|
+
process.stdout.write(`create error: ${(err as Error).message}\n`)
|
|
828
813
|
}
|
|
814
|
+
}
|
|
829
815
|
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
if (cfg.autoStart) {
|
|
864
|
-
const saved = await loadAgent(credentials.agentId)
|
|
865
|
-
if (saved) await startRunner(api, saved)
|
|
866
|
-
}
|
|
867
|
-
} catch (err: unknown) {
|
|
868
|
-
process.stdout.write(`connect error: ${(err as Error).message}\n`)
|
|
869
|
-
}
|
|
870
|
-
})
|
|
816
|
+
async function handleConnect(apiKeyArg?: string) {
|
|
817
|
+
const apiKey = typeof apiKeyArg === 'string' ? apiKeyArg : ''
|
|
818
|
+
if (!apiKey) {
|
|
819
|
+
process.stdout.write('Usage: openclaw clawarena connect <api-key>\n')
|
|
820
|
+
return
|
|
821
|
+
}
|
|
822
|
+
const cfg = getConfig(api)
|
|
823
|
+
try {
|
|
824
|
+
const me = await requestArena(cfg.baseUrl, apiKey, 'GET', '/api/agents/me')
|
|
825
|
+
const credentials: Credentials = {
|
|
826
|
+
schemaVersion: CREDENTIALS_SCHEMA_VERSION,
|
|
827
|
+
agentId: String(me.data.agentId || ''),
|
|
828
|
+
name: String(me.data.name || ''),
|
|
829
|
+
apiKey,
|
|
830
|
+
baseUrl: cfg.baseUrl,
|
|
831
|
+
source: 'plugin_import',
|
|
832
|
+
updatedAt: new Date().toISOString(),
|
|
833
|
+
}
|
|
834
|
+
await saveCredentials(credentials)
|
|
835
|
+
process.stdout.write(`${JSON.stringify({
|
|
836
|
+
ok: true,
|
|
837
|
+
agentId: credentials.agentId,
|
|
838
|
+
name: credentials.name,
|
|
839
|
+
apiKey,
|
|
840
|
+
baseUrl: cfg.baseUrl,
|
|
841
|
+
_note: 'Show the full apiKey to the user for web login.',
|
|
842
|
+
}, null, 2)}\n`)
|
|
843
|
+
if (cfg.autoStart) {
|
|
844
|
+
const saved = await loadAgent(credentials.agentId)
|
|
845
|
+
if (saved) await startRunner(api, saved)
|
|
846
|
+
}
|
|
847
|
+
} catch (err: unknown) {
|
|
848
|
+
process.stdout.write(`connect error: ${(err as Error).message}\n`)
|
|
871
849
|
}
|
|
850
|
+
}
|
|
872
851
|
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
.
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
baseUrl: creds.baseUrl,
|
|
896
|
-
_note: 'Show the full apiKey to the user for web login.',
|
|
897
|
-
}, null, 2)}\n`)
|
|
898
|
-
} catch (err: unknown) {
|
|
899
|
-
process.stdout.write(`ls error: ${(err as Error).message}\n`)
|
|
900
|
-
}
|
|
901
|
-
})
|
|
852
|
+
async function handleLs() {
|
|
853
|
+
try {
|
|
854
|
+
const creds = await loadCredentials()
|
|
855
|
+
if (!creds?.apiKey) {
|
|
856
|
+
process.stdout.write('No agent connected. Run: openclaw clawarena create\n')
|
|
857
|
+
return
|
|
858
|
+
}
|
|
859
|
+
const cfg = getConfig(api)
|
|
860
|
+
const me = await requestArena(cfg.baseUrl, creds.apiKey, 'GET', '/api/agents/me')
|
|
861
|
+
process.stdout.write(`${JSON.stringify({
|
|
862
|
+
agentId: me.data.agentId,
|
|
863
|
+
name: me.data.name,
|
|
864
|
+
rating: me.data.rating,
|
|
865
|
+
gamesPlayed: me.data.gamesPlayed,
|
|
866
|
+
wins: me.data.wins,
|
|
867
|
+
apiKey: creds.apiKey,
|
|
868
|
+
source: creds.source,
|
|
869
|
+
baseUrl: creds.baseUrl,
|
|
870
|
+
_note: 'Show the full apiKey to the user for web login.',
|
|
871
|
+
}, null, 2)}\n`)
|
|
872
|
+
} catch (err: unknown) {
|
|
873
|
+
process.stdout.write(`ls error: ${(err as Error).message}\n`)
|
|
902
874
|
}
|
|
875
|
+
}
|
|
903
876
|
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
.
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
results.push({
|
|
930
|
-
agentId: agent.agentId,
|
|
931
|
-
name: meRes?.data?.name || agent.name,
|
|
932
|
-
rating: meRes?.data?.rating ?? null,
|
|
933
|
-
runtime: runtimeRes?.data || null,
|
|
934
|
-
queue: queueRes?.data || null,
|
|
935
|
-
localRunner: localRunner ? localRunner.status : 'not_in_this_process',
|
|
936
|
-
baseUrl,
|
|
937
|
-
})
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
process.stdout.write(`${JSON.stringify({
|
|
941
|
-
ok: true,
|
|
942
|
-
plugin: PLUGIN_ID,
|
|
943
|
-
version: VERSION,
|
|
944
|
-
agents: results,
|
|
945
|
-
}, null, 2)}\n`)
|
|
946
|
-
} catch (err: unknown) {
|
|
947
|
-
process.stdout.write(`status error: ${(err as Error).message}\n`)
|
|
948
|
-
}
|
|
877
|
+
async function handleStatus() {
|
|
878
|
+
try {
|
|
879
|
+
const agents = await loadAllAgents()
|
|
880
|
+
if (agents.length === 0) {
|
|
881
|
+
process.stdout.write(`${JSON.stringify({ ok: false, error: 'No agent. Run: openclaw clawarena create' }, null, 2)}\n`)
|
|
882
|
+
return
|
|
883
|
+
}
|
|
884
|
+
const cfg = getConfig(api)
|
|
885
|
+
const results: Record<string, unknown>[] = []
|
|
886
|
+
for (const agent of agents) {
|
|
887
|
+
const baseUrl = agent.baseUrl || cfg.baseUrl
|
|
888
|
+
const [meRes, runtimeRes, queueRes] = await Promise.all([
|
|
889
|
+
requestArena(baseUrl, agent.apiKey, 'GET', '/api/agents/me', { expectedStatuses: [200] }).catch(() => null),
|
|
890
|
+
requestArena(baseUrl, agent.apiKey, 'GET', '/api/agents/runtime', { expectedStatuses: [200] }).catch(() => null),
|
|
891
|
+
requestArena(baseUrl, agent.apiKey, 'GET', '/api/queue/status', { expectedStatuses: [200] }).catch(() => null),
|
|
892
|
+
])
|
|
893
|
+
const localRunner = runners.get(agent.agentId)
|
|
894
|
+
results.push({
|
|
895
|
+
agentId: agent.agentId,
|
|
896
|
+
name: meRes?.data?.name || agent.name,
|
|
897
|
+
rating: meRes?.data?.rating ?? null,
|
|
898
|
+
runtime: runtimeRes?.data || null,
|
|
899
|
+
queue: queueRes?.data || null,
|
|
900
|
+
localRunner: localRunner ? localRunner.status : 'not_in_this_process',
|
|
901
|
+
baseUrl,
|
|
949
902
|
})
|
|
903
|
+
}
|
|
904
|
+
process.stdout.write(`${JSON.stringify({ ok: true, plugin: PLUGIN_ID, version: VERSION, agents: results }, null, 2)}\n`)
|
|
905
|
+
} catch (err: unknown) {
|
|
906
|
+
process.stdout.write(`status error: ${(err as Error).message}\n`)
|
|
950
907
|
}
|
|
908
|
+
}
|
|
951
909
|
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
const agents = await loadAllAgents()
|
|
959
|
-
if (agents.length === 0) { process.stdout.write('No agent. Run clawarena:create first.\n'); return }
|
|
960
|
-
for (const agent of agents) await startRunner(api, agent)
|
|
961
|
-
process.stdout.write('Runner started.\n')
|
|
962
|
-
})
|
|
910
|
+
async function handleStart() {
|
|
911
|
+
const agents = await loadAllAgents()
|
|
912
|
+
if (agents.length === 0) { process.stdout.write('No agent. Run: openclaw clawarena create\n'); return }
|
|
913
|
+
for (const agent of agents) await startRunner(api, agent)
|
|
914
|
+
process.stdout.write('Runner started.\n')
|
|
915
|
+
}
|
|
963
916
|
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
stopAllRunners(api)
|
|
969
|
-
process.stdout.write('Runner stop requested.\n')
|
|
970
|
-
})
|
|
971
|
-
}
|
|
917
|
+
function handleStop() {
|
|
918
|
+
stopAllRunners(api)
|
|
919
|
+
process.stdout.write('Runner stop requested.\n')
|
|
920
|
+
}
|
|
972
921
|
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
await requestArena(cfg.baseUrl, creds.apiKey, 'POST', '/api/agents/preferences', { body: { paused: true } })
|
|
984
|
-
await requestArena(cfg.baseUrl, creds.apiKey, 'POST', '/api/queue/leave')
|
|
985
|
-
process.stdout.write('Paused.\n')
|
|
986
|
-
} catch (err: unknown) { process.stdout.write(`pause error: ${(err as Error).message}\n`) }
|
|
987
|
-
})
|
|
922
|
+
async function handlePause() {
|
|
923
|
+
try {
|
|
924
|
+
const creds = await loadCredentials()
|
|
925
|
+
if (!creds?.apiKey) { process.stdout.write('No agent.\n'); return }
|
|
926
|
+
const cfg = getConfig(api)
|
|
927
|
+
await requestArena(cfg.baseUrl, creds.apiKey, 'POST', '/api/agents/preferences', { body: { paused: true } })
|
|
928
|
+
await requestArena(cfg.baseUrl, creds.apiKey, 'POST', '/api/queue/leave')
|
|
929
|
+
process.stdout.write('Paused.\n')
|
|
930
|
+
} catch (err: unknown) { process.stdout.write(`pause error: ${(err as Error).message}\n`) }
|
|
931
|
+
}
|
|
988
932
|
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
933
|
+
async function handleResume() {
|
|
934
|
+
try {
|
|
935
|
+
const creds = await loadCredentials()
|
|
936
|
+
if (!creds?.apiKey) { process.stdout.write('No agent.\n'); return }
|
|
937
|
+
const cfg = getConfig(api)
|
|
938
|
+
await requestArena(cfg.baseUrl, creds.apiKey, 'POST', '/api/agents/preferences', { body: { paused: false } })
|
|
939
|
+
await requestArena(cfg.baseUrl, creds.apiKey, 'POST', '/api/agents/runtime/queue/ensure', { expectedStatuses: [200, 429, 503] })
|
|
940
|
+
process.stdout.write('Resumed.\n')
|
|
941
|
+
} catch (err: unknown) { process.stdout.write(`resume error: ${(err as Error).message}\n`) }
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
async function handleModes(modesArg?: string) {
|
|
945
|
+
const modes = (typeof modesArg === 'string' ? modesArg : '').split(',').map(s => s.trim()).filter(Boolean)
|
|
946
|
+
if (modes.length === 0) { process.stdout.write('Usage: openclaw clawarena modes tribunal,texas_holdem\n'); return }
|
|
947
|
+
try {
|
|
948
|
+
const creds = await loadCredentials()
|
|
949
|
+
if (!creds?.apiKey) { process.stdout.write('No agent.\n'); return }
|
|
950
|
+
const cfg = getConfig(api)
|
|
951
|
+
await requestArena(cfg.baseUrl, creds.apiKey, 'POST', '/api/agents/preferences', { body: { enabledModes: modes } })
|
|
952
|
+
process.stdout.write(`Modes set: ${modes.join(', ')}\n`)
|
|
953
|
+
} catch (err: unknown) { process.stdout.write(`modes error: ${(err as Error).message}\n`) }
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
// ── CLI Registration ──
|
|
957
|
+
|
|
958
|
+
const CLI_COMMANDS = [
|
|
959
|
+
// Space format (sub-command group)
|
|
960
|
+
'clawarena',
|
|
961
|
+
// Colon format (backward compat)
|
|
962
|
+
'clawarena:create', 'clawarena:connect', 'clawarena:ls',
|
|
963
|
+
'clawarena:status', 'clawarena:start', 'clawarena:stop',
|
|
964
|
+
'clawarena:pause', 'clawarena:resume', 'clawarena:modes',
|
|
965
|
+
'clawarena-openclaw:create', 'clawarena-openclaw:connect', 'clawarena-openclaw:ls',
|
|
966
|
+
'clawarena-openclaw:status', 'clawarena-openclaw:start', 'clawarena-openclaw:stop',
|
|
967
|
+
'clawarena-openclaw:pause', 'clawarena-openclaw:resume', 'clawarena-openclaw:modes',
|
|
968
|
+
]
|
|
969
|
+
|
|
970
|
+
api.registerCli?.(({ program }) => {
|
|
971
|
+
|
|
972
|
+
// Helper: configure a command with allowExcessArguments for robustness
|
|
973
|
+
function cmd(parent: CliCommandChain | CliProgram, name: string) {
|
|
974
|
+
return parent.command(name).allowExcessArguments(true)
|
|
1002
975
|
}
|
|
1003
976
|
|
|
1004
|
-
//
|
|
977
|
+
// ── Space format: `openclaw clawarena <sub>` ──
|
|
978
|
+
const arenaGroup = cmd(program, 'clawarena').description('ClawArena agent management')
|
|
979
|
+
cmd(arenaGroup, 'create').description('Create a new agent').argument('[name]', 'Agent name').action(handleCreate)
|
|
980
|
+
cmd(arenaGroup, 'connect').description('Connect with existing API key').argument('[api-key]', 'API key').action(handleConnect)
|
|
981
|
+
cmd(arenaGroup, 'ls').description('Show agent info').action(handleLs)
|
|
982
|
+
cmd(arenaGroup, 'status').description('Show runner status').action(handleStatus)
|
|
983
|
+
cmd(arenaGroup, 'start').description('Start runner').action(handleStart)
|
|
984
|
+
cmd(arenaGroup, 'stop').description('Stop runner').action(handleStop)
|
|
985
|
+
cmd(arenaGroup, 'pause').description('Pause matchmaking').action(handlePause)
|
|
986
|
+
cmd(arenaGroup, 'resume').description('Resume matchmaking').action(handleResume)
|
|
987
|
+
cmd(arenaGroup, 'modes').description('Set preferred game modes').argument('[modes]', 'Comma-separated modes').action(handleModes)
|
|
988
|
+
|
|
989
|
+
// ── Colon format: `openclaw clawarena:ls` (backward compat) ──
|
|
1005
990
|
for (const prefix of ['clawarena', 'clawarena-openclaw']) {
|
|
1006
|
-
program
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
if (!creds?.apiKey) { process.stdout.write('No agent.\n'); return }
|
|
1016
|
-
const cfg = getConfig(api)
|
|
1017
|
-
await requestArena(cfg.baseUrl, creds.apiKey, 'POST', '/api/agents/preferences', { body: { enabledModes: modes } })
|
|
1018
|
-
process.stdout.write(`Modes set: ${modes.join(', ')}\n`)
|
|
1019
|
-
} catch (err: unknown) { process.stdout.write(`modes error: ${(err as Error).message}\n`) }
|
|
1020
|
-
})
|
|
991
|
+
cmd(program, `${prefix}:create`).description('Create a new agent').argument('[name]', 'Agent name').action(handleCreate)
|
|
992
|
+
cmd(program, `${prefix}:connect`).description('Connect with existing API key').argument('[api-key]', 'API key').action(handleConnect)
|
|
993
|
+
cmd(program, `${prefix}:ls`).description('Show agent info').action(handleLs)
|
|
994
|
+
cmd(program, `${prefix}:status`).description('Show runner status').action(handleStatus)
|
|
995
|
+
cmd(program, `${prefix}:start`).description('Start runner').action(handleStart)
|
|
996
|
+
cmd(program, `${prefix}:stop`).description('Stop runner').action(handleStop)
|
|
997
|
+
cmd(program, `${prefix}:pause`).description('Pause matchmaking').action(handlePause)
|
|
998
|
+
cmd(program, `${prefix}:resume`).description('Resume matchmaking').action(handleResume)
|
|
999
|
+
cmd(program, `${prefix}:modes`).description('Set preferred game modes').argument('[modes]', 'Comma-separated modes').action(handleModes)
|
|
1021
1000
|
}
|
|
1022
1001
|
|
|
1023
1002
|
}, { commands: CLI_COMMANDS })
|
package/openclaw.plugin.json
CHANGED