Skip to content

Conversation

@arrrrny
Copy link

@arrrrny arrrrny commented Nov 23, 2025

No description provided.

…support

This commit addresses multiple high-priority issues and adds major new functionality:

🐛 **Critical Bug Fixes:**
- Fix musistudio#993: Add null checks for config.Router to prevent crashes
  * ImageAgent now safely handles undefined config.Router
  * Prevents "Cannot read properties of undefined (reading 'image')" error

- Fix musistudio#958, musistudio#953: Normalize base64 image data to prevent duplicate prefixes
  * Added normalizeImageSource() to strip duplicate "data:image/png;base64" prefixes
  * Validates base64 data before caching to prevent 400 errors from providers
  * Fixes OpenRouter + Claude Sonnet image processing issues

📚 **Documentation & Config Examples:**
- Fix musistudio#1014: Add comprehensive configuration examples
  * config.example.json: All major providers (OpenRouter, DeepSeek, Gemini, Ollama, Groq, Copilot)
  * config.copilot.example.json: GitHub Copilot API integration guide
  * config.multimodel.example.json: Multi-model cost optimization strategy
  * config.multiinstance.example.json: Multiple instances setup guide

- Fix musistudio#1021: Document GitHub Copilot API integration
  * Added complete setup instructions in README
  * Documented working models and known issues
  * Provided transformer configuration for proper message format

🚀 **New Feature: Multiple Instances Support (musistudio#986, musistudio#961):**
- Run unlimited CCR instances simultaneously with different configs
- Auto-allocate ports when specified port is busy
- Instance-specific commands:
  * ccr start --config <path>  # Start custom instance
  * ccr stop --config <path>   # Stop specific instance
  * ccr status --config <path> # Show instance status
  * ccr code --config <path>   # Use specific instance
- Instance registry tracks all running instances
- Clean separation between default and custom instances
- Each instance has independent PID, port, and configuration

📝 **Implementation Details:**
- Created src/utils/instanceManager.ts for instance lifecycle management
- Updated CLI to support --config/-c flag across all commands
- Enhanced status command to show all running instances
- Updated code command to auto-start and use specific instances
- Added comprehensive documentation with usage examples

**Files Changed:**
- src/agents/image.agent.ts (bug fixes)
- src/cli.ts (multi-instance CLI support)
- src/index.ts (instance registration)
- src/utils/instanceManager.ts (new)
- src/utils/status.ts (multi-instance status)
- src/utils/codeCommand.ts (instance selection)
- src/utils/index.ts (config path support)
- README.md (documentation)
- 4 new config examples

**Impact:**
- Fixes crashes affecting macOS users (musistudio#993)
- Resolves image processing errors across multiple providers (musistudio#958, musistudio#953)
- Provides clear configuration guidance for new users (musistudio#1014)
- Enables GitHub Copilot API integration (musistudio#1021)
- Allows running multiple instances for different projects/workflows (musistudio#986, musistudio#961)
- Total: 6 issues resolved, 1 major feature added
Copilot AI review requested due to automatic review settings November 23, 2025 05:32
Copilot finished reviewing on behalf of arrrrny November 23, 2025 05:34
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request implements multiple instance support for Claude Code Router, allowing users to run unlimited CCR instances simultaneously with different configurations. It also adds comprehensive configuration examples for various use cases including multi-model strategies, GitHub Copilot API integration, and multi-instance setups.

Key Changes:

  • Implements instance management system with registry, PID tracking, and automatic port allocation
  • Enhances CLI to support --config flag across all commands
  • Adds configuration examples for different scenarios
  • Improves image agent validation to prevent data corruption

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/utils/instanceManager.ts New module for managing multiple CCR instances with registration, port allocation, and process tracking
src/cli.ts Enhanced CLI with config path support and multi-instance commands
src/index.ts Updated startup logic to support custom configs and instance registration
src/utils/status.ts Enhanced status display showing all instances or specific instance details
src/utils/codeCommand.ts Updated to use instance-specific ports when config is specified
src/agents/image.agent.ts Added base64 validation and normalization to prevent data corruption
config.*.example.json Added comprehensive configuration examples for various use cases
README.md Documentation updates for multiple instances and configuration examples
package-lock.json New package-lock file addition
ui/tsconfig.tsbuildinfo Updated TypeScript build info with PascalCase component names
Comments suppressed due to low confidence (5)

src/utils/codeCommand.ts:52

  • Avoid automated semicolon insertion (90% of all statements in the enclosing function have an explicit semicolon).
    }

src/utils/codeCommand.ts:81

  • Avoid automated semicolon insertion (90% of all statements in the enclosing function have an explicit semicolon).
  const argsObj = minimist(args)

src/utils/codeCommand.ts:82

  • Avoid automated semicolon insertion (90% of all statements in the enclosing function have an explicit semicolon).
  const argsArr = []

src/utils/index.ts:101

  • Avoid automated semicolon insertion (90% of all statements in the enclosing function have an explicit semicolon).
        }

src/utils/index.ts:110

  • Avoid automated semicolon insertion (90% of all statements in the enclosing function have an explicit semicolon).
        return config

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +208 to +221
export function getConfigPath(configArg?: string): string {
if (configArg) {
// If it's a relative path, resolve it from current directory
if (!configArg.startsWith('/') && !configArg.startsWith('~')) {
return join(process.cwd(), configArg);
}
// Expand ~ to home directory
if (configArg.startsWith('~')) {
return join(require('os').homedir(), configArg.substring(1));
}
return configArg;
}
return CONFIG_FILE;
}
Copy link

Copilot AI Nov 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Path resolution logic doesn't handle Windows absolute paths (e.g., 'C:\path'). On Windows, a path like 'C:\config.json' would be incorrectly treated as relative and joined with process.cwd(). Consider using path.isAbsolute() instead of checking for '/' or '~' prefixes.

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot open a new pull request to apply changes based on this feedback

try {
// Remove any existing data:image prefix to prevent duplication
let base64Data = source.data;
const dataUrlMatch = base64Data.match(/^data:image\/[^;]+;base64,(.+)$/);
Copy link

Copilot AI Nov 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Regular expression pattern could be extracted as a named constant at module level for better readability and reusability. Consider defining const DATA_URL_PATTERN = /^data:image\/[^;]+;base64,(.+)$/; at the top of the file.

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot open a new pull request to apply changes based on this feedback

// Join all code arguments into a single string to preserve spaces within quotes
const codeArgs = process.argv.slice(3);
executeCodeCommand(codeArgs);
const codeArgs = process.argv.slice(3).filter(arg => arg !== '--config' && arg !== '-c' && arg !== configPath);
Copy link

Copilot AI Nov 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Argument filtering logic has a flaw: if the user's actual task argument happens to match the configPath value, it will be incorrectly filtered out. For example, if configPath is 'test' and the user runs ccr code --config test 'test', the final 'test' argument will be removed. Consider using a more robust parsing approach that tracks which arguments have been consumed.

Copilot uses AI. Check for mistakes.
Comment on lines +132 to +135
if (port > startPort + 100) {
reject(new Error('No available port found'));
return;
}
Copy link

Copilot AI Nov 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Magic number 100 for port range limit should be extracted as a named constant (e.g., MAX_PORT_SEARCH_RANGE = 100) to improve code readability and maintainability.

Copilot uses AI. Check for mistakes.
arrrrny and others added 3 commits November 23, 2025 08:54
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants