@kaitranntt/ccs 3.4.0 → 3.4.1

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,162 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * TaskClassifier - Classify user prompts as reasoning, execution, or mixed tasks
6
+ *
7
+ * Purpose: Determine task type to inform thinking enable/disable decision.
8
+ * Uses keyword-based matching for fast, deterministic classification.
9
+ *
10
+ * Usage:
11
+ * const classifier = new TaskClassifier();
12
+ * const taskType = classifier.classify(messages);
13
+ *
14
+ * Task types:
15
+ * - reasoning: Planning, design, analysis (enable thinking)
16
+ * - execution: Implementation, fixes, debugging (disable thinking for speed)
17
+ * - mixed: Ambiguous or both (default to safe thinking mode)
18
+ *
19
+ * Classification strategy:
20
+ * 1. Extract text from all user messages
21
+ * 2. Score against reasoning and execution keyword lists
22
+ * 3. Return type with highest score (or 'mixed' if tied/no matches)
23
+ */
24
+ class TaskClassifier {
25
+ constructor(options = {}) {
26
+ this.keywords = {
27
+ reasoning: [
28
+ 'plan', 'design', 'analyze', 'architecture', 'strategy',
29
+ 'approach', 'consider', 'evaluate', 'research', 'explore',
30
+ 'brainstorm', 'think about', 'pros and cons', 'alternatives',
31
+ 'compare', 'recommend', 'assess', 'review', 'investigate'
32
+ ],
33
+ execution: [
34
+ 'fix', 'implement', 'debug', 'refactor', 'optimize',
35
+ 'add', 'remove', 'update', 'create', 'delete',
36
+ 'change', 'modify', 'replace', 'move', 'rename',
37
+ 'test', 'run', 'execute', 'deploy', 'build'
38
+ ]
39
+ };
40
+
41
+ // Allow custom keywords via options
42
+ if (options.customKeywords) {
43
+ this.keywords = { ...this.keywords, ...options.customKeywords };
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Classify messages as reasoning, execution, or mixed
49
+ * @param {Array} messages - Messages array
50
+ * @returns {string} 'reasoning', 'execution', or 'mixed'
51
+ */
52
+ classify(messages) {
53
+ if (!messages || messages.length === 0) {
54
+ return 'mixed'; // Default to safe mode
55
+ }
56
+
57
+ // Extract text from all user messages
58
+ const text = messages
59
+ .filter(m => m.role === 'user')
60
+ .map(m => this._extractText(m.content))
61
+ .join(' ')
62
+ .toLowerCase();
63
+
64
+ if (!text.trim()) {
65
+ return 'mixed'; // No text found
66
+ }
67
+
68
+ // Score against keyword lists
69
+ const reasoningScore = this._matchScore(text, this.keywords.reasoning);
70
+ const executionScore = this._matchScore(text, this.keywords.execution);
71
+
72
+ // Classify based on scores
73
+ if (reasoningScore > executionScore) {
74
+ return 'reasoning';
75
+ } else if (executionScore > reasoningScore) {
76
+ return 'execution';
77
+ } else {
78
+ return 'mixed'; // Tied or no matches
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Extract text from message content
84
+ * @param {string|Array} content - Message content
85
+ * @returns {string} Extracted text
86
+ * @private
87
+ */
88
+ _extractText(content) {
89
+ if (typeof content === 'string') {
90
+ return content;
91
+ }
92
+
93
+ if (Array.isArray(content)) {
94
+ return content
95
+ .filter(block => block.type === 'text')
96
+ .map(block => block.text || '')
97
+ .join(' ');
98
+ }
99
+
100
+ return '';
101
+ }
102
+
103
+ /**
104
+ * Calculate keyword match score
105
+ * @param {string} text - Text to search
106
+ * @param {Array} keywords - Keywords to match
107
+ * @returns {number} Number of matches
108
+ * @private
109
+ */
110
+ _matchScore(text, keywords) {
111
+ return keywords.reduce((score, keyword) => {
112
+ // Support both exact match and word boundary match
113
+ const regex = new RegExp(`\\b${this._escapeRegex(keyword)}\\b`, 'i');
114
+ return score + (regex.test(text) ? 1 : 0);
115
+ }, 0);
116
+ }
117
+
118
+ /**
119
+ * Escape special regex characters
120
+ * @param {string} str - String to escape
121
+ * @returns {string} Escaped string
122
+ * @private
123
+ */
124
+ _escapeRegex(str) {
125
+ return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
126
+ }
127
+
128
+ /**
129
+ * Get classification details (for debugging)
130
+ * @param {Array} messages - Messages array
131
+ * @returns {Object} { type, reasoningScore, executionScore, text }
132
+ */
133
+ classifyWithDetails(messages) {
134
+ const text = messages
135
+ .filter(m => m.role === 'user')
136
+ .map(m => this._extractText(m.content))
137
+ .join(' ')
138
+ .toLowerCase();
139
+
140
+ const reasoningScore = this._matchScore(text, this.keywords.reasoning);
141
+ const executionScore = this._matchScore(text, this.keywords.execution);
142
+
143
+ let type;
144
+ if (reasoningScore > executionScore) {
145
+ type = 'reasoning';
146
+ } else if (executionScore > reasoningScore) {
147
+ type = 'execution';
148
+ } else {
149
+ type = 'mixed';
150
+ }
151
+
152
+ return {
153
+ type,
154
+ reasoningScore,
155
+ executionScore,
156
+ textLength: text.length,
157
+ textPreview: text.substring(0, 100) + (text.length > 100 ? '...' : '')
158
+ };
159
+ }
160
+ }
161
+
162
+ module.exports = TaskClassifier;
@@ -4,8 +4,8 @@ const fs = require('fs');
4
4
  const path = require('path');
5
5
  const os = require('os');
6
6
  const { spawn } = require('child_process');
7
- const { colored } = require('./helpers');
8
- const { detectClaudeCli } = require('./claude-detector');
7
+ const { colored } = require('../utils/helpers');
8
+ const { detectClaudeCli } = require('../utils/claude-detector');
9
9
 
10
10
  /**
11
11
  * Health check results
package/lib/ccs CHANGED
@@ -2,7 +2,7 @@
2
2
  set -euo pipefail
3
3
 
4
4
  # Version (updated by scripts/bump-version.sh)
5
- CCS_VERSION="3.4.0"
5
+ CCS_VERSION="3.4.1"
6
6
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
7
  readonly CONFIG_FILE="${CCS_CONFIG:-$HOME/.ccs/config.json}"
8
8
  readonly PROFILES_JSON="$HOME/.ccs/profiles.json"
package/lib/ccs.ps1 CHANGED
@@ -12,7 +12,7 @@ param(
12
12
  $ErrorActionPreference = "Stop"
13
13
 
14
14
  # Version (updated by scripts/bump-version.sh)
15
- $CcsVersion = "3.4.0"
15
+ $CcsVersion = "3.4.1"
16
16
  $ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
17
17
  $ConfigFile = if ($env:CCS_CONFIG) { $env:CCS_CONFIG } else { "$env:USERPROFILE\.ccs\config.json" }
18
18
  $ProfilesJson = "$env:USERPROFILE\.ccs\profiles.json"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaitranntt/ccs",
3
- "version": "3.4.0",
3
+ "version": "3.4.1",
4
4
  "description": "Claude Code Switch - Instant profile switching between Claude Sonnet 4.5 and GLM 4.6",
5
5
  "keywords": [
6
6
  "cli",
@@ -0,0 +1,35 @@
1
+ #!/bin/bash
2
+ # Auto-install CCS locally for testing changes
3
+
4
+ set -e
5
+
6
+ echo "[CCS Dev Install] Starting..."
7
+
8
+ # Get to the right directory
9
+ cd "$(dirname "$0")/.."
10
+
11
+ # Pack the npm package
12
+ echo "[CCS Dev Install] Creating package..."
13
+ npm pack
14
+
15
+ # Find the tarball
16
+ TARBALL=$(ls -t kaitranntt-ccs-*.tgz | head -1)
17
+
18
+ if [ -z "$TARBALL" ]; then
19
+ echo "[CCS Dev Install] ERROR: No tarball found"
20
+ exit 1
21
+ fi
22
+
23
+ echo "[CCS Dev Install] Found tarball: $TARBALL"
24
+
25
+ # Install globally
26
+ echo "[CCS Dev Install] Installing globally..."
27
+ npm install -g "$TARBALL"
28
+
29
+ # Clean up
30
+ echo "[CCS Dev Install] Cleaning up..."
31
+ rm "$TARBALL"
32
+
33
+ echo "[CCS Dev Install] ✓ Complete! CCS is now updated."
34
+ echo ""
35
+ echo "Test with: ccs glmt --version"
File without changes
File without changes