mirror of
https://github.com/tiennm99/ccs.git
synced 2026-10-13 12:14:19 +00:00
feat: add GLMT proxy and transformer tools
- Add GLMT proxy server for GLM model routing - Add GLMT transformer for output format conversion - Update CLI with new proxy and transformer commands - Add comprehensive test suite for new functionality - Update documentation and architecture guides - Bump version and update changelog
This commit is contained in:
1 parent
daf075dc69
commit
657f99bfe8
21 files changed
+2597
-347
No files matched your search
@@ -522,4 +522,55 @@ ccs glm
|
||||
- CI/CD environments
|
||||
- Log file generation
|
||||
- Terminals without color support
|
||||
- Accessibility preferences
|
||||
- Accessibility preferences
|
||||
|
||||
---
|
||||
|
||||
## GLMT Troubleshooting
|
||||
|
||||
### Thinking Blocks Not Visible
|
||||
|
||||
1. **Enable debug logging**:
|
||||
```bash
|
||||
export CCS_DEBUG_LOG=1
|
||||
ccs glmt --verbose "test"
|
||||
```
|
||||
|
||||
2. **Check raw response**:
|
||||
```bash
|
||||
cat ~/.ccs/logs/*response-openai.json | jq '.choices[0].message.reasoning_content'
|
||||
```
|
||||
|
||||
3. **Scenarios**:
|
||||
- **reasoning_content present**: Transformation issue → check response-anthropic.json
|
||||
- **reasoning_content absent**: Z.AI API issue → verify API key/account status
|
||||
|
||||
### Duplicate "Enchanting" Lines
|
||||
|
||||
**Symptom**: Two spinner lines during thinking
|
||||
|
||||
**Cause**: Terminal rendering (not CCS issue)
|
||||
|
||||
**Solutions**:
|
||||
- Use native terminal (iTerm2, GNOME Terminal, Windows Terminal)
|
||||
- Exit tmux/screen before running
|
||||
- Accept visual glitch (functionality unaffected)
|
||||
|
||||
### Proxy Startup Timeout
|
||||
|
||||
**Error**: "Proxy startup timeout (5s)"
|
||||
|
||||
**Solutions**:
|
||||
```bash
|
||||
# Try non-thinking mode
|
||||
ccs glm "your prompt"
|
||||
|
||||
# Check Node.js
|
||||
node --version # Requires ≥14
|
||||
|
||||
# Check port availability
|
||||
netstat -an | grep 127.0.0.1
|
||||
|
||||
# Verbose details
|
||||
ccs glmt --verbose "test"
|
||||
```
|
||||
+267
-17
@@ -2,7 +2,7 @@
|
||||
|
||||
## Overview
|
||||
|
||||
CCS (Claude Code Switch) is a lightweight CLI wrapper that provides instant profile switching between Claude Sonnet 4.5 and GLM 4.6 models. The architecture has been recently simplified to achieve a 35% reduction in codebase size while maintaining all functionality.
|
||||
CCS (Claude Code Switch) is a lightweight CLI wrapper that provides instant profile switching between Claude Sonnet 4.5 and GLM 4.6 models. Current version **v3.3.0** features GLMT thinking mode with embedded proxy architecture, debug logging, and refined configuration management.
|
||||
|
||||
## Core Architecture Principles
|
||||
|
||||
@@ -62,32 +62,57 @@ graph TB
|
||||
|
||||
**Key Responsibilities**:
|
||||
- Argument parsing and profile detection
|
||||
- Special command handling (--version, --help, auth) [--install/--uninstall WIP]
|
||||
- Special command handling (--version, --help, auth, doctor) [--install/--uninstall WIP]
|
||||
- Profile type routing (settings-based vs account-based)
|
||||
- GLMT proxy lifecycle management
|
||||
- Unified process execution through `execClaude()`
|
||||
- Error propagation and exit code management
|
||||
- Auto-recovery for missing configuration
|
||||
|
||||
**Architecture with Concurrent Sessions**:
|
||||
**Architecture with GLMT Support (v3.3.0)**:
|
||||
```mermaid
|
||||
graph LR
|
||||
graph TD
|
||||
subgraph "Entry Point"
|
||||
ARGS[Parse Arguments]
|
||||
SPECIAL[Handle Special Commands]
|
||||
RECOVER[Auto-recovery]
|
||||
DETECT[ProfileDetector]
|
||||
SETTINGS[Settings-based Profile]
|
||||
GLMT{GLMT Profile?}
|
||||
ACCOUNT[Account-based Profile]
|
||||
PROXY[Spawn Proxy]
|
||||
EXEC[Execute Claude]
|
||||
end
|
||||
|
||||
ARGS --> SPECIAL
|
||||
SPECIAL --> DETECT
|
||||
SPECIAL --> RECOVER
|
||||
RECOVER --> DETECT
|
||||
DETECT --> SETTINGS
|
||||
DETECT --> ACCOUNT
|
||||
SETTINGS --> EXEC
|
||||
SETTINGS --> GLMT
|
||||
GLMT -->|Yes| PROXY
|
||||
GLMT -->|No| EXEC
|
||||
PROXY --> EXEC
|
||||
ACCOUNT --> EXEC
|
||||
```
|
||||
|
||||
**Key Enhancement ()**: Dual-path execution supporting both `--settings` flag (backward compatible) and `CLAUDE_CONFIG_DIR` env var (concurrent sessions).
|
||||
**Key Enhancements**:
|
||||
- **v3.3.0**: GLMT proxy spawning with verbose flag detection, API key validation, 5s timeout
|
||||
- **v3.2.0**: Dual-path execution supporting both `--settings` flag (backward compatible) and `CLAUDE_CONFIG_DIR` env var (concurrent sessions)
|
||||
- **v3.1.0**: Auto-recovery manager for missing configs
|
||||
|
||||
**GLMT-Specific Logic**:
|
||||
```javascript
|
||||
// Check if GLMT profile
|
||||
if (profileInfo.name === 'glmt') {
|
||||
// 1. Read API key from settings
|
||||
// 2. Spawn proxy with --verbose flag (if detected in args)
|
||||
// 3. Wait for PROXY_READY:port signal (5s timeout)
|
||||
// 4. Spawn Claude CLI with proxy URL
|
||||
// 5. Kill proxy when Claude exits
|
||||
await execClaudeWithProxy(claudeCli, 'glmt', remainingArgs);
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Configuration Manager (`bin/config-manager.js`)
|
||||
|
||||
@@ -236,6 +261,132 @@ graph TD
|
||||
"default": "work"
|
||||
}
|
||||
```
|
||||
## GLMT Architecture (v3.2.0+)
|
||||
|
||||
### Overview
|
||||
|
||||
GLMT (GLM with Thinking) uses an embedded HTTP proxy to enable thinking mode support for GLM 4.6. The proxy converts between Anthropic and OpenAI formats, injecting reasoning parameters and transforming `reasoning_content` into thinking blocks.
|
||||
|
||||
### Components
|
||||
|
||||
**1. GLMT Transformer (`bin/glmt-transformer.js`)**
|
||||
- Converts Anthropic Messages API → OpenAI Chat Completions format
|
||||
- Extracts thinking control tags: `<Thinking:On|Off>`, `<Effort:Low|Medium|High>`
|
||||
- Injects reasoning parameters: `reasoning: true`, `reasoning_effort`
|
||||
- Transforms OpenAI `reasoning_content` → Anthropic thinking blocks
|
||||
- Generates thinking signatures for Claude Code UI
|
||||
- Debug logging to `~/.ccs/logs/` when `CCS_DEBUG_LOG=1`
|
||||
|
||||
**2. GLMT Proxy (`bin/glmt-proxy.js`)**
|
||||
- Embedded HTTP server on `127.0.0.1:random_port`
|
||||
- Intercepts Claude CLI → Z.AI requests
|
||||
- Lifecycle tied to parent process
|
||||
- Buffered mode only (streaming not supported)
|
||||
- Request timeout: 120s default
|
||||
|
||||
### GLMT Execution Flow
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User
|
||||
participant CCS as ccs.js
|
||||
participant Proxy as glmt-proxy.js
|
||||
participant Transformer as glmt-transformer.js
|
||||
participant ZAI as Z.AI API
|
||||
participant Claude as Claude CLI
|
||||
|
||||
User->>CCS: ccs glmt "solve problem"
|
||||
CCS->>CCS: Read GLMT settings (API key, config)
|
||||
CCS->>Proxy: Spawn proxy with --verbose flag
|
||||
Proxy->>Proxy: Bind to 127.0.0.1:random_port
|
||||
Proxy-->>CCS: PROXY_READY:port
|
||||
CCS->>Claude: Spawn with ANTHROPIC_BASE_URL=http://127.0.0.1:port
|
||||
Claude->>Proxy: POST /v1/messages (Anthropic format)
|
||||
Proxy->>Transformer: transformRequest(anthropicRequest)
|
||||
Transformer->>Transformer: Extract thinking control tags
|
||||
Transformer->>Transformer: Inject reasoning params
|
||||
Transformer-->>Proxy: OpenAI format request
|
||||
Proxy->>ZAI: POST /api/coding/paas/v4/chat/completions
|
||||
ZAI-->>Proxy: OpenAI response (with reasoning_content)
|
||||
Proxy->>Transformer: transformResponse(openaiResponse)
|
||||
Transformer->>Transformer: Convert reasoning_content → thinking blocks
|
||||
Transformer-->>Proxy: Anthropic format response
|
||||
Proxy-->>Claude: Return Anthropic response
|
||||
Claude-->>User: Display with thinking blocks
|
||||
Claude->>CCS: Exit
|
||||
CCS->>Proxy: Kill (SIGTERM)
|
||||
```
|
||||
|
||||
### Debug Mode Architecture
|
||||
|
||||
**Verbose Logging** (`--verbose` flag):
|
||||
- Console logging with timestamps
|
||||
- Request/response size tracking
|
||||
- Transformation validation results
|
||||
- Proxy lifecycle events
|
||||
|
||||
**Debug File Logging** (`CCS_DEBUG_LOG=1`):
|
||||
- Writes to `~/.ccs/logs/`
|
||||
- Files: `{timestamp}-request-anthropic.json`, `request-openai.json`, `response-openai.json`, `response-anthropic.json`
|
||||
- Pretty-printed JSON with full request/response data
|
||||
- **[!] Warning**: Contains sensitive data (API keys, prompts)
|
||||
|
||||
**Debug Workflow**:
|
||||
```bash
|
||||
# Enable both verbose and debug logging
|
||||
export CCS_DEBUG_LOG=1
|
||||
ccs glmt --verbose "test prompt"
|
||||
|
||||
# Check reasoning content
|
||||
cat ~/.ccs/logs/*response-openai.json | jq '.choices[0].message.reasoning_content'
|
||||
|
||||
# Verify transformation
|
||||
cat ~/.ccs/logs/*response-anthropic.json | jq '.content[] | select(.type=="thinking")'
|
||||
```
|
||||
|
||||
### Configuration Migration (v3.2.0 → v3.3.0)
|
||||
|
||||
**Automatic Migration** (postinstall script):
|
||||
```javascript
|
||||
// Added fields in v3.3.0
|
||||
{
|
||||
"env": {
|
||||
"ANTHROPIC_TEMPERATURE": "0.2", // New
|
||||
"ANTHROPIC_MAX_TOKENS": "65536", // New
|
||||
"MAX_THINKING_TOKENS": "32768", // New
|
||||
"ENABLE_STREAMING": "true", // New
|
||||
"ANTHROPIC_SAFE_MODE": "false", // New
|
||||
"API_TIMEOUT_MS": "3000000" // New (50 minutes)
|
||||
},
|
||||
"alwaysThinkingEnabled": true // New
|
||||
}
|
||||
```
|
||||
|
||||
**Removed/Obsolete Fields** (from v3.2.0):
|
||||
- `BASH_DEFAULT_TIMEOUT_MS` - Moved to Claude CLI config
|
||||
- `BASH_MAX_TIMEOUT_MS` - Moved to Claude CLI config
|
||||
- `DISABLE_TELEMETRY` - No longer needed
|
||||
- `ENABLE_THINKING` - Replaced by `alwaysThinkingEnabled`
|
||||
|
||||
### Proxy Lifecycle Management
|
||||
|
||||
**Startup**:
|
||||
1. CCS spawns `node bin/glmt-proxy.js`
|
||||
2. Proxy binds to `127.0.0.1:0` (random port)
|
||||
3. Proxy emits `PROXY_READY:port` to stdout
|
||||
4. CCS reads port, spawns Claude CLI with proxy URL
|
||||
5. Timeout: 5s (configurable)
|
||||
|
||||
**Cleanup**:
|
||||
- Claude CLI exits → CCS kills proxy (`SIGTERM`)
|
||||
- Parent process dies → Proxy auto-terminates
|
||||
- Uncaught exception → Proxy logs and exits
|
||||
|
||||
**Error Handling**:
|
||||
- Proxy startup timeout → Show workaround (use `ccs glm`)
|
||||
- Port conflict → Uses random port (unlikely)
|
||||
- Upstream timeout → 120s default, configurable
|
||||
|
||||
## Data Flow Architecture
|
||||
|
||||
### Settings-Based Profile Execution Flow (Backward Compatible)
|
||||
@@ -318,27 +469,62 @@ sequenceDiagram
|
||||
|
||||
```
|
||||
~/.ccs/
|
||||
├── config.json # Settings-based profile mappings (glm, kimi)
|
||||
├── config.json # Settings-based profile mappings (glm, glmt, kimi)
|
||||
├── profiles.json # Account-based profile metadata (work, personal)
|
||||
├── glm.settings.json # GLM configuration
|
||||
├── glm.settings.json # GLM configuration (Anthropic endpoint)
|
||||
├── glmt.settings.json # GLMT configuration (v3.3.0 with thinking mode)
|
||||
├── kimi.settings.json # Kimi configuration
|
||||
├── config.json.backup # Single backup file
|
||||
├── VERSION # Version information
|
||||
├── logs/ # Debug logs (CCS_DEBUG_LOG=1)
|
||||
│ ├── {timestamp}-request-anthropic.json
|
||||
│ ├── {timestamp}-request-openai.json
|
||||
│ ├── {timestamp}-response-openai.json
|
||||
│ └── {timestamp}-response-anthropic.json
|
||||
├── shared/ # Shared across all profiles (v3.1+)
|
||||
│ ├── commands/ # Slash commands
|
||||
│ ├── skills/ # Agent skills
|
||||
│ └── agents/ # Agent configs
|
||||
├── accounts/ # Encrypted credential vaults
|
||||
│ ├── .salt # Key derivation salt
|
||||
│ ├── work.json.enc # Work account credentials (encrypted)
|
||||
│ └── personal.json.enc # Personal account credentials (encrypted)
|
||||
└── instances/ # Isolated Claude instances (+)
|
||||
└── instances/ # Isolated Claude instances
|
||||
├── work/ # Work account instance
|
||||
│ ├── session-env/
|
||||
│ ├── todos/
|
||||
│ ├── logs/
|
||||
│ ├── commands@ → shared/commands/
|
||||
│ ├── skills@ → shared/skills/
|
||||
│ ├── agents@ → shared/agents/
|
||||
│ ├── .credentials.json
|
||||
│ └── ...
|
||||
└── personal/ # Personal account instance
|
||||
├── session-env/
|
||||
├── todos/
|
||||
└── ...
|
||||
|
||||
bin/ # CCS source files
|
||||
├── ccs.js # Main entry point (v3.3.0)
|
||||
├── glmt-proxy.js # Embedded HTTP proxy (v3.2.0+)
|
||||
├── glmt-transformer.js # Format conversion (v3.2.0+)
|
||||
├── config-manager.js # Configuration handling
|
||||
├── claude-detector.js # Claude CLI detection
|
||||
├── instance-manager.js # Instance orchestration
|
||||
├── shared-manager.js # Shared data symlinks (v3.1+)
|
||||
├── profile-detector.js # Profile type detection
|
||||
├── profile-registry.js # Account profile metadata
|
||||
├── helpers.js # Utility functions
|
||||
├── error-manager.js # Error handling
|
||||
├── recovery-manager.js # Auto-recovery
|
||||
├── auth-commands.js # Multi-account management
|
||||
└── doctor.js # Health check diagnostics
|
||||
|
||||
config/
|
||||
└── base-glmt.settings.json # GLMT template (v3.3.0)
|
||||
|
||||
scripts/
|
||||
└── postinstall.js # Auto-configuration + migration
|
||||
```
|
||||
|
||||
### Configuration Schema
|
||||
@@ -354,6 +540,7 @@ sequenceDiagram
|
||||
|
||||
### Settings File Format
|
||||
|
||||
**GLM Settings (Anthropic endpoint)**:
|
||||
```json
|
||||
{
|
||||
"env": {
|
||||
@@ -367,6 +554,29 @@ sequenceDiagram
|
||||
}
|
||||
```
|
||||
|
||||
**GLMT Settings (v3.3.0 with thinking mode)**:
|
||||
```json
|
||||
{
|
||||
"env": {
|
||||
"ANTHROPIC_BASE_URL": "https://api.z.ai/api/coding/paas/v4/chat/completions",
|
||||
"ANTHROPIC_AUTH_TOKEN": "your_api_key",
|
||||
"ANTHROPIC_MODEL": "glm-4.6",
|
||||
"ANTHROPIC_DEFAULT_OPUS_MODEL": "glm-4.6",
|
||||
"ANTHROPIC_DEFAULT_SONNET_MODEL": "glm-4.6",
|
||||
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "glm-4.6",
|
||||
"ANTHROPIC_TEMPERATURE": "0.2",
|
||||
"ANTHROPIC_MAX_TOKENS": "65536",
|
||||
"MAX_THINKING_TOKENS": "32768",
|
||||
"ENABLE_STREAMING": "true",
|
||||
"ANTHROPIC_SAFE_MODE": "false",
|
||||
"API_TIMEOUT_MS": "3000000"
|
||||
},
|
||||
"alwaysThinkingEnabled": true
|
||||
}
|
||||
```
|
||||
|
||||
**[i] Note**: All env values are strings (not booleans/numbers) for PowerShell compatibility.
|
||||
|
||||
## Security Architecture
|
||||
|
||||
### Inherent Security Model
|
||||
@@ -503,11 +713,36 @@ graph LR
|
||||
|
||||
### Installation Process
|
||||
|
||||
1. **Package Download**: User installs via npm
|
||||
2. **Post-install Script**: Automatically creates configuration
|
||||
3. **Path Configuration**: Sets up executable in system PATH
|
||||
4. **Validation**: Ensures Claude CLI is available
|
||||
5. **Ready State**: System ready for profile switching
|
||||
1. **Package Download**: User installs via npm/yarn/pnpm/bun
|
||||
2. **Post-install Script** (`scripts/postinstall.js`):
|
||||
- Creates `~/.ccs/` directory structure
|
||||
- Creates `~/.ccs/shared/` (commands, skills, agents)
|
||||
- Migrates from v3.1.1 → v3.2.0 (if needed)
|
||||
- Migrates GLMT configs from v3.2.0 → v3.3.0 (adds new fields)
|
||||
- Creates `config.json` (glm, glmt, kimi, default)
|
||||
- Creates `glm.settings.json` (Anthropic endpoint)
|
||||
- Creates `glmt.settings.json` (OpenAI endpoint + thinking mode)
|
||||
- Creates `kimi.settings.json` (Kimi endpoint)
|
||||
- Creates `~/.claude/settings.json` (if missing)
|
||||
- Validates configuration (checks JSON syntax, file existence)
|
||||
- Shows API key setup instructions
|
||||
3. **Path Configuration**: npm automatically adds to PATH
|
||||
4. **Ready State**: System ready for profile switching
|
||||
|
||||
**Idempotency**: Safe to run multiple times, preserves existing configs
|
||||
|
||||
**Migration Logic** (v3.3.0):
|
||||
```javascript
|
||||
// Auto-adds missing fields to existing GLMT configs
|
||||
const envDefaults = {
|
||||
ANTHROPIC_TEMPERATURE: '0.2',
|
||||
ANTHROPIC_MAX_TOKENS: '65536',
|
||||
MAX_THINKING_TOKENS: '32768',
|
||||
ENABLE_STREAMING: 'true',
|
||||
ANTHROPIC_SAFE_MODE: 'false',
|
||||
API_TIMEOUT_MS: '3000000'
|
||||
};
|
||||
```
|
||||
|
||||
## Concurrent Sessions Architecture ()
|
||||
|
||||
@@ -614,10 +849,25 @@ The CCS system architecture successfully balances simplicity with functionality:
|
||||
- **Performance optimization** achieves 35% code reduction with identical functionality
|
||||
- **Clean separation of concerns** makes the codebase maintainable and extensible
|
||||
|
||||
** Enhancements**:
|
||||
**v3.3.0 Features**:
|
||||
- **GLMT thinking mode**: Embedded proxy for GLM reasoning support
|
||||
- **Debug logging**: File-based logging to `~/.ccs/logs/` when `CCS_DEBUG_LOG=1`
|
||||
- **Verbose mode**: Console logging with `--verbose` flag
|
||||
- **Configuration migration**: Auto-upgrade v3.2.0 configs with new fields
|
||||
- **Enhanced settings**: Temperature, max tokens, thinking controls, API timeout
|
||||
- **Transformation validation**: Self-test request/response conversions
|
||||
|
||||
**v3.2.0 Enhancements**:
|
||||
- Concurrent sessions for account-based profiles
|
||||
- Profile type detection and routing (settings vs account)
|
||||
- Instance isolation with credential synchronization
|
||||
- Backward compatibility maintained for all existing profiles
|
||||
|
||||
The architecture demonstrates how thoughtful design can add sophisticated features (concurrent sessions, multi-account management) while maintaining simplicity, security, and backward compatibility.
|
||||
**v3.3.0 Architecture Highlights**:
|
||||
1. **Proxy Architecture**: Buffered mode with 120s timeout, random port binding
|
||||
2. **Debug Infrastructure**: Dual logging (console + file) with timestamp tracking
|
||||
3. **Config Management**: Automatic migration, string-only env vars, PowerShell compatibility
|
||||
4. **Thinking Mode**: Control tags, reasoning parameters, signature generation
|
||||
5. **Error Recovery**: Timeout handling, fallback options, clear error messages
|
||||
|
||||
The architecture demonstrates how thoughtful design can add sophisticated features (thinking mode, debug infrastructure, multi-account management) while maintaining simplicity, security, and backward compatibility.
|
||||
Reference in new issue
Block a user