@plosson/agentio 0.4.1 → 0.4.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plosson/agentio",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "CLI for LLM agents to interact with communication and tracking services",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -0,0 +1,126 @@
1
+ import { Command } from 'commander';
2
+
3
+ interface CommandInfo {
4
+ fullPath: string;
5
+ description: string;
6
+ arguments: string[];
7
+ options: Array<{ flags: string; description: string; defaultValue?: string }>;
8
+ }
9
+
10
+ function collectCommands(cmd: Command, parentPath: string = ''): CommandInfo[] {
11
+ const results: CommandInfo[] = [];
12
+ const help = cmd.createHelp();
13
+
14
+ // Get visible subcommands (filters out help command)
15
+ const subcommands = help.visibleCommands(cmd).filter((c) => c.name() !== 'help');
16
+
17
+ for (const subcmd of subcommands) {
18
+ const fullPath = parentPath ? `${parentPath} ${subcmd.name()}` : subcmd.name();
19
+
20
+ // Get arguments
21
+ const args = help.visibleArguments(subcmd).map((arg) => {
22
+ const argName = arg.variadic ? `${arg.name()}...` : arg.name();
23
+ return arg.required ? `<${argName}>` : `[${argName}]`;
24
+ });
25
+
26
+ // Get options (filter out help)
27
+ const options = help
28
+ .visibleOptions(subcmd)
29
+ .filter((opt) => !opt.long?.includes('help'))
30
+ .map((opt) => {
31
+ const flags = opt.flags;
32
+ const desc = opt.description;
33
+ const defaultVal = opt.defaultValue;
34
+ return { flags, description: desc, defaultValue: defaultVal };
35
+ });
36
+
37
+ const description = subcmd.description() || '';
38
+
39
+ // Only add if it's a leaf command or has its own action
40
+ const childCommands = help.visibleCommands(subcmd).filter((c) => c.name() !== 'help');
41
+ if (childCommands.length === 0 || options.length > 0 || args.length > 0) {
42
+ results.push({
43
+ fullPath,
44
+ description,
45
+ arguments: args,
46
+ options,
47
+ });
48
+ }
49
+
50
+ // Recurse into subcommands
51
+ results.push(...collectCommands(subcmd, fullPath));
52
+ }
53
+
54
+ return results;
55
+ }
56
+
57
+ function formatOption(opt: { flags: string; description: string; defaultValue?: string }): string {
58
+ let line = opt.flags;
59
+ if (opt.description) {
60
+ line += `: ${opt.description}`;
61
+ }
62
+ if (opt.defaultValue !== undefined && opt.defaultValue !== '') {
63
+ line += ` (default: ${opt.defaultValue})`;
64
+ }
65
+ return line;
66
+ }
67
+
68
+ // Commands excluded from docs output by default (utility/meta commands)
69
+ const EXCLUDED_COMMANDS = ['config', 'status', 'update', 'claude', 'docs'];
70
+
71
+ function generateDocs(program: Command, services?: string[]): string {
72
+ const lines: string[] = [];
73
+ const version = program.version();
74
+
75
+ lines.push(`# agentio CLI v${version}`);
76
+ lines.push('');
77
+
78
+ let commands = collectCommands(program, 'agentio');
79
+
80
+ // Filter by services if specified, otherwise exclude utility commands
81
+ // Always exclude profile subcommands
82
+ commands = commands.filter((cmd) => {
83
+ if (cmd.fullPath.includes(' profile ')) {
84
+ return false;
85
+ }
86
+ const parts = cmd.fullPath.split(' ');
87
+ const service = parts[1];
88
+ if (services && services.length > 0) {
89
+ return services.includes(service);
90
+ }
91
+ return !EXCLUDED_COMMANDS.includes(service);
92
+ });
93
+
94
+ for (const cmd of commands) {
95
+ // Header with full path and arguments
96
+ let header = `## ${cmd.fullPath}`;
97
+ if (cmd.arguments.length > 0) {
98
+ header += ` ${cmd.arguments.join(' ')}`;
99
+ }
100
+ lines.push(header);
101
+
102
+ // Description
103
+ if (cmd.description) {
104
+ lines.push(cmd.description);
105
+ }
106
+
107
+ // Options
108
+ for (const opt of cmd.options) {
109
+ lines.push(formatOption(opt));
110
+ }
111
+
112
+ lines.push('');
113
+ }
114
+
115
+ return lines.join('\n').trimEnd();
116
+ }
117
+
118
+ export function registerDocsCommand(program: Command): void {
119
+ program
120
+ .command('docs')
121
+ .description('Output CLI reference for LLMs')
122
+ .option('--service <names>', 'Filter by service (comma-separated)', (val) => val.split(',').map((s: string) => s.trim()))
123
+ .action((options) => {
124
+ console.log(generateDocs(program, options.service));
125
+ });
126
+ }
@@ -134,7 +134,8 @@ export function registerGChatCommands(program: Command): void {
134
134
  });
135
135
 
136
136
  gchat
137
- .command('get <message-id>')
137
+ .command('get')
138
+ .argument('<message-id>', 'Message ID')
138
139
  .description('Get a message from a Google Chat space (OAuth profiles only)')
139
140
  .option('--profile <name>', 'Profile name (optional if only one profile exists)')
140
141
  .requiredOption('--space <id>', 'Space ID')
@@ -24,7 +24,8 @@ export function registerGDocsCommands(program: Command): void {
24
24
  .description('Google Docs operations');
25
25
 
26
26
  gdocs
27
- .command('get <doc-id-or-url>')
27
+ .command('get')
28
+ .argument('<doc-id-or-url>', 'Document ID or URL')
28
29
  .description('Export a document')
29
30
  .option('--profile <name>', 'Profile name (optional if only one profile exists)')
30
31
  .option('--format <format>', 'Export format: markdown or docx', 'markdown')
@@ -95,7 +95,8 @@ Query Syntax Examples:
95
95
  });
96
96
 
97
97
  gdrive
98
- .command('get <file-id-or-url>')
98
+ .command('get')
99
+ .argument('<file-id-or-url>', 'File ID or URL')
99
100
  .description('Get file metadata')
100
101
  .option('--profile <name>', 'Profile name')
101
102
  .action(async (fileIdOrUrl: string, options) => {
@@ -132,7 +133,8 @@ Query Syntax Examples:
132
133
  });
133
134
 
134
135
  gdrive
135
- .command('download <file-id-or-url>')
136
+ .command('download')
137
+ .argument('<file-id-or-url>', 'File ID or URL')
136
138
  .description('Download a file (or export Google Workspace files)')
137
139
  .option('--profile <name>', 'Profile name')
138
140
  .requiredOption('--output <path>', 'Output file path')
@@ -164,7 +166,8 @@ Examples:
164
166
  });
165
167
 
166
168
  gdrive
167
- .command('put <file-path>')
169
+ .command('put')
170
+ .argument('<file-path>', 'Local file path')
168
171
  .description('Upload a file to Google Drive')
169
172
  .option('--profile <name>', 'Profile name')
170
173
  .option('--name <name>', 'Name for the file in Drive (defaults to local filename)')
@@ -101,7 +101,8 @@ export function registerGmailCommands(program: Command): void {
101
101
  });
102
102
 
103
103
  gmail
104
- .command('get <message-id>')
104
+ .command('get')
105
+ .argument('<message-id>', 'Message ID')
105
106
  .description('Get a message')
106
107
  .option('--profile <name>', 'Profile name (optional if only one profile exists)')
107
108
  .option('--format <format>', 'Body format: text, html, or raw', 'text')
@@ -275,7 +276,8 @@ Query Syntax Examples:
275
276
  });
276
277
 
277
278
  gmail
278
- .command('archive <message-id...>')
279
+ .command('archive')
280
+ .argument('<message-id...>', 'Message ID(s)')
279
281
  .description('Archive one or more messages')
280
282
  .option('--profile <name>', 'Profile name (optional if only one profile exists)')
281
283
  .action(async (messageIds: string[], options) => {
@@ -291,7 +293,8 @@ Query Syntax Examples:
291
293
  });
292
294
 
293
295
  gmail
294
- .command('mark <message-id...>')
296
+ .command('mark')
297
+ .argument('<message-id...>', 'Message ID(s)')
295
298
  .description('Mark one or more messages as read or unread')
296
299
  .option('--profile <name>', 'Profile name (optional if only one profile exists)')
297
300
  .option('--read', 'Mark as read')
@@ -316,7 +319,8 @@ Query Syntax Examples:
316
319
  });
317
320
 
318
321
  gmail
319
- .command('attachment <message-id>')
322
+ .command('attachment')
323
+ .argument('<message-id>', 'Message ID')
320
324
  .description('Download attachments from a message')
321
325
  .option('--profile <name>', 'Profile name (optional if only one profile exists)')
322
326
  .option('--name <filename>', 'Download specific attachment by filename (downloads all if not specified)')
@@ -359,7 +363,8 @@ Query Syntax Examples:
359
363
  });
360
364
 
361
365
  gmail
362
- .command('export <message-id>')
366
+ .command('export')
367
+ .argument('<message-id>', 'Message ID')
363
368
  .description('Export a message as PDF')
364
369
  .option('--profile <name>', 'Profile name (optional if only one profile exists)')
365
370
  .option('--output <path>', 'Output file path', 'message.pdf')
package/src/index.ts CHANGED
@@ -15,6 +15,7 @@ import { registerUpdateCommand } from './commands/update';
15
15
  import { registerConfigCommands } from './commands/config';
16
16
  import { registerClaudeCommands } from './commands/claude';
17
17
  import { registerStatusCommand } from './commands/status';
18
+ import { registerDocsCommand } from './commands/docs';
18
19
 
19
20
  declare const BUILD_VERSION: string | undefined;
20
21
 
@@ -48,5 +49,6 @@ registerUpdateCommand(program);
48
49
  registerConfigCommands(program);
49
50
  registerClaudeCommands(program);
50
51
  registerStatusCommand(program);
52
+ registerDocsCommand(program);
51
53
 
52
54
  program.parse();