agent-relay 3.1.0 → 3.1.2

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.
Files changed (159) hide show
  1. package/bin/agent-relay-broker-linux-x64 +0 -0
  2. package/package.json +9 -9
  3. package/packages/acp-bridge/package.json +2 -2
  4. package/packages/config/package.json +1 -1
  5. package/packages/hooks/package.json +4 -4
  6. package/packages/memory/package.json +2 -2
  7. package/packages/openclaw/README.md +78 -0
  8. package/packages/openclaw/bin/relay-openclaw.mjs +2 -0
  9. package/packages/openclaw/bridge/bridge.mjs +305 -0
  10. package/packages/openclaw/dist/__tests__/gateway-control.test.d.ts +2 -0
  11. package/packages/openclaw/dist/__tests__/gateway-control.test.d.ts.map +1 -0
  12. package/packages/openclaw/dist/__tests__/gateway-control.test.js +250 -0
  13. package/packages/openclaw/dist/__tests__/gateway-control.test.js.map +1 -0
  14. package/packages/openclaw/dist/__tests__/gateway-threads.test.d.ts +2 -0
  15. package/packages/openclaw/dist/__tests__/gateway-threads.test.d.ts.map +1 -0
  16. package/packages/openclaw/dist/__tests__/gateway-threads.test.js +937 -0
  17. package/packages/openclaw/dist/__tests__/gateway-threads.test.js.map +1 -0
  18. package/packages/openclaw/dist/__tests__/naming.test.d.ts +2 -0
  19. package/packages/openclaw/dist/__tests__/naming.test.d.ts.map +1 -0
  20. package/packages/openclaw/dist/__tests__/naming.test.js +21 -0
  21. package/packages/openclaw/dist/__tests__/naming.test.js.map +1 -0
  22. package/packages/openclaw/dist/__tests__/spawn-manager.test.d.ts +2 -0
  23. package/packages/openclaw/dist/__tests__/spawn-manager.test.d.ts.map +1 -0
  24. package/packages/openclaw/dist/__tests__/spawn-manager.test.js +155 -0
  25. package/packages/openclaw/dist/__tests__/spawn-manager.test.js.map +1 -0
  26. package/packages/openclaw/dist/__tests__/ws-client.test.d.ts +2 -0
  27. package/packages/openclaw/dist/__tests__/ws-client.test.d.ts.map +1 -0
  28. package/packages/openclaw/dist/__tests__/ws-client.test.js +324 -0
  29. package/packages/openclaw/dist/__tests__/ws-client.test.js.map +1 -0
  30. package/packages/openclaw/dist/auth/converter.d.ts +28 -0
  31. package/packages/openclaw/dist/auth/converter.d.ts.map +1 -0
  32. package/packages/openclaw/dist/auth/converter.js +64 -0
  33. package/packages/openclaw/dist/auth/converter.js.map +1 -0
  34. package/packages/openclaw/dist/cli.d.ts +2 -0
  35. package/packages/openclaw/dist/cli.d.ts.map +1 -0
  36. package/packages/openclaw/dist/cli.js +230 -0
  37. package/packages/openclaw/dist/cli.js.map +1 -0
  38. package/packages/openclaw/dist/config.d.ts +27 -0
  39. package/packages/openclaw/dist/config.d.ts.map +1 -0
  40. package/packages/openclaw/dist/config.js +97 -0
  41. package/packages/openclaw/dist/config.js.map +1 -0
  42. package/packages/openclaw/dist/control.d.ts +22 -0
  43. package/packages/openclaw/dist/control.d.ts.map +1 -0
  44. package/packages/openclaw/dist/control.js +58 -0
  45. package/packages/openclaw/dist/control.js.map +1 -0
  46. package/packages/openclaw/dist/gateway.d.ts +97 -0
  47. package/packages/openclaw/dist/gateway.d.ts.map +1 -0
  48. package/packages/openclaw/dist/gateway.js +836 -0
  49. package/packages/openclaw/dist/gateway.js.map +1 -0
  50. package/packages/openclaw/dist/identity/contract.d.ts +11 -0
  51. package/packages/openclaw/dist/identity/contract.d.ts.map +1 -0
  52. package/packages/openclaw/dist/identity/contract.js +40 -0
  53. package/packages/openclaw/dist/identity/contract.js.map +1 -0
  54. package/packages/openclaw/dist/identity/files.d.ts +33 -0
  55. package/packages/openclaw/dist/identity/files.d.ts.map +1 -0
  56. package/packages/openclaw/dist/identity/files.js +145 -0
  57. package/packages/openclaw/dist/identity/files.js.map +1 -0
  58. package/packages/openclaw/dist/identity/model.d.ts +11 -0
  59. package/packages/openclaw/dist/identity/model.d.ts.map +1 -0
  60. package/packages/openclaw/dist/identity/model.js +28 -0
  61. package/packages/openclaw/dist/identity/model.js.map +1 -0
  62. package/packages/openclaw/dist/identity/naming.d.ts +5 -0
  63. package/packages/openclaw/dist/identity/naming.d.ts.map +1 -0
  64. package/packages/openclaw/dist/identity/naming.js +7 -0
  65. package/packages/openclaw/dist/identity/naming.js.map +1 -0
  66. package/packages/openclaw/dist/index.d.ts +20 -0
  67. package/packages/openclaw/dist/index.d.ts.map +1 -0
  68. package/packages/openclaw/dist/index.js +27 -0
  69. package/packages/openclaw/dist/index.js.map +1 -0
  70. package/packages/openclaw/dist/inject.d.ts +14 -0
  71. package/packages/openclaw/dist/inject.d.ts.map +1 -0
  72. package/packages/openclaw/dist/inject.js +66 -0
  73. package/packages/openclaw/dist/inject.js.map +1 -0
  74. package/packages/openclaw/dist/mcp/server.d.ts +8 -0
  75. package/packages/openclaw/dist/mcp/server.d.ts.map +1 -0
  76. package/packages/openclaw/dist/mcp/server.js +105 -0
  77. package/packages/openclaw/dist/mcp/server.js.map +1 -0
  78. package/packages/openclaw/dist/mcp/tools.d.ts +17 -0
  79. package/packages/openclaw/dist/mcp/tools.d.ts.map +1 -0
  80. package/packages/openclaw/dist/mcp/tools.js +145 -0
  81. package/packages/openclaw/dist/mcp/tools.js.map +1 -0
  82. package/packages/openclaw/dist/runtime/openclaw-config.d.ts +20 -0
  83. package/packages/openclaw/dist/runtime/openclaw-config.d.ts.map +1 -0
  84. package/packages/openclaw/dist/runtime/openclaw-config.js +50 -0
  85. package/packages/openclaw/dist/runtime/openclaw-config.js.map +1 -0
  86. package/packages/openclaw/dist/runtime/patch.d.ts +24 -0
  87. package/packages/openclaw/dist/runtime/patch.d.ts.map +1 -0
  88. package/packages/openclaw/dist/runtime/patch.js +92 -0
  89. package/packages/openclaw/dist/runtime/patch.js.map +1 -0
  90. package/packages/openclaw/dist/runtime/setup.d.ts +26 -0
  91. package/packages/openclaw/dist/runtime/setup.d.ts.map +1 -0
  92. package/packages/openclaw/dist/runtime/setup.js +58 -0
  93. package/packages/openclaw/dist/runtime/setup.js.map +1 -0
  94. package/packages/openclaw/dist/setup.d.ts +29 -0
  95. package/packages/openclaw/dist/setup.d.ts.map +1 -0
  96. package/packages/openclaw/dist/setup.js +300 -0
  97. package/packages/openclaw/dist/setup.js.map +1 -0
  98. package/packages/openclaw/dist/spawn/docker.d.ts +58 -0
  99. package/packages/openclaw/dist/spawn/docker.d.ts.map +1 -0
  100. package/packages/openclaw/dist/spawn/docker.js +222 -0
  101. package/packages/openclaw/dist/spawn/docker.js.map +1 -0
  102. package/packages/openclaw/dist/spawn/manager.d.ts +45 -0
  103. package/packages/openclaw/dist/spawn/manager.d.ts.map +1 -0
  104. package/packages/openclaw/dist/spawn/manager.js +140 -0
  105. package/packages/openclaw/dist/spawn/manager.js.map +1 -0
  106. package/packages/openclaw/dist/spawn/process.d.ts +16 -0
  107. package/packages/openclaw/dist/spawn/process.d.ts.map +1 -0
  108. package/packages/openclaw/dist/spawn/process.js +241 -0
  109. package/packages/openclaw/dist/spawn/process.js.map +1 -0
  110. package/packages/openclaw/dist/spawn/types.d.ts +42 -0
  111. package/packages/openclaw/dist/spawn/types.d.ts.map +1 -0
  112. package/packages/openclaw/dist/spawn/types.js +2 -0
  113. package/packages/openclaw/dist/spawn/types.js.map +1 -0
  114. package/packages/openclaw/dist/types.d.ts +41 -0
  115. package/packages/openclaw/dist/types.d.ts.map +1 -0
  116. package/packages/openclaw/dist/types.js +2 -0
  117. package/packages/openclaw/dist/types.js.map +1 -0
  118. package/packages/openclaw/package.json +63 -0
  119. package/packages/openclaw/skill/SKILL.md +216 -0
  120. package/packages/openclaw/src/__tests__/SPEC-ws-client-testing.md +192 -0
  121. package/packages/openclaw/src/__tests__/gateway-control.test.ts +288 -0
  122. package/packages/openclaw/src/__tests__/gateway-threads.test.ts +1130 -0
  123. package/packages/openclaw/src/__tests__/naming.test.ts +24 -0
  124. package/packages/openclaw/src/__tests__/spawn-manager.test.ts +189 -0
  125. package/packages/openclaw/src/__tests__/ws-client.test.ts +395 -0
  126. package/packages/openclaw/src/auth/converter.ts +90 -0
  127. package/packages/openclaw/src/cli.ts +269 -0
  128. package/packages/openclaw/src/config.ts +124 -0
  129. package/packages/openclaw/src/control.ts +100 -0
  130. package/packages/openclaw/src/gateway.ts +1014 -0
  131. package/packages/openclaw/src/identity/contract.ts +44 -0
  132. package/packages/openclaw/src/identity/files.ts +198 -0
  133. package/packages/openclaw/src/identity/model.ts +27 -0
  134. package/packages/openclaw/src/identity/naming.ts +6 -0
  135. package/packages/openclaw/src/index.ts +59 -0
  136. package/packages/openclaw/src/inject.ts +77 -0
  137. package/packages/openclaw/src/mcp/server.ts +121 -0
  138. package/packages/openclaw/src/mcp/tools.ts +174 -0
  139. package/packages/openclaw/src/runtime/openclaw-config.ts +64 -0
  140. package/packages/openclaw/src/runtime/patch.ts +103 -0
  141. package/packages/openclaw/src/runtime/setup.ts +89 -0
  142. package/packages/openclaw/src/setup.ts +336 -0
  143. package/packages/openclaw/src/spawn/docker.ts +261 -0
  144. package/packages/openclaw/src/spawn/manager.ts +181 -0
  145. package/packages/openclaw/src/spawn/process.ts +272 -0
  146. package/packages/openclaw/src/spawn/types.ts +43 -0
  147. package/packages/openclaw/src/types.ts +42 -0
  148. package/packages/openclaw/templates/SOUL.md.template +34 -0
  149. package/packages/openclaw/tsconfig.json +12 -0
  150. package/packages/policy/package.json +2 -2
  151. package/packages/sdk/package.json +2 -2
  152. package/packages/sdk-py/pyproject.toml +1 -1
  153. package/packages/telemetry/package.json +1 -1
  154. package/packages/trajectory/package.json +2 -2
  155. package/packages/user-directory/package.json +2 -2
  156. package/packages/utils/package.json +2 -2
  157. package/bin/agent-relay-broker-darwin-arm64 +0 -0
  158. package/bin/agent-relay-broker-darwin-x64 +0 -0
  159. package/bin/agent-relay-broker-linux-arm64 +0 -0
@@ -0,0 +1,28 @@
1
+ export interface CodexOAuthTokens {
2
+ access_token: string;
3
+ refresh_token?: string;
4
+ }
5
+ export interface CodexAuth {
6
+ tokens?: CodexOAuthTokens;
7
+ OPENAI_API_KEY?: string;
8
+ }
9
+ export interface ConvertResult {
10
+ /** Whether auth was written. */
11
+ ok: boolean;
12
+ /** Provider hint derived from auth source (e.g. 'openai-codex' for OAuth). */
13
+ preferredProvider: string;
14
+ }
15
+ /**
16
+ * Convert Codex CLI auth.json into OpenClaw's legacy auth format.
17
+ *
18
+ * Reads ~/.codex/auth.json (or codexAuthPath) and writes the converted
19
+ * auth to ~/.openclaw/agents/main/agent/auth.json (or openclawAuthDir).
20
+ *
21
+ * Falls back to OPENAI_API_KEY env var if no codex auth file exists.
22
+ */
23
+ export declare function convertCodexAuth(options?: {
24
+ codexAuthPath?: string;
25
+ openclawAuthDir?: string;
26
+ openaiApiKey?: string;
27
+ }): Promise<ConvertResult>;
28
+ //# sourceMappingURL=converter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"converter.d.ts","sourceRoot":"","sources":["../../src/auth/converter.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,aAAa;IAC5B,gCAAgC;IAChC,EAAE,EAAE,OAAO,CAAC;IACZ,8EAA8E;IAC9E,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,CAAC,EAAE;IAC/C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,aAAa,CAAC,CAwDzB"}
@@ -0,0 +1,64 @@
1
+ import { readFile, writeFile, mkdir } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { existsSync } from 'node:fs';
4
+ /**
5
+ * Convert Codex CLI auth.json into OpenClaw's legacy auth format.
6
+ *
7
+ * Reads ~/.codex/auth.json (or codexAuthPath) and writes the converted
8
+ * auth to ~/.openclaw/agents/main/agent/auth.json (or openclawAuthDir).
9
+ *
10
+ * Falls back to OPENAI_API_KEY env var if no codex auth file exists.
11
+ */
12
+ export async function convertCodexAuth(options) {
13
+ const home = process.env.HOME ?? '/home/node';
14
+ const codexPath = options?.codexAuthPath ?? join(home, '.codex', 'auth.json');
15
+ const openclawAgentDir = options?.openclawAuthDir ?? join(home, '.openclaw', 'agents', 'main', 'agent');
16
+ const openclawAuthPath = join(openclawAgentDir, 'auth.json');
17
+ let preferredProvider = 'openai';
18
+ if (existsSync(codexPath)) {
19
+ const codex = JSON.parse(await readFile(codexPath, 'utf8'));
20
+ await mkdir(openclawAgentDir, { recursive: true });
21
+ if (codex.tokens?.access_token) {
22
+ // OAuth tokens from codex subscription
23
+ const auth = {
24
+ 'openai-codex': {
25
+ type: 'oauth',
26
+ provider: 'openai-codex',
27
+ access: codex.tokens.access_token,
28
+ refresh: codex.tokens.refresh_token ?? '',
29
+ expires: Date.now() + 3600000,
30
+ },
31
+ };
32
+ await writeFile(openclawAuthPath, JSON.stringify(auth, null, 2), 'utf8');
33
+ preferredProvider = 'openai-codex';
34
+ return { ok: true, preferredProvider };
35
+ }
36
+ if (codex.OPENAI_API_KEY && typeof codex.OPENAI_API_KEY === 'string') {
37
+ const auth = {
38
+ openai: {
39
+ type: 'api_key',
40
+ provider: 'openai',
41
+ key: codex.OPENAI_API_KEY,
42
+ },
43
+ };
44
+ await writeFile(openclawAuthPath, JSON.stringify(auth, null, 2), 'utf8');
45
+ return { ok: true, preferredProvider };
46
+ }
47
+ }
48
+ // Fallback: use OPENAI_API_KEY from env
49
+ const envKey = options?.openaiApiKey ?? process.env.OPENAI_API_KEY;
50
+ if (envKey) {
51
+ await mkdir(openclawAgentDir, { recursive: true });
52
+ const auth = {
53
+ openai: {
54
+ type: 'api_key',
55
+ provider: 'openai',
56
+ key: envKey,
57
+ },
58
+ };
59
+ await writeFile(openclawAuthPath, JSON.stringify(auth, null, 2), 'utf8');
60
+ return { ok: true, preferredProvider };
61
+ }
62
+ return { ok: false, preferredProvider };
63
+ }
64
+ //# sourceMappingURL=converter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"converter.js","sourceRoot":"","sources":["../../src/auth/converter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
@@ -0,0 +1,230 @@
1
+ import { setup } from './setup.js';
2
+ import { loadGatewayConfig } from './config.js';
3
+ import { InboundGateway } from './gateway.js';
4
+ import { listOpenClaws, releaseOpenClaw, spawnOpenClaw } from './control.js';
5
+ import { startMcpServer } from './mcp/server.js';
6
+ import { runtimeSetup } from './runtime/setup.js';
7
+ function printUsage() {
8
+ console.log(`
9
+ relay-openclaw — Relaycast bridge for OpenClaw
10
+
11
+ Usage:
12
+ relay-openclaw setup [key] Install & configure Relaycast bridge
13
+ relay-openclaw gateway Start inbound message gateway
14
+ relay-openclaw status Check connection status
15
+ relay-openclaw spawn Spawn an OpenClaw via ClawRunner control API
16
+ relay-openclaw list List OpenClaws in a workspace
17
+ relay-openclaw release Release an OpenClaw by agent name
18
+ relay-openclaw mcp-server Start MCP server (spawn/list/release tools)
19
+ relay-openclaw runtime-setup Run container runtime setup (auth, config, identity, patching)
20
+ relay-openclaw help Show this help
21
+
22
+ Setup options:
23
+ --name <name> Claw name (default: hostname)
24
+ --channels <ch1,ch2> Channels to join (default: general)
25
+ --base-url <url> Relaycast API URL (default: https://api.relaycast.dev)
26
+
27
+ Control API options:
28
+ --workspace-id <id> Workspace UUID (required for spawn/list/release)
29
+ --name <name> Claw name (required for spawn)
30
+ --agent <agentName> Agent name (required for release)
31
+ --role <role> Optional role for spawned claw
32
+ --model <modelRef> Optional model reference
33
+ --channels <a,b,c> Optional channels
34
+ --system-prompt <txt> Optional system prompt
35
+ --reason <text> Optional release reason
36
+
37
+ Examples:
38
+ relay-openclaw setup rk_live_abc123
39
+ relay-openclaw setup --name my-claw --channels general,alerts
40
+ relay-openclaw gateway
41
+ relay-openclaw spawn --workspace-id ws_uuid --name researcher-1
42
+ relay-openclaw list --workspace-id ws_uuid
43
+ relay-openclaw release --workspace-id ws_uuid --agent claw-ws_uuid-researcher-1
44
+ `.trim());
45
+ }
46
+ function parseArgs(argv) {
47
+ const args = argv.slice(2); // skip node + script
48
+ const command = args[0] ?? 'help';
49
+ const positional = [];
50
+ const flags = {};
51
+ for (let i = 1; i < args.length; i++) {
52
+ const arg = args[i];
53
+ if (arg.startsWith('--')) {
54
+ const key = arg.slice(2);
55
+ const value = args[i + 1];
56
+ if (value && !value.startsWith('--')) {
57
+ flags[key] = value;
58
+ i++;
59
+ }
60
+ else {
61
+ flags[key] = 'true';
62
+ }
63
+ }
64
+ else {
65
+ positional.push(arg);
66
+ }
67
+ }
68
+ return { command, positional, flags };
69
+ }
70
+ async function runSetup(positional, flags) {
71
+ const apiKey = positional[0] ?? undefined;
72
+ const clawName = flags['name'] ?? undefined;
73
+ const channels = flags['channels']?.split(',').map((c) => c.trim());
74
+ const baseUrl = flags['base-url'] ?? undefined;
75
+ console.log('Setting up Relaycast bridge for OpenClaw...\n');
76
+ const result = await setup({ apiKey, clawName, channels, baseUrl });
77
+ if (result.ok) {
78
+ console.log(result.message);
79
+ console.log(`\nWorkspace key: ${result.apiKey}`);
80
+ console.log('Share this key with other claws to join the same workspace.');
81
+ }
82
+ else {
83
+ console.error(`Setup failed: ${result.message}`);
84
+ process.exit(1);
85
+ }
86
+ }
87
+ async function runGateway() {
88
+ const config = await loadGatewayConfig();
89
+ if (!config) {
90
+ console.error('No gateway config found. Run "relay-openclaw setup" first.');
91
+ process.exit(1);
92
+ }
93
+ console.log(`Starting inbound gateway for ${config.clawName}...`);
94
+ console.log(`Channels: ${config.channels.join(', ')}`);
95
+ console.log(`Base URL: ${config.baseUrl}\n`);
96
+ const gateway = new InboundGateway({ config });
97
+ // Graceful shutdown
98
+ const shutdown = async () => {
99
+ console.log('\nShutting down gateway...');
100
+ await gateway.stop();
101
+ process.exit(0);
102
+ };
103
+ process.on('SIGINT', shutdown);
104
+ process.on('SIGTERM', shutdown);
105
+ await gateway.start();
106
+ console.log('Gateway running. Press Ctrl+C to stop.');
107
+ }
108
+ async function runStatus() {
109
+ const config = await loadGatewayConfig();
110
+ if (!config) {
111
+ console.log('Status: NOT CONFIGURED');
112
+ console.log('Run "relay-openclaw setup" to configure.');
113
+ return;
114
+ }
115
+ console.log('Status: CONFIGURED');
116
+ console.log(`Claw name: ${config.clawName}`);
117
+ console.log(`Channels: ${config.channels.join(', ')}`);
118
+ console.log(`Base URL: ${config.baseUrl}`);
119
+ console.log(`API key: ${config.apiKey.slice(0, 12)}...`);
120
+ // Try to check connectivity
121
+ try {
122
+ const res = await fetch(`${config.baseUrl}/health`);
123
+ console.log(`API connectivity: ${res.ok ? 'OK' : `Error (${res.status})`}`);
124
+ }
125
+ catch (err) {
126
+ console.log(`API connectivity: UNREACHABLE (${err instanceof Error ? err.message : String(err)})`);
127
+ }
128
+ }
129
+ async function runSpawn(flags) {
130
+ const workspaceId = flags['workspace-id'];
131
+ const name = flags['name'];
132
+ if (!workspaceId || !name) {
133
+ console.error('spawn requires --workspace-id and --name');
134
+ process.exit(1);
135
+ }
136
+ const channels = flags['channels']
137
+ ?.split(',')
138
+ .map((ch) => ch.trim())
139
+ .filter(Boolean);
140
+ const result = await spawnOpenClaw({
141
+ workspaceId,
142
+ name,
143
+ role: flags['role'],
144
+ model: flags['model'],
145
+ channels,
146
+ systemPrompt: flags['system-prompt'],
147
+ idempotencyKey: flags['idempotency-key'],
148
+ });
149
+ console.log(JSON.stringify(result, null, 2));
150
+ }
151
+ async function runList(flags) {
152
+ const workspaceId = flags['workspace-id'];
153
+ if (!workspaceId) {
154
+ console.error('list requires --workspace-id');
155
+ process.exit(1);
156
+ }
157
+ const result = await listOpenClaws(workspaceId);
158
+ console.log(JSON.stringify(result, null, 2));
159
+ }
160
+ async function runRelease(flags) {
161
+ const workspaceId = flags['workspace-id'];
162
+ const agentName = flags['agent'];
163
+ if (!workspaceId || !agentName) {
164
+ console.error('release requires --workspace-id and --agent');
165
+ process.exit(1);
166
+ }
167
+ const result = await releaseOpenClaw({
168
+ workspaceId,
169
+ agentName,
170
+ reason: flags['reason'],
171
+ });
172
+ console.log(JSON.stringify(result, null, 2));
173
+ }
174
+ async function runRuntimeSetup(flags) {
175
+ console.log('Running container runtime setup...');
176
+ const result = await runtimeSetup({
177
+ model: flags['model'],
178
+ name: flags['name'],
179
+ workspaceId: flags['workspace-id'],
180
+ role: flags['role'],
181
+ openclawDistDir: flags['dist-dir'],
182
+ });
183
+ console.log(`Runtime setup complete:`);
184
+ console.log(` Model: ${result.modelRef}`);
185
+ console.log(` Agent: ${result.agentName}`);
186
+ console.log(` Workspace: ${result.workspaceId}`);
187
+ }
188
+ async function main() {
189
+ const { command, positional, flags } = parseArgs(process.argv);
190
+ switch (command) {
191
+ case 'setup':
192
+ await runSetup(positional, flags);
193
+ break;
194
+ case 'gateway':
195
+ await runGateway();
196
+ break;
197
+ case 'status':
198
+ await runStatus();
199
+ break;
200
+ case 'spawn':
201
+ await runSpawn(flags);
202
+ break;
203
+ case 'list':
204
+ await runList(flags);
205
+ break;
206
+ case 'release':
207
+ await runRelease(flags);
208
+ break;
209
+ case 'mcp-server':
210
+ await startMcpServer();
211
+ break;
212
+ case 'runtime-setup':
213
+ await runRuntimeSetup(flags);
214
+ break;
215
+ case 'help':
216
+ case '--help':
217
+ case '-h':
218
+ printUsage();
219
+ break;
220
+ default:
221
+ console.error(`Unknown command: ${command}`);
222
+ printUsage();
223
+ process.exit(1);
224
+ }
225
+ }
226
+ main().catch((err) => {
227
+ console.error(err);
228
+ process.exit(1);
229
+ });
230
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,SAAS,UAAU;IACjB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoCb,CAAC,IAAI,EAAE,CAAC,CAAC;AACV,CAAC;AAED,SAAS,SAAS,CAAC,IAAc;IAK/B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,qBAAqB;IACjD,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC;IAClC,MAAM,UAAU,GAAa,EAAE,CAAC;IAChC,MAAM,KAAK,GAA2B,EAAE,CAAC;IAEzC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACpB,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACzB,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC1B,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBACrC,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;gBACnB,CAAC,EAAE,CAAC;YACN,CAAC;iBAAM,CAAC;gBACN,KAAK,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC;YACtB,CAAC;QACH,CAAC;aAAM,CAAC;YACN,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC;AACxC,CAAC;AAED,KAAK,UAAU,QAAQ,CACrB,UAAoB,EACpB,KAA6B;IAE7B,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC;IAC1C,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,SAAS,CAAC;IAC5C,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACpE,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,IAAI,SAAS,CAAC;IAE/C,OAAO,CAAC,GAAG,CAAC,+CAA+C,CAAC,CAAC;IAE7D,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;IAEpE,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,oBAAoB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACjD,OAAO,CAAC,GAAG,CAAC,6DAA6D,CAAC,CAAC;IAC7E,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,iBAAiB,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QACjD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,UAAU;IACvB,MAAM,MAAM,GAAG,MAAM,iBAAiB,EAAE,CAAC;IAEzC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CACX,4DAA4D,CAC7D,CAAC;QACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,gCAAgC,MAAM,CAAC,QAAQ,KAAK,CAAC,CAAC;IAClE,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,OAAO,IAAI,CAAC,CAAC;IAE7C,MAAM,OAAO,GAAG,IAAI,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IAE/C,oBAAoB;IACpB,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;QAC1B,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAC1C,MAAM,OAAO,CAAC,IAAI,EAAE,CAAC;QACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAEhC,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACtB,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;AACxD,CAAC;AAED,KAAK,UAAU,SAAS;IACtB,MAAM,MAAM,GAAG,MAAM,iBAAiB,EAAE,CAAC;IAEzC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;QACxD,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAClC,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvD,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IAC3C,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;IAEzD,4BAA4B;IAC5B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,MAAM,CAAC,OAAO,SAAS,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CACT,qBAAqB,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,MAAM,GAAG,EAAE,CAC/D,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CACT,kCAAkC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CACtF,CAAC;IACJ,CAAC;AACH,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,KAA6B;IACnD,MAAM,WAAW,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3B,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1B,OAAO,CAAC,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC1D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,CAAC;QAChC,EAAE,KAAK,CAAC,GAAG,CAAC;SACX,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;SACtB,MAAM,CAAC,OAAO,CAAC,CAAC;IAEnB,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC;QACjC,WAAW;QACX,IAAI;QACJ,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC;QACnB,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC;QACrB,QAAQ;QACR,YAAY,EAAE,KAAK,CAAC,eAAe,CAAC;QACpC,cAAc,EAAE,KAAK,CAAC,iBAAiB,CAAC;KACzC,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,KAA6B;IAClD,MAAM,WAAW,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC;IAC1C,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAC9C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,KAA6B;IACrD,MAAM,WAAW,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;IACjC,IAAI,CAAC,WAAW,IAAI,CAAC,SAAS,EAAE,CAAC;QAC/B,OAAO,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,eAAe,CAAC;QACnC,WAAW;QACX,SAAS;QACT,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC;KACxB,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,KAA6B;IAC1D,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC;QAChC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC;QACrB,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC;QACnB,WAAW,EAAE,KAAK,CAAC,cAAc,CAAC;QAClC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC;QACnB,eAAe,EAAE,KAAK,CAAC,UAAU,CAAC;KACnC,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC3C,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;IAC5C,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;AACpD,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAE/D,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,OAAO;YACV,MAAM,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;YAClC,MAAM;QACR,KAAK,SAAS;YACZ,MAAM,UAAU,EAAE,CAAC;YACnB,MAAM;QACR,KAAK,QAAQ;YACX,MAAM,SAAS,EAAE,CAAC;YAClB,MAAM;QACR,KAAK,OAAO;YACV,MAAM,QAAQ,CAAC,KAAK,CAAC,CAAC;YACtB,MAAM;QACR,KAAK,MAAM;YACT,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC;YACrB,MAAM;QACR,KAAK,SAAS;YACZ,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;YACxB,MAAM;QACR,KAAK,YAAY;YACf,MAAM,cAAc,EAAE,CAAC;YACvB,MAAM;QACR,KAAK,eAAe;YAClB,MAAM,eAAe,CAAC,KAAK,CAAC,CAAC;YAC7B,MAAM;QACR,KAAK,MAAM,CAAC;QACZ,KAAK,QAAQ,CAAC;QACd,KAAK,IAAI;YACP,UAAU,EAAE,CAAC;YACb,MAAM;QACR;YACE,OAAO,CAAC,KAAK,CAAC,oBAAoB,OAAO,EAAE,CAAC,CAAC;YAC7C,UAAU,EAAE,CAAC;YACb,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { GatewayConfig } from './types.js';
2
+ export interface OpenClawDetection {
3
+ /** Whether OpenClaw is installed. */
4
+ installed: boolean;
5
+ /** Path to ~/.openclaw/ */
6
+ homeDir: string;
7
+ /** Path to ~/.openclaw/workspace/ */
8
+ workspaceDir: string;
9
+ /** Path to openclaw.json config (if found). */
10
+ configFile: string | null;
11
+ /** Parsed openclaw.json (if exists). */
12
+ config: Record<string, unknown> | null;
13
+ }
14
+ /**
15
+ * Detect whether OpenClaw is installed and return paths/config.
16
+ */
17
+ export declare function detectOpenClaw(): Promise<OpenClawDetection>;
18
+ /**
19
+ * Load the gateway config from ~/.openclaw/workspace/relaycast/.env.
20
+ * Returns null if the file doesn't exist or can't be parsed.
21
+ */
22
+ export declare function loadGatewayConfig(): Promise<GatewayConfig | null>;
23
+ /**
24
+ * Save gateway config to ~/.openclaw/workspace/relaycast/.env.
25
+ */
26
+ export declare function saveGatewayConfig(config: GatewayConfig): Promise<void>;
27
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,WAAW,iBAAiB;IAChC,qCAAqC;IACrC,SAAS,EAAE,OAAO,CAAC;IACnB,2BAA2B;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,qCAAqC;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CACxC;AAOD;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAoBjE;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAgDvE;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB5E"}
@@ -0,0 +1,97 @@
1
+ import { readFile, writeFile, mkdir } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ import { homedir } from 'node:os';
4
+ import { existsSync } from 'node:fs';
5
+ /** Default OpenClaw config directory. */
6
+ function openclawHome() {
7
+ return join(homedir(), '.openclaw');
8
+ }
9
+ /**
10
+ * Detect whether OpenClaw is installed and return paths/config.
11
+ */
12
+ export async function detectOpenClaw() {
13
+ const homeDir = openclawHome();
14
+ const configPath = join(homeDir, 'openclaw.json');
15
+ const workspaceDir = join(homeDir, 'workspace');
16
+ const installed = existsSync(homeDir);
17
+ let config = null;
18
+ let configFile = null;
19
+ if (existsSync(configPath)) {
20
+ configFile = configPath;
21
+ try {
22
+ const raw = await readFile(configPath, 'utf-8');
23
+ config = JSON.parse(raw);
24
+ }
25
+ catch {
26
+ // Config exists but isn't valid JSON — that's fine
27
+ }
28
+ }
29
+ return { installed, homeDir, workspaceDir, configFile, config };
30
+ }
31
+ /**
32
+ * Load the gateway config from ~/.openclaw/workspace/relaycast/.env.
33
+ * Returns null if the file doesn't exist or can't be parsed.
34
+ */
35
+ export async function loadGatewayConfig() {
36
+ const detection = await detectOpenClaw();
37
+ const envPath = join(detection.workspaceDir, 'relaycast', '.env');
38
+ if (!existsSync(envPath)) {
39
+ return null;
40
+ }
41
+ try {
42
+ const raw = await readFile(envPath, 'utf-8');
43
+ const vars = {};
44
+ for (const line of raw.split('\n')) {
45
+ const trimmed = line.trim();
46
+ if (!trimmed || trimmed.startsWith('#'))
47
+ continue;
48
+ const eqIdx = trimmed.indexOf('=');
49
+ if (eqIdx === -1)
50
+ continue;
51
+ let value = trimmed.slice(eqIdx + 1);
52
+ // Strip surrounding quotes (single or double) that are common in .env files
53
+ if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
54
+ value = value.slice(1, -1);
55
+ }
56
+ vars[trimmed.slice(0, eqIdx)] = value;
57
+ }
58
+ const apiKey = vars['RELAY_API_KEY'];
59
+ const clawName = vars['RELAY_CLAW_NAME'];
60
+ if (!apiKey || !clawName) {
61
+ return null;
62
+ }
63
+ const portStr = vars['OPENCLAW_GATEWAY_PORT'];
64
+ const port = portStr ? Number(portStr) : undefined;
65
+ return {
66
+ apiKey,
67
+ clawName,
68
+ baseUrl: vars['RELAY_BASE_URL'] || 'https://api.relaycast.dev',
69
+ channels: vars['RELAY_CHANNELS']
70
+ ? vars['RELAY_CHANNELS'].split(',').map((c) => c.trim())
71
+ : ['general'],
72
+ openclawGatewayToken: vars['OPENCLAW_GATEWAY_TOKEN'] || process.env.OPENCLAW_GATEWAY_TOKEN,
73
+ openclawGatewayPort: Number.isFinite(port) ? port : undefined,
74
+ };
75
+ }
76
+ catch {
77
+ return null;
78
+ }
79
+ }
80
+ /**
81
+ * Save gateway config to ~/.openclaw/workspace/relaycast/.env.
82
+ */
83
+ export async function saveGatewayConfig(config) {
84
+ const detection = await detectOpenClaw();
85
+ const relaycastDir = join(detection.workspaceDir, 'relaycast');
86
+ await mkdir(relaycastDir, { recursive: true });
87
+ const env = [
88
+ '# Relaycast configuration for this OpenClaw skill',
89
+ `RELAY_API_KEY=${config.apiKey}`,
90
+ `RELAY_CLAW_NAME=${config.clawName}`,
91
+ `RELAY_BASE_URL=${config.baseUrl}`,
92
+ `RELAY_CHANNELS=${config.channels.join(',')}`,
93
+ '',
94
+ ].join('\n');
95
+ await writeFile(join(relaycastDir, '.env'), env, 'utf-8');
96
+ }
97
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ export interface ClawRunnerControlConfig {
2
+ baseUrl: string;
3
+ token: string;
4
+ }
5
+ export interface SpawnOpenClawInput {
6
+ workspaceId: string;
7
+ name: string;
8
+ role?: string;
9
+ model?: string;
10
+ channels?: string[];
11
+ systemPrompt?: string;
12
+ idempotencyKey?: string;
13
+ }
14
+ export interface ReleaseOpenClawInput {
15
+ workspaceId: string;
16
+ agentName: string;
17
+ reason?: string;
18
+ }
19
+ export declare function spawnOpenClaw(input: SpawnOpenClawInput, config?: Partial<ClawRunnerControlConfig>): Promise<unknown>;
20
+ export declare function listOpenClaws(workspaceId: string, config?: Partial<ClawRunnerControlConfig>): Promise<unknown>;
21
+ export declare function releaseOpenClaw(input: ReleaseOpenClawInput, config?: Partial<ClawRunnerControlConfig>): Promise<unknown>;
22
+ //# sourceMappingURL=control.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control.d.ts","sourceRoot":"","sources":["../src/control.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAgDD,wBAAsB,aAAa,CACjC,KAAK,EAAE,kBAAkB,EACzB,MAAM,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,GACxC,OAAO,CAAC,OAAO,CAAC,CAUlB;AAED,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,MAAM,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,GACxC,OAAO,CAAC,OAAO,CAAC,CAGlB;AAED,wBAAsB,eAAe,CACnC,KAAK,EAAE,oBAAoB,EAC3B,MAAM,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,GACxC,OAAO,CAAC,OAAO,CAAC,CAMlB"}
@@ -0,0 +1,58 @@
1
+ function trimSlash(value) {
2
+ return value.endsWith('/') ? value.slice(0, -1) : value;
3
+ }
4
+ function resolveConfig(config) {
5
+ const baseUrl = (config?.baseUrl ?? process.env.CLAWRUNNER_API_BASE_URL ?? '').trim();
6
+ const token = (config?.token ?? process.env.CLAWRUNNER_AGENT_TOKEN ?? '').trim();
7
+ if (!baseUrl) {
8
+ throw new Error('CLAWRUNNER_API_BASE_URL is required');
9
+ }
10
+ if (!token) {
11
+ throw new Error('CLAWRUNNER_AGENT_TOKEN is required');
12
+ }
13
+ return {
14
+ baseUrl: trimSlash(baseUrl),
15
+ token,
16
+ };
17
+ }
18
+ async function callApi(path, method, config, body) {
19
+ const resolved = resolveConfig(config);
20
+ const response = await fetch(`${resolved.baseUrl}${path}`, {
21
+ method,
22
+ headers: {
23
+ Authorization: `Bearer ${resolved.token}`,
24
+ 'Content-Type': 'application/json',
25
+ },
26
+ body: body === undefined ? undefined : JSON.stringify(body),
27
+ });
28
+ const text = await response.text();
29
+ const json = text ? JSON.parse(text) : null;
30
+ if (!response.ok) {
31
+ const msg = (json && typeof json.error === 'string') ? json.error : `HTTP ${response.status}`;
32
+ throw new Error(`ClawRunner control API error: ${msg}`);
33
+ }
34
+ return json;
35
+ }
36
+ export async function spawnOpenClaw(input, config) {
37
+ return callApi('/api/agents/spawn', 'POST', config, {
38
+ workspaceId: input.workspaceId,
39
+ name: input.name,
40
+ role: input.role,
41
+ model: input.model,
42
+ channels: input.channels,
43
+ systemPrompt: input.systemPrompt,
44
+ idempotencyKey: input.idempotencyKey,
45
+ });
46
+ }
47
+ export async function listOpenClaws(workspaceId, config) {
48
+ const query = new URLSearchParams({ workspaceId }).toString();
49
+ return callApi(`/api/agents?${query}`, 'GET', config);
50
+ }
51
+ export async function releaseOpenClaw(input, config) {
52
+ const path = `/api/agents/${encodeURIComponent(input.agentName)}/release`;
53
+ return callApi(path, 'POST', config, {
54
+ workspaceId: input.workspaceId,
55
+ reason: input.reason,
56
+ });
57
+ }
58
+ //# sourceMappingURL=control.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"control.js","sourceRoot":"","sources":["../src/control.ts"],"names":[],"mappings":"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"}