Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 67 additions & 70 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,81 +1,78 @@
// eslint.config.js
import eslint from "@eslint/js";
import tseslint from "typescript-eslint";
import eslintConfigPrettier from "eslint-config-prettier";
import js from "@eslint/js";
import ts from "typescript-eslint";
import prettierRecommended from "eslint-plugin-prettier/recommended";
import importPlugin from "eslint-plugin-import";
import unusedImports from "eslint-plugin-unused-imports";
import pluginPromise from "eslint-plugin-promise";

export default [
export default ts.config(
js.configs.recommended,
ts.configs.recommendedTypeChecked,
prettierRecommended,
importPlugin.flatConfigs.recommended,
pluginPromise.configs["flat/recommended"],
{
ignores: ["**/dist/**", "**/node_modules/**", "**/coverage/**"],
},
...tseslint.config(
eslint.configs.recommended,
...tseslint.configs.recommended,
eslintConfigPrettier,
{
files: ["src/**/*.{js,ts}", "tests/**/*.{js,ts}", "bin/**/*.{js,ts}"],
plugins: {
import: importPlugin,
"unused-imports": unusedImports,
languageOptions: {
ecmaVersion: 2022,
sourceType: "module",
parserOptions: {
project: ["./tsconfig.eslint.json"],
tsconfigRootDir: import.meta.dirname,
},
languageOptions: {
ecmaVersion: 2022,
sourceType: "module",
parser: tseslint.parser,
},
rules: {
// Basic TypeScript rules
"@typescript-eslint/no-unused-vars": [
"warn",
{
ignoreRestSiblings: true,
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
caughtErrorsIgnorePattern: "^_",
},
],
"unused-imports/no-unused-imports": "error",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-floating-promises": "off",

// Basic code quality rules
"no-console": "off",
"prefer-const": "warn",
"no-var": "warn",
eqeqeq: ["warn", "always"],
},
plugins: {
"unused-imports": unusedImports,
},
files: ["{src,test}/**/*.{js,ts}"],
rules: {
// Basic code quality rules
"no-console": "off",
"prefer-const": "warn",
"no-var": "warn",
eqeqeq: ["warn", "always"],

// Light complexity rules
complexity: ["warn", { max: 20 }],
"max-depth": ["warn", { max: 4 }],
"max-lines-per-function": ["warn", { max: 150 }],
// Light complexity rules
complexity: ["warn", { max: 20 }],
"max-depth": ["warn", { max: 4 }],
"max-lines-per-function": ["warn", { max: 150 }],

// Error prevention
"import/no-duplicates": "error",
"no-template-curly-in-string": "warn",
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-unsafe-return": "off",
"@typescript-eslint/no-unsafe-argument": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
],

// Format and whitespace
"max-len": [
"warn",
{
code: 120,
ignoreComments: true,
ignoreStrings: true,
ignoreTemplateLiterals: true,
},
],
"import/no-unresolved": "off",
"import/named": "off",
"import/extensions": [
"error",
"ignorePackages",
{ js: "always", ts: "never" },
],

// Import rules
"import/extensions": ["off"],
"import/no-unresolved": "off",
"no-unused-vars": "off", // or "@typescript-eslint/no-unused-vars": "off",
"unused-imports/no-unused-imports": "error",

// Disable specific TypeScript rules that require type information
"@typescript-eslint/no-unsafe-assignment": "off",
"@typescript-eslint/no-unsafe-member-access": "off",
"@typescript-eslint/no-unsafe-call": "off",
"@typescript-eslint/no-unsafe-return": "off",
},
}
),
];
"promise/always-return": "error",
"promise/no-return-wrap": "error",
"promise/param-names": "error",
"promise/catch-or-return": "error",
"promise/no-native": "off",
"promise/no-nesting": "warn",
"promise/no-promise-in-callback": "warn",
"promise/no-callback-in-promise": "warn",
"promise/avoid-new": "off",
"promise/no-new-statics": "error",
"promise/no-return-in-finally": "warn",
"promise/valid-params": "warn",
"promise/no-multiple-resolved": "error",
},
}
);
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"build:ci": "tsc",
"clean": "rimraf dist",
"clean:all": "rimraf dist node_modules",
"lint": "eslint . --fix",
"lint": "eslint \"{src,test}/**/*.{js,ts}\" --fix",
"format": "prettier --write \"src/**/*.*\"",
"test": "vitest run",
"test:watch": "vitest",
Expand Down Expand Up @@ -52,6 +52,7 @@
"@anthropic-ai/sdk": "^0.36",
"chalk": "^5",
"dotenv": "^16",
"eslint-plugin-promise": "^7.2.1",
"semver": "^7.7.1",
"source-map-support": "^0.5",
"uuid": "^11",
Expand Down
14 changes: 14 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions prettier.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// prettier.config.ts, .prettierrc.ts, prettier.config.mts, or .prettierrc.mts

import { type Config } from "prettier";

const config: Config = {
trailingComma: "all",
tabWidth: 2,
semi: true,
singleQuote: true,
};

export default config;
63 changes: 31 additions & 32 deletions src/commands/$default.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,38 @@
import * as fs from "fs/promises";
import { createInterface } from "readline/promises";
import { ArgumentsCamelCase } from "yargs";
import { toolAgent } from "../core/toolAgent.js";
import { SharedOptions } from "../options.js";
import { createRequire } from "module";
import { Logger } from "../utils/logger.js";
import { getTools } from "../tools/getTools.js";
import * as fs from 'fs/promises';
import { createInterface } from 'readline/promises';
import { ArgumentsCamelCase, Argv } from 'yargs';
import { toolAgent } from '../core/toolAgent.js';
import { SharedOptions } from '../options.js';
import { Logger } from '../utils/logger.js';
import { getTools } from '../tools/getTools.js';

import { getAnthropicApiKeyError } from "../utils/errors.js";
import { getAnthropicApiKeyError } from '../utils/errors.js';
import { getPackageInfo } from '../utils/versionCheck.js';

interface Options extends SharedOptions {
prompt?: string;
}

export const command = "* [prompt]";
export const describe = "Execute a prompt or start interactive mode";
export const command = '* [prompt]';
export const describe = 'Execute a prompt or start interactive mode';

export const builder = (yargs) => {
return yargs.positional("prompt", {
type: "string",
description: "The prompt to execute",
export const builder = (yargs: Argv<Options>) => {
return yargs.positional('prompt', {
type: 'string',
description: 'The prompt to execute',
}); // Type assertion needed due to yargs typing complexity
};

export const handler = async (argv: ArgumentsCamelCase<Options>) => {
const logger = new Logger({ name: "Default" });
const require = createRequire(import.meta.url);
const packageInfo = require("../../package.json");
const logger = new Logger({ name: 'Default' });
const packageInfo = getPackageInfo();

logger.info(`MyCoder v${packageInfo.version} - AI-powered coding assistant`);
logger.warn(
"WARNING: This tool can do anything on your command line that you ask it to.",
"It can delete files, install software, and even send data to remote servers.",
"It is a powerful tool that should be used with caution.",
"By using this tool, you agree that the authors and contributors are not responsible for any damage that may occur as a result of using this tool.",
'WARNING: This tool can do anything on your command line that you ask it to.',
'It can delete files, install software, and even send data to remote servers.',
'It is a powerful tool that should be used with caution.',
'By using this tool, you agree that the authors and contributors are not responsible for any damage that may occur as a result of using this tool.',
);
try {
// Early API key check
Expand All @@ -47,7 +46,7 @@ export const handler = async (argv: ArgumentsCamelCase<Options>) => {
// If promptFile is specified, read from file
if (argv.file) {
try {
prompt = await fs.readFile(argv.file, "utf-8");
prompt = await fs.readFile(argv.file, 'utf-8');
} catch (error: any) {
logger.error(
`Failed to read prompt file: ${argv.file}, ${error?.message}`,
Expand All @@ -67,7 +66,7 @@ export const handler = async (argv: ArgumentsCamelCase<Options>) => {
logger.info(
"Type your request below or 'help' for usage information. Use Ctrl+C to exit.",
);
prompt = await readline.question("\n> ");
prompt = await readline.question('\n> ');
} finally {
readline.close();
}
Expand All @@ -78,27 +77,27 @@ export const handler = async (argv: ArgumentsCamelCase<Options>) => {

if (!prompt) {
logger.error(
"No prompt provided. Either specify a prompt, use --promptFile, or run in --interactive mode.",
'No prompt provided. Either specify a prompt, use --promptFile, or run in --interactive mode.',
);
process.exit(1);
}

// Add the standard suffix to all prompts
prompt += [
"Please ask for clarifications if required or if the tasks is confusing.",
'Please ask for clarifications if required or if the tasks is confusing.',
"If you need more context, don't be scared to create a sub-agent to investigate and generate report back, this can save a lot of time and prevent obvious mistakes.",
"Once the task is complete ask the user, via the userPrompt tool if the results are acceptable or if changes are needed or if there are additional follow on tasks.",
].join("\n");
'Once the task is complete ask the user, via the userPrompt tool if the results are acceptable or if changes are needed or if there are additional follow on tasks.',
].join('\n');

const tools = await getTools();
const tools = getTools();
const result = await toolAgent(prompt, tools, logger);
const output =
typeof result.result === "string"
typeof result.result === 'string'
? result.result
: JSON.stringify(result.result, null, 2);
logger.info("\n=== Result ===\n", output);
logger.info('\n=== Result ===\n', output);
} catch (error) {
logger.error("An error occurred:", error);
logger.error('An error occurred:', error);
process.exit(1);
}
};
Loading