@anh3d0nic/qwen-code-termux-ice 16.0.4 → 16.0.7
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/bin/qwen-ice +25 -5
- package/package.json +6 -5
- package/scripts/build.js +88 -0
- package/scripts/build_package.js +37 -0
- package/scripts/build_sandbox.js +174 -0
- package/scripts/build_vscode_companion.js +30 -0
- package/scripts/check-build-status.js +148 -0
- package/scripts/check-i18n.ts +462 -0
- package/scripts/check-lockfile.js +74 -0
- package/scripts/clean.js +59 -0
- package/scripts/copy_bundle_assets.js +90 -0
- package/scripts/copy_files.js +86 -0
- package/scripts/create_alias.sh +39 -0
- package/scripts/dev.js +109 -0
- package/scripts/esbuild-shims.js +29 -0
- package/scripts/generate-git-commit-info.js +71 -0
- package/scripts/generate-settings-schema.ts +146 -0
- package/scripts/get-release-version.js +411 -0
- package/scripts/ice-mobile.js +5 -0
- package/scripts/ice-session.js +6 -0
- package/scripts/ice-skills.js +31 -0
- package/scripts/ice-teams.js +34 -0
- package/scripts/ice-v10.js +276 -0
- package/scripts/ice-v11.js +276 -0
- package/scripts/ice-v12.js +568 -0
- package/scripts/ice-v13.js +824 -0
- package/scripts/ice-v14.js +1059 -0
- package/scripts/ice-v15.js +1501 -0
- package/scripts/ice-v2.js +26 -0
- package/scripts/ice-v3-core.js +261 -0
- package/scripts/ice-v3.js +46 -0
- package/scripts/ice-v4.js +657 -0
- package/scripts/ice-v5.js +371 -0
- package/scripts/ice-v6.js +305 -0
- package/scripts/ice-v7.js +291 -0
- package/scripts/ice-v8.js +550 -0
- package/scripts/ice-v9.js +546 -0
- package/scripts/install-ice.sh +70 -0
- package/scripts/install.sh +136 -0
- package/scripts/installation/INSTALLATION_GUIDE.md +250 -0
- package/scripts/installation/install-qwen-with-source.bat +302 -0
- package/scripts/installation/install-qwen-with-source.sh +570 -0
- package/scripts/lint.js +205 -0
- package/scripts/local_telemetry.js +219 -0
- package/scripts/postinstall.cjs +235 -0
- package/scripts/pre-commit.js +22 -0
- package/scripts/prepare-package.js +186 -0
- package/scripts/prepare-termux.cjs +26 -0
- package/scripts/sandbox_command.js +128 -0
- package/scripts/start.js +86 -0
- package/scripts/telemetry.js +85 -0
- package/scripts/telemetry_gcp.js +188 -0
- package/scripts/telemetry_utils.js +450 -0
- package/scripts/test-v10.js +18 -0
- package/scripts/test-v11.js +18 -0
- package/scripts/test-v12.js +18 -0
- package/scripts/test-v13.js +18 -0
- package/scripts/test-v14.js +18 -0
- package/scripts/test-v3.js +47 -0
- package/scripts/test-v4.js +47 -0
- package/scripts/test-v6.js +59 -0
- package/scripts/test-v8.js +42 -0
- package/scripts/test-v9.js +18 -0
- package/scripts/test-windows-paths.js +51 -0
- package/scripts/tests/get-release-version.test.js +186 -0
- package/scripts/tests/test-setup.ts +12 -0
- package/scripts/tests/vitest.config.ts +26 -0
- package/scripts/unused-keys-only-in-locales.json +62 -0
- package/scripts/version.js +112 -0
|
@@ -0,0 +1,1501 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ❄️ ICE v15.0.0 - Compounding Intelligence
|
|
4
|
+
*
|
|
5
|
+
* NEW SYSTEMS (v15):
|
|
6
|
+
* 1. CompoundLearner - cross-session learning, compounds intelligence
|
|
7
|
+
* 2. ErrorFingerprinter - deduplicates errors, auto-applies known fixes
|
|
8
|
+
* 3. TrendAnalyzer - tracks quality trends, alerts on decline
|
|
9
|
+
* 4. TermuxInstaller - auto-installs missing packages
|
|
10
|
+
*
|
|
11
|
+
* PRESERVED (v14 verified):
|
|
12
|
+
* - ColdStartIntelligence ✅
|
|
13
|
+
* - PatternPreventer ✅
|
|
14
|
+
* - QualityBlocker ✅
|
|
15
|
+
* - SessionSummary ✅
|
|
16
|
+
* - All other systems ✅
|
|
17
|
+
*
|
|
18
|
+
* PIPELINE:
|
|
19
|
+
* userInput → ColdStartIntelligence → CompoundLearner → PatternPreventer
|
|
20
|
+
* → ErrorFingerprinter → IntentLadder → ConfidenceGating
|
|
21
|
+
* → SmartContext → Generate → SelfCritique(7) → CodeQualityGate
|
|
22
|
+
* → AutoRunLoop → TermuxInstaller → QualityBlocker → DomainMemory
|
|
23
|
+
* → QualityScorer → TrendAnalyzer → SessionSummary → response
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
const { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, renameSync } = require('fs');
|
|
27
|
+
const { join } = require('path');
|
|
28
|
+
const { execSync } = require('child_process');
|
|
29
|
+
const { createHash } = require('crypto');
|
|
30
|
+
|
|
31
|
+
const SESSIONS_DIR = join(process.env.HOME, '.qwen', 'sessions');
|
|
32
|
+
const SESSION_FILE = join(process.env.HOME, '.qwen', 'ice_session.json');
|
|
33
|
+
const CONTEXT_FILE = join(process.env.HOME, '.qwen', 'ice_active_context.json');
|
|
34
|
+
const MEMORY_FILE = join(process.env.HOME, '.qwen', 'session_memory.json');
|
|
35
|
+
const CONFIDENCE_FILE = join(process.env.HOME, '.qwen', 'confidence_history.json');
|
|
36
|
+
const QUALITY_FILE = join(process.env.HOME, '.qwen', 'quality_history.json');
|
|
37
|
+
const SESSION_SUMMARY_FILE = join(process.env.HOME, '.qwen', 'session_summary.json');
|
|
38
|
+
const TREND_FILE = join(process.env.HOME, '.qwen', 'trend_history.json');
|
|
39
|
+
const MANIFEST_FILE = join(process.env.HOME, '.qwen', 'v15_manifest.json');
|
|
40
|
+
|
|
41
|
+
const TERMUX = {
|
|
42
|
+
PREFIX: '/data/data/com.termux/files/usr',
|
|
43
|
+
HOME: '/data/data/com.termux/files/home',
|
|
44
|
+
NO_SUDO: true,
|
|
45
|
+
ARM64: true,
|
|
46
|
+
PKG_MANAGER: 'pkg'
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// Package mapping for Termux
|
|
50
|
+
const PACKAGE_MAP = {
|
|
51
|
+
'python3': 'python',
|
|
52
|
+
'python': 'python',
|
|
53
|
+
'node-gyp': 'nodejs',
|
|
54
|
+
'nodejs': 'nodejs',
|
|
55
|
+
'sharp': 'libvips',
|
|
56
|
+
'canvas': 'libpixman',
|
|
57
|
+
'sqlite3': 'sqlite',
|
|
58
|
+
'bcrypt': 'openssl',
|
|
59
|
+
'argon2': 'openssl'
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// Session tracking
|
|
63
|
+
let sessionStats = {
|
|
64
|
+
queries: 0,
|
|
65
|
+
errorsFixed: 0,
|
|
66
|
+
patternsLearned: 0,
|
|
67
|
+
intentCounts: {},
|
|
68
|
+
sessionId: Date.now()
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// ============================================
|
|
72
|
+
// NEW SYSTEM 1 — COMPOUND LEARNER
|
|
73
|
+
// ============================================
|
|
74
|
+
|
|
75
|
+
class CompoundLearner {
|
|
76
|
+
constructor() {
|
|
77
|
+
this.sessionsDir = SESSIONS_DIR;
|
|
78
|
+
this.ensureSessionsDir();
|
|
79
|
+
this.pastSessions = this.loadPastSessions();
|
|
80
|
+
this.compoundStats = this.calculateCompoundStats();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
ensureSessionsDir() {
|
|
84
|
+
if (!existsSync(this.sessionsDir)) {
|
|
85
|
+
mkdirSync(this.sessionsDir, { recursive: true });
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
archiveCurrentSession() {
|
|
90
|
+
// Move current session_summary.json to sessions/ with timestamp
|
|
91
|
+
if (existsSync(SESSION_SUMMARY_FILE)) {
|
|
92
|
+
try {
|
|
93
|
+
const summary = JSON.parse(readFileSync(SESSION_SUMMARY_FILE, 'utf-8'));
|
|
94
|
+
const timestamp = summary.date ? summary.date.replace(/[:.]/g, '-').split('T')[0] : new Date().toISOString().split('T')[0];
|
|
95
|
+
const sessionNum = this.pastSessions.length + 1;
|
|
96
|
+
const archiveFile = join(this.sessionsDir, `session_${timestamp}_${sessionNum}.json`);
|
|
97
|
+
|
|
98
|
+
// Add session ID
|
|
99
|
+
summary.session_id = sessionStats.sessionId;
|
|
100
|
+
summary.session_number = sessionNum;
|
|
101
|
+
|
|
102
|
+
writeFileSync(archiveFile, JSON.stringify(summary, null, 2));
|
|
103
|
+
} catch (e) {
|
|
104
|
+
// Silent fail
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
loadPastSessions() {
|
|
110
|
+
const sessions = [];
|
|
111
|
+
if (!existsSync(this.sessionsDir)) return sessions;
|
|
112
|
+
|
|
113
|
+
try {
|
|
114
|
+
const files = readdirSync(this.sessionsDir)
|
|
115
|
+
.filter(f => f.startsWith('session_') && f.endsWith('.json'))
|
|
116
|
+
.sort();
|
|
117
|
+
|
|
118
|
+
for (const file of files) {
|
|
119
|
+
try {
|
|
120
|
+
const data = JSON.parse(readFileSync(join(this.sessionsDir, file), 'utf-8'));
|
|
121
|
+
sessions.push(data);
|
|
122
|
+
} catch (e) {}
|
|
123
|
+
}
|
|
124
|
+
} catch (e) {}
|
|
125
|
+
|
|
126
|
+
return sessions;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
calculateCompoundStats() {
|
|
130
|
+
const totalSessions = this.pastSessions.length;
|
|
131
|
+
const lifetimeQueries = this.pastSessions.reduce((sum, s) => sum + (s.total_queries || 0), 0);
|
|
132
|
+
|
|
133
|
+
// Quality trend (last 10 sessions)
|
|
134
|
+
const qualityTrend = this.pastSessions
|
|
135
|
+
.slice(-10)
|
|
136
|
+
.map(s => s.avg_quality || 0);
|
|
137
|
+
|
|
138
|
+
// Most fixed errors
|
|
139
|
+
const errorCounts = {};
|
|
140
|
+
this.pastSessions.forEach(s => {
|
|
141
|
+
if (s.errors_fixed) {
|
|
142
|
+
errorCounts['errors_fixed'] = (errorCounts['errors_fixed'] || 0) + s.errors_fixed;
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
const mostFixedErrors = Object.entries(errorCounts)
|
|
146
|
+
.sort((a, b) => b[1] - a[1])
|
|
147
|
+
.slice(0, 3)
|
|
148
|
+
.map(([err, count]) => ({ error: err, count }));
|
|
149
|
+
|
|
150
|
+
// Strongest patterns (from session_memory.json)
|
|
151
|
+
let strongestPatterns = [];
|
|
152
|
+
try {
|
|
153
|
+
if (existsSync(MEMORY_FILE)) {
|
|
154
|
+
const memory = JSON.parse(readFileSync(MEMORY_FILE, 'utf-8'));
|
|
155
|
+
strongestPatterns = (memory.user_patterns || []).slice(0, 5);
|
|
156
|
+
}
|
|
157
|
+
} catch (e) {}
|
|
158
|
+
|
|
159
|
+
// Improvement rate
|
|
160
|
+
let improvementRate = 0;
|
|
161
|
+
if (qualityTrend.length >= 2) {
|
|
162
|
+
const firstAvg = qualityTrend[0];
|
|
163
|
+
const latestAvg = qualityTrend[qualityTrend.length - 1];
|
|
164
|
+
improvementRate = ((latestAvg - firstAvg) / totalSessions).toFixed(2);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return {
|
|
168
|
+
totalSessions,
|
|
169
|
+
lifetimeQueries,
|
|
170
|
+
qualityTrend,
|
|
171
|
+
mostFixedErrors,
|
|
172
|
+
strongestPatterns,
|
|
173
|
+
improvementRate
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
showSessionHeader() {
|
|
178
|
+
const sessionNum = this.compoundStats.totalSessions + 1;
|
|
179
|
+
const lifetimeQueries = this.compoundStats.lifetimeQueries;
|
|
180
|
+
const trend = this.compoundStats.qualityTrend;
|
|
181
|
+
const trendDisplay = trend.length >= 2
|
|
182
|
+
? `${trend[0].toFixed(1)}→${trend[trend.length - 1].toFixed(1)}`
|
|
183
|
+
: 'N/A';
|
|
184
|
+
const topPattern = this.compoundStats.strongestPatterns[0] || 'none';
|
|
185
|
+
const trendArrow = trend.length >= 2 && trend[trend.length - 1] > trend[0] ? '↑' : trend.length >= 2 && trend[trend.length - 1] < trend[0] ? '↓' : '→';
|
|
186
|
+
|
|
187
|
+
console.log('\n' + '='.repeat(60));
|
|
188
|
+
console.log(`❄️ ICE v15.0 — Session ${sessionNum}`);
|
|
189
|
+
console.log('='.repeat(60));
|
|
190
|
+
console.log(`📊 Lifetime: ${lifetimeQueries} queries | Quality trend: ${trendArrow} ${trendDisplay}`);
|
|
191
|
+
console.log(`🧠 Top pattern: ${topPattern}`);
|
|
192
|
+
if (this.compoundStats.mostFixedErrors.length > 0) {
|
|
193
|
+
console.log(`⚠️ Most fixed: ${this.compoundStats.mostFixedErrors[0]?.error || 'none'}`);
|
|
194
|
+
}
|
|
195
|
+
console.log('='.repeat(60) + '\n');
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
saveSessionSummary(summary) {
|
|
199
|
+
this.archiveCurrentSession();
|
|
200
|
+
|
|
201
|
+
// Add compound data
|
|
202
|
+
summary.compound_stats = this.compoundStats;
|
|
203
|
+
summary.session_id = sessionStats.sessionId;
|
|
204
|
+
|
|
205
|
+
writeFileSync(SESSION_SUMMARY_FILE, JSON.stringify(summary, null, 2));
|
|
206
|
+
|
|
207
|
+
// Reload sessions for next time
|
|
208
|
+
this.pastSessions = this.loadPastSessions();
|
|
209
|
+
this.compoundStats = this.calculateCompoundStats();
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// ============================================
|
|
214
|
+
// NEW SYSTEM 2 — ERROR FINGERPRINTER
|
|
215
|
+
// ============================================
|
|
216
|
+
|
|
217
|
+
class ErrorFingerprinter {
|
|
218
|
+
constructor(memory) {
|
|
219
|
+
this.memory = memory;
|
|
220
|
+
this.fingerprints = this.loadFingerprints();
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
loadFingerprints() {
|
|
224
|
+
try {
|
|
225
|
+
if (existsSync(MEMORY_FILE)) {
|
|
226
|
+
const memory = JSON.parse(readFileSync(MEMORY_FILE, 'utf-8'));
|
|
227
|
+
return memory.known_errors?.map(e => ({
|
|
228
|
+
fingerprint: this.hashError(e.error),
|
|
229
|
+
error: e.error,
|
|
230
|
+
fix: e.fix,
|
|
231
|
+
count: e.count || 1,
|
|
232
|
+
last_seen: e.timestamp
|
|
233
|
+
})) || [];
|
|
234
|
+
}
|
|
235
|
+
} catch (e) {}
|
|
236
|
+
return [];
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
hashError(errorStr) {
|
|
240
|
+
// Hash first 50 chars + detect error type
|
|
241
|
+
const truncated = errorStr.substring(0, 50).toLowerCase();
|
|
242
|
+
const type = this.detectErrorType(errorStr);
|
|
243
|
+
return createHash('md5').update(truncated + type).digest('hex').substring(0, 8);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
detectErrorType(error) {
|
|
247
|
+
if (error.includes('sudo')) return 'sudo_error';
|
|
248
|
+
if (error.includes('permission')) return 'permission_error';
|
|
249
|
+
if (error.includes('not found')) return 'not_found_error';
|
|
250
|
+
if (error.includes('EACCES')) return 'access_error';
|
|
251
|
+
if (error.includes('ENOENT')) return 'file_not_found';
|
|
252
|
+
return 'generic_error';
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
check(query) {
|
|
256
|
+
const fingerprint = this.hashError(query);
|
|
257
|
+
const match = this.fingerprints.find(f => f.fingerprint === fingerprint);
|
|
258
|
+
|
|
259
|
+
if (match) {
|
|
260
|
+
match.count++;
|
|
261
|
+
match.last_seen = Date.now();
|
|
262
|
+
console.log(`🔍 ErrorFingerprinter: Known error #${match.count} (seen ${match.count}x). Auto-applying fix...`);
|
|
263
|
+
return { known: true, fix: match.fix, fingerprint: match.fingerprint };
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return { known: false, fingerprint };
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
addError(error, fix) {
|
|
270
|
+
const fingerprint = this.hashError(error);
|
|
271
|
+
const existing = this.fingerprints.find(f => f.fingerprint === fingerprint);
|
|
272
|
+
|
|
273
|
+
if (existing) {
|
|
274
|
+
existing.count++;
|
|
275
|
+
existing.last_seen = Date.now();
|
|
276
|
+
existing.fix = fix;
|
|
277
|
+
} else {
|
|
278
|
+
this.fingerprints.push({
|
|
279
|
+
fingerprint,
|
|
280
|
+
error,
|
|
281
|
+
fix,
|
|
282
|
+
count: 1,
|
|
283
|
+
last_seen: Date.now()
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Save to memory
|
|
288
|
+
try {
|
|
289
|
+
const memory = this.memory.get();
|
|
290
|
+
memory.known_errors = this.fingerprints.map(f => ({
|
|
291
|
+
error: f.error,
|
|
292
|
+
fix: f.fix,
|
|
293
|
+
count: f.count,
|
|
294
|
+
timestamp: f.last_seen
|
|
295
|
+
}));
|
|
296
|
+
this.memory.save();
|
|
297
|
+
} catch (e) {}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// ============================================
|
|
302
|
+
// NEW SYSTEM 3 — TREND ANALYZER
|
|
303
|
+
// ============================================
|
|
304
|
+
|
|
305
|
+
class TrendAnalyzer {
|
|
306
|
+
constructor() {
|
|
307
|
+
this.history = this.loadHistory();
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
loadHistory() {
|
|
311
|
+
try {
|
|
312
|
+
if (existsSync(TREND_FILE)) {
|
|
313
|
+
return JSON.parse(readFileSync(TREND_FILE, 'utf-8'));
|
|
314
|
+
}
|
|
315
|
+
} catch (e) {}
|
|
316
|
+
return { trends: [], alerts: [] };
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
saveHistory() {
|
|
320
|
+
try {
|
|
321
|
+
writeFileSync(TREND_FILE, JSON.stringify(this.history, null, 2));
|
|
322
|
+
} catch (e) {}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
update(currentScore) {
|
|
326
|
+
// Add current score
|
|
327
|
+
this.history.trends.push({
|
|
328
|
+
score: currentScore,
|
|
329
|
+
timestamp: Date.now(),
|
|
330
|
+
session_id: sessionStats.sessionId
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
// Keep last 100 scores
|
|
334
|
+
if (this.history.trends.length > 100) {
|
|
335
|
+
this.history.trends.shift();
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Calculate rolling average (last 5)
|
|
339
|
+
const last5 = this.history.trends.slice(-5);
|
|
340
|
+
if (last5.length >= 5) {
|
|
341
|
+
const currentAvg = last5.reduce((a, b) => a + b.score, 0) / 5;
|
|
342
|
+
const previous5 = this.history.trends.slice(-10, -5);
|
|
343
|
+
|
|
344
|
+
if (previous5.length >= 5) {
|
|
345
|
+
const previousAvg = previous5.reduce((a, b) => a + b.score, 0) / 5;
|
|
346
|
+
|
|
347
|
+
// Check trend direction
|
|
348
|
+
if (currentAvg < previousAvg - 0.5) {
|
|
349
|
+
// Declining
|
|
350
|
+
console.log(`\n⚠️ TREND ALERT: Quality declining: ${previousAvg.toFixed(1)}→${currentAvg.toFixed(1)}`);
|
|
351
|
+
console.log(' Running self-audit...\n');
|
|
352
|
+
this.history.alerts.push({
|
|
353
|
+
type: 'declining',
|
|
354
|
+
from: previousAvg,
|
|
355
|
+
to: currentAvg,
|
|
356
|
+
timestamp: Date.now()
|
|
357
|
+
});
|
|
358
|
+
} else if (currentAvg > previousAvg + 0.5) {
|
|
359
|
+
// Improving
|
|
360
|
+
console.log(`\n📈 Quality improving: ${previousAvg.toFixed(1)}→${currentAvg.toFixed(1)}`);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
this.saveHistory();
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
getTrend() {
|
|
369
|
+
if (this.history.trends.length < 5) return 'insufficient_data';
|
|
370
|
+
const last5 = this.history.trends.slice(-5);
|
|
371
|
+
const previous5 = this.history.trends.slice(-10, -5);
|
|
372
|
+
if (previous5.length < 5) return 'insufficient_data';
|
|
373
|
+
|
|
374
|
+
const currentAvg = last5.reduce((a, b) => a + b.score, 0) / 5;
|
|
375
|
+
const previousAvg = previous5.reduce((a, b) => a + b.score, 0) / 5;
|
|
376
|
+
|
|
377
|
+
if (currentAvg > previousAvg + 0.5) return 'improving';
|
|
378
|
+
if (currentAvg < previousAvg - 0.5) return 'declining';
|
|
379
|
+
return 'stable';
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// ============================================
|
|
384
|
+
// NEW SYSTEM 4 — TERMUX INSTALLER
|
|
385
|
+
// ============================================
|
|
386
|
+
|
|
387
|
+
class TermuxInstaller {
|
|
388
|
+
constructor() {
|
|
389
|
+
this.installedPackages = this.detectInstalledPackages();
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
detectInstalledPackages() {
|
|
393
|
+
const installed = new Set();
|
|
394
|
+
try {
|
|
395
|
+
// Check common packages
|
|
396
|
+
const checks = [
|
|
397
|
+
{ cmd: 'python --version', pkg: 'python' },
|
|
398
|
+
{ cmd: 'node --version', pkg: 'nodejs' },
|
|
399
|
+
{ cmd: 'git --version', pkg: 'git' },
|
|
400
|
+
{ cmd: 'pkg list-installed 2>/dev/null', pkg: null }
|
|
401
|
+
];
|
|
402
|
+
|
|
403
|
+
for (const check of checks) {
|
|
404
|
+
try {
|
|
405
|
+
const result = execSync(check.cmd, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
406
|
+
if (check.pkg) installed.add(check.pkg);
|
|
407
|
+
if (check.cmd.includes('list-installed')) {
|
|
408
|
+
const lines = result.split('\n');
|
|
409
|
+
lines.forEach(line => {
|
|
410
|
+
const pkg = line.split(' ')[0];
|
|
411
|
+
if (pkg) installed.add(pkg);
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
} catch (e) {}
|
|
415
|
+
}
|
|
416
|
+
} catch (e) {}
|
|
417
|
+
return installed;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
scanForImports(code) {
|
|
421
|
+
const imports = [];
|
|
422
|
+
|
|
423
|
+
// Python imports
|
|
424
|
+
const pythonImports = code.match(/^(?:import|from)\s+(\w+)/gm);
|
|
425
|
+
if (pythonImports) {
|
|
426
|
+
pythonImports.forEach(imp => {
|
|
427
|
+
const match = imp.match(/(\w+)/);
|
|
428
|
+
if (match) imports.push({ lang: 'python', pkg: match[1] });
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// Node.js requires
|
|
433
|
+
const nodeRequires = code.match(/require\s*\(\s*['"]([^'"]+)['"]\s*\)/g);
|
|
434
|
+
if (nodeRequires) {
|
|
435
|
+
nodeRequires.forEach(req => {
|
|
436
|
+
const match = req.match(/['"]([^'"]+)['"]/);
|
|
437
|
+
if (match) imports.push({ lang: 'node', pkg: match[1] });
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
return imports;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
getTermuxPackage(pkg) {
|
|
445
|
+
return PACKAGE_MAP[pkg] || pkg;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
async ensurePackages(code) {
|
|
449
|
+
const imports = this.scanForImports(code);
|
|
450
|
+
const missing = [];
|
|
451
|
+
|
|
452
|
+
for (const imp of imports) {
|
|
453
|
+
const termuxPkg = this.getTermuxPackage(imp.pkg);
|
|
454
|
+
if (!this.installedPackages.has(termuxPkg)) {
|
|
455
|
+
missing.push({ original: imp.pkg, termux: termuxPkg, lang: imp.lang });
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
if (missing.length > 0) {
|
|
460
|
+
console.log('\n📦 TermuxInstaller: Missing packages detected');
|
|
461
|
+
for (const pkg of missing) {
|
|
462
|
+
console.log(` Installing ${pkg.termux} (for ${pkg.original})...`);
|
|
463
|
+
try {
|
|
464
|
+
execSync(`pkg install ${pkg.termux} -y`, {
|
|
465
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
466
|
+
timeout: 30000
|
|
467
|
+
});
|
|
468
|
+
this.installedPackages.add(pkg.termux);
|
|
469
|
+
console.log(` ✅ ${pkg.termux} installed`);
|
|
470
|
+
} catch (e) {
|
|
471
|
+
console.log(` ⚠️ Failed to install ${pkg.termux}`);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
console.log();
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// ============================================
|
|
480
|
+
// EXISTING CLASSES (from v14, preserved)
|
|
481
|
+
// ============================================
|
|
482
|
+
|
|
483
|
+
class ColdStartIntelligence {
|
|
484
|
+
constructor() {
|
|
485
|
+
this.sessionMemory = this.loadJson(MEMORY_FILE, { user_patterns: [], known_errors: [] });
|
|
486
|
+
this.qualityHistory = this.loadJson(QUALITY_FILE, { history: [] });
|
|
487
|
+
this.confidenceHistory = this.loadJson(CONFIDENCE_FILE, { history: [] });
|
|
488
|
+
this.sessionSummary = this.loadJson(SESSION_SUMMARY_FILE, { total_queries: 0, avg_quality: 0 });
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
loadJson(file, defaultVal) {
|
|
492
|
+
try {
|
|
493
|
+
if (existsSync(file)) {
|
|
494
|
+
return JSON.parse(readFileSync(file, 'utf-8'));
|
|
495
|
+
}
|
|
496
|
+
} catch (e) {}
|
|
497
|
+
return defaultVal;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
showWelcome() {
|
|
501
|
+
const patternsCount = this.sessionMemory.user_patterns?.length || 0;
|
|
502
|
+
const errorsCount = this.sessionMemory.known_errors?.length || 0;
|
|
503
|
+
const avgQuality = this.getAverageQuality();
|
|
504
|
+
const totalQueries = this.sessionSummary.total_queries || 0;
|
|
505
|
+
|
|
506
|
+
if (patternsCount === 0 && totalQueries === 0) {
|
|
507
|
+
return `\n❄️ Welcome to Qwen Code ICE v15.0.0\n🔑 First run - type your query to begin\n`;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
return `\n❄️ Welcome back to Qwen Code ICE v15.0.0\n📊 Last session: ${totalQueries} queries, avg quality ${avgQuality}/10\n🧠 ${patternsCount} patterns learned | ⚠️ ${errorsCount} known errors\n`;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
getAverageQuality() {
|
|
514
|
+
if (!this.qualityHistory.history || this.qualityHistory.history.length === 0) return 'N/A';
|
|
515
|
+
const sum = this.qualityHistory.history.reduce((a, b) => a + (b.score || 0), 0);
|
|
516
|
+
return (sum / this.qualityHistory.history.length).toFixed(1);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
getStats() {
|
|
520
|
+
return {
|
|
521
|
+
patternsCount: this.sessionMemory.user_patterns?.length || 0,
|
|
522
|
+
knownErrorsCount: this.sessionMemory.known_errors?.length || 0,
|
|
523
|
+
avgQuality: this.getAverageQuality(),
|
|
524
|
+
totalQueries: this.sessionSummary.total_queries || 0
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
class PatternPreventer {
|
|
530
|
+
constructor(memory) {
|
|
531
|
+
this.memory = memory;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
preventErrors(query) {
|
|
535
|
+
const mem = this.memory.get();
|
|
536
|
+
const knownErrors = mem.known_errors || [];
|
|
537
|
+
const userPatterns = mem.user_patterns || [];
|
|
538
|
+
|
|
539
|
+
let enhancedQuery = query;
|
|
540
|
+
const warnings = [];
|
|
541
|
+
const preAppliedFixes = [];
|
|
542
|
+
|
|
543
|
+
if (query.toLowerCase().includes('sudo')) {
|
|
544
|
+
enhancedQuery = enhancedQuery.replace(/\bsudo\b\s*/gi, '');
|
|
545
|
+
warnings.push('⚠️ Auto-removed sudo (Termux uses pkg)');
|
|
546
|
+
preAppliedFixes.push('sudo_stripped');
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
if (query.includes('/usr/bin') || query.includes('/bin/')) {
|
|
550
|
+
enhancedQuery = enhancedQuery
|
|
551
|
+
.replace(/\/usr\/bin/g, `${TERMUX.PREFIX}/bin`)
|
|
552
|
+
.replace(/\/bin\//g, `${TERMUX.PREFIX}/bin/`);
|
|
553
|
+
warnings.push('⚠️ Auto-fixed paths for Termux');
|
|
554
|
+
preAppliedFixes.push('paths_fixed');
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
knownErrors.forEach(err => {
|
|
558
|
+
if (query.toLowerCase().includes(err.error.toLowerCase())) {
|
|
559
|
+
warnings.push(`⚠️ Known issue: ${err.error} → ${err.fix}`);
|
|
560
|
+
preAppliedFixes.push(`known_error:${err.error}`);
|
|
561
|
+
}
|
|
562
|
+
});
|
|
563
|
+
|
|
564
|
+
userPatterns.forEach(pattern => {
|
|
565
|
+
if (typeof pattern === 'string' && query.toLowerCase().includes(pattern.toLowerCase())) {
|
|
566
|
+
warnings.push(`📌 Pattern matched: ${pattern}`);
|
|
567
|
+
}
|
|
568
|
+
});
|
|
569
|
+
|
|
570
|
+
return { enhancedQuery, warnings, preAppliedFixes };
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
class QualityBlocker {
|
|
575
|
+
constructor(minScore = 5) {
|
|
576
|
+
this.minScore = minScore;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
shouldBlock(score) {
|
|
580
|
+
return score < this.minScore;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
getAction(score) {
|
|
584
|
+
if (score >= 8) return 'excellent';
|
|
585
|
+
if (score >= 5) return 'acceptable';
|
|
586
|
+
return 'block_and_regenerate';
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
class SessionSummary {
|
|
591
|
+
constructor() {
|
|
592
|
+
this.data = this.load();
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
load() {
|
|
596
|
+
try {
|
|
597
|
+
if (existsSync(SESSION_SUMMARY_FILE)) {
|
|
598
|
+
return JSON.parse(readFileSync(SESSION_SUMMARY_FILE, 'utf-8'));
|
|
599
|
+
}
|
|
600
|
+
} catch (e) {}
|
|
601
|
+
return { total_queries: 0, avg_quality: 0, patterns_learned: 0, errors_fixed: 0, top_intent: '' };
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
save(stats) {
|
|
605
|
+
const summary = {
|
|
606
|
+
date: new Date().toISOString(),
|
|
607
|
+
total_queries: stats.queries,
|
|
608
|
+
avg_quality: parseFloat(stats.avgQuality) || 0,
|
|
609
|
+
patterns_learned: stats.patternsLearned,
|
|
610
|
+
errors_fixed: stats.errorsFixed,
|
|
611
|
+
top_intent: stats.topIntent || 'none'
|
|
612
|
+
};
|
|
613
|
+
writeFileSync(SESSION_SUMMARY_FILE, JSON.stringify(summary, null, 2));
|
|
614
|
+
return summary;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
printAndSave(stats) {
|
|
618
|
+
const summary = this.save(stats);
|
|
619
|
+
console.log('\n' + '='.repeat(60));
|
|
620
|
+
console.log('📊 SESSION SUMMARY');
|
|
621
|
+
console.log('='.repeat(60));
|
|
622
|
+
console.log(` Total queries: ${summary.total_queries}`);
|
|
623
|
+
console.log(` Avg quality: ${summary.avg_quality.toFixed(1)}/10`);
|
|
624
|
+
console.log(` Patterns learned: ${summary.patterns_learned}`);
|
|
625
|
+
console.log(` Errors fixed: ${summary.errors_fixed}`);
|
|
626
|
+
console.log(` Top intent: ${summary.top_intent}`);
|
|
627
|
+
console.log('='.repeat(60) + '\n');
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
class AutoRunLoop {
|
|
632
|
+
extractCode(response) {
|
|
633
|
+
const match = response.match(/```(?:bash|sh|js|javascript|python|py)?\n([\s\S]*?)\n```/);
|
|
634
|
+
return match ? match[1].trim() : null;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
exec(code, maxRetries = 3) {
|
|
638
|
+
const extractedCode = this.extractCode(code);
|
|
639
|
+
if (!extractedCode) return { success: true, output: 'No executable code found', code: code };
|
|
640
|
+
|
|
641
|
+
console.log('\n⚡ Auto-Run Loop: Executing code...\n');
|
|
642
|
+
|
|
643
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
644
|
+
try {
|
|
645
|
+
console.log(`Attempt ${attempt}/${maxRetries}...`);
|
|
646
|
+
const output = execSync(extractedCode, {
|
|
647
|
+
cwd: TERMUX.HOME,
|
|
648
|
+
env: { ...process.env, PREFIX: TERMUX.PREFIX },
|
|
649
|
+
timeout: 30000,
|
|
650
|
+
encoding: 'utf-8',
|
|
651
|
+
stdio: ['pipe', 'pipe', 'pipe']
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
console.log(`✅ Code executed successfully (exit code 0)\n`);
|
|
655
|
+
return { success: true, output, code: extractedCode, attempt };
|
|
656
|
+
|
|
657
|
+
} catch (error) {
|
|
658
|
+
const stderr = error.stderr || '';
|
|
659
|
+
const status = error.status;
|
|
660
|
+
|
|
661
|
+
if (status === 0) {
|
|
662
|
+
console.log(`✅ Code executed with warnings (exit code 0)\n`);
|
|
663
|
+
return { success: true, output: stderr, code: extractedCode, attempt, hasWarnings: true };
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
const errorMsg = stderr || error.message;
|
|
667
|
+
console.log(`❌ Attempt ${attempt} failed: ${errorMsg.substring(0, 100)}\n`);
|
|
668
|
+
|
|
669
|
+
if (attempt === maxRetries) {
|
|
670
|
+
return {
|
|
671
|
+
success: false,
|
|
672
|
+
output: errorMsg,
|
|
673
|
+
code: extractedCode,
|
|
674
|
+
attempts: maxRetries,
|
|
675
|
+
warning: `⚠️ Code failed after ${maxRetries} attempts. Please review and fix manually.`
|
|
676
|
+
};
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
class ConfidenceGating {
|
|
684
|
+
constructor() {
|
|
685
|
+
this.thresholds = {
|
|
686
|
+
CERTAIN: { min: 90, action: 'respond_directly' },
|
|
687
|
+
LIKELY: { min: 70, action: 'respond_with_assumption_flag' },
|
|
688
|
+
UNCERTAIN: { min: 0, action: 'ask_clarifying_question' }
|
|
689
|
+
};
|
|
690
|
+
this.history = [];
|
|
691
|
+
this.loadHistory();
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
loadHistory() {
|
|
695
|
+
if (existsSync(CONFIDENCE_FILE)) {
|
|
696
|
+
try {
|
|
697
|
+
this.history = JSON.parse(readFileSync(CONFIDENCE_FILE, 'utf-8'));
|
|
698
|
+
} catch (e) {
|
|
699
|
+
this.history = [];
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
saveHistory() {
|
|
705
|
+
const dir = join(process.env.HOME, '.qwen');
|
|
706
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
707
|
+
writeFileSync(CONFIDENCE_FILE, JSON.stringify(this.history.slice(-20), null, 2));
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
recordOutcome(confidence, wasAccurate) {
|
|
711
|
+
this.history.push({ confidence, wasAccurate, timestamp: Date.now() });
|
|
712
|
+
if (this.history.length > 20) this.history.shift();
|
|
713
|
+
this.saveHistory();
|
|
714
|
+
this.adjustThresholds();
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
adjustThresholds() {
|
|
718
|
+
if (this.history.length < 10) return;
|
|
719
|
+
const recent = this.history.slice(-10);
|
|
720
|
+
const inaccurateCertain = recent.filter(h => h.confidence >= 90 && !h.wasAccurate).length;
|
|
721
|
+
const inaccurateUncertain = recent.filter(h => h.confidence < 70 && h.wasAccurate).length;
|
|
722
|
+
if (inaccurateCertain > 2) {
|
|
723
|
+
this.thresholds.CERTAIN.min = Math.min(95, this.thresholds.CERTAIN.min + 2);
|
|
724
|
+
}
|
|
725
|
+
if (inaccurateUncertain > 2) {
|
|
726
|
+
this.thresholds.UNCERTAIN.min = Math.max(0, this.thresholds.UNCERTAIN.min - 5);
|
|
727
|
+
this.thresholds.LIKELY.min = Math.max(50, this.thresholds.LIKELY.min - 5);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
calculateConfidence(query, context) {
|
|
732
|
+
let confidence = 50;
|
|
733
|
+
if (query.includes('how to') || query.includes('how do i')) confidence += 20;
|
|
734
|
+
if (query.includes('fix') || query.includes('error')) confidence += 15;
|
|
735
|
+
if (query.includes('termux') || query.includes('android')) confidence += 15;
|
|
736
|
+
if (query.length < 10) confidence -= 20;
|
|
737
|
+
if (query.includes('maybe') || query.includes('not sure')) confidence -= 15;
|
|
738
|
+
if (query.endsWith('?')) confidence -= 5;
|
|
739
|
+
if (context && context.goal) confidence += 10;
|
|
740
|
+
return Math.min(100, Math.max(0, confidence));
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
getLevel(confidence) {
|
|
744
|
+
if (confidence >= this.thresholds.CERTAIN.min) return 'CERTAIN';
|
|
745
|
+
if (confidence >= this.thresholds.LIKELY.min) return 'LIKELY';
|
|
746
|
+
return 'UNCERTAIN';
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
assess(query, context) {
|
|
750
|
+
const confidence = this.calculateConfidence(query, context);
|
|
751
|
+
const level = this.getLevel(confidence);
|
|
752
|
+
return { confidence, level, action: this.thresholds[level].action };
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
class PatternLearningEngine {
|
|
757
|
+
constructor(memory) {
|
|
758
|
+
this.memory = memory;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
applyPatterns(query) {
|
|
762
|
+
const mem = this.memory.get();
|
|
763
|
+
const knownErrors = mem.known_errors || [];
|
|
764
|
+
const userPatterns = mem.user_patterns || [];
|
|
765
|
+
|
|
766
|
+
let enhancedQuery = query;
|
|
767
|
+
const warnings = [];
|
|
768
|
+
const preAppliedFixes = [];
|
|
769
|
+
|
|
770
|
+
if (query.toLowerCase().includes('sudo')) {
|
|
771
|
+
enhancedQuery = enhancedQuery.replace(/\bsudo\b\s*/gi, '');
|
|
772
|
+
warnings.push('⚠️ Auto-removed sudo (Termux uses pkg)');
|
|
773
|
+
preAppliedFixes.push('sudo_stripped');
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
if (query.includes('/usr/bin') || query.includes('/bin/')) {
|
|
777
|
+
enhancedQuery = enhancedQuery
|
|
778
|
+
.replace(/\/usr\/bin/g, `${TERMUX.PREFIX}/bin`)
|
|
779
|
+
.replace(/\/bin\//g, `${TERMUX.PREFIX}/bin/`);
|
|
780
|
+
warnings.push('⚠️ Auto-fixed paths for Termux');
|
|
781
|
+
preAppliedFixes.push('paths_fixed');
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
knownErrors.forEach(err => {
|
|
785
|
+
if (query.toLowerCase().includes(err.error.toLowerCase())) {
|
|
786
|
+
warnings.push(`⚠️ Known issue: ${err.error} → ${err.fix}`);
|
|
787
|
+
preAppliedFixes.push(`known_error:${err.error}`);
|
|
788
|
+
}
|
|
789
|
+
});
|
|
790
|
+
|
|
791
|
+
userPatterns.forEach(pattern => {
|
|
792
|
+
if (typeof pattern === 'string' && query.toLowerCase().includes(pattern.toLowerCase())) {
|
|
793
|
+
warnings.push(`📌 Pattern matched: ${pattern}`);
|
|
794
|
+
}
|
|
795
|
+
});
|
|
796
|
+
|
|
797
|
+
return { enhancedQuery, warnings, preAppliedFixes };
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
class ResponseQualityScorer {
|
|
802
|
+
constructor() {
|
|
803
|
+
this.history = [];
|
|
804
|
+
this.loadHistory();
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
loadHistory() {
|
|
808
|
+
if (existsSync(QUALITY_FILE)) {
|
|
809
|
+
try {
|
|
810
|
+
this.history = JSON.parse(readFileSync(QUALITY_FILE, 'utf-8'));
|
|
811
|
+
} catch (e) {
|
|
812
|
+
this.history = [];
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
saveHistory() {
|
|
818
|
+
const dir = join(process.env.HOME, '.qwen');
|
|
819
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
820
|
+
writeFileSync(QUALITY_FILE, JSON.stringify(this.history.slice(-20), null, 2));
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
score(response, intent, critique, codeResult) {
|
|
824
|
+
let score = 5;
|
|
825
|
+
if (codeResult) {
|
|
826
|
+
if (codeResult.success) score += 3;
|
|
827
|
+
else score -= 2;
|
|
828
|
+
}
|
|
829
|
+
const tokenCount = Math.ceil(response.length / 4);
|
|
830
|
+
if (tokenCount < 200) score += 1;
|
|
831
|
+
if (tokenCount > 500) score -= 1;
|
|
832
|
+
if (!response.includes('sudo') && !response.includes('/usr/bin/') && !response.includes('apt-get')) {
|
|
833
|
+
score += 1;
|
|
834
|
+
}
|
|
835
|
+
if (intent && intent.deep && response.toLowerCase().includes(intent.deep.toLowerCase().split(' ')[0])) {
|
|
836
|
+
score += 1;
|
|
837
|
+
}
|
|
838
|
+
if (critique && critique.issues && critique.issues.length === 0) {
|
|
839
|
+
score += 1;
|
|
840
|
+
}
|
|
841
|
+
score = Math.max(1, Math.min(10, score));
|
|
842
|
+
this.history.push({ score, timestamp: Date.now() });
|
|
843
|
+
if (this.history.length > 20) this.history.shift();
|
|
844
|
+
this.saveHistory();
|
|
845
|
+
return score;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
getAverage() {
|
|
849
|
+
if (this.history.length === 0) return null;
|
|
850
|
+
const sum = this.history.reduce((a, b) => a + b.score, 0);
|
|
851
|
+
return (sum / this.history.length).toFixed(1);
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
getTrend() {
|
|
855
|
+
if (this.history.length < 5) return 'insufficient_data';
|
|
856
|
+
const recent = this.history.slice(-5);
|
|
857
|
+
const older = this.history.slice(-10, -5);
|
|
858
|
+
const recentAvg = recent.reduce((a, b) => a + b.score, 0) / recent.length;
|
|
859
|
+
const olderAvg = older.reduce((a, b) => a + b.score, 0) / older.length;
|
|
860
|
+
if (recentAvg > olderAvg + 0.5) return 'improving';
|
|
861
|
+
if (recentAvg < olderAvg - 0.5) return 'declining';
|
|
862
|
+
return 'stable';
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
shouldAudit() {
|
|
866
|
+
const avg = parseFloat(this.getAverage() || 10);
|
|
867
|
+
return avg < 7;
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
class SmartContextCompression {
|
|
872
|
+
constructor(contextEngine) {
|
|
873
|
+
this.contextEngine = contextEngine;
|
|
874
|
+
this.turnHistory = [];
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
addTurn(turn) {
|
|
878
|
+
this.turnHistory.push(turn);
|
|
879
|
+
if (this.turnHistory.length > 10) {
|
|
880
|
+
this.turnHistory.shift();
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
getCompressed() {
|
|
885
|
+
if (this.turnHistory.length === 0) return '';
|
|
886
|
+
const recentTurns = this.turnHistory.slice(-3);
|
|
887
|
+
const olderTurns = this.turnHistory.slice(0, -3);
|
|
888
|
+
let compressed = '';
|
|
889
|
+
if (olderTurns.length > 0) {
|
|
890
|
+
compressed += `[${olderTurns.length} earlier turns summarized]\n`;
|
|
891
|
+
olderTurns.forEach(turn => {
|
|
892
|
+
const summary = turn.content.substring(0, 50) + (turn.content.length > 50 ? '...' : '');
|
|
893
|
+
compressed += ` ${turn.role}: ${summary}\n`;
|
|
894
|
+
});
|
|
895
|
+
}
|
|
896
|
+
recentTurns.forEach(turn => {
|
|
897
|
+
const content = turn.content.substring(0, 200) + (turn.content.length > 200 ? '...' : '');
|
|
898
|
+
compressed += `${turn.role}: ${content}\n`;
|
|
899
|
+
});
|
|
900
|
+
const ctx = this.contextEngine.get();
|
|
901
|
+
if (ctx.goal) compressed += `\n[Current goal: ${ctx.goal}]\n`;
|
|
902
|
+
if (ctx.blockers && ctx.blockers.length > 0) {
|
|
903
|
+
compressed += `[Blockers: ${ctx.blockers.join(', ')}]\n`;
|
|
904
|
+
}
|
|
905
|
+
const tokenCount = Math.ceil(compressed.length / 4);
|
|
906
|
+
if (tokenCount > 300) {
|
|
907
|
+
compressed = compressed.substring(0, 1200) + '...\n[truncated to 300 tokens]';
|
|
908
|
+
}
|
|
909
|
+
return compressed;
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
clear() {
|
|
913
|
+
this.turnHistory = [];
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
class SelfCritiqueLoop {
|
|
918
|
+
constructor() {
|
|
919
|
+
this.questions = [
|
|
920
|
+
'What is wrong with this?',
|
|
921
|
+
'What did I miss?',
|
|
922
|
+
'Will this break on Termux?',
|
|
923
|
+
'Is this the shortest correct solution?',
|
|
924
|
+
'Am I answering what they actually want, not what they typed?',
|
|
925
|
+
'Does this have any hardcoded paths that break on mobile?',
|
|
926
|
+
'Would a senior dev approve this?'
|
|
927
|
+
];
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
critique(draft) {
|
|
931
|
+
const issues = [];
|
|
932
|
+
if (draft.includes('sudo')) issues.push('❌ Uses sudo (not available on Termux)');
|
|
933
|
+
if (draft.includes('/usr/bin') || draft.includes('/bin/')) issues.push('❌ Hardcoded paths (will fail on Termux)');
|
|
934
|
+
if (draft.length < 50) issues.push('⚠️ Response too short - may be incomplete');
|
|
935
|
+
if (!draft.includes('try') && !draft.includes('if') && draft.includes('function')) issues.push('⚠️ No error handling');
|
|
936
|
+
if (draft.includes('TODO') || draft.includes('FIXME')) issues.push('⚠️ Contains unresolved placeholders');
|
|
937
|
+
if (draft.includes('apt-get') || draft.includes('apt ')) issues.push('❌ Uses apt (should be pkg on Termux)');
|
|
938
|
+
if (draft.includes('systemctl')) issues.push('❌ Uses systemd (not available on Termux)');
|
|
939
|
+
return issues;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
fix(draft, issues) {
|
|
943
|
+
let fixed = draft;
|
|
944
|
+
issues.forEach(issue => {
|
|
945
|
+
if (issue.includes('sudo')) fixed = fixed.replace(/sudo\s+/g, '# Termux: no sudo needed\n');
|
|
946
|
+
if (issue.includes('Hardcoded paths')) {
|
|
947
|
+
fixed = fixed.replace(/\/usr\/bin\//g, `${TERMUX.PREFIX}/bin/`);
|
|
948
|
+
fixed = fixed.replace(/\/bin\//g, `${TERMUX.PREFIX}/bin/`);
|
|
949
|
+
}
|
|
950
|
+
if (issue.includes('apt')) fixed = fixed.replace(/apt-get\s+install/g, 'pkg install').replace(/apt\s+install/g, 'pkg install');
|
|
951
|
+
if (issue.includes('systemctl')) fixed = fixed.replace(/systemctl\s+/g, '# Termux: no systemd\n# ');
|
|
952
|
+
});
|
|
953
|
+
return fixed;
|
|
954
|
+
}
|
|
955
|
+
|
|
956
|
+
process(draft) {
|
|
957
|
+
const issues = this.critique(draft);
|
|
958
|
+
if (issues.length === 0) return { draft, issues: [], fixed: draft };
|
|
959
|
+
const fixed = this.fix(draft, issues);
|
|
960
|
+
return { draft, issues, fixed };
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
regenerateForQuality(draft, qualityScore) {
|
|
964
|
+
const issues = this.critique(draft);
|
|
965
|
+
issues.push(`Quality score: ${qualityScore}/10 - needs improvement`);
|
|
966
|
+
const fixed = this.fix(draft, issues);
|
|
967
|
+
return { draft, issues, fixed, qualityFeedback: true };
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
class DomainMemory {
|
|
972
|
+
constructor() {
|
|
973
|
+
this.memory = { user_patterns: [], known_errors: [], project_state: {}, user_preferences: [] };
|
|
974
|
+
this.load();
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
load() {
|
|
978
|
+
if (existsSync(MEMORY_FILE)) {
|
|
979
|
+
try {
|
|
980
|
+
this.memory = JSON.parse(readFileSync(MEMORY_FILE, 'utf-8'));
|
|
981
|
+
} catch (e) {
|
|
982
|
+
this.memory = { user_patterns: [], known_errors: [], project_state: {}, user_preferences: [] };
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
save() {
|
|
988
|
+
const dir = join(process.env.HOME, '.qwen');
|
|
989
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
990
|
+
writeFileSync(MEMORY_FILE, JSON.stringify(this.memory, null, 2));
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
addPattern(pattern) {
|
|
994
|
+
if (!this.memory.user_patterns.includes(pattern)) {
|
|
995
|
+
this.memory.user_patterns.push(pattern);
|
|
996
|
+
this.save();
|
|
997
|
+
sessionStats.patternsLearned++;
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
addError(error, fix) {
|
|
1002
|
+
this.memory.known_errors.push({ error, fix, timestamp: Date.now() });
|
|
1003
|
+
if (this.memory.known_errors.length > 20) this.memory.known_errors.shift();
|
|
1004
|
+
this.save();
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
updateProjectState(key, value) {
|
|
1008
|
+
this.memory.project_state[key] = value;
|
|
1009
|
+
this.save();
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
addPreference(pref) {
|
|
1013
|
+
if (!this.memory.user_preferences.includes(pref)) {
|
|
1014
|
+
this.memory.user_preferences.push(pref);
|
|
1015
|
+
this.save();
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
onResponseComplete() {
|
|
1020
|
+
this.save();
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
get() {
|
|
1024
|
+
return this.memory;
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
clear() {
|
|
1028
|
+
this.memory = { user_patterns: [], known_errors: [], project_state: {}, user_preferences: [] };
|
|
1029
|
+
this.save();
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
class IntentLadder {
|
|
1034
|
+
classify(query) {
|
|
1035
|
+
const surface = query;
|
|
1036
|
+
let real = surface;
|
|
1037
|
+
if (surface.includes('how to')) real = 'User needs step-by-step instructions';
|
|
1038
|
+
else if (surface.includes('why')) real = 'User needs root cause explanation';
|
|
1039
|
+
else if (surface.includes('fix') || surface.includes('error')) real = 'User needs working solution';
|
|
1040
|
+
else if (surface.includes('best') || surface.includes('recommended')) real = 'User needs expert recommendation';
|
|
1041
|
+
else if (surface.includes('write') || surface.includes('create') || surface.includes('build')) real = 'User needs code implementation';
|
|
1042
|
+
else if (surface.includes('debug') || surface.includes('troubleshoot')) real = 'User needs debugging help';
|
|
1043
|
+
else real = 'User needs assistance';
|
|
1044
|
+
|
|
1045
|
+
let deep = real;
|
|
1046
|
+
if (surface.includes('fix') || surface.includes('error') || surface.includes('broken')) deep = 'Build stable production code that won\'t break again';
|
|
1047
|
+
else if (surface.includes('write') || surface.includes('create') || surface.includes('build') || surface.includes('function')) deep = 'Ship working feature fast without technical debt';
|
|
1048
|
+
else if (surface.includes('debug') || surface.includes('troubleshoot')) deep = 'Understand root cause, not just apply quick fix';
|
|
1049
|
+
else if (surface.includes('how to') || surface.includes('learn')) deep = 'Become self-sufficient, not dependent on AI';
|
|
1050
|
+
else if (surface.includes('best') || surface.includes('recommended') || surface.includes('optimal')) deep = 'Make informed long-term architectural decision';
|
|
1051
|
+
else if (surface.includes('test') || surface.includes('validate')) deep = 'Ensure code reliability before deployment';
|
|
1052
|
+
else deep = 'Complete request successfully with minimal friction';
|
|
1053
|
+
|
|
1054
|
+
if (!sessionStats.intentCounts[deep]) {
|
|
1055
|
+
sessionStats.intentCounts[deep] = 0;
|
|
1056
|
+
}
|
|
1057
|
+
sessionStats.intentCounts[deep]++;
|
|
1058
|
+
|
|
1059
|
+
return { surface, real, deep };
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
class TermuxSpecialist {
|
|
1064
|
+
apply(response) {
|
|
1065
|
+
let fixed = response;
|
|
1066
|
+
fixed = fixed.replace(/sudo\s+/g, '');
|
|
1067
|
+
fixed = fixed.replace(/apt-get\s+install/g, 'pkg install');
|
|
1068
|
+
fixed = fixed.replace(/apt\s+install/g, 'pkg install');
|
|
1069
|
+
fixed = fixed.replace(/\/usr\/bin\//g, `${TERMUX.PREFIX}/bin/`);
|
|
1070
|
+
fixed = fixed.replace(/\/bin\//g, `${TERMUX.PREFIX}/bin/`);
|
|
1071
|
+
fixed = fixed.replace(/systemctl\s+/g, '# systemctl not available on Termux\n# ');
|
|
1072
|
+
return fixed;
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
class ParallelTaskSplitter {
|
|
1077
|
+
split(input) {
|
|
1078
|
+
const separators = [';', '&&', '||', '\n'];
|
|
1079
|
+
for (const sep of separators) {
|
|
1080
|
+
if (input.includes(sep)) {
|
|
1081
|
+
return input.split(sep).map(s => s.trim()).filter(s => s.length > 0);
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
return [input];
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
async execute(tasks, executor) {
|
|
1088
|
+
const results = [];
|
|
1089
|
+
for (const task of tasks) {
|
|
1090
|
+
results.push(await executor(task));
|
|
1091
|
+
}
|
|
1092
|
+
return results;
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
class CodeQualityGate {
|
|
1097
|
+
check(code) {
|
|
1098
|
+
const issues = [];
|
|
1099
|
+
if (code.includes('sudo')) issues.push('Uses sudo');
|
|
1100
|
+
if (code.includes('/usr/bin/') || code.includes('/bin/')) issues.push('Hardcoded paths');
|
|
1101
|
+
if (!code.includes('try') && !code.includes('if') && code.includes('function')) issues.push('No error handling');
|
|
1102
|
+
return { valid: issues.length === 0, issues };
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
class ActiveContextEngine {
|
|
1107
|
+
constructor() {
|
|
1108
|
+
this.context = { goal: '', decisions: [], blockers: [], last_action: '', turn_count: 0 };
|
|
1109
|
+
this.load();
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
load() {
|
|
1113
|
+
if (existsSync(CONTEXT_FILE)) {
|
|
1114
|
+
try {
|
|
1115
|
+
this.context = JSON.parse(readFileSync(CONTEXT_FILE, 'utf-8'));
|
|
1116
|
+
} catch (e) {
|
|
1117
|
+
this.context = { goal: '', decisions: [], blockers: [], last_action: '', turn_count: 0 };
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
save() {
|
|
1123
|
+
writeFileSync(CONTEXT_FILE, JSON.stringify(this.context, null, 2));
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
update(goal, decision, blocker, action) {
|
|
1127
|
+
if (goal) this.context.goal = goal;
|
|
1128
|
+
if (decision) this.context.decisions.push(decision);
|
|
1129
|
+
if (blocker && !this.context.blockers.includes(blocker)) this.context.blockers.push(blocker);
|
|
1130
|
+
if (action) this.context.last_action = action;
|
|
1131
|
+
this.context.turn_count++;
|
|
1132
|
+
this.compress();
|
|
1133
|
+
this.save();
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
compress() {
|
|
1137
|
+
const maxLen = 1000;
|
|
1138
|
+
const json = JSON.stringify(this.context);
|
|
1139
|
+
if (json.length > maxLen) {
|
|
1140
|
+
this.context.decisions = this.context.decisions.slice(-3);
|
|
1141
|
+
this.context.blockers = this.context.blockers.slice(-3);
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
get() {
|
|
1146
|
+
return this.context;
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
format() {
|
|
1150
|
+
const c = this.context;
|
|
1151
|
+
return `\nACTIVE_CONTEXT:\n goal: ${c.goal || 'not set'}\n decisions: ${c.decisions.length > 0 ? c.decisions.join(', ') : 'none'}\n blockers: ${c.blockers.length > 0 ? c.blockers.join(', ') : 'none'}\n last_action: ${c.last_action || 'none'}\n turn: ${c.turn_count}`;
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
clear() {
|
|
1155
|
+
this.context = { goal: '', decisions: [], blockers: [], last_action: '', turn_count: 0 };
|
|
1156
|
+
if (existsSync(CONTEXT_FILE)) writeFileSync(CONTEXT_FILE, JSON.stringify(this.context, null, 2));
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
// ============================================
|
|
1161
|
+
// UNIFIED PIPELINE v15.0.0
|
|
1162
|
+
// ============================================
|
|
1163
|
+
|
|
1164
|
+
class UnifiedPipeline {
|
|
1165
|
+
constructor() {
|
|
1166
|
+
// v14 preserved
|
|
1167
|
+
this.coldStart = new ColdStartIntelligence();
|
|
1168
|
+
this.domainMemory = new DomainMemory();
|
|
1169
|
+
this.patternPreventer = new PatternPreventer(this.domainMemory);
|
|
1170
|
+
this.intentLadder = new IntentLadder();
|
|
1171
|
+
this.confidenceGate = new ConfidenceGating();
|
|
1172
|
+
this.contextEngine = new ActiveContextEngine();
|
|
1173
|
+
this.smartContext = new SmartContextCompression(this.contextEngine);
|
|
1174
|
+
this.selfCritique = new SelfCritiqueLoop();
|
|
1175
|
+
this.codeQualityGate = new CodeQualityGate();
|
|
1176
|
+
this.autoRunLoop = new AutoRunLoop();
|
|
1177
|
+
this.termuxSpecialist = new TermuxSpecialist();
|
|
1178
|
+
this.parallelSplitter = new ParallelTaskSplitter();
|
|
1179
|
+
this.qualityScorer = new ResponseQualityScorer();
|
|
1180
|
+
this.qualityBlocker = new QualityBlocker(5);
|
|
1181
|
+
this.sessionSummary = new SessionSummary();
|
|
1182
|
+
|
|
1183
|
+
// v15 NEW SYSTEMS
|
|
1184
|
+
this.compoundLearner = new CompoundLearner();
|
|
1185
|
+
this.errorFingerprinter = new ErrorFingerprinter(this.domainMemory);
|
|
1186
|
+
this.trendAnalyzer = new TrendAnalyzer();
|
|
1187
|
+
this.termuxInstaller = new TermuxInstaller();
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
async process(userInput) {
|
|
1191
|
+
// v14 Cold Start
|
|
1192
|
+
if (sessionStats.queries === 0) {
|
|
1193
|
+
console.log(this.coldStart.showWelcome());
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
// v15 NEW: Compound Learner session header
|
|
1197
|
+
this.compoundLearner.showSessionHeader();
|
|
1198
|
+
|
|
1199
|
+
console.log('\n❄️ ICE v15.0 - Compounding Intelligence\n');
|
|
1200
|
+
console.log('='.repeat(60));
|
|
1201
|
+
|
|
1202
|
+
// Step 0: Pattern Prevention (v14 verified)
|
|
1203
|
+
console.log('🛡️ Step 0: PatternPreventer');
|
|
1204
|
+
const patternResult = this.patternPreventer.preventErrors(userInput);
|
|
1205
|
+
if (patternResult.warnings.length > 0) {
|
|
1206
|
+
console.log(' ' + patternResult.warnings.join('\n '));
|
|
1207
|
+
} else {
|
|
1208
|
+
console.log(' No patterns matched - proceeding normally');
|
|
1209
|
+
}
|
|
1210
|
+
const enhancedInput = patternResult.enhancedQuery;
|
|
1211
|
+
console.log();
|
|
1212
|
+
|
|
1213
|
+
// v15 NEW: Error Fingerprinting
|
|
1214
|
+
console.log('🔍 Step 0.5: ErrorFingerprinter');
|
|
1215
|
+
const fingerprintResult = this.errorFingerprinter.check(userInput);
|
|
1216
|
+
if (fingerprintResult.known) {
|
|
1217
|
+
console.log(` ✅ Known error detected. Applying fix: ${fingerprintResult.fix}\n`);
|
|
1218
|
+
sessionStats.errorsFixed++;
|
|
1219
|
+
} else {
|
|
1220
|
+
console.log(' No known error fingerprint match\n');
|
|
1221
|
+
}
|
|
1222
|
+
|
|
1223
|
+
// Step 1: Intent Analysis
|
|
1224
|
+
console.log('🪜 Step 1: Intent Ladder');
|
|
1225
|
+
const intent = this.intentLadder.classify(enhancedInput);
|
|
1226
|
+
console.log(` SURFACE: "${intent.surface}"`);
|
|
1227
|
+
console.log(` REAL: ${intent.real}`);
|
|
1228
|
+
console.log(` DEEP: ${intent.deep}\n`);
|
|
1229
|
+
|
|
1230
|
+
// Step 2: Confidence Assessment
|
|
1231
|
+
console.log('🎯 Step 2: Confidence Gating');
|
|
1232
|
+
const confidence = this.confidenceGate.assess(enhancedInput, { goal: intent.deep });
|
|
1233
|
+
console.log(` Confidence: ${confidence.confidence}%`);
|
|
1234
|
+
console.log(` Level: ${confidence.level}`);
|
|
1235
|
+
console.log(` Thresholds: CERTAIN≥${this.confidenceGate.thresholds.CERTAIN.min}, LIKELY≥${this.confidenceGate.thresholds.LIKELY.min}\n`);
|
|
1236
|
+
|
|
1237
|
+
// Step 3: Smart Context
|
|
1238
|
+
console.log('📋 Step 3: Smart Context Compression');
|
|
1239
|
+
this.contextEngine.update(intent.deep, null, null, enhancedInput);
|
|
1240
|
+
this.smartContext.addTurn({ role: 'user', content: enhancedInput });
|
|
1241
|
+
const contextBlock = this.smartContext.getCompressed();
|
|
1242
|
+
console.log(` Context turns: ${this.smartContext.turnHistory.length}`);
|
|
1243
|
+
console.log(` Token estimate: ~${Math.ceil(contextBlock.length / 4)}\n`);
|
|
1244
|
+
|
|
1245
|
+
// Step 4: Generate response
|
|
1246
|
+
console.log('✏️ Step 4: Generate Response');
|
|
1247
|
+
let response = this.generateResponse(enhancedInput, intent);
|
|
1248
|
+
console.log(' Response generated\n');
|
|
1249
|
+
|
|
1250
|
+
// Step 5: Self-Critique
|
|
1251
|
+
console.log('🔍 Step 5: Self-Critique Loop (7 questions)');
|
|
1252
|
+
const critique = this.selfCritique.process(response);
|
|
1253
|
+
if (critique.issues.length > 0) {
|
|
1254
|
+
console.log(` Found ${critique.issues.length} issues:`);
|
|
1255
|
+
critique.issues.forEach(i => console.log(` - ${i}`));
|
|
1256
|
+
response = critique.fixed;
|
|
1257
|
+
console.log(' ✅ Fixed\n');
|
|
1258
|
+
} else {
|
|
1259
|
+
console.log(' ✅ No issues\n');
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
// Step 6: Code Quality Gate
|
|
1263
|
+
let codeResult = null;
|
|
1264
|
+
if (response.includes('function') || response.includes('const ') || response.includes('import ')) {
|
|
1265
|
+
console.log('🔒 Step 6: Code Quality Gate');
|
|
1266
|
+
const quality = this.codeQualityGate.check(response);
|
|
1267
|
+
if (!quality.valid) {
|
|
1268
|
+
console.log(` Found ${quality.issues.length} issues:`);
|
|
1269
|
+
quality.issues.forEach(i => console.log(` - ${i}`));
|
|
1270
|
+
response = this.termuxSpecialist.apply(response);
|
|
1271
|
+
console.log(' ✅ Applied Termux fixes\n');
|
|
1272
|
+
} else {
|
|
1273
|
+
console.log(' ✅ Code passes quality gate\n');
|
|
1274
|
+
}
|
|
1275
|
+
}
|
|
1276
|
+
|
|
1277
|
+
// Step 7: Auto-Run Loop
|
|
1278
|
+
if (response.includes('```')) {
|
|
1279
|
+
console.log('⚡ Step 7: Auto-Run Loop');
|
|
1280
|
+
codeResult = this.autoRunLoop.exec(response);
|
|
1281
|
+
if (!codeResult.success) {
|
|
1282
|
+
console.log(` ⚠️ ${codeResult.warning}`);
|
|
1283
|
+
response += `\n\n${codeResult.warning}`;
|
|
1284
|
+
} else if (codeResult.hasWarnings) {
|
|
1285
|
+
console.log(' ✅ Code executed with warnings\n');
|
|
1286
|
+
} else if (codeResult.attempt) {
|
|
1287
|
+
console.log(` ✅ Code executed (attempt ${codeResult.attempt})\n`);
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
// v15 NEW: TermuxInstaller - check for missing packages
|
|
1292
|
+
console.log('📦 Step 7.5: TermuxInstaller');
|
|
1293
|
+
if (response.includes('```')) {
|
|
1294
|
+
const codeBlocks = response.match(/```[\s\S]*?```/g);
|
|
1295
|
+
if (codeBlocks) {
|
|
1296
|
+
for (const block of codeBlocks) {
|
|
1297
|
+
await this.termuxInstaller.ensurePackages(block);
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
console.log(' Package check complete\n');
|
|
1302
|
+
|
|
1303
|
+
// Step 8: Domain Memory
|
|
1304
|
+
console.log('💾 Step 8: Domain Memory');
|
|
1305
|
+
this.domainMemory.addPattern(intent.real);
|
|
1306
|
+
this.domainMemory.onResponseComplete();
|
|
1307
|
+
console.log(' ✅ Pattern learned and saved\n');
|
|
1308
|
+
|
|
1309
|
+
// Step 9: Quality Scoring
|
|
1310
|
+
console.log('📊 Step 9: Response Quality Scorer');
|
|
1311
|
+
let qualityScore = this.qualityScorer.score(response, intent, critique, codeResult);
|
|
1312
|
+
const avgQuality = this.qualityScorer.getAverage();
|
|
1313
|
+
const trend = this.qualityScorer.getTrend();
|
|
1314
|
+
console.log(` Score: ${qualityScore}/10`);
|
|
1315
|
+
console.log(` Average: ${avgQuality || 'N/A'}/10 (${trend})`);
|
|
1316
|
+
|
|
1317
|
+
// v15 NEW: Trend Analyzer
|
|
1318
|
+
console.log('\n📈 Step 9.5: TrendAnalyzer');
|
|
1319
|
+
this.trendAnalyzer.update(qualityScore);
|
|
1320
|
+
const trendStatus = this.trendAnalyzer.getTrend();
|
|
1321
|
+
console.log(` Trend status: ${trendStatus}\n`);
|
|
1322
|
+
|
|
1323
|
+
// v14 Quality Blocker
|
|
1324
|
+
if (this.qualityBlocker.shouldBlock(qualityScore)) {
|
|
1325
|
+
console.log(`\n⚠️ Quality Blocker activated`);
|
|
1326
|
+
console.log(` Score ${qualityScore}/10 is below threshold (${this.qualityBlocker.minScore}/10)`);
|
|
1327
|
+
console.log(' Regenerating with quality feedback...\n');
|
|
1328
|
+
|
|
1329
|
+
const regenCritique = this.selfCritique.regenerateForQuality(response, qualityScore);
|
|
1330
|
+
response = regenCritique.fixed;
|
|
1331
|
+
console.log(' ✅ Regenerated response\n');
|
|
1332
|
+
|
|
1333
|
+
qualityScore = this.qualityScorer.score(response, intent, regenCritique, codeResult);
|
|
1334
|
+
console.log(` New score: ${qualityScore}/10`);
|
|
1335
|
+
|
|
1336
|
+
if (this.qualityBlocker.shouldBlock(qualityScore)) {
|
|
1337
|
+
console.log(`\n⚠️ WARNING: Response still scores ${qualityScore}/10 after regeneration`);
|
|
1338
|
+
response += `\n\n⚠️ Note: This response scored ${qualityScore}/10 on quality metrics. Please review carefully.`;
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
console.log();
|
|
1342
|
+
|
|
1343
|
+
// Record confidence outcome
|
|
1344
|
+
const wasAccurate = critique.issues.length === 0;
|
|
1345
|
+
this.confidenceGate.recordOutcome(confidence.confidence, wasAccurate);
|
|
1346
|
+
|
|
1347
|
+
// Track session stats
|
|
1348
|
+
sessionStats.queries++;
|
|
1349
|
+
if (patternResult.preAppliedFixes.length > 0) {
|
|
1350
|
+
sessionStats.errorsFixed += patternResult.preAppliedFixes.length;
|
|
1351
|
+
}
|
|
1352
|
+
if (fingerprintResult.known) {
|
|
1353
|
+
sessionStats.errorsFixed++;
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
console.log('='.repeat(60));
|
|
1357
|
+
console.log('\n📤 Final Response:\n');
|
|
1358
|
+
return response;
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
generateResponse(input, intent) {
|
|
1362
|
+
if (input.includes('sudo')) {
|
|
1363
|
+
return `To fix this on Termux, use pkg instead:\n\`\`\`bash\npkg install python\n\`\`\`\nNote: sudo is not available on Termux.`;
|
|
1364
|
+
}
|
|
1365
|
+
if (input.includes('function')) {
|
|
1366
|
+
return `Here's the function:\n\`\`\`javascript\nfunction example() {\n return 'Hello from Termux';\n}\n\`\`\`\nThis follows Termux best practices.`;
|
|
1367
|
+
}
|
|
1368
|
+
return `I understand you want to ${intent.real}. The deep goal is: ${intent.deep}.\n\nHere's how to proceed...`;
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
printSessionSummary() {
|
|
1372
|
+
const avgQuality = this.qualityScorer.getAverage();
|
|
1373
|
+
const topIntent = Object.entries(sessionStats.intentCounts)
|
|
1374
|
+
.sort((a, b) => b[1] - a[1])[0]?.[0] || 'none';
|
|
1375
|
+
|
|
1376
|
+
const stats = {
|
|
1377
|
+
queries: sessionStats.queries,
|
|
1378
|
+
avgQuality: avgQuality || '0',
|
|
1379
|
+
patternsLearned: sessionStats.patternsLearned,
|
|
1380
|
+
errorsFixed: sessionStats.errorsFixed,
|
|
1381
|
+
topIntent
|
|
1382
|
+
};
|
|
1383
|
+
|
|
1384
|
+
// v15: Archive to sessions directory
|
|
1385
|
+
this.compoundLearner.saveSessionSummary(stats);
|
|
1386
|
+
|
|
1387
|
+
this.sessionSummary.printAndSave(stats);
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
|
|
1391
|
+
// ============================================
|
|
1392
|
+
// CLI
|
|
1393
|
+
// ============================================
|
|
1394
|
+
|
|
1395
|
+
// Only run CLI if this is the main module
|
|
1396
|
+
if (require.main !== module) { module.exports = { UnifiedPipeline, CompoundLearner, ErrorFingerprinter, TrendAnalyzer, TermuxInstaller }; return; }
|
|
1397
|
+
|
|
1398
|
+
const args = process.argv.slice(2);
|
|
1399
|
+
const command = args[0];
|
|
1400
|
+
const input = args.slice(1).join(' ');
|
|
1401
|
+
|
|
1402
|
+
function handleExit(pipeline) {
|
|
1403
|
+
console.log('\n👋 Saving session summary...\n');
|
|
1404
|
+
pipeline.printSessionSummary();
|
|
1405
|
+
process.exit(0);
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
process.on('SIGINT', () => {
|
|
1409
|
+
if (currentPipeline) {
|
|
1410
|
+
handleExit(currentPipeline);
|
|
1411
|
+
} else {
|
|
1412
|
+
process.exit(0);
|
|
1413
|
+
}
|
|
1414
|
+
});
|
|
1415
|
+
|
|
1416
|
+
if (!command) {
|
|
1417
|
+
console.log('❄️ ICE v15.0 - Compounding Intelligence\n');
|
|
1418
|
+
console.log('NEW SYSTEMS (v15):');
|
|
1419
|
+
console.log(' 1. CompoundLearner - cross-session learning');
|
|
1420
|
+
console.log(' 2. ErrorFingerprinter - deduplicates errors');
|
|
1421
|
+
console.log(' 3. TrendAnalyzer - tracks quality trends');
|
|
1422
|
+
console.log(' 4. TermuxInstaller - auto-installs packages\n');
|
|
1423
|
+
console.log('PRESERVED (v14 verified):');
|
|
1424
|
+
console.log(' - ColdStartIntelligence ✅');
|
|
1425
|
+
console.log(' - PatternPreventer ✅');
|
|
1426
|
+
console.log(' - QualityBlocker ✅');
|
|
1427
|
+
console.log(' - SessionSummary ✅\n');
|
|
1428
|
+
console.log('PIPELINE:');
|
|
1429
|
+
console.log(' userInput → ColdStartIntelligence → CompoundLearner → PatternPreventer');
|
|
1430
|
+
console.log(' → ErrorFingerprinter → IntentLadder → ConfidenceGating');
|
|
1431
|
+
console.log(' → SmartContext → Generate → SelfCritique(7)');
|
|
1432
|
+
console.log(' → CodeQualityGate → AutoRunLoop → TermuxInstaller');
|
|
1433
|
+
console.log(' → QualityBlocker → DomainMemory → QualityScorer');
|
|
1434
|
+
console.log(' → TrendAnalyzer → SessionSummary → response\n');
|
|
1435
|
+
console.log('Usage:');
|
|
1436
|
+
console.log(' ice-v15 "your message" # Run unified pipeline');
|
|
1437
|
+
console.log(' ice-v15 parallel [task] # Parallel task splitter');
|
|
1438
|
+
console.log(' ice-v15 init # Initialize config files');
|
|
1439
|
+
console.log(' ice-v15 exit # Show session summary and exit\n');
|
|
1440
|
+
console.log('Termux:');
|
|
1441
|
+
console.log(' PREFIX=' + TERMUX.PREFIX);
|
|
1442
|
+
console.log(' HOME=' + TERMUX.HOME);
|
|
1443
|
+
console.log(' No sudo | pkg manager | ARM64 only\n');
|
|
1444
|
+
process.exit(0);
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
if (command === 'init') {
|
|
1448
|
+
const dir = join(process.env.HOME, '.qwen');
|
|
1449
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
1450
|
+
if (!existsSync(SESSIONS_DIR)) mkdirSync(SESSIONS_DIR, { recursive: true });
|
|
1451
|
+
|
|
1452
|
+
const files = {
|
|
1453
|
+
[SESSION_FILE]: { timestamp: Date.now(), conversation: [] },
|
|
1454
|
+
[CONTEXT_FILE]: { goal: '', decisions: [], blockers: [], last_action: '', turn_count: 0 },
|
|
1455
|
+
[MEMORY_FILE]: { user_patterns: [], known_errors: [], project_state: {}, user_preferences: [] },
|
|
1456
|
+
[CONFIDENCE_FILE]: [],
|
|
1457
|
+
[QUALITY_FILE]: [],
|
|
1458
|
+
[SESSION_SUMMARY_FILE]: { total_queries: 0, avg_quality: 0 },
|
|
1459
|
+
[TREND_FILE]: { trends: [], alerts: [] }
|
|
1460
|
+
};
|
|
1461
|
+
|
|
1462
|
+
Object.entries(files).forEach(([file, data]) => {
|
|
1463
|
+
if (!existsSync(file)) {
|
|
1464
|
+
writeFileSync(file, JSON.stringify(data, null, 2));
|
|
1465
|
+
console.log(`✅ Created ${file}`);
|
|
1466
|
+
}
|
|
1467
|
+
});
|
|
1468
|
+
|
|
1469
|
+
console.log('\n✅ ICE v15.0 initialized\n');
|
|
1470
|
+
process.exit(0);
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
if (command === 'exit') {
|
|
1474
|
+
const pipeline = new UnifiedPipeline();
|
|
1475
|
+
handleExit(pipeline);
|
|
1476
|
+
process.exit(0);
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
if (command === 'parallel') {
|
|
1480
|
+
const pipeline = new UnifiedPipeline();
|
|
1481
|
+
const tasks = pipeline.parallelSplitter.split(input);
|
|
1482
|
+
console.log(`🔀 Split into ${tasks.length} parallel tasks:\n`);
|
|
1483
|
+
tasks.forEach((t, i) => console.log(` ${i + 1}. ${t}`));
|
|
1484
|
+
console.log();
|
|
1485
|
+
Promise.all(tasks.map(task => pipeline.process(task))).then(() => {
|
|
1486
|
+
handleExit(pipeline);
|
|
1487
|
+
process.exit(0);
|
|
1488
|
+
});
|
|
1489
|
+
process.exit(0);
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
let currentPipeline = null;
|
|
1493
|
+
const pipeline = new UnifiedPipeline();
|
|
1494
|
+
currentPipeline = pipeline;
|
|
1495
|
+
pipeline.process(command + ' ' + input).then(response => {
|
|
1496
|
+
console.log(response);
|
|
1497
|
+
});
|
|
1498
|
+
|
|
1499
|
+
// Export for use as module
|
|
1500
|
+
module.exports = { UnifiedPipeline, CompoundLearner, ErrorFingerprinter, TrendAnalyzer, TermuxInstaller };
|
|
1501
|
+
|