Forked from crunch3r/ai-toolbox
Thank you for your interest in contributing to the AI Toolbox plugin! This document provides guidelines and instructions for contributing.
This project follows a simple code of conduct:
Before contributing, ensure you have:
Always create a new branch for your changes:
Follow the project structure when making changes:
src/tools/ directorysrc/config.ts for new settingstests/ directoryBefore committing, ensure all checks pass:
All checks must pass before submitting a pull request.
Create a new file in src/tools/ directory (e.g., newToolModule.ts):
Add your tool module to the registration flow in src/toolsProvider.ts:
If your tool requires configuration toggles or settings, update src/config.ts:
Create test file in tests/ directory (e.g., newToolModule.test.ts):
Update the following documentation files to reflect your new tool:
| File | What to Update |
|---|---|
README.md | Add tool to category list in Tool Categories section |
TOOLS_REFERENCE.md | Add complete tool reference with parameter table |
ARCHITECTURE.md | Update module count if adding new tool file |
CHANGELOG.md | Document the addition under [Unreleased] or next version |
All contributions must include comprehensive tests:
Every tool function should have unit tests covering:
| Category | Minimum Coverage |
|---|---|
| Tool implementations | 80%+ line coverage |
| Security validators | 100% branch coverage |
| Configuration parsing | 90%+ coverage |
Must include:
Each tool must document:
Must include:
Security is a top priority for this project. Follow these guidelines when contributing:
All user inputs must be validated using Zod schemas:
All file paths must pass through validatePath():
Shell commands must be sanitized before execution:
Never commit API keys, tokens, or credentials:
.gitignoreEnsure your PR includes:
npm test)npm run typecheck)npm run lint)Before submitting your PR, verify:
If you need help contributing:
Thank you for helping make AI Toolbox better! 🚀
.mdnpm run build)# Clone the repository
git clone https://github.com/lmstudio-ai/ai-toolbox.git
cd ai-toolbox
# Install dependencies
npm install
# Build the project
npm run build
# Run type checking
npm run typecheck
# Run tests
npm test
git checkout -b feature/add-new-tool
# or
git checkout -b fix/bug-description
# or
git checkout -b docs/update-documentation
# Run type checking
npm run typecheck
# Run linter
npm run lint
# Run test suite
npm test
# Build the project
npm run build
import { tool, type Tool } from '@lmstudio/sdk';
import { z } from 'zod';
import type { PluginConfig } from '@/config.js'; // ✅ Use @/ alias for cleaner imports
interface NewToolParams {
parameter1: string;
parameter2?: number;
}
export function registerNewTools(_config: PluginConfig): Tool[] {
const tools: Tool[] = [];
// Define the tool using Zod schema for validation
tools.push(tool({
name: 'new_tool_name',
description: 'Clear, concise description of what this tool does.',
parameters: {
parameter1: z.string().describe('Description of parameter1'),
parameter2: z.number().optional().describe('Optional parameter with default'),
},
implementation: async ({ parameter1, parameter2 }: NewToolParams) => {
try {
// Your tool logic here (must be async)
return { success: true, data: { result: 'success' } };
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
return { success: false, error: `Operation failed: ${message}` };
}
},
}));
return tools;
}
// Import your new tool module
import { registerNewTools } from './tools/newToolModule.js';
export function createToolsProvider(config: PluginConfig) {
// ... existing code ...
const tools = [...tools, ...registerNewTools(config)];
return tools;
}
export const ConfigSchema = z.object({
// ... existing schema ...
newToolEnabled: z.boolean().default(true).describe('Enable the new tool'),
});
import { registerNewTools } from '../src/tools/newToolModule';
import type { PluginConfig } from '../src/config';
describe('registerNewTools', () => {
let config: PluginConfig;
beforeEach(() => {
// Create a mock config for testing
config = {
newToolEnabled: true,
// ... other required config fields
} as unknown as PluginConfig;
});
test('should register tool with correct name', () => {
const tools = registerNewTools(config);
expect(tools).toHaveLength(1);
expect(tools[0].name).toBe('new_tool_name');
});
// Add more tests for tool functionality
});
# Run all tests
npm test
# Run with coverage report
npm run test:coverage
# Run specific test file
npm test -- newToolModule.test.ts
// ✅ Good - Validate with Zod
parameters: {
userInput: z.string().min(1).max(1000),
}
// ❌ Bad - No validation
parameters: {
userInput: z.any(),
}
import { validatePath } from '../security.js';
if (!validatePath(userPath, getWorkingDir())) {
return { success: false, error: 'Invalid path: directory traversal detected' };
}
import { sanitizeCommand } from '../security.js';
const sanitized = sanitizeCommand(command);
if (!sanitized.safe) {
return { success: false, error: `Unsafe command detected: ${sanitized.reason}` };
}
## 📝 Summary
Brief description of changes made.
## 🔍 Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Documentation update
- [ ] Performance improvement
- [ ] Security fix
## ✅ Testing
- [ ] Unit tests added/updated
- [ ] All existing tests passing
- [ ] Manual testing completed
## 📚 Documentation
- [ ] README.md updated
- [ ] TOOLS_REFERENCE.md updated (if adding/changing tools)
- [ ] CHANGELOG.md updated