diff --git a/cmd/schema/README.md b/cmd/schema/README.md deleted file mode 100644 index c7f0102e590dcd98ce150e506c28f9016ef50bbc..0000000000000000000000000000000000000000 --- a/cmd/schema/README.md +++ /dev/null @@ -1,182 +0,0 @@ -# Crush Configuration Schema Generator - -This tool automatically generates a JSON Schema for the Crush configuration file by using Go reflection to analyze the configuration structs. The schema provides validation, autocompletion, and documentation for configuration files. - -## Features - -- **Automated Generation**: Uses reflection to automatically generate schemas from Go structs -- **Always Up-to-Date**: Schema stays in sync with code changes automatically -- **Comprehensive**: Includes all configuration options, types, and validation rules -- **Enhanced**: Adds provider enums, model lists, and custom descriptions -- **Extensible**: Easy to add new fields and modify existing ones - -## Usage - -```bash -# Generate the schema -go run cmd/schema/main.go > crush-schema.json - -# Or use the task runner -task schema -``` - -## How It Works - -The generator: - -1. **Reflects on Config Structs**: Analyzes the `config.Config` struct and all related types -2. **Generates Base Schema**: Creates JSON Schema definitions for all struct fields -3. **Enhances with Runtime Data**: Adds provider lists, model enums, and tool lists from the actual codebase -4. **Adds Custom Descriptions**: Provides meaningful descriptions for configuration options -5. **Sets Default Values**: Includes appropriate defaults for optional fields - -## Schema Features - -The generated schema includes: - -- **Type Safety**: Proper type definitions for all configuration fields -- **Validation**: Required fields, enum constraints, and format validation -- **Documentation**: Descriptions for all configuration options -- **Defaults**: Default values for optional settings -- **Provider Enums**: Current list of supported providers -- **Model Enums**: Available models from all configured providers -- **Tool Lists**: Valid tool names for agent configurations -- **Cross-References**: Proper relationships between different config sections - -## Adding New Configuration Fields - -To add new configuration options: - -1. **Add to Config Structs**: Add the field to the appropriate struct in `internal/config/` -2. **Add JSON Tags**: Include proper JSON tags with field names -3. **Regenerate Schema**: Run the schema generator to update the JSON schema -4. **Update Validation**: Add any custom validation logic if needed - -Example: -```go -type Options struct { - // ... existing fields ... - - // New field with JSON tag and description - NewFeature bool `json:"new_feature,omitempty"` -} -``` - -The schema generator will automatically: -- Detect the new field -- Generate appropriate JSON schema -- Add type information -- Include in validation - -## Using the Schema - -### Editor Integration - -Most modern editors support JSON Schema: - -**VS Code**: Add to your workspace settings: -```json -{ - "json.schemas": [ - { - "fileMatch": ["crush.json", ".crush.json"], - "url": "./crush-schema.json" - } - ] -} -``` - -**JetBrains IDEs**: Configure in Settings → Languages & Frameworks → Schemas and DTDs → JSON Schema Mappings - -### Validation Tools - -```bash -# Using jsonschema (Python) -pip install jsonschema -jsonschema -i crush.json crush-schema.json - -# Using ajv-cli (Node.js) -npm install -g ajv-cli -ajv validate -s crush-schema.json -d crush.json -``` - -### Configuration Example - -```json -{ - "models": { - "large": { - "model_id": "claude-3-5-sonnet-20241022", - "provider": "anthropic", - "reasoning_effort": "medium", - "max_tokens": 8192 - }, - "small": { - "model_id": "claude-3-5-haiku-20241022", - "provider": "anthropic" - } - }, - "providers": { - "anthropic": { - "id": "anthropic", - "provider_type": "anthropic", - "api_key": "your-api-key", - "disabled": false - } - }, - "agents": { - "coder": { - "id": "coder", - "name": "Coder", - "model": "large", - "disabled": false - }, - "custom-agent": { - "id": "custom-agent", - "name": "Custom Agent", - "description": "A custom agent for specific tasks", - "model": "small", - "allowed_tools": ["glob", "grep", "view"], - "allowed_mcp": { - "filesystem": ["read", "write"] - } - } - }, - "mcp": { - "filesystem": { - "command": "mcp-filesystem", - "args": ["--root", "/workspace"], - "type": "stdio" - } - }, - "lsp": { - "typescript": { - "command": "typescript-language-server", - "args": ["--stdio"], - "enabled": true - } - }, - "options": { - "context_paths": [ - "README.md", - "docs/", - ".cursorrules" - ], - "data_directory": ".crush", - "debug": false, - "tui": { - "compact_mode": false - } - } -} -``` - -## Maintenance - -The schema generator is designed to be maintenance-free. As long as: - -- Configuration structs have proper JSON tags -- New enums are added to the enhancement functions -- The generator is run after significant config changes - -The schema will stay current with the codebase automatically. \ No newline at end of file diff --git a/pkg/log/log.go b/pkg/log/log.go index 1cfcf6522c1e8c9114d2e9f86a68ba786f1df2f0..c17ca366936ce540b9bfdfc588ef8c862e74ac95 100644 --- a/pkg/log/log.go +++ b/pkg/log/log.go @@ -3,30 +3,35 @@ package log import ( "log/slog" "path/filepath" + "sync" "github.com/charmbracelet/crush/pkg/config" "gopkg.in/natefinch/lumberjack.v2" ) +var initOnce sync.Once + func Init(cfg *config.Config) { - logRotator := &lumberjack.Logger{ - Filename: filepath.Join(cfg.Options.DataDirectory, "logs", "crush.log"), - MaxSize: 10, // Max size in MB - MaxBackups: 0, // Number of backups - MaxAge: 30, // Days - Compress: false, // Enable compression - } - - level := slog.LevelInfo - if cfg.Options.Debug { - level = slog.LevelDebug - } - - logger := slog.NewJSONHandler(logRotator, &slog.HandlerOptions{ - Level: level, - AddSource: true, - }) + initOnce.Do(func() { + logRotator := &lumberjack.Logger{ + Filename: filepath.Join(cfg.Options.DataDirectory, "logs", "crush.log"), + MaxSize: 10, // Max size in MB + MaxBackups: 0, // Number of backups + MaxAge: 30, // Days + Compress: false, // Enable compression + } + + level := slog.LevelInfo + if cfg.Options.Debug { + level = slog.LevelDebug + } - slog.SetDefault(slog.New(logger)) + logger := slog.NewJSONHandler(logRotator, &slog.HandlerOptions{ + Level: level, + AddSource: true, + }) + + slog.SetDefault(slog.New(logger)) + }) }