@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.
- package/README.md +40 -6
- package/VERSION +1 -1
- package/bin/{auth-commands.js → auth/auth-commands.js} +3 -3
- package/bin/ccs.js +38 -19
- package/bin/glmt/budget-calculator.js +114 -0
- package/bin/{delta-accumulator.js → glmt/delta-accumulator.js} +108 -2
- package/bin/{glmt-proxy.js → glmt/glmt-proxy.js} +25 -4
- package/bin/{glmt-transformer.js → glmt/glmt-transformer.js} +289 -54
- package/bin/glmt/locale-enforcer.js +80 -0
- package/bin/glmt/task-classifier.js +162 -0
- package/bin/{doctor.js → management/doctor.js} +2 -2
- package/lib/ccs +1 -1
- package/lib/ccs.ps1 +1 -1
- package/package.json +1 -1
- package/scripts/dev-install.sh +35 -0
- /package/bin/{profile-detector.js → auth/profile-detector.js} +0 -0
- /package/bin/{profile-registry.js → auth/profile-registry.js} +0 -0
- /package/bin/{sse-parser.js → glmt/sse-parser.js} +0 -0
- /package/bin/{instance-manager.js → management/instance-manager.js} +0 -0
- /package/bin/{recovery-manager.js → management/recovery-manager.js} +0 -0
- /package/bin/{shared-manager.js → management/shared-manager.js} +0 -0
- /package/bin/{claude-detector.js → utils/claude-detector.js} +0 -0
- /package/bin/{config-manager.js → utils/config-manager.js} +0 -0
- /package/bin/{error-manager.js → utils/error-manager.js} +0 -0
- /package/bin/{helpers.js → utils/helpers.js} +0 -0
|
@@ -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('
|
|
8
|
-
const { detectClaudeCli } = require('
|
|
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.
|
|
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.
|
|
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
|
@@ -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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|