From 2096982662f621897a55d9d95a0f6039fa47aca0 Mon Sep 17 00:00:00 2001 From: Raphael MANSUY Date: Tue, 3 Sep 2024 22:38:13 +0800 Subject: [PATCH] feat(cursorrules): add new cursorrules file --- .cursorrules | 55 +++++++++++++ packages/qllm-cli/README.md | 15 ++-- packages/qllm-cli/eslint.config.mjs | 7 ++ packages/qllm-cli/src/commands/run-command.ts | 34 ++++---- packages/qllm-cli/src/qllm.ts | 77 +++++++++++-------- 5 files changed, 137 insertions(+), 51 deletions(-) create mode 100644 .cursorrules diff --git a/.cursorrules b/.cursorrules new file mode 100644 index 0000000..6df26fa --- /dev/null +++ b/.cursorrules @@ -0,0 +1,55 @@ +## Role and Expertise: + +You are an elite software engineer and product manager with the following expertise: + +- Extensive experience in implementing multi-provider architectures for Large Language Models (LLMs) +- Master of functional programming, especially in TypeScript +- Deep understanding of TypeScript and its ecosystem +- Expert at creating code libraries with APIs that delight developers +- Advocate for composability, immutability, and simple pragmatic solutions +- Prefer Function over Class if possible +- Prefer Types over Interfaces if possible + +## Coding Standards: + +### Naming Conventions: +- Use kebab-case for file names (e.g., `my-component.ts`) +- Use camelCase for variables and function names (e.g., `myVariable`, `myFunction()`) +- Use UpperCamelCase (PascalCase) for classes, types, and interfaces (e.g., `MyClass`, `MyInterface`) +- Use ALL_CAPS for constants and enum values (e.g., `MAX_COUNT`, `Color.RED`) + +### File Organization: +- Group related functionality into modules +- Use index files to simplify imports +- Separate concerns: keep business logic, UI components, and utilities in different directories + +### Code Style: +- Prefer `const` over `let` when variables won't be reassigned +- Use arrow functions for better lexical scoping and concise syntax +- Utilize TypeScript's type system fully: use interfaces, type aliases, and generics where appropriate +- Implement error handling with custom error types +- Write pure functions where possible to improve testability and reduce side effects + +### Best Practices: +- Follow the Single Responsibility Principle +- Use dependency injection to improve testability and flexibility +- Implement proper error handling and logging +- Write comprehensive unit tests for all business logic +- Use async/await for asynchronous operations instead of callbacks or raw promises +- Leverage TypeScript's strict mode for enhanced type checking + +### Documentation: +- Use JSDoc comments for functions, classes, and complex types +- Include examples in documentation where appropriate +- Keep README files up-to-date with setup instructions, usage examples, and contribution guidelines + +## Library Usage: +Utilize the following libraries effectively: +- axios (^1.7.5): For HTTP requests, implement interceptors for global error handling and authentication +- js-yaml (^4.1.0): For parsing and stringifying YAML, use type-safe schemas +- mime-types (^2.1.35): For MIME type detection and file extension mapping +- node-gyp (^10.2.0): For native addon build tool, ensure proper setup in your build pipeline +- uuid (^10.0.0): For generating unique identifiers, prefer v4 for random UUIDs +- zod (^3.23.8): For runtime type checking and data validation, create reusable schemas + + diff --git a/packages/qllm-cli/README.md b/packages/qllm-cli/README.md index 7d2abd1..9b048a9 100644 --- a/packages/qllm-cli/README.md +++ b/packages/qllm-cli/README.md @@ -157,21 +157,21 @@ QLLM CLI stores its configuration in a JSON file located at `~/.qllmrc`. While m QLLM CLI offers a variety of commands for interacting with LLMs. Here's an overview of the primary usage patterns: -### Asking Questions +### Running Templates -For one-time queries, use the `ask` command: +QLLM CLI allows you to run templates directly. This is now the default behavior when no specific command is provided: ```bash -qllm ask "What is the capital of France?" +qllm ``` -Specify a provider and model: +For example: ```bash -qllm ask "Explain quantum computing" -p openai -m gpt-4 +qllm https://raw.githubusercontent.com/quantalogic/qllm/main/prompts/chain_of_thought_leader.yaml ``` -The `ask` command supports various options: +The `run` command supports various options: - `-p, --provider `: Specify the LLM provider (default: openai) - `-m, --model `: Choose a specific model @@ -212,8 +212,7 @@ qllm ask "Write a short story about AI" -s ````bash qllm ask "Explain the theory of relativity" -o relativity_explanation.txt - - +``` ### Interactive Chat diff --git a/packages/qllm-cli/eslint.config.mjs b/packages/qllm-cli/eslint.config.mjs index 328db35..d5fbe15 100644 --- a/packages/qllm-cli/eslint.config.mjs +++ b/packages/qllm-cli/eslint.config.mjs @@ -6,10 +6,16 @@ import tseslint from "typescript-eslint"; export default tseslint.config( { ignores: ["**/node_modules/**", "**/dist/**"], + "settings": { + "env": { + "node": true, + }, + }, }, eslint.configs.recommended, ...tseslint.configs.recommended, { + rules: { "@typescript-eslint/no-unused-vars": [ "warn", @@ -28,5 +34,6 @@ export default tseslint.config( "no-useless-catch": "warn", // Changed from 'error' to 'warn', "no-throw-literal": "warn", // Example rule to treat literal throws as warnings }, + }, ); diff --git a/packages/qllm-cli/src/commands/run-command.ts b/packages/qllm-cli/src/commands/run-command.ts index 5a5a585..422a2b5 100644 --- a/packages/qllm-cli/src/commands/run-command.ts +++ b/packages/qllm-cli/src/commands/run-command.ts @@ -15,6 +15,8 @@ import { processAndExit } from "../utils/common"; import { parseVariables } from "../utils/template-utils"; import { writeToFile } from "../utils/write-file"; +declare var process: NodeJS.Process; //eslint-disable-line + const runAction = async ( templateSource: string, options: Partial, @@ -106,12 +108,12 @@ const setupExecutor = (ioManager: IOManager, spinner: Spinner) => { const executor = new TemplateExecutor(); executor.on("streamChunk", (chunk: string) => process.stdout.write(chunk)); - executor.on("streamComplete", (response: string) => {}); - executor.on("streamError", (error: any) => { + executor.on("streamComplete", (_response: string) => {}); + executor.on("streamError", (error: unknown) => { spinner.stop(); ioManager.displayError(`Error during completion: ${error}`); }); - executor.on("requestSent", (request: any) => { + executor.on("requestSent", (request: unknown) => { const length = JSON.stringify(request).length; spinner.start(); spinner.update({ @@ -122,7 +124,7 @@ const setupExecutor = (ioManager: IOManager, spinner: Spinner) => { spinner.update({ text: "" }); spinner.stop(); }); - executor.on("executionError", (error: any) => { + executor.on("executionError", (error: unknown) => { spinner.stop(); ioManager.displayError(`Error executing template: ${error}`); }); @@ -136,7 +138,7 @@ const setupExecutor = (ioManager: IOManager, spinner: Spinner) => { }; const handleOutput = async ( - result: any, + result: unknown, validOptions: RunCommandOptions, ioManager: IOManager, ) => { @@ -148,18 +150,21 @@ const handleOutput = async ( }; const handleExtractedOutput = async ( - result: any, + result: unknown, validOptions: RunCommandOptions, ioManager: IOManager, ) => { const extractedVariables = validOptions .extract!.split(",") .map((v) => v.trim()); - const extractedData: Record = {}; + const extractedData: Record = {}; //eslint-disable-line + + // Cast result to a known type + const outputResult = result as { outputVariables: Record }; //eslint-disable-line for (const variable of extractedVariables) { - if (result.outputVariables.hasOwnProperty(variable)) { - extractedData[variable] = result.outputVariables[variable]; + if (outputResult.outputVariables.hasOwnProperty(variable)) { //eslint-disable-line + extractedData[variable] = outputResult.outputVariables[variable]; } else { ioManager.displayWarning( `Variable "${variable}" not found in the output.`, @@ -182,7 +187,7 @@ const handleExtractedOutput = async ( }; const handleFullOutput = async ( - result: any, + result: any, //eslint-disable-line validOptions: RunCommandOptions, ioManager: IOManager, ) => { @@ -200,20 +205,20 @@ const handleFullOutput = async ( }; const displayExtractedVariables = ( - variables: Record, + variables: Record, ioManager: IOManager, ) => { ioManager.displayInfo("Output Variables:"); for (const [key, value] of Object.entries(variables)) { ioManager.displayInfo(`${ioManager.colorize(key, "green")}:`); - ioManager.displayInfo(`${ioManager.colorize(value, "yellow")}`); + ioManager.displayInfo(`${ioManager.colorize(value as string, "yellow")}`); ioManager.displayInfo("-------------------------"); } }; export const runCommand = new Command("run") .description("Execute a template") - .argument("