@kaitranntt/ccs 3.4.6 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,120 @@
1
+ # CCS Progress Indicator (PowerShell 5.1+ compatible)
2
+ # Simple spinner for long-running operations
3
+ # NO external dependencies - ASCII-only for cross-platform compatibility
4
+
5
+ $ErrorActionPreference = "Stop"
6
+
7
+ # Show simple spinner (synchronous)
8
+ function Show-Spinner {
9
+ param(
10
+ [string]$Message,
11
+ [scriptblock]$Task
12
+ )
13
+
14
+ # TTY detection: only animate if not redirected and not in CI
15
+ $IsTTY = -not [Console]::IsOutputRedirected -and -not $env:CI -and -not $env:NO_COLOR
16
+
17
+ $StartTime = Get-Date
18
+
19
+ if (-not $IsTTY) {
20
+ # Non-TTY: just print message and run task
21
+ Write-Host "[i] $Message..." -ForegroundColor Gray
22
+ $result = & $Task
23
+ Write-Host "[OK] $Message" -ForegroundColor Green
24
+ return $result
25
+ }
26
+
27
+ # ASCII-only frames for cross-platform compatibility
28
+ $Frames = @('|', '/', '-', '\')
29
+ $FrameIndex = 0
30
+
31
+ # Start task in background job
32
+ $Job = Start-Job -ScriptBlock $Task
33
+
34
+ try {
35
+ # Animate spinner while job is running
36
+ while ($Job.State -eq 'Running') {
37
+ $Frame = $Frames[$FrameIndex]
38
+ $Elapsed = [math]::Round(((Get-Date) - $StartTime).TotalSeconds, 1)
39
+ Write-Host "`r[$Frame] $Message... ($($Elapsed)s)" -NoNewline -ForegroundColor Cyan
40
+ $FrameIndex = ($FrameIndex + 1) % $Frames.Length
41
+ Start-Sleep -Milliseconds 100
42
+ }
43
+
44
+ # Clear spinner line
45
+ Write-Host "`r$(' ' * 80)`r" -NoNewline
46
+
47
+ # Check job result
48
+ $JobResult = Receive-Job -Job $Job -ErrorAction Stop
49
+ $Elapsed = [math]::Round(((Get-Date) - $StartTime).TotalSeconds, 1)
50
+ Write-Host "[OK] $Message ($($Elapsed)s)" -ForegroundColor Green
51
+
52
+ return $JobResult
53
+ }
54
+ catch {
55
+ # Clear spinner line
56
+ Write-Host "`r$(' ' * 80)`r" -NoNewline
57
+ Write-Host "[X] $Message" -ForegroundColor Red
58
+ throw
59
+ }
60
+ finally {
61
+ # Cleanup job
62
+ if ($Job) {
63
+ Remove-Job -Job $Job -Force -ErrorAction SilentlyContinue
64
+ }
65
+ }
66
+ }
67
+
68
+ # Show progress counter for multi-step operations
69
+ function Show-ProgressStep {
70
+ param(
71
+ [int]$Current,
72
+ [int]$Total,
73
+ [string]$Message
74
+ )
75
+
76
+ # TTY detection
77
+ $IsTTY = -not [Console]::IsOutputRedirected -and -not $env:CI
78
+
79
+ if (-not $IsTTY) {
80
+ Write-Host "[$Current/$Total] $Message" -ForegroundColor Gray
81
+ return
82
+ }
83
+
84
+ # Show progress with carriage return (can be overwritten)
85
+ Write-Host "`r[$Current/$Total] $Message..." -NoNewline -ForegroundColor Cyan
86
+ }
87
+
88
+ # Clear progress line
89
+ function Clear-Progress {
90
+ $IsTTY = -not [Console]::IsOutputRedirected -and -not $env:CI
91
+
92
+ if ($IsTTY) {
93
+ Write-Host "`r$(' ' * 80)`r" -NoNewline
94
+ }
95
+ }
96
+
97
+ # Simple status message (for operations that don't need spinners)
98
+ function Write-Status {
99
+ param(
100
+ [string]$Message,
101
+ [ValidateSet('Info', 'Success', 'Warning', 'Error')]
102
+ [string]$Type = 'Info'
103
+ )
104
+
105
+ $Prefix = switch ($Type) {
106
+ 'Info' { '[i]'; break }
107
+ 'Success' { '[OK]'; break }
108
+ 'Warning' { '[!]'; break }
109
+ 'Error' { '[X]'; break }
110
+ }
111
+
112
+ $Color = switch ($Type) {
113
+ 'Info' { 'Gray'; break }
114
+ 'Success' { 'Green'; break }
115
+ 'Warning' { 'Yellow'; break }
116
+ 'Error' { 'Red'; break }
117
+ }
118
+
119
+ Write-Host "$Prefix $Message" -ForegroundColor $Color
120
+ }
@@ -0,0 +1,117 @@
1
+ #!/usr/bin/env bash
2
+ # CCS Progress Indicator (bash 3.2+ compatible)
3
+ # Simple spinner for long-running operations
4
+ # NO external dependencies - ASCII-only for cross-platform compatibility
5
+
6
+ set -euo pipefail
7
+
8
+ # Show spinner while a background process is running
9
+ # Usage: show_spinner "message" $pid
10
+ show_spinner() {
11
+ local message="$1"
12
+ local pid="$2"
13
+
14
+ # TTY detection: only animate if stderr is TTY and not in CI
15
+ if [[ ! -t 2 ]] || [[ -n "${CI:-}" ]] || [[ -n "${NO_COLOR:-}" ]]; then
16
+ # Non-TTY: just print message once
17
+ echo "[i] $message..." >&2
18
+ wait "$pid" 2>/dev/null || true
19
+ return
20
+ fi
21
+
22
+ # ASCII-only frames for cross-platform compatibility
23
+ local frames=('|' '/' '-' '\\')
24
+ local frame_idx=0
25
+ local start_time=$(date +%s)
26
+
27
+ # Animate spinner while process is running
28
+ while kill -0 "$pid" 2>/dev/null; do
29
+ local frame="${frames[$frame_idx]}"
30
+ local elapsed=$(($(date +%s) - start_time))
31
+ printf "\r[%s] %s... (%ds)" "$frame" "$message" "$elapsed" >&2
32
+ frame_idx=$(( (frame_idx + 1) % 4 ))
33
+ sleep 0.1
34
+ done
35
+
36
+ # Clear spinner line
37
+ printf "\r\033[K" >&2
38
+
39
+ # Wait for process to complete and capture exit code
40
+ wait "$pid" 2>/dev/null || true
41
+ }
42
+
43
+ # Show spinner with success/fail result
44
+ # Usage: spinner_with_result "message" "command"
45
+ spinner_with_result() {
46
+ local message="$1"
47
+ shift
48
+ local command=("$@")
49
+
50
+ local start_time=$(date +%s)
51
+
52
+ # TTY detection
53
+ if [[ ! -t 2 ]] || [[ -n "${CI:-}" ]] || [[ -n "${NO_COLOR:-}" ]]; then
54
+ # Non-TTY: just print message and run command
55
+ echo "[i] $message..." >&2
56
+ if "${command[@]}"; then
57
+ echo "[OK] $message" >&2
58
+ return 0
59
+ else
60
+ echo "[X] $message" >&2
61
+ return 1
62
+ fi
63
+ fi
64
+
65
+ # Run command in background
66
+ "${command[@]}" &>/dev/null &
67
+ local pid=$!
68
+
69
+ # Show spinner
70
+ local frames=('|' '/' '-' '\\')
71
+ local frame_idx=0
72
+
73
+ while kill -0 "$pid" 2>/dev/null; do
74
+ local frame="${frames[$frame_idx]}"
75
+ local elapsed=$(($(date +%s) - start_time))
76
+ printf "\r[%s] %s... (%ds)" "$frame" "$message" "$elapsed" >&2
77
+ frame_idx=$(( (frame_idx + 1) % 4 ))
78
+ sleep 0.1
79
+ done
80
+
81
+ # Clear spinner line
82
+ printf "\r\033[K" >&2
83
+
84
+ # Check result
85
+ if wait "$pid" 2>/dev/null; then
86
+ local elapsed=$(($(date +%s) - start_time))
87
+ echo "[OK] $message (${elapsed}s)" >&2
88
+ return 0
89
+ else
90
+ echo "[X] $message" >&2
91
+ return 1
92
+ fi
93
+ }
94
+
95
+ # Simple progress counter (for multi-step operations)
96
+ # Usage: show_progress_step 3 10 "Checking configuration"
97
+ show_progress_step() {
98
+ local current="$1"
99
+ local total="$2"
100
+ local message="$3"
101
+
102
+ # TTY detection
103
+ if [[ ! -t 2 ]] || [[ -n "${CI:-}" ]]; then
104
+ echo "[${current}/${total}] $message" >&2
105
+ return
106
+ fi
107
+
108
+ # Show progress with carriage return (can be overwritten)
109
+ printf "\r[%d/%d] %s..." "$current" "$total" "$message" >&2
110
+ }
111
+
112
+ # Clear progress line
113
+ clear_progress() {
114
+ if [[ -t 2 ]] && [[ -z "${CI:-}" ]]; then
115
+ printf "\r\033[K" >&2
116
+ fi
117
+ }
package/lib/prompt.ps1 ADDED
@@ -0,0 +1,109 @@
1
+ # CCS Interactive Prompt Utilities (PowerShell 5.1+ compatible)
2
+ # NO external dependencies
3
+
4
+ $ErrorActionPreference = "Stop"
5
+
6
+ # Interactive confirmation prompt
7
+ function Confirm-Action {
8
+ param(
9
+ [string]$Message,
10
+ [ValidateSet('Yes', 'No')]
11
+ [string]$Default = 'No'
12
+ )
13
+
14
+ # Check for --yes flag (automation)
15
+ if ($env:CCS_YES -eq '1' -or $global:RemainingArgs -contains '--yes' -or $global:RemainingArgs -contains '-y') {
16
+ return $Default -eq 'Yes'
17
+ }
18
+
19
+ # Check for --no-input flag (CI)
20
+ if ($env:CCS_NO_INPUT -eq '1' -or $global:RemainingArgs -contains '--no-input') {
21
+ Write-Host "[X] Interactive input required but --no-input specified" -ForegroundColor Red
22
+ exit 1
23
+ }
24
+
25
+ # Non-TTY: use default
26
+ if ([Console]::IsInputRedirected) {
27
+ return $Default -eq 'Yes'
28
+ }
29
+
30
+ # Interactive prompt
31
+ $PromptText = if ($Default -eq 'Yes') {
32
+ "$Message [Y/n]: "
33
+ } else {
34
+ "$Message [y/N]: "
35
+ }
36
+
37
+ while ($true) {
38
+ Write-Host $PromptText -NoNewline -ForegroundColor Cyan
39
+ $Response = Read-Host
40
+
41
+ $Normalized = $Response.Trim().ToLower()
42
+
43
+ # Empty answer: use default
44
+ if ($Normalized -eq '' -or $Normalized -eq ' ') {
45
+ return $Default -eq 'Yes'
46
+ }
47
+
48
+ # Valid answers
49
+ if ($Normalized -eq 'y' -or $Normalized -eq 'yes') {
50
+ return $true
51
+ }
52
+
53
+ if ($Normalized -eq 'n' -or $Normalized -eq 'no') {
54
+ return $false
55
+ }
56
+
57
+ # Invalid input: retry
58
+ Write-Host "[!] Please answer y or n" -ForegroundColor Yellow
59
+ }
60
+ }
61
+
62
+ # Interactive text input
63
+ function Read-Input {
64
+ param(
65
+ [string]$Message,
66
+ [string]$Default = '',
67
+ [scriptblock]$Validate = $null
68
+ )
69
+
70
+ # Non-TTY: use default or error
71
+ if ([Console]::IsInputRedirected) {
72
+ if ($Default) {
73
+ return $Default
74
+ }
75
+ throw "Interactive input required but stdin is redirected"
76
+ }
77
+
78
+ # Interactive prompt
79
+ $PromptText = if ($Default) {
80
+ "$Message [$Default]: "
81
+ } else {
82
+ "$Message: "
83
+ }
84
+
85
+ while ($true) {
86
+ Write-Host $PromptText -NoNewline -ForegroundColor Cyan
87
+ $Response = Read-Host
88
+
89
+ $Value = if ($Response.Trim()) { $Response.Trim() } else { $Default }
90
+
91
+ # Validate input if validator provided
92
+ if ($Validate) {
93
+ $Error = & $Validate $Value
94
+ if ($Error) {
95
+ Write-Host "[!] $Error" -ForegroundColor Yellow
96
+ continue
97
+ }
98
+ }
99
+
100
+ return $Value
101
+ }
102
+ }
103
+
104
+ # Check if running in non-interactive mode
105
+ function Test-NonInteractive {
106
+ return [Console]::IsInputRedirected -or
107
+ $env:CCS_YES -eq '1' -or
108
+ $env:CCS_NO_INPUT -eq '1'
109
+ }
package/lib/prompt.sh ADDED
@@ -0,0 +1,99 @@
1
+ #!/usr/bin/env bash
2
+ # CCS Interactive Prompt Utilities (bash 3.2+ compatible)
3
+ # NO external dependencies
4
+
5
+ set -euo pipefail
6
+
7
+ # Interactive confirmation prompt
8
+ # Usage: confirm_action "message" "yes"|"no"
9
+ # Returns: 0 (true) or 1 (false)
10
+ confirm_action() {
11
+ local message="$1"
12
+ local default="${2:-no}" # Default to NO for safety
13
+
14
+ # Check for --yes flag (automation) - always returns true (0)
15
+ if [[ "${CCS_YES:-}" == "1" ]]; then
16
+ return 0
17
+ fi
18
+
19
+ # Check for --no-input flag (CI)
20
+ if [[ "${CCS_NO_INPUT:-}" == "1" ]]; then
21
+ echo "[X] Interactive input required but --no-input specified" >&2
22
+ exit 1
23
+ fi
24
+
25
+ # Non-TTY: use default
26
+ if [[ ! -t 0 ]]; then
27
+ [[ "$default" == "yes" ]] && return 0 || return 1
28
+ fi
29
+
30
+ # Interactive prompt
31
+ local prompt
32
+ if [[ "$default" == "yes" ]]; then
33
+ prompt="$message [Y/n]: "
34
+ else
35
+ prompt="$message [y/N]: "
36
+ fi
37
+
38
+ while true; do
39
+ read -r -p "$prompt" response >&2
40
+ response=$(echo "$response" | tr '[:upper:]' '[:lower:]')
41
+
42
+ case "$response" in
43
+ ""|" ")
44
+ # Empty answer: use default
45
+ [[ "$default" == "yes" ]] && return 0 || return 1
46
+ ;;
47
+ y|yes)
48
+ return 0
49
+ ;;
50
+ n|no)
51
+ return 1
52
+ ;;
53
+ *)
54
+ echo "[!] Please answer y or n" >&2
55
+ ;;
56
+ esac
57
+ done
58
+ }
59
+
60
+ # Interactive text input
61
+ # Usage: prompt_input "message" "default_value"
62
+ # Outputs: user input to stdout
63
+ prompt_input() {
64
+ local message="$1"
65
+ local default="${2:-}"
66
+
67
+ # Non-TTY: use default or error
68
+ if [[ ! -t 0 ]]; then
69
+ if [[ -n "$default" ]]; then
70
+ echo "$default"
71
+ return 0
72
+ else
73
+ echo "[X] Interactive input required but stdin is not a TTY" >&2
74
+ exit 1
75
+ fi
76
+ fi
77
+
78
+ # Interactive prompt
79
+ local prompt
80
+ if [[ -n "$default" ]]; then
81
+ prompt="$message [$default]: "
82
+ else
83
+ prompt="$message: "
84
+ fi
85
+
86
+ read -r -p "$prompt" response >&2
87
+
88
+ # Return user input or default
89
+ if [[ -z "$response" ]]; then
90
+ echo "$default"
91
+ else
92
+ echo "$response"
93
+ fi
94
+ }
95
+
96
+ # Check if running in non-interactive mode
97
+ is_non_interactive() {
98
+ [[ ! -t 0 ]] || [[ "${CCS_YES:-}" == "1" ]] || [[ "${CCS_NO_INPUT:-}" == "1" ]]
99
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaitranntt/ccs",
3
- "version": "3.4.6",
3
+ "version": "3.5.0",
4
4
  "description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6",
5
5
  "keywords": [
6
6
  "cli",