Skip to content

feat: add bot CLI and codegen#16

Merged
sealday merged 1 commit intotegojs:mainfrom
mhingston:main
Feb 3, 2026
Merged

feat: add bot CLI and codegen#16
sealday merged 1 commit intotegojs:mainfrom
mhingston:main

Conversation

@mhingston
Copy link
Contributor

This pull request introduces the initial implementation of the @tego/bot-cli package, providing a command-line interface for invoking @tego/botjs functions. It includes CLI command parsing, argument validation, system readiness checks, output handling (including buffer/file output), and code generation for API metadata. The package also comes with documentation and basic unit tests.

The most important changes are:

Core CLI Functionality:

  • Implements the main CLI entrypoint in src/index.ts, defining the call and doctor commands and integrating generated command registration.
  • Adds the callCommand logic in src/commands/call.ts for invoking @tego/botjs exports with flexible argument input modes (JSON, file, stdin), dry-run support, and output options.
  • Implements invokeExport in src/commands/invoke.ts to handle dynamic function invocation, argument validation, and output formatting (including writing buffer results to files).

Argument Validation and API Metadata:

  • Adds argument validation against a generated API spec in src/commands/validate.ts, ensuring correct argument counts/types for function calls.
  • Introduces the tools/gen-api.ts script to statically analyze @tego/botjs exports and generate a comprehensive api.json used for validation and command generation.

System Readiness and Documentation:

  • Implements a doctorCommand in src/commands/doctor.ts to check platform-specific requirements and provide user guidance, with optional JSON output.
  • Adds a detailed readme.md with installation, usage, and command documentation.

Testing and Package Metadata:

  • Provides basic unit tests for the call and doctor commands in tests/call.test.ts and src/commands/doctor.test.ts. [1] [2]
  • Adds a complete package.json for the new package, specifying dependencies, scripts, and publishing metadata.

Copilot AI review requested due to automatic review settings January 28, 2026 20:14
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request introduces the @tego/bot-cli package, a command-line interface for invoking @tego/botjs functions. The implementation includes CLI command parsing, argument validation, system readiness checks, output handling, and automated code generation for API metadata and CLI commands.

Changes:

  • Added a new @tego/bot-cli package with core CLI functionality including call and doctor commands
  • Implemented code generation tools to extract API metadata from @tego/botjs and generate CLI commands automatically
  • Created argument validation, invocation logic, and flexible output handling (JSON, file, stdout)

Reviewed changes

Copilot reviewed 14 out of 18 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
packages/bot-cli/package.json Package metadata, dependencies (commander, ts-morph), and build scripts
packages/bot-cli/bin/bot.ts CLI entry point that parses commands
packages/bot-cli/src/index.ts Main CLI module defining call and doctor commands
packages/bot-cli/src/commands/call.ts Implements the call command with JSON/file/stdin input modes
packages/bot-cli/src/commands/invoke.ts Function invocation logic with output formatting and buffer handling
packages/bot-cli/src/commands/validate.ts Argument validation against API spec
packages/bot-cli/src/commands/doctor.ts System readiness checks for platform-specific requirements
packages/bot-cli/tools/gen-api.ts Static analysis tool to extract API metadata from botjs
packages/bot-cli/tools/gen-commands.ts Code generator for CLI command registration
packages/bot-cli/src/generated/commands.ts Generated CLI commands for all botjs functions
packages/botjs/generated/api.json Generated API metadata with function signatures and documentation
packages/bot-cli/tests/call.test.ts Basic unit tests for call command
packages/bot-cli/src/commands/doctor.test.ts Unit tests for doctor command
packages/bot-cli/readme.md Usage documentation and examples
pnpm-lock.yaml Dependency lock file updates for new packages
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +44 to +46
function dirname(path: string): string {
return path.slice(0, Math.max(0, path.lastIndexOf("/")));
}
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The custom dirname implementation is unnecessary and should be removed. Instead, import dirname from node:path on line 2, similar to how it's done in tools/gen-api.ts and tools/gen-commands.ts.

Copilot uses AI. Check for mistakes.
## Output

- Default output is human-readable.
- Use `--json` to emit machine JSON output.
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation states to use --json to emit machine JSON output, but the correct flag is --json-output as seen in the CLI implementation (src/index.ts line 22) and the generated commands. This inconsistency will confuse users.

Copilot uses AI. Check for mistakes.
Comment on lines +60 to +62
for (const param of argList) {
lines.push(` .argument("<${param}>", "${param}")`);
}
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code generation script doesn't distinguish between required and optional parameters. All parameters are generated as required arguments (using <param> syntax) even when they are optional in the API. For example, moveMouseSmooth has an optional speed parameter, and mouseClick has two optional parameters (button and double), but they are all generated as required CLI arguments. The script should check the optional field from the API spec and use [param] syntax for optional arguments instead of <param>.

Copilot uses AI. Check for mistakes.
exports: Array<{
name: string;
kind: string;
params?: Array<{ name: string; type: string }>;
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TypeScript interface for parsing the API spec is incomplete. It only includes name and type for parameters, but the actual API spec also contains optional, default, jsdoc, and enum fields. Add the missing fields to ensure the type definition matches the actual data structure: params?: Array<{ name: string; type: string; optional?: boolean; default?: string; jsdoc?: string; enum?: unknown[] }>;

Suggested change
params?: Array<{ name: string; type: string }>;
params?: Array<{
name: string;
type: string;
optional?: boolean;
default?: string;
jsdoc?: string;
enum?: unknown[];
}>;

Copilot uses AI. Check for mistakes.
Comment on lines +58 to +74
function getLiteralUnionValues(
type: Type,
): Array<string | number | boolean> | undefined {
const unionTypes = type.getUnionTypes();
if (unionTypes.length === 0) return undefined;
const values: Array<string | number | boolean> = [];
for (const unionType of unionTypes) {
if (unionType.isStringLiteral()) {
values.push(unionType.getLiteralValue() as string);
} else if (unionType.isNumberLiteral()) {
values.push(unionType.getLiteralValue() as number);
} else if (unionType.isBooleanLiteral()) {
values.push(unionType.getLiteralValue() as boolean);
}
}
return values.length > 0 ? values : undefined;
}
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The getLiteralUnionValues function extracts boolean literals from union types, which results in [null, null] being stored in the enum array for boolean parameters (line 76 in the generated api.json). Boolean types shouldn't be treated as enums. Consider filtering out boolean literal types from enum extraction, or only extracting enums for string/number literal unions.

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,46 @@
import { readFile } from "node:fs/promises";
import { resolve } from "node:path";
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The custom dirname implementation is reimplementing functionality that's already available from Node.js's node:path module. The import statement on line 2 should include dirname alongside resolve, and the custom implementation on lines 44-46 should be removed. This would be more reliable and consistent with the rest of the codebase (see tools/gen-api.ts and tools/gen-commands.ts which properly import dirname from node:path).

Copilot uses AI. Check for mistakes.
Comment on lines +36 to +43
lines.push(" }");
lines.push(" const lower = value.toLowerCase();");
lines.push(" if (BOOL_TRUE.has(lower)) return true;");
lines.push(" if (BOOL_FALSE.has(lower)) return false;");
lines.push(" if (/^-?\\\\d+(?:\\\\.\\\\d+)?$/.test(value)) {");
lines.push(" return Number(value);");
lines.push(" }");
lines.push(" return value;");
Copy link

Copilot AI Jan 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The regex pattern has excessive escaping. In a regular string (not a template literal), \\d should be \d and \\. should be \.. The current pattern \\\\d and \\\\. will literally match backslashes followed by 'd' or '.', not digits or decimal points. This should be: if (/^-?\d+(?:\.\d+)?$/.test(value)) {

Suggested change
lines.push(" }");
lines.push(" const lower = value.toLowerCase();");
lines.push(" if (BOOL_TRUE.has(lower)) return true;");
lines.push(" if (BOOL_FALSE.has(lower)) return false;");
lines.push(" if (/^-?\\\\d+(?:\\\\.\\\\d+)?$/.test(value)) {");
lines.push(" return Number(value);");
lines.push(" }");
lines.push(" return value;");
lines.push(" }");
lines.push(" const lower = value.toLowerCase();");
lines.push(" if (BOOL_TRUE.has(lower)) return true;");
lines.push(" if (BOOL_FALSE.has(lower)) return false;");
lines.push(" if (/^-?\\d+(?:\\.\\d+)?$/.test(value)) {");
lines.push(" return Number(value);");
lines.push(" }");
lines.push(" return value;");

Copilot uses AI. Check for mistakes.
@sealday
Copy link
Contributor

sealday commented Feb 3, 2026

Could you add the corresponding CI to publish this package to npm?

@sealday sealday merged commit 233e969 into tegojs:main Feb 3, 2026
7 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants