@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.
Files changed (69) hide show
  1. package/bin/qwen-ice +25 -5
  2. package/package.json +6 -5
  3. package/scripts/build.js +88 -0
  4. package/scripts/build_package.js +37 -0
  5. package/scripts/build_sandbox.js +174 -0
  6. package/scripts/build_vscode_companion.js +30 -0
  7. package/scripts/check-build-status.js +148 -0
  8. package/scripts/check-i18n.ts +462 -0
  9. package/scripts/check-lockfile.js +74 -0
  10. package/scripts/clean.js +59 -0
  11. package/scripts/copy_bundle_assets.js +90 -0
  12. package/scripts/copy_files.js +86 -0
  13. package/scripts/create_alias.sh +39 -0
  14. package/scripts/dev.js +109 -0
  15. package/scripts/esbuild-shims.js +29 -0
  16. package/scripts/generate-git-commit-info.js +71 -0
  17. package/scripts/generate-settings-schema.ts +146 -0
  18. package/scripts/get-release-version.js +411 -0
  19. package/scripts/ice-mobile.js +5 -0
  20. package/scripts/ice-session.js +6 -0
  21. package/scripts/ice-skills.js +31 -0
  22. package/scripts/ice-teams.js +34 -0
  23. package/scripts/ice-v10.js +276 -0
  24. package/scripts/ice-v11.js +276 -0
  25. package/scripts/ice-v12.js +568 -0
  26. package/scripts/ice-v13.js +824 -0
  27. package/scripts/ice-v14.js +1059 -0
  28. package/scripts/ice-v15.js +1501 -0
  29. package/scripts/ice-v2.js +26 -0
  30. package/scripts/ice-v3-core.js +261 -0
  31. package/scripts/ice-v3.js +46 -0
  32. package/scripts/ice-v4.js +657 -0
  33. package/scripts/ice-v5.js +371 -0
  34. package/scripts/ice-v6.js +305 -0
  35. package/scripts/ice-v7.js +291 -0
  36. package/scripts/ice-v8.js +550 -0
  37. package/scripts/ice-v9.js +546 -0
  38. package/scripts/install-ice.sh +70 -0
  39. package/scripts/install.sh +136 -0
  40. package/scripts/installation/INSTALLATION_GUIDE.md +250 -0
  41. package/scripts/installation/install-qwen-with-source.bat +302 -0
  42. package/scripts/installation/install-qwen-with-source.sh +570 -0
  43. package/scripts/lint.js +205 -0
  44. package/scripts/local_telemetry.js +219 -0
  45. package/scripts/postinstall.cjs +235 -0
  46. package/scripts/pre-commit.js +22 -0
  47. package/scripts/prepare-package.js +186 -0
  48. package/scripts/prepare-termux.cjs +26 -0
  49. package/scripts/sandbox_command.js +128 -0
  50. package/scripts/start.js +86 -0
  51. package/scripts/telemetry.js +85 -0
  52. package/scripts/telemetry_gcp.js +188 -0
  53. package/scripts/telemetry_utils.js +450 -0
  54. package/scripts/test-v10.js +18 -0
  55. package/scripts/test-v11.js +18 -0
  56. package/scripts/test-v12.js +18 -0
  57. package/scripts/test-v13.js +18 -0
  58. package/scripts/test-v14.js +18 -0
  59. package/scripts/test-v3.js +47 -0
  60. package/scripts/test-v4.js +47 -0
  61. package/scripts/test-v6.js +59 -0
  62. package/scripts/test-v8.js +42 -0
  63. package/scripts/test-v9.js +18 -0
  64. package/scripts/test-windows-paths.js +51 -0
  65. package/scripts/tests/get-release-version.test.js +186 -0
  66. package/scripts/tests/test-setup.ts +12 -0
  67. package/scripts/tests/vitest.config.ts +26 -0
  68. package/scripts/unused-keys-only-in-locales.json +62 -0
  69. 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
+