@anh3d0nic/ice 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +35 -0
- package/src/agent-crews.ts +189 -0
- package/src/cli.ts +96 -0
- package/src/d20-learner.ts +161 -0
- package/src/engine.ts +219 -0
- package/src/index.ts +40 -0
- package/src/intent-decoder.ts +200 -0
- package/src/multi-provider-client.ts +200 -0
- package/src/reasoning/chain-of-thought.ts +166 -0
- package/src/reasoning/index.ts +16 -0
- package/src/reasoning/self-reflection.ts +160 -0
- package/src/reasoning/socratic-reviewer.ts +167 -0
- package/src/reasoning/tree-of-thoughts.ts +212 -0
- package/src/reasoning/types.ts +40 -0
- package/src/status-cli.ts +77 -0
- package/src/types.ts +81 -0
- package/tsconfig.json +25 -0
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@anh3d0nic/ice",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Persistent AI Brain for Qwen Code Termux",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"types": "src/index.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"ice": "src/cli.ts",
|
|
10
|
+
"ice-status": "src/status-cli.ts"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"ice": "tsx src/cli.ts",
|
|
14
|
+
"status": "tsx src/status-cli.ts"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"ice",
|
|
18
|
+
"termux",
|
|
19
|
+
"qwen",
|
|
20
|
+
"ai",
|
|
21
|
+
"code-assistant",
|
|
22
|
+
"android",
|
|
23
|
+
"groq",
|
|
24
|
+
"gemini"
|
|
25
|
+
],
|
|
26
|
+
"author": "anh3d0nic",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"axios": "^1.6.0",
|
|
30
|
+
"chalk": "^5.3.0",
|
|
31
|
+
"commander": "^11.1.0",
|
|
32
|
+
"dotenv": "^16.3.1",
|
|
33
|
+
"ora": "^7.0.1"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ICE v4.3 — Agent Crews
|
|
3
|
+
* 102 specialized agents across 5 elite crews
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export enum CrewType {
|
|
7
|
+
ALPHA = 'alpha',
|
|
8
|
+
BETA = 'beta',
|
|
9
|
+
GAMMA = 'gamma',
|
|
10
|
+
DELTA = 'delta',
|
|
11
|
+
EPSILON = 'epsilon'
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export enum AgentStatus {
|
|
15
|
+
IDLE = 'idle',
|
|
16
|
+
BUSY = 'busy',
|
|
17
|
+
ERROR = 'error'
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface Agent {
|
|
21
|
+
id: string;
|
|
22
|
+
name: string;
|
|
23
|
+
role: string;
|
|
24
|
+
specialty: string;
|
|
25
|
+
crew: CrewType;
|
|
26
|
+
status: AgentStatus;
|
|
27
|
+
tasksCompleted: number;
|
|
28
|
+
successRate: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface Crew {
|
|
32
|
+
name: string;
|
|
33
|
+
type: CrewType;
|
|
34
|
+
agents: Agent[];
|
|
35
|
+
triggerKeywords: string[];
|
|
36
|
+
description: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export class AgentCrews {
|
|
40
|
+
private crews: Map<CrewType, Crew>;
|
|
41
|
+
|
|
42
|
+
constructor() {
|
|
43
|
+
this.crews = new Map();
|
|
44
|
+
this._initializeCrews();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private _initializeCrews(): void {
|
|
48
|
+
// Alpha Crew — Frontend & Infrastructure (A01-A20)
|
|
49
|
+
this.crews.set(CrewType.ALPHA, {
|
|
50
|
+
name: 'Alpha',
|
|
51
|
+
type: CrewType.ALPHA,
|
|
52
|
+
agents: this._createAgents(CrewType.ALPHA, 20, 'Frontend', 'UI/UX, databases, APIs, deployment'),
|
|
53
|
+
triggerKeywords: ['ui', 'frontend', 'html', 'css', 'react', 'vue', 'angular', 'database', 'sql', 'api', 'deploy', 'docker', 'aws'],
|
|
54
|
+
description: 'Frontend development, UI/UX, databases, APIs, and cloud deployment'
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Beta Crew — Code Quality & Security (B01-B20)
|
|
58
|
+
this.crews.set(CrewType.BETA, {
|
|
59
|
+
name: 'Beta',
|
|
60
|
+
type: CrewType.BETA,
|
|
61
|
+
agents: this._createAgents(CrewType.BETA, 20, 'Engineering', 'Code quality, testing, security, architecture'),
|
|
62
|
+
triggerKeywords: ['code', 'refactor', 'test', 'security', 'architecture', 'review', 'optimize', 'debug'],
|
|
63
|
+
description: 'Code quality, testing, security auditing, and system architecture'
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Gamma Crew — Android & Termux (G01-G20)
|
|
67
|
+
this.crews.set(CrewType.GAMMA, {
|
|
68
|
+
name: 'Gamma',
|
|
69
|
+
type: CrewType.GAMMA,
|
|
70
|
+
agents: this._createAgents(CrewType.GAMMA, 20, 'Android', 'Termux, Android, mobile development'),
|
|
71
|
+
triggerKeywords: ['termux', 'android', 'pkg', 'apk', 'mobile', 'path', 'permissions', 'apt'],
|
|
72
|
+
description: 'Android Termux environment, package management, and mobile development'
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// Delta Crew — Orchestration & Memory (D01-D20)
|
|
76
|
+
this.crews.set(CrewType.DELTA, {
|
|
77
|
+
name: 'Delta',
|
|
78
|
+
type: CrewType.DELTA,
|
|
79
|
+
agents: this._createAgents(CrewType.DELTA, 20, 'Orchestration', 'Planning, routing, memory, learning'),
|
|
80
|
+
triggerKeywords: ['orchestrate', 'route', 'plan', 'coordinate', 'memory', 'learn', 'optimize'],
|
|
81
|
+
description: 'Task orchestration, routing, memory management, and meta-learning'
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Epsilon Crew — Tools & Infrastructure (E01-E20)
|
|
85
|
+
this.crews.set(CrewType.EPSILON, {
|
|
86
|
+
name: 'Epsilon',
|
|
87
|
+
type: CrewType.EPSILON,
|
|
88
|
+
agents: this._createAgents(CrewType.EPSILON, 20, 'Tools', 'Infrastructure, MCP, scaffolding'),
|
|
89
|
+
triggerKeywords: ['infra', 'tools', 'mcp', 'forge', 'scaffold', 'web', 'scrape', 'fetch'],
|
|
90
|
+
description: 'Infrastructure tools, MCP servers, project scaffolding, and web actions'
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
private _createAgents(crew: CrewType, count: number, role: string, specialty: string): Agent[] {
|
|
95
|
+
const agents: Agent[] = [];
|
|
96
|
+
const prefix = crew.charAt(0).toUpperCase() + crew.slice(1);
|
|
97
|
+
|
|
98
|
+
for (let i = 1; i <= count; i++) {
|
|
99
|
+
agents.push({
|
|
100
|
+
id: `${crew}-${String(i).padStart(2, '0')}`,
|
|
101
|
+
name: `Agent ${prefix}-${i}`,
|
|
102
|
+
role,
|
|
103
|
+
specialty,
|
|
104
|
+
crew,
|
|
105
|
+
status: AgentStatus.IDLE,
|
|
106
|
+
tasksCompleted: 0,
|
|
107
|
+
successRate: 1.0
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return agents;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
selectCrews(intent: string, entities: Record<string, unknown>): Crew[] {
|
|
115
|
+
const text = `${intent} ${JSON.stringify(entities)}`.toLowerCase();
|
|
116
|
+
const selected: Crew[] = [];
|
|
117
|
+
|
|
118
|
+
for (const crew of this.crews.values()) {
|
|
119
|
+
if (crew.triggerKeywords.some(kw => text.includes(kw))) {
|
|
120
|
+
selected.push(crew);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Default to Delta (orchestration) if none match
|
|
125
|
+
if (selected.length === 0) {
|
|
126
|
+
selected.push(this.crews.get(CrewType.DELTA)!);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return selected;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
getCrew(type: CrewType): Crew | undefined {
|
|
133
|
+
return this.crews.get(type);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
getAllCrews(): Crew[] {
|
|
137
|
+
return Array.from(this.crews.values());
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
getAgent(agentId: string): Agent | undefined {
|
|
141
|
+
for (const crew of this.crews.values()) {
|
|
142
|
+
const agent = crew.agents.find(a => a.id === agentId);
|
|
143
|
+
if (agent) return agent;
|
|
144
|
+
}
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
getTotalAgents(): number {
|
|
149
|
+
let total = 0;
|
|
150
|
+
for (const crew of this.crews.values()) {
|
|
151
|
+
total += crew.agents.length;
|
|
152
|
+
}
|
|
153
|
+
return total;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
getStatus(): Record<string, unknown> {
|
|
157
|
+
return {
|
|
158
|
+
crews: this.crews.size,
|
|
159
|
+
totalAgents: this.getTotalAgents(),
|
|
160
|
+
crewNames: Array.from(this.crews.values()).map(c => c.name),
|
|
161
|
+
agentCrews: Object.fromEntries(
|
|
162
|
+
Array.from(this.crews.entries()).map(([type, crew]) => [type, crew.agents.length])
|
|
163
|
+
)
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
assignTask(agentId: string): boolean {
|
|
168
|
+
const agent = this.getAgent(agentId);
|
|
169
|
+
if (!agent) return false;
|
|
170
|
+
|
|
171
|
+
agent.status = AgentStatus.BUSY;
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
completeTask(agentId: string, success: boolean): boolean {
|
|
176
|
+
const agent = this.getAgent(agentId);
|
|
177
|
+
if (!agent) return false;
|
|
178
|
+
|
|
179
|
+
agent.status = AgentStatus.IDLE;
|
|
180
|
+
agent.tasksCompleted++;
|
|
181
|
+
|
|
182
|
+
// Update success rate
|
|
183
|
+
const totalTasks = agent.tasksCompleted;
|
|
184
|
+
const successfulTasks = success ? totalTasks : totalTasks - 1;
|
|
185
|
+
agent.successRate = successfulTasks / totalTasks;
|
|
186
|
+
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
}
|
package/src/cli.ts
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ICE v4.3 — CLI Command
|
|
4
|
+
* Main interactive CLI for ICE
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { ICEEngine } from './engine.js';
|
|
8
|
+
import chalk from 'chalk';
|
|
9
|
+
import { Command } from 'commander';
|
|
10
|
+
import ora from 'ora';
|
|
11
|
+
|
|
12
|
+
const program = new Command();
|
|
13
|
+
|
|
14
|
+
program
|
|
15
|
+
.name('ice')
|
|
16
|
+
.description('✦ ICE v4.3 — Interactive AI Assistant')
|
|
17
|
+
.version('4.3.0-termux')
|
|
18
|
+
.option('-v, --verbose', 'Enable verbose output')
|
|
19
|
+
.option('-j, --json', 'Output in JSON format')
|
|
20
|
+
.action(async (options) => {
|
|
21
|
+
const engine = new ICEEngine();
|
|
22
|
+
|
|
23
|
+
console.log(chalk.blue.bold('\n✦ ICE v4.3 — Qwen Code Termux'));
|
|
24
|
+
console.log(chalk.blue('by @anh3d0nic'));
|
|
25
|
+
console.log(chalk.gray('Type "exit" to quit\n'));
|
|
26
|
+
|
|
27
|
+
const status = engine.getStatus();
|
|
28
|
+
console.log(chalk.green('✓'), `Version: ${status.version}`);
|
|
29
|
+
console.log(chalk.green('✓'), `User: ${status.user}`);
|
|
30
|
+
console.log(chalk.green('✓'), `Providers: ${(status.providers as string[]).join(', ') || 'None (fallback mode)'}`);
|
|
31
|
+
console.log(chalk.green('✓'), `Crews: ${(status.crews as Record<string, unknown>).crews} (${(status.crews as Record<string, unknown>).totalAgents} agents)`);
|
|
32
|
+
console.log();
|
|
33
|
+
|
|
34
|
+
const readline = await import('readline');
|
|
35
|
+
const rl = readline.createInterface({
|
|
36
|
+
input: process.stdin,
|
|
37
|
+
output: process.stdout
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const prompt = () => {
|
|
41
|
+
rl.question(chalk.cyan.bold('You: '), async (message) => {
|
|
42
|
+
if (message.toLowerCase() === 'exit' || message.toLowerCase() === 'quit') {
|
|
43
|
+
console.log(chalk.blue('\nGoodbye!\n'));
|
|
44
|
+
rl.close();
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (message.toLowerCase() === 'status') {
|
|
49
|
+
console.log(chalk.yellow('\n[ICE STATUS]'));
|
|
50
|
+
console.log(JSON.stringify(engine.getStatus(), null, 2));
|
|
51
|
+
console.log();
|
|
52
|
+
prompt();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const spinner = ora('ICE thinking...').start();
|
|
57
|
+
|
|
58
|
+
try {
|
|
59
|
+
const result = await engine.process(message);
|
|
60
|
+
spinner.stop();
|
|
61
|
+
|
|
62
|
+
if (options.json) {
|
|
63
|
+
console.log(JSON.stringify(result, null, 2));
|
|
64
|
+
} else {
|
|
65
|
+
console.log(chalk.yellow('\n[ICE THINKING]'));
|
|
66
|
+
console.log(chalk.gray(` Intent: ${result.intent.primary_intent}`));
|
|
67
|
+
console.log(chalk.gray(` Confidence: ${(result.intent.confidence * 100).toFixed(0)}%`));
|
|
68
|
+
console.log(chalk.gray(` Complexity: ${result.complexity}`));
|
|
69
|
+
console.log(chalk.gray(` Crews: ${result.crews.join(', ')}`));
|
|
70
|
+
console.log(chalk.gray(` Provider: ${result.provider}`));
|
|
71
|
+
console.log(chalk.gray(` Time: ${result.time.toFixed(3)}s`));
|
|
72
|
+
|
|
73
|
+
console.log(chalk.cyan('\n[RESPONSE]'));
|
|
74
|
+
console.log(result.response);
|
|
75
|
+
|
|
76
|
+
if (result.intent.needs_clarification && result.intent.clarifying_questions) {
|
|
77
|
+
console.log(chalk.yellow('\n[CLARIFICATION NEEDED]'));
|
|
78
|
+
for (const question of result.intent.clarifying_questions) {
|
|
79
|
+
console.log(chalk.gray(` - ${question}`));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
} catch (error) {
|
|
84
|
+
spinner.stop();
|
|
85
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : error);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
console.log();
|
|
89
|
+
prompt();
|
|
90
|
+
});
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
prompt();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
program.parse();
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ICE v4.3 — D20 Learner
|
|
3
|
+
* Pattern learning and storage with user isolation
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import fs from 'fs/promises';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import os from 'os';
|
|
9
|
+
|
|
10
|
+
export interface LearningPattern {
|
|
11
|
+
id: string;
|
|
12
|
+
type: 'routing' | 'reasoning' | 'optimization';
|
|
13
|
+
intent: string;
|
|
14
|
+
successCount: number;
|
|
15
|
+
totalCount: number;
|
|
16
|
+
avgTime: number;
|
|
17
|
+
provider: string;
|
|
18
|
+
lastUsed: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface InteractionRecord {
|
|
22
|
+
input: string;
|
|
23
|
+
intent: string;
|
|
24
|
+
complexity: string;
|
|
25
|
+
crews: string[];
|
|
26
|
+
provider: string;
|
|
27
|
+
model: string;
|
|
28
|
+
responseTime: number;
|
|
29
|
+
timestamp: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export class D20Learner {
|
|
33
|
+
private patterns: Map<string, LearningPattern>;
|
|
34
|
+
private memory: InteractionRecord[];
|
|
35
|
+
private storagePath: string;
|
|
36
|
+
private currentUser: string;
|
|
37
|
+
|
|
38
|
+
constructor() {
|
|
39
|
+
this.currentUser = process.env.ICE_USER_ID || process.env.USER || os.userInfo().username || 'default';
|
|
40
|
+
this.storagePath = path.join(os.homedir(), '.qwen', 'ice-memory', this.currentUser);
|
|
41
|
+
this.patterns = new Map();
|
|
42
|
+
this.memory = [];
|
|
43
|
+
this._initialize();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
private async _initialize(): Promise<void> {
|
|
47
|
+
try {
|
|
48
|
+
await fs.mkdir(this.storagePath, { recursive: true, mode: 0o700 });
|
|
49
|
+
await this._loadPatterns();
|
|
50
|
+
await this._loadMemory();
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.error('[D20] Initialization error:', error instanceof Error ? error.message : error);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private async _loadPatterns(): Promise<void> {
|
|
57
|
+
try {
|
|
58
|
+
const patternsFile = path.join(this.storagePath, `${this.currentUser}_patterns.json`);
|
|
59
|
+
const data = await fs.readFile(patternsFile, 'utf-8');
|
|
60
|
+
const patternsData = JSON.parse(data);
|
|
61
|
+
|
|
62
|
+
for (const [key, pattern] of Object.entries(patternsData)) {
|
|
63
|
+
this.patterns.set(key, pattern as LearningPattern);
|
|
64
|
+
}
|
|
65
|
+
} catch {
|
|
66
|
+
// Start fresh if file doesn't exist
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private async _loadMemory(): Promise<void> {
|
|
71
|
+
try {
|
|
72
|
+
const memoryFile = path.join(this.storagePath, `${this.currentUser}_memory.json`);
|
|
73
|
+
const data = await fs.readFile(memoryFile, 'utf-8');
|
|
74
|
+
this.memory = JSON.parse(data);
|
|
75
|
+
} catch {
|
|
76
|
+
// Start fresh if file doesn't exist
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private async _savePatterns(): Promise<void> {
|
|
81
|
+
try {
|
|
82
|
+
const patternsFile = path.join(this.storagePath, `${this.currentUser}_patterns.json`);
|
|
83
|
+
const patternsData = Object.fromEntries(this.patterns);
|
|
84
|
+
await fs.writeFile(patternsFile, JSON.stringify(patternsData, null, 2), { mode: 0o600 });
|
|
85
|
+
} catch (error) {
|
|
86
|
+
console.error('[D20] Save patterns error:', error instanceof Error ? error.message : error);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private async _saveMemory(): Promise<void> {
|
|
91
|
+
try {
|
|
92
|
+
const memoryFile = path.join(this.storagePath, `${this.currentUser}_memory.json`);
|
|
93
|
+
await fs.writeFile(memoryFile, JSON.stringify(this.memory.slice(-100), null, 2), { mode: 0o600 });
|
|
94
|
+
} catch (error) {
|
|
95
|
+
console.error('[D20] Save memory error:', error instanceof Error ? error.message : error);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async learn(intent: string, success: boolean, responseTime: number, provider: string): Promise<void> {
|
|
100
|
+
const pattern = this.patterns.get(intent) || {
|
|
101
|
+
id: intent,
|
|
102
|
+
type: 'routing' as const,
|
|
103
|
+
intent,
|
|
104
|
+
successCount: 0,
|
|
105
|
+
totalCount: 0,
|
|
106
|
+
avgTime: 0,
|
|
107
|
+
provider,
|
|
108
|
+
lastUsed: Date.now()
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
pattern.totalCount++;
|
|
112
|
+
if (success) {
|
|
113
|
+
pattern.successCount++;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Update average time
|
|
117
|
+
pattern.avgTime = ((pattern.avgTime * (pattern.totalCount - 1)) + responseTime) / pattern.totalCount;
|
|
118
|
+
pattern.provider = provider;
|
|
119
|
+
pattern.lastUsed = Date.now();
|
|
120
|
+
|
|
121
|
+
this.patterns.set(intent, pattern);
|
|
122
|
+
await this._savePatterns();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async store(interaction: InteractionRecord): Promise<void> {
|
|
126
|
+
this.memory.push({
|
|
127
|
+
...interaction,
|
|
128
|
+
timestamp: Date.now()
|
|
129
|
+
});
|
|
130
|
+
await this._saveMemory();
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
getPattern(intent: string): LearningPattern | undefined {
|
|
134
|
+
return this.patterns.get(intent);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
getPatterns(): LearningPattern[] {
|
|
138
|
+
return Array.from(this.patterns.values());
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
getMemory(limit: number = 100): InteractionRecord[] {
|
|
142
|
+
return this.memory.slice(-limit);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
getStatus(): Record<string, unknown> {
|
|
146
|
+
return {
|
|
147
|
+
patternsCount: this.patterns.size,
|
|
148
|
+
memorySize: this.memory.length,
|
|
149
|
+
routingPatterns: Array.from(this.patterns.values()).filter(p => p.type === 'routing').length,
|
|
150
|
+
user: this.currentUser,
|
|
151
|
+
storagePath: this.storagePath
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
async clear(): Promise<void> {
|
|
156
|
+
this.patterns.clear();
|
|
157
|
+
this.memory = [];
|
|
158
|
+
await this._savePatterns();
|
|
159
|
+
await this._saveMemory();
|
|
160
|
+
}
|
|
161
|
+
}
|
package/src/engine.ts
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ICE v4.3 — Main Engine (With Scientific Reasoning)
|
|
3
|
+
* Orchestrates intent decoding, reasoning, and response generation
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { MultiProviderClient } from './multi-provider-client.js';
|
|
7
|
+
import { IntentDecoder } from './intent-decoder.js';
|
|
8
|
+
import { D20Learner } from './d20-learner.js';
|
|
9
|
+
import { AgentCrews } from './agent-crews.js';
|
|
10
|
+
import { ChainOfThought } from './reasoning/chain-of-thought.js';
|
|
11
|
+
import { TreeOfThoughts } from './reasoning/tree-of-thoughts.js';
|
|
12
|
+
import { SelfReflection } from './reasoning/self-reflection.js';
|
|
13
|
+
import { SocraticReviewer } from './reasoning/socratic-reviewer.js';
|
|
14
|
+
import type { IntentResult, ProcessingResult, ICEConfig } from './types.js';
|
|
15
|
+
import os from 'os';
|
|
16
|
+
|
|
17
|
+
const DEFAULT_CONFIG: ICEConfig = {
|
|
18
|
+
storagePath: os.homedir() + '/.qwen',
|
|
19
|
+
memoryPath: os.homedir() + '/.qwen/ice-memory',
|
|
20
|
+
models: {
|
|
21
|
+
groq_primary: 'qwen/qwen3-32b',
|
|
22
|
+
groq_fast: 'llama-3.1-8b-instant',
|
|
23
|
+
gemini: 'gemini-2.0-flash'
|
|
24
|
+
},
|
|
25
|
+
temperature: 0.4,
|
|
26
|
+
maxTokens: 2048,
|
|
27
|
+
timeout: 30000
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export class ICEEngine {
|
|
31
|
+
private api: MultiProviderClient;
|
|
32
|
+
private intentDecoder: IntentDecoder;
|
|
33
|
+
private d20: D20Learner;
|
|
34
|
+
private crews: AgentCrews;
|
|
35
|
+
private cot: ChainOfThought;
|
|
36
|
+
private tot: TreeOfThoughts;
|
|
37
|
+
private reflection: SelfReflection;
|
|
38
|
+
private socratic: SocraticReviewer;
|
|
39
|
+
private config: ICEConfig;
|
|
40
|
+
private startTime: number;
|
|
41
|
+
private currentUser: string;
|
|
42
|
+
|
|
43
|
+
constructor(config?: Partial<ICEConfig>) {
|
|
44
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
45
|
+
this.api = new MultiProviderClient();
|
|
46
|
+
this.intentDecoder = new IntentDecoder(this.api);
|
|
47
|
+
this.d20 = new D20Learner();
|
|
48
|
+
this.crews = new AgentCrews();
|
|
49
|
+
this.cot = new ChainOfThought();
|
|
50
|
+
this.tot = new TreeOfThoughts();
|
|
51
|
+
this.reflection = new SelfReflection();
|
|
52
|
+
this.socratic = new SocraticReviewer();
|
|
53
|
+
this.startTime = Date.now();
|
|
54
|
+
this.currentUser = process.env.ICE_USER_ID || process.env.USER || os.userInfo().username || 'default';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async process(message: string, context?: string): Promise<ProcessingResult> {
|
|
58
|
+
const start = Date.now();
|
|
59
|
+
|
|
60
|
+
// Step 1: Decode intent
|
|
61
|
+
const intent = await this.intentDecoder.decode(message, context);
|
|
62
|
+
|
|
63
|
+
// Step 2: Assess complexity and select reasoning mode
|
|
64
|
+
const complexity = this._assessComplexity(intent);
|
|
65
|
+
const reasoningMode = this._selectReasoningMode(complexity, intent);
|
|
66
|
+
|
|
67
|
+
// Step 3: Apply scientific reasoning based on mode
|
|
68
|
+
let enhancedContext = context || '';
|
|
69
|
+
if (reasoningMode === 'cot') {
|
|
70
|
+
const steps = await this.cot.reason(message, context);
|
|
71
|
+
enhancedContext += `\n\n[Chain of Thought: ${steps.length} steps, confidence: ${(this.cot.getFinalConfidence() * 100).toFixed(0)}%]`;
|
|
72
|
+
} else if (reasoningMode === 'tot') {
|
|
73
|
+
const branch = await this.tot.explore(message, context);
|
|
74
|
+
enhancedContext += `\n\n[Tree of Thoughts: ${this.tot.getBranches().length} branches, best score: ${(branch.score * 100).toFixed(0)}%]`;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Step 4: Select crews
|
|
78
|
+
const crews = this.crews.selectCrews(intent.primary_intent, intent.entities);
|
|
79
|
+
|
|
80
|
+
// Step 5: Select provider
|
|
81
|
+
const provider = this.api.selectBestProvider(intent.primary_intent, complexity);
|
|
82
|
+
const model = this._getModelForProvider(provider, intent.primary_intent);
|
|
83
|
+
|
|
84
|
+
// Step 6: Generate response with reasoning context
|
|
85
|
+
const response = await this._generateResponse(message, intent, provider, model, enhancedContext);
|
|
86
|
+
|
|
87
|
+
// Step 7: Self-reflection (critique before delivery)
|
|
88
|
+
const reflection = await this.reflection.reflect(message, response, enhancedContext);
|
|
89
|
+
const finalResponse = reflection.confidenceGain > 0.05 ? reflection.revisedAnswer : response;
|
|
90
|
+
|
|
91
|
+
const elapsed = (Date.now() - start) / 1000;
|
|
92
|
+
|
|
93
|
+
// Step 8: Learn from this interaction
|
|
94
|
+
await this.d20.learn(intent.primary_intent, true, elapsed, provider);
|
|
95
|
+
await this.d20.store({
|
|
96
|
+
input: message,
|
|
97
|
+
intent: intent.primary_intent,
|
|
98
|
+
complexity,
|
|
99
|
+
crews: crews.map(c => c.name),
|
|
100
|
+
provider,
|
|
101
|
+
model,
|
|
102
|
+
responseTime: elapsed
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
intent,
|
|
107
|
+
complexity,
|
|
108
|
+
crews: crews.map(c => c.name),
|
|
109
|
+
provider,
|
|
110
|
+
model,
|
|
111
|
+
response: finalResponse,
|
|
112
|
+
time: elapsed,
|
|
113
|
+
user: this.currentUser,
|
|
114
|
+
reasoning: {
|
|
115
|
+
mode: reasoningMode,
|
|
116
|
+
reflectionApplied: reflection.confidenceGain > 0.05,
|
|
117
|
+
confidenceGain: reflection.confidenceGain
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
private _assessComplexity(intent: IntentResult): string {
|
|
123
|
+
if (intent.confidence < 0.5) return 'complex';
|
|
124
|
+
if (['code_request', 'math_problem', 'causal'].includes(intent.primary_intent)) return 'moderate';
|
|
125
|
+
if (intent.secondary_intents.length > 2) return 'moderate';
|
|
126
|
+
return 'simple';
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private _selectReasoningMode(complexity: string, intent: IntentResult): 'cot' | 'tot' | 'direct' {
|
|
130
|
+
// Use Chain of Thought for moderate complexity
|
|
131
|
+
if (complexity === 'moderate') return 'cot';
|
|
132
|
+
|
|
133
|
+
// Use Tree of Thoughts for complex problems
|
|
134
|
+
if (complexity === 'complex') return 'tot';
|
|
135
|
+
|
|
136
|
+
// Direct for simple queries
|
|
137
|
+
return 'direct';
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
private _getModelForProvider(provider: string, intent: string): string {
|
|
141
|
+
if (provider === 'groq') {
|
|
142
|
+
return intent === 'code_request'
|
|
143
|
+
? this.config.models.groq_primary
|
|
144
|
+
: this.config.models.groq_fast;
|
|
145
|
+
}
|
|
146
|
+
return this.config.models.gemini;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
private async _generateResponse(
|
|
150
|
+
message: string,
|
|
151
|
+
intent: IntentResult,
|
|
152
|
+
provider: string,
|
|
153
|
+
model: string,
|
|
154
|
+
context: string
|
|
155
|
+
): Promise<string> {
|
|
156
|
+
if (!this.api.isAvailable(provider)) {
|
|
157
|
+
return this._fallbackResponse(message, intent);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const prompt = `You are ICE v4.3 by @anh3d0nic. Think first, then respond.
|
|
161
|
+
|
|
162
|
+
[ICE THINKING]
|
|
163
|
+
Intent: ${intent.primary_intent}
|
|
164
|
+
Entities: ${JSON.stringify(intent.entities)}
|
|
165
|
+
Confidence: ${(intent.confidence * 100).toFixed(0)}%
|
|
166
|
+
Needs Clarification: ${intent.needs_clarification}
|
|
167
|
+
${context ? `\nReasoning Context: ${context}` : ''}
|
|
168
|
+
|
|
169
|
+
[RESPONSE]
|
|
170
|
+
User request: ${message}
|
|
171
|
+
|
|
172
|
+
Here's my response:
|
|
173
|
+
`;
|
|
174
|
+
|
|
175
|
+
const response = await this.api.chat(
|
|
176
|
+
[{ role: 'user', content: prompt }],
|
|
177
|
+
provider,
|
|
178
|
+
model,
|
|
179
|
+
this.config.temperature,
|
|
180
|
+
this.config.maxTokens
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
return response?.content || this._fallbackResponse(message, intent);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private _fallbackResponse(message: string, intent: IntentResult): string {
|
|
187
|
+
if (intent.needs_clarification) {
|
|
188
|
+
const questions = this.socratic.generateQuestions(message);
|
|
189
|
+
return `I need more information. ${questions[0]?.question || 'Could you clarify your request?'}`;
|
|
190
|
+
}
|
|
191
|
+
return `[Fallback] You asked about ${intent.primary_intent}: ${message}`;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
getStatus(): Record<string, unknown> {
|
|
195
|
+
return {
|
|
196
|
+
version: '4.3.0-termux',
|
|
197
|
+
user: this.currentUser,
|
|
198
|
+
memoryDir: this.config.memoryPath + '/' + this.currentUser,
|
|
199
|
+
providers: this.api.getAvailableProviders(),
|
|
200
|
+
providerStatus: {
|
|
201
|
+
groq: this.api.isAvailable('groq'),
|
|
202
|
+
gemini: this.api.isAvailable('gemini')
|
|
203
|
+
},
|
|
204
|
+
uptime: Math.round((Date.now() - this.startTime) / 1000),
|
|
205
|
+
reasoning: {
|
|
206
|
+
chainOfThought: 'available',
|
|
207
|
+
treeOfThoughts: 'available',
|
|
208
|
+
selfReflection: 'available',
|
|
209
|
+
socraticReviewer: 'available'
|
|
210
|
+
},
|
|
211
|
+
crews: {
|
|
212
|
+
crews: 5,
|
|
213
|
+
totalAgents: 100,
|
|
214
|
+
crewNames: ['Alpha', 'Beta', 'Gamma', 'Delta', 'Epsilon']
|
|
215
|
+
},
|
|
216
|
+
d20: this.d20.getStatus()
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
}
|