#!/bin/bash # qwen-wrapper - Token-aware wrapper for qwen command # Location: ~/.claude/scripts/qwen-wrapper # # This wrapper automatically manages --all-files flag based on project token count # and provides intelligent approval mode defaults # # Usage: qwen-wrapper [all qwen options] # # Approval Mode Options: # --approval-mode default : Prompt for approval on each tool call (default) # --approval-mode auto_edit : Auto-approve edit tools, prompt for others # --approval-mode yolo : Auto-approve all tool calls # # Note: Executes in current working directory set -e # Function to show help show_help() { echo "qwen-wrapper - Token-aware wrapper for qwen command" echo "" echo "Usage: qwen-wrapper [options] [qwen options]" echo "" echo "Options:" echo " --approval-mode Sets the approval mode for tool calls" echo " Available modes:" echo " default : Prompt for approval on each tool call (default)" echo " auto_edit : Auto-approve edit tools, prompt for others" echo " yolo : Auto-approve all tool calls" echo " --help Show this help message" echo "" echo "Features:" echo " - Automatically manages --all-files flag based on project token count" echo " - Intelligent approval mode detection based on task type" echo " - Token limit: $DEFAULT_TOKEN_LIMIT (set QWEN_TOKEN_LIMIT to override)" echo "" echo "Examples:" echo " qwen-wrapper -p \"Analyze the codebase structure\"" echo " qwen-wrapper --approval-mode yolo -p \"Implement user authentication\"" echo " qwen-wrapper --approval-mode auto_edit -p \"Fix all linting errors\"" echo "" } # Function to validate approval mode validate_approval_mode() { local mode="$1" case "$mode" in "default"|"auto_edit"|"yolo") return 0 ;; *) echo -e "${RED}❌ Invalid approval mode: $mode${NC}" >&2 echo -e "${YELLOW}Valid modes: default, auto_edit, yolo${NC}" >&2 return 1 ;; esac } # Configuration DEFAULT_TOKEN_LIMIT=2000000 TOKEN_LIMIT=${QWEN_TOKEN_LIMIT:-$DEFAULT_TOKEN_LIMIT} # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color # Function to count tokens (approximate: chars/4) count_tokens() { local total_chars=0 local file_count=0 # Count characters in common source files while IFS= read -r -d '' file; do if [[ -f "$file" && -r "$file" ]]; then local chars=$(wc -c < "$file" 2>/dev/null || echo 0) total_chars=$((total_chars + chars)) file_count=$((file_count + 1)) fi done < <(find . -type f \( -name "*.py" -o -name "*.js" -o -name "*.ts" -o -name "*.tsx" -o -name "*.jsx" -o -name "*.java" -o -name "*.cpp" -o -name "*.c" -o -name "*.h" -o -name "*.rs" -o -name "*.go" -o -name "*.md" -o -name "*.txt" -o -name "*.json" -o -name "*.yaml" -o -name "*.yml" -o -name "*.xml" -o -name "*.html" -o -name "*.css" -o -name "*.scss" -o -name "*.sass" -o -name "*.php" -o -name "*.rb" -o -name "*.sh" -o -name "*.bash" \) -not -path "*/node_modules/*" -not -path "*/.git/*" -not -path "*/dist/*" -not -path "*/build/*" -not -path "*/.next/*" -not -path "*/.nuxt/*" -not -path "*/target/*" -not -path "*/vendor/*" -print0 2>/dev/null) local estimated_tokens=$((total_chars / 4)) echo "$estimated_tokens $file_count" } # Parse arguments to check for flags has_all_files=false has_approval_mode=false approval_mode_value="" # Parse arguments with proper handling of --approval-mode value args=("$@") # Start with all arguments parsed_args=() skip_next=false for ((i=0; i<${#args[@]}; i++)); do if [[ "$skip_next" == true ]]; then skip_next=false continue fi arg="${args[i]}" case "$arg" in "--help"|"-h") show_help exit 0 ;; "--all-files") has_all_files=true parsed_args+=("$arg") ;; "--approval-mode") has_approval_mode=true # Get the next argument as the mode value if [[ $((i+1)) -lt ${#args[@]} ]]; then approval_mode_value="${args[$((i+1))]}" if validate_approval_mode "$approval_mode_value"; then parsed_args+=("$arg" "$approval_mode_value") skip_next=true else exit 1 fi else echo -e "${RED}❌ --approval-mode requires a value${NC}" >&2 echo -e "${YELLOW}Valid modes: default, auto_edit, yolo${NC}" >&2 exit 1 fi ;; --approval-mode=*) has_approval_mode=true approval_mode_value="${arg#*=}" if validate_approval_mode "$approval_mode_value"; then parsed_args+=("$arg") else exit 1 fi ;; *) parsed_args+=("$arg") ;; esac done # Replace args with parsed_args args=("${parsed_args[@]}") # Analyze current working directory echo -e "${GREEN}📁 Analyzing current directory: $(pwd)${NC}" >&2 # Count tokens (in the target directory if -c was used) echo -e "${YELLOW}🔍 Analyzing project size...${NC}" >&2 read -r token_count file_count <<< "$(count_tokens)" echo -e "${YELLOW}📊 Project stats: ~${token_count} tokens across ${file_count} files${NC}" >&2 # Decision logic for --all-files flag if [[ $token_count -lt $TOKEN_LIMIT ]]; then if [[ "$has_all_files" == false ]]; then echo -e "${GREEN}✅ Small project (${token_count} < ${TOKEN_LIMIT} tokens): Adding --all-files${NC}" >&2 args=("--all-files" "${args[@]}") else echo -e "${GREEN}✅ Small project (${token_count} < ${TOKEN_LIMIT} tokens): Keeping --all-files${NC}" >&2 fi else if [[ "$has_all_files" == true ]]; then echo -e "${RED}⚠️ Large project (${token_count} >= ${TOKEN_LIMIT} tokens): Removing --all-files to avoid token limits${NC}" >&2 echo -e "${YELLOW}💡 Consider using specific @{patterns} for targeted analysis${NC}" >&2 # Remove --all-files from args new_args=() for arg in "${args[@]}"; do if [[ "$arg" != "--all-files" ]]; then new_args+=("$arg") fi done args=("${new_args[@]}") else echo -e "${RED}⚠️ Large project (${token_count} >= ${TOKEN_LIMIT} tokens): Avoiding --all-files${NC}" >&2 echo -e "${YELLOW}💡 Consider using specific @{patterns} for targeted analysis${NC}" >&2 fi fi # Auto-add approval-mode if not specified if [[ "$has_approval_mode" == false ]]; then # Intelligent approval mode detection based on prompt content prompt_text="${args[*]}" # Analysis/Research tasks - use default (prompt for each tool) if [[ "$prompt_text" =~ (analyze|analysis|review|understand|inspect|examine|research|study|explore|investigate) ]]; then echo -e "${GREEN}📋 Analysis task detected: Adding --approval-mode default${NC}" >&2 args=("--approval-mode" "default" "${args[@]}") # Development/Edit tasks - use auto_edit (auto-approve edits, prompt for others) elif [[ "$prompt_text" =~ (implement|create|build|develop|code|write|edit|modify|update|fix|refactor|generate) ]]; then echo -e "${GREEN}🔧 Development task detected: Adding --approval-mode auto_edit${NC}" >&2 args=("--approval-mode" "auto_edit" "${args[@]}") # Automation/Batch tasks - use yolo (auto-approve all) elif [[ "$prompt_text" =~ (automate|batch|mass|bulk|all|execute|run|deploy|install|setup) ]]; then echo -e "${YELLOW}⚡ Automation task detected: Adding --approval-mode yolo${NC}" >&2 args=("--approval-mode" "yolo" "${args[@]}") # Default fallback - use default mode for safety else echo -e "${YELLOW}🔍 General task detected: Adding --approval-mode default${NC}" >&2 args=("--approval-mode" "default" "${args[@]}") fi # Show approval mode explanation case "${args[1]}" in "default") echo -e "${YELLOW} → Will prompt for approval on each tool call${NC}" >&2 ;; "auto_edit") echo -e "${YELLOW} → Will auto-approve edit tools, prompt for others${NC}" >&2 ;; "yolo") echo -e "${YELLOW} → Will auto-approve all tool calls${NC}" >&2 ;; esac fi # Show final command (for transparency) echo -e "${YELLOW}🚀 Executing: qwen ${args[*]}${NC}" >&2 # Execute qwen with adjusted arguments (we're already in the right directory) qwen "${args[@]}"