Forked from
Forked from
CONTRIBUTING.md
CONTRIBUTING.md
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! 🚀
git commit, git push, or other destructive commands without explicit user confirmation.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! 🚀
git commit, git push, or other destructive commands without explicit user confirmation..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
.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