relaycast 0.3.2 → 1.1.1

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 (69) hide show
  1. package/dist/cli.d.ts +3 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +9 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/index.d.ts +35 -2
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +452 -126
  8. package/dist/index.js.map +1 -1
  9. package/dist/version.d.ts +2 -0
  10. package/dist/version.d.ts.map +1 -0
  11. package/dist/version.js +2 -0
  12. package/dist/version.js.map +1 -0
  13. package/package.json +21 -26
  14. package/dist/commands/agent.d.ts +0 -3
  15. package/dist/commands/agent.d.ts.map +0 -1
  16. package/dist/commands/agent.js +0 -51
  17. package/dist/commands/agent.js.map +0 -1
  18. package/dist/commands/billing.d.ts +0 -3
  19. package/dist/commands/billing.d.ts.map +0 -1
  20. package/dist/commands/billing.js +0 -37
  21. package/dist/commands/billing.js.map +0 -1
  22. package/dist/commands/channel.d.ts +0 -3
  23. package/dist/commands/channel.d.ts.map +0 -1
  24. package/dist/commands/channel.js +0 -67
  25. package/dist/commands/channel.js.map +0 -1
  26. package/dist/commands/config.d.ts +0 -3
  27. package/dist/commands/config.d.ts.map +0 -1
  28. package/dist/commands/config.js +0 -23
  29. package/dist/commands/config.js.map +0 -1
  30. package/dist/commands/files.d.ts +0 -3
  31. package/dist/commands/files.d.ts.map +0 -1
  32. package/dist/commands/files.js +0 -52
  33. package/dist/commands/files.js.map +0 -1
  34. package/dist/commands/messaging.d.ts +0 -3
  35. package/dist/commands/messaging.d.ts.map +0 -1
  36. package/dist/commands/messaging.js +0 -54
  37. package/dist/commands/messaging.js.map +0 -1
  38. package/dist/commands/openclaw.d.ts +0 -3
  39. package/dist/commands/openclaw.d.ts.map +0 -1
  40. package/dist/commands/openclaw.js +0 -51
  41. package/dist/commands/openclaw.js.map +0 -1
  42. package/dist/commands/reactions.d.ts +0 -3
  43. package/dist/commands/reactions.d.ts.map +0 -1
  44. package/dist/commands/reactions.js +0 -32
  45. package/dist/commands/reactions.js.map +0 -1
  46. package/dist/commands/read.d.ts +0 -3
  47. package/dist/commands/read.d.ts.map +0 -1
  48. package/dist/commands/read.js +0 -80
  49. package/dist/commands/read.js.map +0 -1
  50. package/dist/commands/search.d.ts +0 -3
  51. package/dist/commands/search.d.ts.map +0 -1
  52. package/dist/commands/search.js +0 -31
  53. package/dist/commands/search.js.map +0 -1
  54. package/dist/commands/telemetry.d.ts +0 -4
  55. package/dist/commands/telemetry.d.ts.map +0 -1
  56. package/dist/commands/telemetry.js +0 -45
  57. package/dist/commands/telemetry.js.map +0 -1
  58. package/dist/commands/workspace.d.ts +0 -3
  59. package/dist/commands/workspace.d.ts.map +0 -1
  60. package/dist/commands/workspace.js +0 -35
  61. package/dist/commands/workspace.js.map +0 -1
  62. package/dist/config.d.ts +0 -9
  63. package/dist/config.d.ts.map +0 -1
  64. package/dist/config.js +0 -29
  65. package/dist/config.js.map +0 -1
  66. package/dist/telemetry.d.ts +0 -17
  67. package/dist/telemetry.d.ts.map +0 -1
  68. package/dist/telemetry.js +0 -214
  69. package/dist/telemetry.js.map +0 -1
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env node
2
+ import { runCli } from './index.js';
3
+ const exitCode = await runCli(process.argv.slice(2), {
4
+ stdout: process.stdout,
5
+ stderr: process.stderr,
6
+ env: process.env,
7
+ });
8
+ process.exit(exitCode);
9
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEpC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;IACnD,MAAM,EAAE,OAAO,CAAC,MAAM;IACtB,MAAM,EAAE,OAAO,CAAC,MAAM;IACtB,GAAG,EAAE,OAAO,CAAC,GAAG;CACjB,CAAC,CAAC;AAEH,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,36 @@
1
- #!/usr/bin/env node
2
- export declare const CLI_VERSION: "0.1.2";
1
+ type WritableStreamLike = {
2
+ write(chunk: string): unknown;
3
+ };
4
+ type EnvLike = Record<string, string | undefined>;
5
+ type JsonObject = Record<string, unknown>;
6
+ type JsonSchema = {
7
+ type?: string | string[];
8
+ properties?: Record<string, JsonSchema>;
9
+ items?: JsonSchema;
10
+ };
11
+ type ToolDefinition = {
12
+ name: string;
13
+ title?: string;
14
+ description?: string;
15
+ inputSchema?: JsonSchema;
16
+ };
17
+ type CliIo = {
18
+ stdout: WritableStreamLike;
19
+ stderr: WritableStreamLike;
20
+ env?: EnvLike;
21
+ };
22
+ type CliConfig = {
23
+ apiKey?: string;
24
+ baseUrl?: string;
25
+ agentToken?: string;
26
+ agentName?: string;
27
+ agentType?: 'agent' | 'human';
28
+ strictAgentName?: boolean;
29
+ workspacesJson?: string;
30
+ defaultWorkspace?: string;
31
+ };
32
+ export declare function runCli(argv: string[], io: CliIo): Promise<number>;
33
+ export declare function listCliTools(config?: CliConfig): Promise<ToolDefinition[]>;
34
+ export declare function callCliTool(name: string, args: JsonObject, config?: CliConfig): Promise<unknown>;
35
+ export {};
3
36
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAiBA,eAAO,MAAM,WAAW,EAAG,OAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AASA,KAAK,kBAAkB,GAAG;IAAE,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,CAAC;AAC5D,KAAK,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAClD,KAAK,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC1C,KAAK,UAAU,GAAG;IAChB,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACxC,KAAK,CAAC,EAAE,UAAU,CAAC;CACpB,CAAC;AACF,KAAK,cAAc,GAAG;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,UAAU,CAAC;CAC1B,CAAC;AACF,KAAK,KAAK,GAAG;IACX,MAAM,EAAE,kBAAkB,CAAC;IAC3B,MAAM,EAAE,kBAAkB,CAAC;IAC3B,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,CAAC;AAQF,KAAK,SAAS,GAAG;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAC9B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAkBF,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAiDvE;AAED,wBAAsB,YAAY,CAAC,MAAM,GAAE,SAAc,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAQpF;AAED,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,MAAM,GAAE,SAAc,GACrB,OAAO,CAAC,OAAO,CAAC,CAOlB"}
package/dist/index.js CHANGED
@@ -1,137 +1,463 @@
1
- #!/usr/bin/env node
2
- import { Command } from 'commander';
3
- import { registerWorkspaceCommands } from './commands/workspace.js';
4
- import { registerAgentCommands } from './commands/agent.js';
5
- import { registerConfigCommands } from './commands/config.js';
6
- import { registerChannelCommands } from './commands/channel.js';
7
- import { registerMessagingCommands } from './commands/messaging.js';
8
- import { registerReadCommands } from './commands/read.js';
9
- import { registerSearchCommands } from './commands/search.js';
10
- import { registerReactionCommands } from './commands/reactions.js';
11
- import { registerFileCommands } from './commands/files.js';
12
- import { registerBillingCommands } from './commands/billing.js';
13
- import { registerOpenClawCommands } from './commands/openclaw.js';
14
- import { registerTelemetryCommands } from './commands/telemetry.js';
15
- import { createCliTelemetry } from './telemetry.js';
16
- export const CLI_VERSION = '0.1.2';
17
- const program = new Command();
18
- const telemetry = createCliTelemetry(CLI_VERSION);
19
- let activeCommandPath = null;
20
- let activeCommandStartedAt = 0;
21
- function getCommandPath(command) {
22
- const names = [];
23
- let current = command;
24
- while (current && current.parent) {
25
- const name = current.name();
26
- if (name)
27
- names.unshift(name);
28
- current = current.parent;
29
- }
30
- return names.join(' ');
31
- }
32
- function captureDerivedEvents(commandPath, args) {
33
- if (commandPath === 'workspace create') {
34
- telemetry.capture('relaycast_workspace_created', { source_surface: 'cli' });
35
- return;
1
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2
+ import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';
3
+ import { createRelayMcpServer, parseWorkspaceEnv, } from '@relaycast/mcp';
4
+ import { CLI_VERSION } from './version.js';
5
+ const GLOBAL_FLAG_NAMES = new Set([
6
+ 'relay-api-key',
7
+ 'relay-base-url',
8
+ 'relay-agent-token',
9
+ 'relay-agent-name',
10
+ 'relay-agent-type',
11
+ 'relay-strict-agent-name',
12
+ 'relay-workspaces-json',
13
+ 'relay-default-workspace',
14
+ 'json',
15
+ 'help',
16
+ 'h',
17
+ ]);
18
+ const TOOL_JSON_FLAG_NAMES = new Set(['json-args', 'args-json']);
19
+ export async function runCli(argv, io) {
20
+ try {
21
+ if (argv.length === 1 && (argv[0] === 'version' || argv[0] === '--version' || argv[0] === '-v')) {
22
+ io.stdout.write(`relaycast ${CLI_VERSION}\n`);
23
+ return 0;
24
+ }
25
+ const parsed = parseCliArgs(argv, io.env ?? process.env);
26
+ if (parsed.command === 'version') {
27
+ io.stdout.write(`relaycast ${CLI_VERSION}\n`);
28
+ return 0;
29
+ }
30
+ const session = await createCliMcpSession(parsed.config);
31
+ try {
32
+ const tools = await session.listTools();
33
+ const toolDefinitions = tools.tools;
34
+ if (!parsed.command || parsed.command === 'help' || parsed.command === '--help' || parsed.command === '-h') {
35
+ io.stdout.write(formatHelp(toolDefinitions));
36
+ return 0;
37
+ }
38
+ if (parsed.command === 'tools' || parsed.command === 'tool.list') {
39
+ if (parsed.outputJson) {
40
+ io.stdout.write(`${JSON.stringify(toolDefinitions, null, 2)}\n`);
41
+ }
42
+ else {
43
+ io.stdout.write(formatToolList(toolDefinitions));
44
+ }
45
+ return 0;
46
+ }
47
+ const tool = toolDefinitions.find((candidate) => candidate.name === parsed.command);
48
+ if (parsed.help) {
49
+ io.stdout.write(formatToolHelp(parsed.command, tool));
50
+ return 0;
51
+ }
52
+ const toolArgs = parseToolArgs(parsed.commandArgs, tool?.inputSchema);
53
+ const result = await session.callTool(parsed.command, toolArgs);
54
+ writeToolResult(io.stdout, result, parsed.outputJson);
55
+ return isToolErrorResult(result) ? 1 : 0;
56
+ }
57
+ finally {
58
+ await session.close();
59
+ }
36
60
  }
37
- if (commandPath === 'send') {
38
- const target = typeof args[0] === 'string' ? args[0] : '';
39
- telemetry.capture('relaycast_message_sent', {
40
- source_surface: 'cli',
41
- message_kind: target.startsWith('@') ? 'dm' : 'channel',
42
- command: commandPath,
43
- });
44
- return;
61
+ catch (err) {
62
+ io.stderr.write(`${formatError(err)}\n`);
63
+ return 1;
64
+ }
65
+ }
66
+ export async function listCliTools(config = {}) {
67
+ const session = await createCliMcpSession(config);
68
+ try {
69
+ const tools = await session.listTools();
70
+ return tools.tools;
71
+ }
72
+ finally {
73
+ await session.close();
74
+ }
75
+ }
76
+ export async function callCliTool(name, args, config = {}) {
77
+ const session = await createCliMcpSession(config);
78
+ try {
79
+ return await session.callTool(name, args);
80
+ }
81
+ finally {
82
+ await session.close();
83
+ }
84
+ }
85
+ function parseCliArgs(argv, env) {
86
+ const config = {
87
+ apiKey: env.RELAY_API_KEY,
88
+ baseUrl: env.RELAY_BASE_URL,
89
+ agentToken: env.RELAY_AGENT_TOKEN,
90
+ agentName: env.RELAY_AGENT_NAME,
91
+ agentType: parseAgentType(env.RELAY_AGENT_TYPE),
92
+ strictAgentName: parseBooleanFlag(env.RELAY_STRICT_AGENT_NAME),
93
+ workspacesJson: env.RELAY_WORKSPACES_JSON,
94
+ defaultWorkspace: env.RELAY_DEFAULT_WORKSPACE,
95
+ };
96
+ let outputJson = false;
97
+ let help = false;
98
+ let command = null;
99
+ const commandArgs = [];
100
+ for (let i = 0; i < argv.length; i += 1) {
101
+ const token = argv[i];
102
+ if (!command && isFlag(token)) {
103
+ const { name, inlineValue, negated } = splitFlag(token);
104
+ if (negated || !GLOBAL_FLAG_NAMES.has(name)) {
105
+ throw new Error(`Unknown global option "${token}". Put tool arguments after the tool name.`);
106
+ }
107
+ const value = readGlobalFlagValue(argv, i, name, inlineValue);
108
+ if (value.consumed)
109
+ i += 1;
110
+ applyGlobalFlag(config, name, value.value, () => { outputJson = true; }, () => { help = true; });
111
+ continue;
112
+ }
113
+ if (!command) {
114
+ command = token;
115
+ continue;
116
+ }
117
+ if (isFlag(token)) {
118
+ const { name, inlineValue, negated } = splitFlag(token);
119
+ if (!negated && GLOBAL_FLAG_NAMES.has(name)) {
120
+ const value = readGlobalFlagValue(argv, i, name, inlineValue);
121
+ if (value.consumed)
122
+ i += 1;
123
+ applyGlobalFlag(config, name, value.value, () => { outputJson = true; }, () => { help = true; });
124
+ continue;
125
+ }
126
+ }
127
+ commandArgs.push(token);
128
+ }
129
+ return { command, commandArgs, config, outputJson, help };
130
+ }
131
+ async function createCliMcpSession(config) {
132
+ const options = {
133
+ apiKey: config.apiKey,
134
+ baseUrl: config.baseUrl,
135
+ agentToken: config.agentToken,
136
+ agentName: config.agentName,
137
+ agentType: config.agentType,
138
+ strictAgentName: config.strictAgentName,
139
+ defaultWorkspace: config.defaultWorkspace,
140
+ workspaces: config.workspacesJson ? parseWorkspaceEnv(config.workspacesJson) : undefined,
141
+ telemetryTransport: 'stdio',
142
+ };
143
+ const server = createRelayMcpServer(options);
144
+ const client = new Client({ name: 'relaycast', version: CLI_VERSION });
145
+ const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
146
+ await Promise.all([
147
+ client.connect(clientTransport),
148
+ server.connect(serverTransport),
149
+ ]);
150
+ return {
151
+ listTools: () => client.listTools(),
152
+ callTool: (name, args) => client.callTool({ name, arguments: args }),
153
+ close: async () => {
154
+ await Promise.allSettled([
155
+ client.close(),
156
+ server.close(),
157
+ ]);
158
+ },
159
+ };
160
+ }
161
+ function parseToolArgs(argv, inputSchema) {
162
+ const jsonFlagIndex = argv.findIndex((arg) => isFlag(arg) && TOOL_JSON_FLAG_NAMES.has(splitFlag(arg).name));
163
+ if (jsonFlagIndex >= 0) {
164
+ const token = argv[jsonFlagIndex];
165
+ const { inlineValue } = splitFlag(token);
166
+ const raw = inlineValue ?? argv[jsonFlagIndex + 1];
167
+ if (!raw) {
168
+ throw new Error(`Missing value for ${token}`);
169
+ }
170
+ const parsed = JSON.parse(raw);
171
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
172
+ throw new Error(`${token} must be a JSON object`);
173
+ }
174
+ return parsed;
45
175
  }
46
- if (commandPath === 'reply') {
47
- telemetry.capture('relaycast_message_sent', {
48
- source_surface: 'cli',
49
- message_kind: 'thread_reply',
50
- command: commandPath,
51
- });
176
+ const args = {};
177
+ for (let i = 0; i < argv.length; i += 1) {
178
+ const token = argv[i];
179
+ if (!isFlag(token)) {
180
+ throw new Error(`Unexpected positional argument "${token}". Use --name value arguments.`);
181
+ }
182
+ const { name, inlineValue, negated } = splitFlag(token);
183
+ const key = normalizeArgName(name);
184
+ const schema = inputSchema?.properties?.[key];
185
+ let rawValue;
186
+ if (negated) {
187
+ rawValue = false;
188
+ }
189
+ else if (inlineValue != null) {
190
+ rawValue = inlineValue;
191
+ }
192
+ else {
193
+ const isBoolean = schemaHasType(schema, 'boolean');
194
+ const value = readFlagValue(argv, i, name, isBoolean);
195
+ rawValue = value.value;
196
+ if (value.consumed)
197
+ i += 1;
198
+ }
199
+ const value = coerceToolValue(rawValue, schema);
200
+ appendArgValue(args, key, value, schema);
201
+ }
202
+ return args;
203
+ }
204
+ function formatHelp(tools) {
205
+ return [
206
+ 'relaycast - Relaycast command line tools',
207
+ '',
208
+ 'Usage:',
209
+ ' relaycast tools',
210
+ ' relaycast <mcp-tool-name> [--arg value]',
211
+ ' relaycast <mcp-tool-name> --json-args \'{"key":"value"}\'',
212
+ '',
213
+ 'Global options:',
214
+ ' --relay-api-key <key> Workspace key, defaults to RELAY_API_KEY',
215
+ ' --relay-base-url <url> API base URL, defaults to RELAY_BASE_URL',
216
+ ' --relay-agent-token <token> Agent token, defaults to RELAY_AGENT_TOKEN',
217
+ ' --relay-agent-name <name> Agent name, defaults to RELAY_AGENT_NAME',
218
+ ' --json Print raw JSON output',
219
+ '',
220
+ 'Commands:',
221
+ formatToolList(tools).trimEnd(),
222
+ ].join('\n') + '\n';
223
+ }
224
+ function formatToolList(tools) {
225
+ const width = tools.reduce((max, tool) => Math.max(max, tool.name.length), 0);
226
+ return tools
227
+ .map((tool) => {
228
+ const summary = tool.title ?? firstSentence(tool.description) ?? '';
229
+ return ` ${tool.name.padEnd(width)} ${summary}`.trimEnd();
230
+ })
231
+ .join('\n') + '\n';
232
+ }
233
+ function formatToolHelp(command, tool) {
234
+ if (!tool) {
235
+ return [
236
+ `No MCP tool named "${command}" was found in the tool list.`,
237
+ 'Legacy MCP aliases are still accepted when called directly.',
238
+ '',
239
+ `Usage: relaycast ${command} --json-args '{"key":"value"}'`,
240
+ ].join('\n') + '\n';
241
+ }
242
+ const lines = [
243
+ `${tool.name}${tool.title ? ` - ${tool.title}` : ''}`,
244
+ '',
245
+ tool.description ?? '',
246
+ '',
247
+ `Usage: relaycast ${tool.name} [--arg value]`,
248
+ ];
249
+ const properties = tool.inputSchema?.properties ?? {};
250
+ const argLines = Object.entries(properties).map(([name, schema]) => ` --${name.replace(/_/g, '-')} ${formatSchemaType(schema)}`);
251
+ if (argLines.length) {
252
+ lines.push('', 'Arguments:', ...argLines);
253
+ }
254
+ return lines.filter((line, index) => line || index !== 2).join('\n') + '\n';
255
+ }
256
+ function writeToolResult(stdout, result, rawJson) {
257
+ if (rawJson) {
258
+ stdout.write(`${JSON.stringify(result, null, 2)}\n`);
52
259
  return;
53
260
  }
54
- if (commandPath === 'group-dm') {
55
- const participants = Array.isArray(args[0]) ? args[0].length : undefined;
56
- telemetry.capture('relaycast_message_sent', {
57
- source_surface: 'cli',
58
- message_kind: 'group_dm',
59
- participants_count: participants,
60
- command: commandPath,
61
- });
261
+ const structured = getStructuredContent(result);
262
+ if (structured !== undefined) {
263
+ stdout.write(`${JSON.stringify(structured, null, 2)}\n`);
62
264
  return;
63
265
  }
64
- if (commandPath === 'inbox') {
65
- telemetry.capture('relaycast_inbox_checked', { source_surface: 'cli' });
266
+ const contentText = getTextContent(result);
267
+ if (contentText) {
268
+ stdout.write(`${contentText}\n`);
66
269
  return;
67
270
  }
68
- if (commandPath === 'agent register') {
69
- telemetry.capture('relaycast_agent_registered', { source_surface: 'cli' });
70
- }
71
- }
72
- program
73
- .name('relaycast')
74
- .description('Relaycast — agent-to-agent messaging CLI')
75
- .version(CLI_VERSION);
76
- registerWorkspaceCommands(program);
77
- registerAgentCommands(program);
78
- registerConfigCommands(program);
79
- registerChannelCommands(program);
80
- registerMessagingCommands(program);
81
- registerReadCommands(program);
82
- registerSearchCommands(program);
83
- registerReactionCommands(program);
84
- registerFileCommands(program);
85
- registerBillingCommands(program);
86
- registerOpenClawCommands(program);
87
- registerTelemetryCommands(program, telemetry);
88
- program.hook('preAction', (_thisCommand, actionCommand) => {
89
- const commandPath = getCommandPath(actionCommand);
90
- if (!commandPath)
271
+ stdout.write(`${JSON.stringify(result, null, 2)}\n`);
272
+ }
273
+ function isToolErrorResult(result) {
274
+ if (!result || typeof result !== 'object')
275
+ return false;
276
+ return result.isError === true;
277
+ }
278
+ function getStructuredContent(result) {
279
+ if (!result || typeof result !== 'object')
280
+ return undefined;
281
+ return result.structuredContent;
282
+ }
283
+ function getTextContent(result) {
284
+ if (!result || typeof result !== 'object')
285
+ return null;
286
+ const content = result.content;
287
+ if (!Array.isArray(content))
288
+ return null;
289
+ const parts = content
290
+ .map((item) => {
291
+ if (!item || typeof item !== 'object')
292
+ return null;
293
+ const text = item.text;
294
+ return typeof text === 'string' ? text : null;
295
+ })
296
+ .filter((item) => item != null);
297
+ return parts.length ? parts.join('\n') : null;
298
+ }
299
+ function splitFlag(token) {
300
+ const trimmed = token.replace(/^--?/, '');
301
+ const eqIndex = trimmed.indexOf('=');
302
+ const rawName = eqIndex >= 0 ? trimmed.slice(0, eqIndex) : trimmed;
303
+ const negated = rawName.startsWith('no-');
304
+ return {
305
+ name: negated ? rawName.slice(3) : rawName,
306
+ inlineValue: eqIndex >= 0 ? trimmed.slice(eqIndex + 1) : undefined,
307
+ negated,
308
+ };
309
+ }
310
+ function isFlag(token) {
311
+ return token.startsWith('-') && token.length > 1;
312
+ }
313
+ function readFlagValue(argv, index, flagName, allowBooleanDefault = false) {
314
+ const next = argv[index + 1];
315
+ if (!next || isFlag(next)) {
316
+ if (allowBooleanDefault) {
317
+ return { value: true, consumed: false };
318
+ }
319
+ throw new Error(`Missing value for --${flagName}`);
320
+ }
321
+ return { value: next, consumed: true };
322
+ }
323
+ function readGlobalFlagValue(argv, index, flagName, inlineValue) {
324
+ if (inlineValue != null) {
325
+ return { value: inlineValue, consumed: false };
326
+ }
327
+ if (flagName === 'json' || flagName === 'help' || flagName === 'h' || flagName === 'relay-strict-agent-name') {
328
+ return { value: true, consumed: false };
329
+ }
330
+ return readFlagValue(argv, index, flagName, false);
331
+ }
332
+ function applyGlobalFlag(config, flag, value, setJson, setHelp) {
333
+ const stringValue = value === true ? undefined : String(value);
334
+ switch (flag) {
335
+ case 'relay-api-key':
336
+ config.apiKey = stringValue;
337
+ break;
338
+ case 'relay-base-url':
339
+ config.baseUrl = stringValue;
340
+ break;
341
+ case 'relay-agent-token':
342
+ config.agentToken = stringValue;
343
+ break;
344
+ case 'relay-agent-name':
345
+ config.agentName = stringValue;
346
+ break;
347
+ case 'relay-agent-type':
348
+ config.agentType = parseAgentType(stringValue);
349
+ break;
350
+ case 'relay-strict-agent-name':
351
+ config.strictAgentName = parseBooleanFlag(value);
352
+ break;
353
+ case 'relay-workspaces-json':
354
+ config.workspacesJson = stringValue;
355
+ break;
356
+ case 'relay-default-workspace':
357
+ config.defaultWorkspace = stringValue;
358
+ break;
359
+ case 'json':
360
+ setJson();
361
+ break;
362
+ case 'help':
363
+ case 'h':
364
+ setHelp();
365
+ break;
366
+ default:
367
+ throw new Error(`Unknown global option "--${flag}"`);
368
+ }
369
+ }
370
+ function normalizeArgName(name) {
371
+ return name.replace(/-/g, '_');
372
+ }
373
+ function appendArgValue(args, key, value, schema) {
374
+ if (schemaHasType(schema, 'array')) {
375
+ const existing = args[key];
376
+ if (Array.isArray(value)) {
377
+ args[key] = Array.isArray(existing) ? [...existing, ...value] : value;
378
+ }
379
+ else {
380
+ args[key] = Array.isArray(existing) ? [...existing, value] : [value];
381
+ }
91
382
  return;
92
- activeCommandPath = commandPath;
93
- activeCommandStartedAt = Date.now();
94
- });
95
- program.hook('postAction', async (_thisCommand, actionCommand) => {
96
- const commandPath = getCommandPath(actionCommand);
97
- if (!commandPath)
383
+ }
384
+ if (Object.prototype.hasOwnProperty.call(args, key)) {
385
+ const existing = args[key];
386
+ args[key] = Array.isArray(existing) ? [...existing, value] : [existing, value];
98
387
  return;
99
- const durationMs = Math.max(Date.now() - activeCommandStartedAt, 0);
100
- telemetry.capture('relaycast_cli_command_completed', {
101
- command: commandPath,
102
- duration_ms: durationMs,
103
- source_surface: 'cli',
104
- });
105
- captureDerivedEvents(commandPath, actionCommand.processedArgs);
106
- activeCommandPath = null;
107
- activeCommandStartedAt = 0;
108
- await telemetry.flush();
109
- });
110
- telemetry.capture('relaycast_cli_started', {
111
- source_surface: 'cli',
112
- command_count: Math.max(process.argv.length - 2, 0),
113
- });
114
- telemetry.captureFirstRunIfNeeded();
115
- process.on('beforeExit', () => {
116
- void telemetry.flush();
117
- });
118
- void program.parseAsync().catch(async (error) => {
119
- if (activeCommandPath) {
120
- const durationMs = Math.max(Date.now() - activeCommandStartedAt, 0);
121
- telemetry.capture('relaycast_cli_command_failed', {
122
- command: activeCommandPath,
123
- duration_ms: durationMs,
124
- source_surface: 'cli',
125
- error_name: error instanceof Error ? error.name : 'UnknownError',
126
- });
127
- }
128
- await telemetry.flush();
129
- if (error instanceof Error) {
130
- console.error(error.message);
131
- }
132
- else {
133
- console.error(String(error));
134
- }
135
- process.exit(1);
136
- });
388
+ }
389
+ args[key] = value;
390
+ }
391
+ function coerceToolValue(value, schema) {
392
+ if (typeof value === 'boolean')
393
+ return value;
394
+ if (schemaHasType(schema, 'array')) {
395
+ const parsed = parseJsonIfPossible(value);
396
+ if (Array.isArray(parsed)) {
397
+ return parsed;
398
+ }
399
+ return [coerceToolValue(value, schema?.items)];
400
+ }
401
+ if (schemaHasType(schema, 'object')) {
402
+ return JSON.parse(value);
403
+ }
404
+ if (schemaHasType(schema, 'number') || schemaHasType(schema, 'integer')) {
405
+ const parsed = Number(value);
406
+ if (Number.isNaN(parsed)) {
407
+ throw new Error(`Expected number, received "${value}"`);
408
+ }
409
+ return parsed;
410
+ }
411
+ if (schemaHasType(schema, 'boolean')) {
412
+ return parseBooleanFlag(value);
413
+ }
414
+ return value;
415
+ }
416
+ function schemaHasType(schema, type) {
417
+ if (!schema?.type)
418
+ return false;
419
+ return Array.isArray(schema.type) ? schema.type.includes(type) : schema.type === type;
420
+ }
421
+ function parseJsonIfPossible(value) {
422
+ try {
423
+ return JSON.parse(value);
424
+ }
425
+ catch {
426
+ return value;
427
+ }
428
+ }
429
+ function parseBooleanFlag(value) {
430
+ if (value === undefined)
431
+ return undefined;
432
+ if (typeof value === 'boolean')
433
+ return value;
434
+ const normalized = value.trim().toLowerCase();
435
+ if (['1', 'true', 'yes', 'on'].includes(normalized))
436
+ return true;
437
+ if (['0', 'false', 'no', 'off'].includes(normalized))
438
+ return false;
439
+ return undefined;
440
+ }
441
+ function parseAgentType(value) {
442
+ if (value === 'agent' || value === 'human')
443
+ return value;
444
+ return undefined;
445
+ }
446
+ function firstSentence(value) {
447
+ if (!value)
448
+ return undefined;
449
+ const [sentence] = value.split('.');
450
+ return sentence ? `${sentence}.` : value;
451
+ }
452
+ function formatSchemaType(schema) {
453
+ if (!schema.type)
454
+ return 'value';
455
+ return Array.isArray(schema.type) ? schema.type.join('|') : schema.type;
456
+ }
457
+ function formatError(err) {
458
+ if (err instanceof Error) {
459
+ return err.message;
460
+ }
461
+ return String(err);
462
+ }
137
463
  //# sourceMappingURL=index.js.map