aiden-runtime 3.16.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/LICENSE +661 -0
- package/README.md +465 -0
- package/config/devos.config.json +186 -0
- package/config/hardware.json +9 -0
- package/config/model-selection.json +7 -0
- package/config/setup-complete.json +20 -0
- package/dist/api/routes/computerUse.js +112 -0
- package/dist/api/server.js +6870 -0
- package/dist/bin/npx-init.js +71 -0
- package/dist/coordination/commandGate.js +115 -0
- package/dist/coordination/livePulse.js +127 -0
- package/dist/core/agentLoop.js +2718 -0
- package/dist/core/agentShield.js +231 -0
- package/dist/core/aidenIdentity.js +215 -0
- package/dist/core/aidenPersonality.js +166 -0
- package/dist/core/aidenSdk.js +374 -0
- package/dist/core/asyncTasks.js +82 -0
- package/dist/core/auditTrail.js +61 -0
- package/dist/core/auxiliaryClient.js +114 -0
- package/dist/core/bgLLM.js +108 -0
- package/dist/core/bm25.js +68 -0
- package/dist/core/callbackSystem.js +64 -0
- package/dist/core/channels/adapter.js +6 -0
- package/dist/core/channels/discord.js +173 -0
- package/dist/core/channels/email.js +253 -0
- package/dist/core/channels/imessage.js +164 -0
- package/dist/core/channels/manager.js +96 -0
- package/dist/core/channels/signal.js +140 -0
- package/dist/core/channels/slack.js +139 -0
- package/dist/core/channels/twilio.js +144 -0
- package/dist/core/channels/webhook.js +186 -0
- package/dist/core/channels/whatsapp.js +185 -0
- package/dist/core/clarifyBus.js +75 -0
- package/dist/core/codeInterpreter.js +82 -0
- package/dist/core/computerControl.js +439 -0
- package/dist/core/conversationMemory.js +334 -0
- package/dist/core/costTracker.js +221 -0
- package/dist/core/cronManager.js +217 -0
- package/dist/core/deepKB.js +77 -0
- package/dist/core/doctor.js +279 -0
- package/dist/core/dreamEngine.js +334 -0
- package/dist/core/entityGraph.js +169 -0
- package/dist/core/eventBus.js +16 -0
- package/dist/core/evolutionAnalyzer.js +153 -0
- package/dist/core/executionLoop.js +309 -0
- package/dist/core/executor.js +224 -0
- package/dist/core/failureAnalyzer.js +166 -0
- package/dist/core/fastPathExpansion.js +82 -0
- package/dist/core/faultEngine.js +106 -0
- package/dist/core/featureGates.js +70 -0
- package/dist/core/fileIngestion.js +113 -0
- package/dist/core/gateway.js +97 -0
- package/dist/core/goalTracker.js +75 -0
- package/dist/core/growthEngine.js +168 -0
- package/dist/core/hardwareDetector.js +98 -0
- package/dist/core/hooks.js +45 -0
- package/dist/core/httpKeepalive.js +46 -0
- package/dist/core/hybridSearch.js +101 -0
- package/dist/core/importers.js +164 -0
- package/dist/core/instinctSystem.js +223 -0
- package/dist/core/knowledgeBase.js +351 -0
- package/dist/core/learningMemory.js +121 -0
- package/dist/core/lessonsBrowser.js +125 -0
- package/dist/core/licenseManager.js +399 -0
- package/dist/core/logBuffer.js +85 -0
- package/dist/core/machineId.js +87 -0
- package/dist/core/mcpClient.js +442 -0
- package/dist/core/memoryDistiller.js +165 -0
- package/dist/core/memoryExtractor.js +212 -0
- package/dist/core/memoryIds.js +213 -0
- package/dist/core/memoryPreamble.js +113 -0
- package/dist/core/memoryQuery.js +136 -0
- package/dist/core/memoryRecall.js +140 -0
- package/dist/core/memoryStrategy.js +201 -0
- package/dist/core/messageValidator.js +85 -0
- package/dist/core/modelDiscovery.js +108 -0
- package/dist/core/modelRouter.js +118 -0
- package/dist/core/morningBriefing.js +203 -0
- package/dist/core/multiGoalValidator.js +51 -0
- package/dist/core/parallelExecutor.js +43 -0
- package/dist/core/passiveSkillObserver.js +204 -0
- package/dist/core/paths.js +57 -0
- package/dist/core/patternDetector.js +83 -0
- package/dist/core/planResponseRepair.js +64 -0
- package/dist/core/planTool.js +111 -0
- package/dist/core/playwrightBridge.js +356 -0
- package/dist/core/pluginSystem.js +121 -0
- package/dist/core/privateMode.js +85 -0
- package/dist/core/reactLoop.js +156 -0
- package/dist/core/recipeEngine.js +166 -0
- package/dist/core/responseCache.js +128 -0
- package/dist/core/runSandbox.js +132 -0
- package/dist/core/sandboxRunner.js +200 -0
- package/dist/core/scheduler.js +543 -0
- package/dist/core/secretScanner.js +49 -0
- package/dist/core/semanticMemory.js +223 -0
- package/dist/core/sessionMemory.js +259 -0
- package/dist/core/sessionRouter.js +91 -0
- package/dist/core/sessionSearch.js +163 -0
- package/dist/core/setupWizard.js +225 -0
- package/dist/core/skillImporter.js +303 -0
- package/dist/core/skillLibrary.js +144 -0
- package/dist/core/skillLoader.js +471 -0
- package/dist/core/skillTeacher.js +352 -0
- package/dist/core/skillValidator.js +210 -0
- package/dist/core/skillWriter.js +384 -0
- package/dist/core/slashAsTool.js +226 -0
- package/dist/core/spawnManager.js +197 -0
- package/dist/core/statusVerbs.js +43 -0
- package/dist/core/swarmManager.js +109 -0
- package/dist/core/taskQueue.js +119 -0
- package/dist/core/taskRecovery.js +128 -0
- package/dist/core/taskState.js +168 -0
- package/dist/core/telegramBot.js +152 -0
- package/dist/core/todoManager.js +70 -0
- package/dist/core/toolNameRepair.js +71 -0
- package/dist/core/toolRegistry.js +2730 -0
- package/dist/core/tools/calendarTool.js +98 -0
- package/dist/core/tools/companyFilingsTool.js +98 -0
- package/dist/core/tools/gmailTool.js +87 -0
- package/dist/core/tools/marketDataTool.js +135 -0
- package/dist/core/tools/socialResearchTool.js +121 -0
- package/dist/core/truthCheck.js +57 -0
- package/dist/core/updateChecker.js +74 -0
- package/dist/core/userCognitionProfile.js +238 -0
- package/dist/core/userProfile.js +341 -0
- package/dist/core/version.js +5 -0
- package/dist/core/visionAnalyze.js +161 -0
- package/dist/core/voice/audio.js +187 -0
- package/dist/core/voice/stt.js +226 -0
- package/dist/core/voice/tts.js +310 -0
- package/dist/core/voiceInput.js +118 -0
- package/dist/core/voiceOutput.js +130 -0
- package/dist/core/webSearch.js +326 -0
- package/dist/core/workflowTracker.js +72 -0
- package/dist/core/workspaceMemory.js +54 -0
- package/dist/core/youtubeTranscript.js +224 -0
- package/dist/integrations/computerUse/apiRegistry.js +113 -0
- package/dist/integrations/computerUse/screenAgent.js +203 -0
- package/dist/integrations/computerUse/visionLoop.js +296 -0
- package/dist/memory/memoryLayers.js +143 -0
- package/dist/providers/boa.js +93 -0
- package/dist/providers/cerebras.js +70 -0
- package/dist/providers/custom.js +89 -0
- package/dist/providers/gemini.js +82 -0
- package/dist/providers/groq.js +92 -0
- package/dist/providers/index.js +149 -0
- package/dist/providers/nvidia.js +70 -0
- package/dist/providers/ollama.js +99 -0
- package/dist/providers/openrouter.js +74 -0
- package/dist/providers/router.js +497 -0
- package/dist/providers/types.js +6 -0
- package/dist/security/browserVault.js +129 -0
- package/dist/security/dataGuard.js +89 -0
- package/dist/tools/eonetTool.js +72 -0
- package/dist/types/computerUse.js +2 -0
- package/dist/types/executor.js +2 -0
- package/dist-bundle/cli.js +357859 -0
- package/package.json +256 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ============================================================
|
|
3
|
+
// DevOS — Autonomous AI Execution System
|
|
4
|
+
// Copyright (c) 2026 Shiva Deore. All rights reserved.
|
|
5
|
+
// ============================================================
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.runGoalLoop = runGoalLoop;
|
|
41
|
+
// core/executionLoop.ts — Outer goal-level execution loop.
|
|
42
|
+
// Plans → Executes → Replans → Reports to EvolutionAnalyzer.
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
const os = __importStar(require("os"));
|
|
46
|
+
const executor_1 = require("./executor");
|
|
47
|
+
const truthCheck_1 = require("./truthCheck");
|
|
48
|
+
const faultEngine_1 = require("./faultEngine");
|
|
49
|
+
const memoryLayers_1 = require("../memory/memoryLayers");
|
|
50
|
+
const evolutionAnalyzer_1 = require("./evolutionAnalyzer");
|
|
51
|
+
const livePulse_1 = require("../coordination/livePulse");
|
|
52
|
+
// ── Payload parser ────────────────────────────────────────────
|
|
53
|
+
function parsePayload(skill, command) {
|
|
54
|
+
// Try JSON first (for compound payloads like file_write)
|
|
55
|
+
try {
|
|
56
|
+
return JSON.parse(command);
|
|
57
|
+
}
|
|
58
|
+
catch { }
|
|
59
|
+
// Skill-specific scalar mappings
|
|
60
|
+
switch (skill) {
|
|
61
|
+
case 'open_browser': return { url: command };
|
|
62
|
+
case 'web_search': return { query: command };
|
|
63
|
+
case 'shell_exec': return { command };
|
|
64
|
+
case 'run_powershell': return { script: command };
|
|
65
|
+
case 'file_read': return { path: command };
|
|
66
|
+
case 'file_list': return { path: command };
|
|
67
|
+
case 'system_info': return {};
|
|
68
|
+
case 'notify': return { message: command };
|
|
69
|
+
default: return { command };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// ── Planner ───────────────────────────────────────────────────
|
|
73
|
+
async function generatePlan(goal, goalId) {
|
|
74
|
+
livePulse_1.livePulse.thinking('CEO', `Planning: ${goal}`);
|
|
75
|
+
const lower = goal.toLowerCase();
|
|
76
|
+
// ── Direct tool mapping — no LLM needed for common patterns ──
|
|
77
|
+
const urlMatch = goal.match(/https?:\/\/[^\s]+/) ||
|
|
78
|
+
goal.match(/([a-zA-Z0-9-]+\.(com|org|net|io|dev|co|uk))/i);
|
|
79
|
+
if (urlMatch && /open|go to|browse|show|navigate|launch/.test(lower)) {
|
|
80
|
+
const url = urlMatch[0].startsWith('http') ? urlMatch[0] : `https://${urlMatch[0]}`;
|
|
81
|
+
return {
|
|
82
|
+
goalId, goal, complete: false,
|
|
83
|
+
steps: [{ id: 'step_0', skill: 'open_browser', description: `Open ${url}`, command: url, status: 'pending' }],
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
if (/system info|my pc|computer specs|my ram|my cpu|disk space/i.test(lower)) {
|
|
87
|
+
return {
|
|
88
|
+
goalId, goal, complete: false,
|
|
89
|
+
steps: [{ id: 'step_0', skill: 'system_info', description: 'Get system info', command: '', status: 'pending' }],
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
if (/(create|write|make).+(file|txt|py|js|html|md)/i.test(lower)) {
|
|
93
|
+
const nameMatch = goal.match(/called?\s+["']?([^\s"',]+\.?\w*)["']?/i);
|
|
94
|
+
const fileName = nameMatch?.[1] || 'devos-file.txt';
|
|
95
|
+
const contentMatch = goal.match(/(?:with|containing|content)[:\s]+["']?(.+?)["']?$/i);
|
|
96
|
+
const content = contentMatch?.[1] || `Created by DevOS on ${new Date().toLocaleDateString()}`;
|
|
97
|
+
const desktopPath = path.join(os.homedir(), 'Desktop', fileName);
|
|
98
|
+
return {
|
|
99
|
+
goalId, goal, complete: false,
|
|
100
|
+
steps: [{
|
|
101
|
+
id: 'step_0', skill: 'file_write',
|
|
102
|
+
description: `Create ${fileName} on Desktop`,
|
|
103
|
+
command: JSON.stringify({ path: desktopPath, content }),
|
|
104
|
+
status: 'pending',
|
|
105
|
+
}],
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
if (/^(search|find|look up|search for|find me)/i.test(lower)) {
|
|
109
|
+
const query = goal.replace(/^(search|find|look up|search for|find me)/i, '').trim();
|
|
110
|
+
return {
|
|
111
|
+
goalId, goal, complete: false,
|
|
112
|
+
steps: [{ id: 'step_0', skill: 'web_search', description: `Search: ${query}`, command: query, status: 'pending' }],
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
if (/notify|notification|alert/i.test(lower)) {
|
|
116
|
+
const msg = goal.replace(/^(notify|send notification|alert|send alert)[:\s]*/i, '').trim();
|
|
117
|
+
return {
|
|
118
|
+
goalId, goal, complete: false,
|
|
119
|
+
steps: [{ id: 'step_0', skill: 'notify', description: `Notify: ${msg}`, command: JSON.stringify({ message: msg }), status: 'pending' }],
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
// ── LLM planning for complex tasks (tries Groq first, then Ollama) ──
|
|
123
|
+
try {
|
|
124
|
+
const { loadConfig } = await Promise.resolve().then(() => __importStar(require('../providers/index')));
|
|
125
|
+
const config = loadConfig();
|
|
126
|
+
const api = config.providers.apis.find((a) => a.enabled && !a.rateLimited && a.provider === 'groq');
|
|
127
|
+
if (api) {
|
|
128
|
+
const prompt = `Plan this task on Windows: "${goal}"
|
|
129
|
+
Respond ONLY with JSON (no markdown):
|
|
130
|
+
{"steps":[{"skill":"open_browser","description":"what this does","command":"https://example.com"}]}
|
|
131
|
+
Skills: open_browser(command=url), file_write(command=json{path,content}), shell_exec(command=powershell), web_search(command=query), run_python(command=json{script}), system_info(command=""), notify(command=json{message})
|
|
132
|
+
Max 3 steps.`;
|
|
133
|
+
const r = await fetch('https://api.groq.com/openai/v1/chat/completions', {
|
|
134
|
+
method: 'POST',
|
|
135
|
+
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${api.key}` },
|
|
136
|
+
body: JSON.stringify({
|
|
137
|
+
model: api.model || 'llama-3.3-70b-versatile',
|
|
138
|
+
messages: [{ role: 'user', content: prompt }],
|
|
139
|
+
max_tokens: 300,
|
|
140
|
+
}),
|
|
141
|
+
signal: AbortSignal.timeout(10000),
|
|
142
|
+
});
|
|
143
|
+
const d = await r.json();
|
|
144
|
+
const raw = d?.choices?.[0]?.message?.content || '';
|
|
145
|
+
const parsed = JSON.parse(raw.replace(/```json|```/g, '').trim());
|
|
146
|
+
if (parsed.steps?.length) {
|
|
147
|
+
return {
|
|
148
|
+
goalId, goal, complete: false,
|
|
149
|
+
steps: parsed.steps.map((s, i) => ({
|
|
150
|
+
id: `step_${i}`, skill: s.skill, description: s.description, command: s.command, status: 'pending',
|
|
151
|
+
})),
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch { /* fall through to Ollama */ }
|
|
157
|
+
// ── Ollama fallback ───────────────────────────────────────────
|
|
158
|
+
try {
|
|
159
|
+
let ollamaModel = 'mistral:7b';
|
|
160
|
+
try {
|
|
161
|
+
const cfg = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'config/model-selection.json'), 'utf-8'));
|
|
162
|
+
ollamaModel = cfg.reasoning || cfg.chat || ollamaModel;
|
|
163
|
+
}
|
|
164
|
+
catch { }
|
|
165
|
+
const res = await fetch('http://localhost:11434/api/chat', {
|
|
166
|
+
method: 'POST',
|
|
167
|
+
headers: { 'Content-Type': 'application/json' },
|
|
168
|
+
body: JSON.stringify({
|
|
169
|
+
model: ollamaModel,
|
|
170
|
+
stream: false,
|
|
171
|
+
messages: [{ role: 'user', content: `Plan this Windows task in JSON only (no markdown): "${goal}"\n{"steps":[{"skill":"shell_exec","description":"step","command":"command"}]}` }],
|
|
172
|
+
}),
|
|
173
|
+
});
|
|
174
|
+
const data = await res.json();
|
|
175
|
+
const raw = data?.message?.content || '';
|
|
176
|
+
const parsed = JSON.parse(raw.replace(/```json|```/g, '').trim());
|
|
177
|
+
if (parsed.steps?.length) {
|
|
178
|
+
return {
|
|
179
|
+
goalId, goal, complete: false,
|
|
180
|
+
steps: parsed.steps.map((s, i) => ({
|
|
181
|
+
id: `step_${i}`, skill: s.skill, description: s.description, command: s.command, status: 'pending',
|
|
182
|
+
})),
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
catch { }
|
|
187
|
+
// Last resort
|
|
188
|
+
return {
|
|
189
|
+
goalId, goal, complete: false,
|
|
190
|
+
steps: [{ id: 'step_0', skill: 'notify', description: 'Could not plan', command: JSON.stringify({ message: `Could not plan: ${goal.slice(0, 40)}` }), status: 'pending' }],
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
// ── Replanner ─────────────────────────────────────────────────
|
|
194
|
+
async function replan(plan, _lastResult) {
|
|
195
|
+
const remaining = plan.steps.filter(s => s.status === 'pending');
|
|
196
|
+
// If nothing left, mark complete
|
|
197
|
+
if (!remaining.length)
|
|
198
|
+
return { ...plan, complete: true };
|
|
199
|
+
// Otherwise keep going with remaining steps
|
|
200
|
+
return plan;
|
|
201
|
+
}
|
|
202
|
+
// ── Main execution loop ───────────────────────────────────────
|
|
203
|
+
async function runGoalLoop(goal) {
|
|
204
|
+
const goalId = `goal_${Date.now()}`;
|
|
205
|
+
const startTime = Date.now();
|
|
206
|
+
const report = {
|
|
207
|
+
goalId, goal, success: false, totalDuration: 0,
|
|
208
|
+
steps: [], timestamp: startTime,
|
|
209
|
+
};
|
|
210
|
+
livePulse_1.livePulse.act('CEO', `Starting goal: ${goal}`);
|
|
211
|
+
let plan = await generatePlan(goal, goalId);
|
|
212
|
+
let iterations = 0;
|
|
213
|
+
const MAX_ITER = 10;
|
|
214
|
+
while (!plan.complete && iterations < MAX_ITER) {
|
|
215
|
+
iterations++;
|
|
216
|
+
const nextStep = plan.steps.find(s => s.status === 'pending');
|
|
217
|
+
if (!nextStep) {
|
|
218
|
+
plan.complete = true;
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
nextStep.status = 'running';
|
|
222
|
+
// Emit thinking before we run — lets UI show "planning this step"
|
|
223
|
+
livePulse_1.livePulse.thinking('CEO', `Next: ${nextStep.description}`);
|
|
224
|
+
// Emit tool event so UI knows exactly what will run
|
|
225
|
+
livePulse_1.livePulse.tool('Engineer', nextStep.skill, nextStep.command);
|
|
226
|
+
const stepStart = Date.now();
|
|
227
|
+
let stepResult;
|
|
228
|
+
let stepSuccess = false;
|
|
229
|
+
let stepError;
|
|
230
|
+
try {
|
|
231
|
+
const stepPayload = parsePayload(nextStep.skill, nextStep.command);
|
|
232
|
+
const execResult = await executor_1.executor.execute({
|
|
233
|
+
id: nextStep.id,
|
|
234
|
+
type: nextStep.skill,
|
|
235
|
+
confidence: 0.9,
|
|
236
|
+
description: nextStep.description,
|
|
237
|
+
payload: stepPayload,
|
|
238
|
+
retries: 1,
|
|
239
|
+
timeoutMs: 30000,
|
|
240
|
+
});
|
|
241
|
+
stepResult = execResult;
|
|
242
|
+
stepSuccess = execResult.status === 'success' || execResult.status === 'retried';
|
|
243
|
+
if (stepSuccess) {
|
|
244
|
+
// Verify with TruthCheck (uses actual signature)
|
|
245
|
+
const verified = await truthCheck_1.truthCheck.verifyAction(nextStep.skill, { expected: nextStep.description, actual: execResult });
|
|
246
|
+
if (verified) {
|
|
247
|
+
nextStep.status = 'done';
|
|
248
|
+
nextStep.result = execResult;
|
|
249
|
+
const toolOutput = typeof execResult.data === 'string'
|
|
250
|
+
? execResult.data.slice(0, 120)
|
|
251
|
+
: undefined;
|
|
252
|
+
// Emit tool event with output so UI can show result
|
|
253
|
+
livePulse_1.livePulse.tool('Engineer', nextStep.skill, nextStep.command, toolOutput);
|
|
254
|
+
livePulse_1.livePulse.done('Engineer', `${nextStep.description}${toolOutput ? ` → ${toolOutput}` : ''}`);
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
stepSuccess = false;
|
|
258
|
+
stepError = 'TruthCheck failed';
|
|
259
|
+
// Log fault classification for diagnostics
|
|
260
|
+
faultEngine_1.faultEngine.classify(stepError);
|
|
261
|
+
nextStep.status = 'failed';
|
|
262
|
+
livePulse_1.livePulse.error('Engineer', `${nextStep.description}: TruthCheck failed`);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
nextStep.status = 'failed';
|
|
267
|
+
stepError = execResult.error?.message;
|
|
268
|
+
livePulse_1.livePulse.error('Engineer', `${nextStep.description}: ${stepError}`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
catch (err) {
|
|
272
|
+
nextStep.status = 'failed';
|
|
273
|
+
stepError = err.message;
|
|
274
|
+
stepSuccess = false;
|
|
275
|
+
livePulse_1.livePulse.error('Engineer', `${nextStep.skill} threw: ${err.message}`);
|
|
276
|
+
}
|
|
277
|
+
// Record step in evolution report
|
|
278
|
+
report.steps.push({
|
|
279
|
+
skill: nextStep.skill,
|
|
280
|
+
success: stepSuccess,
|
|
281
|
+
duration: Date.now() - stepStart,
|
|
282
|
+
error: stepError,
|
|
283
|
+
});
|
|
284
|
+
// Store result in memory (sync — await is a no-op on void)
|
|
285
|
+
memoryLayers_1.memoryLayers.write(`Goal ${goalId} step ${nextStep.id}: ${nextStep.description} → ${stepSuccess ? 'success' : 'failed'}`, ['goal', 'execution', nextStep.skill]);
|
|
286
|
+
// Replan after each successful step
|
|
287
|
+
if (stepSuccess) {
|
|
288
|
+
plan = await replan(plan, stepResult);
|
|
289
|
+
}
|
|
290
|
+
// Stop if too many failures
|
|
291
|
+
const failures = plan.steps.filter(s => s.status === 'failed').length;
|
|
292
|
+
if (failures >= 3) {
|
|
293
|
+
livePulse_1.livePulse.error('CEO', 'Too many failures — stopping goal');
|
|
294
|
+
break;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
// Finalise report
|
|
298
|
+
const successSteps = report.steps.filter(s => s.success).length;
|
|
299
|
+
report.success = successSteps > 0 && successSteps >= report.steps.length * 0.6;
|
|
300
|
+
report.totalDuration = Date.now() - startTime;
|
|
301
|
+
// Send to evolution analyzer
|
|
302
|
+
evolutionAnalyzer_1.evolutionAnalyzer.collect(report);
|
|
303
|
+
const summary = report.success
|
|
304
|
+
? `Goal complete in ${Math.round(report.totalDuration / 1000)}s — ${successSteps}/${report.steps.length} steps succeeded`
|
|
305
|
+
: `Goal incomplete — ${successSteps}/${report.steps.length} steps succeeded`;
|
|
306
|
+
livePulse_1.livePulse.done('CEO', summary);
|
|
307
|
+
memoryLayers_1.memoryLayers.write(`Goal complete: ${goal} → ${summary}`, ['goal', 'complete']);
|
|
308
|
+
return { success: report.success, summary };
|
|
309
|
+
}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ============================================================
|
|
3
|
+
// DevOS — Autonomous AI Execution System
|
|
4
|
+
// Copyright (c) 2026 Shiva Deore. All rights reserved.
|
|
5
|
+
// ============================================================
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.executor = void 0;
|
|
8
|
+
const screenAgent_1 = require("../integrations/computerUse/screenAgent");
|
|
9
|
+
const apiRegistry_1 = require("../integrations/computerUse/apiRegistry");
|
|
10
|
+
const faultEngine_1 = require("./faultEngine");
|
|
11
|
+
const truthCheck_1 = require("./truthCheck");
|
|
12
|
+
const memoryLayers_1 = require("../memory/memoryLayers");
|
|
13
|
+
const toolRegistry_1 = require("./toolRegistry");
|
|
14
|
+
// ── Executor ──────────────────────────────────────────────────
|
|
15
|
+
class Executor {
|
|
16
|
+
constructor() {
|
|
17
|
+
/** Exposed as a getter so the API route can read live progress. */
|
|
18
|
+
this.currentSession = null;
|
|
19
|
+
}
|
|
20
|
+
// ── Session management ────────────────────────────────────────
|
|
21
|
+
startSession(goal) {
|
|
22
|
+
const sessionId = `exec_${Date.now()}`;
|
|
23
|
+
this.currentSession = {
|
|
24
|
+
sessionId,
|
|
25
|
+
goal,
|
|
26
|
+
startedAt: new Date().toISOString(),
|
|
27
|
+
results: [],
|
|
28
|
+
totalDurationMs: 0,
|
|
29
|
+
successRate: 0,
|
|
30
|
+
};
|
|
31
|
+
return sessionId;
|
|
32
|
+
}
|
|
33
|
+
endSession() {
|
|
34
|
+
if (!this.currentSession)
|
|
35
|
+
return null;
|
|
36
|
+
const s = this.currentSession;
|
|
37
|
+
s.totalDurationMs = s.results.reduce((acc, r) => acc + r.durationMs, 0);
|
|
38
|
+
const successes = s.results.filter(r => r.status === 'success' || r.status === 'fallback' || r.status === 'retried').length;
|
|
39
|
+
s.successRate = s.results.length ? successes / s.results.length : 0;
|
|
40
|
+
this.currentSession = null;
|
|
41
|
+
return s;
|
|
42
|
+
}
|
|
43
|
+
// ── Main execute ──────────────────────────────────────────────
|
|
44
|
+
/**
|
|
45
|
+
* Execute a single ComputerUseAction with:
|
|
46
|
+
* - configurable retry loop with exponential backoff
|
|
47
|
+
* - timeout wrapper per attempt
|
|
48
|
+
* - TruthCheck verification on success
|
|
49
|
+
* - FaultEngine error classification on failure
|
|
50
|
+
* - fallback action when all retries exhausted
|
|
51
|
+
*/
|
|
52
|
+
async execute(action) {
|
|
53
|
+
const start = Date.now();
|
|
54
|
+
let retriesUsed = 0;
|
|
55
|
+
let usedFallback = false;
|
|
56
|
+
let verifiedByTruthCheck = false;
|
|
57
|
+
const maxRetries = action.retries ?? 2;
|
|
58
|
+
const timeoutMs = action.timeoutMs ?? 15000;
|
|
59
|
+
// ── Retry loop ────────────────────────────────────────────
|
|
60
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
61
|
+
try {
|
|
62
|
+
// Per-attempt timeout
|
|
63
|
+
const data = await Promise.race([
|
|
64
|
+
this.route(action),
|
|
65
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error('timeout')), timeoutMs)),
|
|
66
|
+
]);
|
|
67
|
+
// TruthCheck verification
|
|
68
|
+
verifiedByTruthCheck = await truthCheck_1.truthCheck.verifyAction(action.type, { actionId: action.id });
|
|
69
|
+
const result = {
|
|
70
|
+
actionId: action.id,
|
|
71
|
+
status: retriesUsed > 0 ? 'retried' : 'success',
|
|
72
|
+
data,
|
|
73
|
+
durationMs: Date.now() - start,
|
|
74
|
+
retriesUsed,
|
|
75
|
+
usedFallback,
|
|
76
|
+
verifiedByTruthCheck,
|
|
77
|
+
};
|
|
78
|
+
await this.audit(action, result);
|
|
79
|
+
this.currentSession?.results.push(result);
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
const classified = this.classifyError(err);
|
|
84
|
+
// Retry if retryable and attempts remain
|
|
85
|
+
if (classified.retryable && attempt < maxRetries) {
|
|
86
|
+
retriesUsed++;
|
|
87
|
+
console.warn(`[Executor] Retry ${retriesUsed}/${maxRetries} for action ${action.id} — ${classified.message}`);
|
|
88
|
+
await new Promise(r => setTimeout(r, 800 * retriesUsed)); // linear backoff
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
// Attempt fallback action
|
|
92
|
+
if (action.fallback && !usedFallback) {
|
|
93
|
+
usedFallback = true;
|
|
94
|
+
console.warn(`[Executor] Running fallback for action ${action.id}`);
|
|
95
|
+
try {
|
|
96
|
+
const fallbackData = await this.route(action.fallback);
|
|
97
|
+
const result = {
|
|
98
|
+
actionId: action.id,
|
|
99
|
+
status: 'fallback',
|
|
100
|
+
data: fallbackData,
|
|
101
|
+
durationMs: Date.now() - start,
|
|
102
|
+
retriesUsed,
|
|
103
|
+
usedFallback: true,
|
|
104
|
+
verifiedByTruthCheck: false,
|
|
105
|
+
};
|
|
106
|
+
await this.audit(action, result);
|
|
107
|
+
this.currentSession?.results.push(result);
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
// Fallback also failed — fall through to fail result
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// All attempts and fallback exhausted
|
|
115
|
+
const result = {
|
|
116
|
+
actionId: action.id,
|
|
117
|
+
status: 'failed',
|
|
118
|
+
error: classified,
|
|
119
|
+
durationMs: Date.now() - start,
|
|
120
|
+
retriesUsed,
|
|
121
|
+
usedFallback,
|
|
122
|
+
verifiedByTruthCheck,
|
|
123
|
+
};
|
|
124
|
+
await this.audit(action, result);
|
|
125
|
+
this.currentSession?.results.push(result);
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Should never be reached
|
|
130
|
+
return {
|
|
131
|
+
actionId: action.id,
|
|
132
|
+
status: 'skipped',
|
|
133
|
+
durationMs: Date.now() - start,
|
|
134
|
+
retriesUsed: 0,
|
|
135
|
+
usedFallback: false,
|
|
136
|
+
verifiedByTruthCheck: false,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
// ── Smart routing ─────────────────────────────────────────────
|
|
140
|
+
async route(action) {
|
|
141
|
+
switch (action.type) {
|
|
142
|
+
case 'api_call': {
|
|
143
|
+
const a = action;
|
|
144
|
+
const { result } = await apiRegistry_1.apiRegistry.execute(a.service, {
|
|
145
|
+
endpoint: a.endpoint,
|
|
146
|
+
method: a.method,
|
|
147
|
+
payload: a.payload,
|
|
148
|
+
headers: a.headers,
|
|
149
|
+
});
|
|
150
|
+
return result;
|
|
151
|
+
}
|
|
152
|
+
case 'click':
|
|
153
|
+
case 'type':
|
|
154
|
+
case 'scroll':
|
|
155
|
+
case 'keypress':
|
|
156
|
+
case 'screenshot':
|
|
157
|
+
return screenAgent_1.screenAgent.execute(action);
|
|
158
|
+
default: {
|
|
159
|
+
// Real tool execution via centralized toolRegistry
|
|
160
|
+
const a = action;
|
|
161
|
+
const payload = a.payload || { command: a.command || a.description };
|
|
162
|
+
const result = await (0, toolRegistry_1.executeTool)(a.type, payload);
|
|
163
|
+
if (!result.success)
|
|
164
|
+
throw new Error(result.error || 'Tool execution failed');
|
|
165
|
+
return result.output;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// ── Error classification ──────────────────────────────────────
|
|
170
|
+
/**
|
|
171
|
+
* Map a raw error to a typed ExecutorError.
|
|
172
|
+
* Uses FaultEngine for the repair suggestion, then performs pattern
|
|
173
|
+
* matching on the message to determine ExecutorErrorType.
|
|
174
|
+
*/
|
|
175
|
+
classifyError(err) {
|
|
176
|
+
const msg = err?.message ?? String(err);
|
|
177
|
+
// FaultEngine for repair suggestion (sync call)
|
|
178
|
+
let repairSuggestion;
|
|
179
|
+
try {
|
|
180
|
+
const fault = faultEngine_1.faultEngine.classify(msg);
|
|
181
|
+
repairSuggestion = fault.repairCommand ?? fault.manualFix;
|
|
182
|
+
}
|
|
183
|
+
catch { /* non-fatal */ }
|
|
184
|
+
let type = 'UNKNOWN';
|
|
185
|
+
let retryable = true;
|
|
186
|
+
if (msg.includes('timeout')) {
|
|
187
|
+
type = 'TIMEOUT';
|
|
188
|
+
retryable = true;
|
|
189
|
+
}
|
|
190
|
+
else if (/API|fetch|ECONNREFUSED|ENOTFOUND/i.test(msg)) {
|
|
191
|
+
type = 'API_ERROR';
|
|
192
|
+
retryable = true;
|
|
193
|
+
}
|
|
194
|
+
else if (/selector|element|visible/i.test(msg)) {
|
|
195
|
+
type = 'UI_ERROR';
|
|
196
|
+
retryable = true;
|
|
197
|
+
}
|
|
198
|
+
else if (/screen|mouse|keyboard/i.test(msg)) {
|
|
199
|
+
type = 'SCREEN_ERROR';
|
|
200
|
+
retryable = true;
|
|
201
|
+
}
|
|
202
|
+
else if (/Rejected by|CommandGate/i.test(msg)) {
|
|
203
|
+
type = 'REJECTED_BY_USER';
|
|
204
|
+
retryable = false;
|
|
205
|
+
}
|
|
206
|
+
else if (/confidence/i.test(msg)) {
|
|
207
|
+
type = 'CONFIDENCE_TOO_LOW';
|
|
208
|
+
retryable = false;
|
|
209
|
+
}
|
|
210
|
+
else if (/Unknown action/i.test(msg)) {
|
|
211
|
+
type = 'VALIDATION_ERROR';
|
|
212
|
+
retryable = false;
|
|
213
|
+
}
|
|
214
|
+
return { type, message: msg, retryable, repairSuggestion };
|
|
215
|
+
}
|
|
216
|
+
// ── Audit ─────────────────────────────────────────────────────
|
|
217
|
+
async audit(action, result) {
|
|
218
|
+
const entry = `[${new Date().toISOString()}] ${action.type} → ${result.status}` +
|
|
219
|
+
` (${result.durationMs}ms, retries:${result.retriesUsed})` +
|
|
220
|
+
(result.error ? ` | ERROR: ${result.error.message}` : '');
|
|
221
|
+
memoryLayers_1.memoryLayers.write(entry, ['computer_use', 'audit', result.status]);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
exports.executor = new Executor();
|