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,203 @@
|
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
40
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
41
|
+
};
|
|
42
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
43
|
+
exports.loadBriefingConfig = loadBriefingConfig;
|
|
44
|
+
exports.saveBriefingConfig = saveBriefingConfig;
|
|
45
|
+
exports.generateBriefing = generateBriefing;
|
|
46
|
+
exports.deliverBriefing = deliverBriefing;
|
|
47
|
+
// core/morningBriefing.ts — Daily morning briefing: weather, markets, news,
|
|
48
|
+
// unfinished tasks, and a proactive automation suggestion.
|
|
49
|
+
const path_1 = __importDefault(require("path"));
|
|
50
|
+
const fs_1 = __importDefault(require("fs"));
|
|
51
|
+
const eonetTool_1 = require("../tools/eonetTool");
|
|
52
|
+
const BRIEFING_CONFIG_PATH = path_1.default.join(process.cwd(), 'workspace', 'morning-briefing.json');
|
|
53
|
+
const DEFAULT_CONFIG = {
|
|
54
|
+
enabled: false, // user must opt in
|
|
55
|
+
time: '08:00',
|
|
56
|
+
channels: ['dashboard'],
|
|
57
|
+
sections: {
|
|
58
|
+
unfinishedTasks: true,
|
|
59
|
+
calendar: true,
|
|
60
|
+
marketData: true,
|
|
61
|
+
weather: true,
|
|
62
|
+
news: true,
|
|
63
|
+
},
|
|
64
|
+
marketSymbols: ['NIFTY', 'SENSEX'],
|
|
65
|
+
city: 'Mumbai',
|
|
66
|
+
proactiveSuggestion: true,
|
|
67
|
+
};
|
|
68
|
+
// ── Config I/O ────────────────────────────────────────────────
|
|
69
|
+
function loadBriefingConfig() {
|
|
70
|
+
try {
|
|
71
|
+
if (fs_1.default.existsSync(BRIEFING_CONFIG_PATH)) {
|
|
72
|
+
return { ...DEFAULT_CONFIG, ...JSON.parse(fs_1.default.readFileSync(BRIEFING_CONFIG_PATH, 'utf-8')) };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch { }
|
|
76
|
+
return { ...DEFAULT_CONFIG };
|
|
77
|
+
}
|
|
78
|
+
function saveBriefingConfig(config) {
|
|
79
|
+
fs_1.default.mkdirSync(path_1.default.dirname(BRIEFING_CONFIG_PATH), { recursive: true });
|
|
80
|
+
fs_1.default.writeFileSync(BRIEFING_CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
81
|
+
}
|
|
82
|
+
// ── Briefing generator ────────────────────────────────────────
|
|
83
|
+
async function generateBriefing(config) {
|
|
84
|
+
const parts = [];
|
|
85
|
+
const now = new Date();
|
|
86
|
+
const timeStr = now.toLocaleTimeString('en-IN', { hour: '2-digit', minute: '2-digit' });
|
|
87
|
+
const dateStr = now.toLocaleDateString('en-IN', { weekday: 'long', month: 'long', day: 'numeric' });
|
|
88
|
+
parts.push(`Good morning. It is ${timeStr} on ${dateStr}.`);
|
|
89
|
+
parts.push('');
|
|
90
|
+
// ── Section 1: Unfinished tasks from yesterday ────────────
|
|
91
|
+
if (config.sections.unfinishedTasks) {
|
|
92
|
+
try {
|
|
93
|
+
const { auditTrail } = await Promise.resolve().then(() => __importStar(require('./auditTrail')));
|
|
94
|
+
const entries = auditTrail.getToday();
|
|
95
|
+
const failed = entries.filter((e) => !e.success);
|
|
96
|
+
if (failed.length > 0) {
|
|
97
|
+
const names = failed.map((e) => e.tool || e.action).filter(Boolean).slice(0, 3).join(', ');
|
|
98
|
+
parts.push(`**Unfinished from yesterday:** ${failed.length} task${failed.length > 1 ? 's' : ''} did not complete${names ? ' — ' + names : ''}.`);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
parts.push(`**Yesterday:** All tasks completed successfully.`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
parts.push(`**Tasks:** No data from yesterday.`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// ── Section 2: Market data — personalised ────────────────
|
|
109
|
+
if (config.sections.marketData && config.marketSymbols.length > 0) {
|
|
110
|
+
try {
|
|
111
|
+
const { executeTool } = await Promise.resolve().then(() => __importStar(require('./toolRegistry')));
|
|
112
|
+
const result = await executeTool('get_market_data', { symbol: config.marketSymbols[0] });
|
|
113
|
+
if (result.success) {
|
|
114
|
+
parts.push(`**Markets:** ${result.output.slice(0, 120)}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch { }
|
|
118
|
+
}
|
|
119
|
+
// ── Section 3: Weather — one line ────────────────────────
|
|
120
|
+
if (config.sections.weather) {
|
|
121
|
+
try {
|
|
122
|
+
const { executeTool } = await Promise.resolve().then(() => __importStar(require('./toolRegistry')));
|
|
123
|
+
const result = await executeTool('web_search', { query: `${config.city} weather today` });
|
|
124
|
+
if (result.success) {
|
|
125
|
+
const match = result.output.match(/(\d+).*?\xb0[CF].*?(rain|sun|cloud|clear|humid|hot|warm|cold)/i);
|
|
126
|
+
parts.push(`**Weather:** ${config.city} — ${match ? match[0].slice(0, 60) : result.output.slice(0, 80)}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
catch { }
|
|
130
|
+
}
|
|
131
|
+
// ── Section 4: News — filtered by UserCognition interests ─
|
|
132
|
+
if (config.sections.news) {
|
|
133
|
+
try {
|
|
134
|
+
const { executeTool } = await Promise.resolve().then(() => __importStar(require('./toolRegistry')));
|
|
135
|
+
const { userCognitionProfile } = await Promise.resolve().then(() => __importStar(require('./userCognitionProfile')));
|
|
136
|
+
const profile = userCognitionProfile.getProfile();
|
|
137
|
+
const topic = profile?.interests?.[0] || 'technology India';
|
|
138
|
+
const result = await executeTool('web_search', { query: `${topic} news today` });
|
|
139
|
+
if (result.success) {
|
|
140
|
+
parts.push(`**News:** ${result.output.slice(0, 150)}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
catch { }
|
|
144
|
+
}
|
|
145
|
+
// ── Section 5: Proactive suggestion from pattern detection ─
|
|
146
|
+
if (config.proactiveSuggestion) {
|
|
147
|
+
try {
|
|
148
|
+
const { userCognitionProfile } = await Promise.resolve().then(() => __importStar(require('./userCognitionProfile')));
|
|
149
|
+
const patterns = userCognitionProfile.detectRepetitivePatterns();
|
|
150
|
+
if (patterns.length > 0) {
|
|
151
|
+
parts.push(`**Suggestion:** ${patterns[0].suggestion}`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
catch { }
|
|
155
|
+
}
|
|
156
|
+
// ── Section 6: NASA EONET natural events ──────────────────
|
|
157
|
+
try {
|
|
158
|
+
const eonetEvents = await (0, eonetTool_1.getActiveNaturalEvents)(1, 10);
|
|
159
|
+
const eonetSection = (0, eonetTool_1.formatEonetEvents)(eonetEvents);
|
|
160
|
+
if (eonetSection)
|
|
161
|
+
parts.push(eonetSection);
|
|
162
|
+
}
|
|
163
|
+
catch { }
|
|
164
|
+
return parts.join('\n');
|
|
165
|
+
}
|
|
166
|
+
// ── Briefing delivery ─────────────────────────────────────────
|
|
167
|
+
async function deliverBriefing(config) {
|
|
168
|
+
const [briefing, eonetEvents] = await Promise.all([
|
|
169
|
+
generateBriefing(config),
|
|
170
|
+
(0, eonetTool_1.getActiveNaturalEvents)(1, 10).catch(() => []),
|
|
171
|
+
]);
|
|
172
|
+
const eonetSummary = (0, eonetTool_1.getEonetSummary)(eonetEvents);
|
|
173
|
+
const date = new Date().toLocaleDateString('en-IN', { month: 'long', day: 'numeric' });
|
|
174
|
+
// Deliver to dashboard — POST as a special briefing event
|
|
175
|
+
try {
|
|
176
|
+
await fetch('http://localhost:4200/api/briefing', {
|
|
177
|
+
method: 'POST',
|
|
178
|
+
headers: { 'Content-Type': 'application/json' },
|
|
179
|
+
body: JSON.stringify({
|
|
180
|
+
content: briefing,
|
|
181
|
+
label: `Morning Briefing \u00b7 ${date}`,
|
|
182
|
+
type: 'briefing',
|
|
183
|
+
}),
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
catch { }
|
|
187
|
+
// Desktop notification — short punchy hook
|
|
188
|
+
try {
|
|
189
|
+
const { executeTool } = await Promise.resolve().then(() => __importStar(require('./toolRegistry')));
|
|
190
|
+
const firstLine = briefing
|
|
191
|
+
.split('\n')
|
|
192
|
+
.filter(l => l.trim() && !l.startsWith('Good morning'))
|
|
193
|
+
.slice(0, 2)
|
|
194
|
+
.join(' \u00b7 ')
|
|
195
|
+
.slice(0, 100);
|
|
196
|
+
const notifyMsg = [firstLine, eonetSummary].filter(Boolean).join(' \u00b7 ').slice(0, 140);
|
|
197
|
+
await executeTool('notify', {
|
|
198
|
+
title: `Good morning — Aiden briefing`,
|
|
199
|
+
message: notifyMsg,
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
catch { }
|
|
203
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
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.validateMultiGoalCoverage = validateMultiGoalCoverage;
|
|
8
|
+
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
9
|
+
// Stop-words to exclude from keyword matching
|
|
10
|
+
const STOP_WORDS = new Set([
|
|
11
|
+
'the', 'and', 'for', 'are', 'with', 'this', 'that', 'from', 'have',
|
|
12
|
+
'will', 'was', 'what', 'how', 'when', 'why', 'who', 'can', 'you',
|
|
13
|
+
'your', 'some', 'into', 'also', 'then', 'than', 'been', 'more',
|
|
14
|
+
'they', 'them', 'its', 'our', 'their', 'does', 'did', 'just', 'but',
|
|
15
|
+
]);
|
|
16
|
+
function extractKeywords(text) {
|
|
17
|
+
return text
|
|
18
|
+
.toLowerCase()
|
|
19
|
+
.replace(/[^a-z0-9\s]/g, ' ')
|
|
20
|
+
.split(/\s+/)
|
|
21
|
+
.filter(w => w.length > 3 && !STOP_WORDS.has(w));
|
|
22
|
+
}
|
|
23
|
+
// Coverage threshold: a goal is "covered" when ≥40% of its keywords appear
|
|
24
|
+
// in the response. This is intentionally lenient — the LLM often rephrases.
|
|
25
|
+
const COVERAGE_THRESHOLD = 0.4;
|
|
26
|
+
// ── Main export ───────────────────────────────────────────────────────────────
|
|
27
|
+
/**
|
|
28
|
+
* Check whether `response` covers all items in `goals`.
|
|
29
|
+
*
|
|
30
|
+
* @param _userMessage - Original user message (reserved for future LLM upgrade)
|
|
31
|
+
* @param response - Full assistant reply to validate
|
|
32
|
+
* @param goals - Goal phrases from AgentPlan.goals
|
|
33
|
+
*/
|
|
34
|
+
function validateMultiGoalCoverage(_userMessage, response, goals) {
|
|
35
|
+
if (!goals || goals.length === 0) {
|
|
36
|
+
return { covered: true, missed: [] };
|
|
37
|
+
}
|
|
38
|
+
const responseLower = response.toLowerCase();
|
|
39
|
+
const missed = [];
|
|
40
|
+
for (const goal of goals) {
|
|
41
|
+
const keywords = extractKeywords(goal);
|
|
42
|
+
if (keywords.length === 0)
|
|
43
|
+
continue; // nothing to check
|
|
44
|
+
const hits = keywords.filter(kw => responseLower.includes(kw)).length;
|
|
45
|
+
const ratio = hits / keywords.length;
|
|
46
|
+
if (ratio < COVERAGE_THRESHOLD) {
|
|
47
|
+
missed.push(goal);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return { covered: missed.length === 0, missed };
|
|
51
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
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.MAX_PARALLEL = void 0;
|
|
8
|
+
exports.chunkSteps = chunkSteps;
|
|
9
|
+
exports.hasParallelism = hasParallelism;
|
|
10
|
+
exports.toParallelGroups = toParallelGroups;
|
|
11
|
+
// ── Constants ──────────────────────────────────────────────────
|
|
12
|
+
/** Hard cap on simultaneous tool calls per batch. */
|
|
13
|
+
exports.MAX_PARALLEL = 3;
|
|
14
|
+
// ── Utilities ──────────────────────────────────────────────────
|
|
15
|
+
/**
|
|
16
|
+
* Split `steps` into sub-arrays of at most MAX_PARALLEL entries.
|
|
17
|
+
* Used by agentLoop when a batch exceeds the safety limit.
|
|
18
|
+
*/
|
|
19
|
+
function chunkSteps(steps, maxSize = exports.MAX_PARALLEL) {
|
|
20
|
+
const chunks = [];
|
|
21
|
+
for (let i = 0; i < steps.length; i += maxSize) {
|
|
22
|
+
chunks.push(steps.slice(i, i + maxSize));
|
|
23
|
+
}
|
|
24
|
+
return chunks;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Returns true if any group in the provided list contains more
|
|
28
|
+
* than one step — useful for conditional logging at the call site.
|
|
29
|
+
*/
|
|
30
|
+
function hasParallelism(groups) {
|
|
31
|
+
return groups.some(g => g.length > 1);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Converts a raw `ToolStep[][]` (output of buildDependencyGroups)
|
|
35
|
+
* into typed `ParallelGroup[]` for downstream consumers.
|
|
36
|
+
*/
|
|
37
|
+
function toParallelGroups(groups) {
|
|
38
|
+
return groups.map(steps => ({
|
|
39
|
+
steps,
|
|
40
|
+
parallel: steps.length > 1,
|
|
41
|
+
groupSize: steps.length,
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
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.recordTask = recordTask;
|
|
8
|
+
exports.start = start;
|
|
9
|
+
exports.getBuffer = getBuffer;
|
|
10
|
+
// core/passiveSkillObserver.ts — Background observer that detects
|
|
11
|
+
// repeated tool-call patterns and auto-drafts skills for review.
|
|
12
|
+
//
|
|
13
|
+
// Gated by: AIDEN_PASSIVE_LEARNING !== 'false'
|
|
14
|
+
// Throttled: 1 proposal per hour, max 5 pending at once.
|
|
15
|
+
const skillWriter_1 = require("./skillWriter");
|
|
16
|
+
// ── Rolling buffer ────────────────────────────────────────────
|
|
17
|
+
const BUFFER_SIZE = 100;
|
|
18
|
+
const MIN_SEQUENCE = 2; // min distinct tool calls in a workflow
|
|
19
|
+
const PATTERN_HITS = 3; // how many times pattern must recur
|
|
20
|
+
const taskBuffer = [];
|
|
21
|
+
// ── Throttle ──────────────────────────────────────────────────
|
|
22
|
+
let lastProposalAt = 0;
|
|
23
|
+
const THROTTLE_MS = 60 * 60 * 1000; // 1 hour
|
|
24
|
+
const MAX_PENDING = 5;
|
|
25
|
+
// ── Proposed set (in-memory, to avoid duplicate drafts) ───────
|
|
26
|
+
const proposedPatterns = new Set();
|
|
27
|
+
// ── recordTask ────────────────────────────────────────────────
|
|
28
|
+
// Called by executionLoop after each successful task completion.
|
|
29
|
+
function recordTask(task) {
|
|
30
|
+
taskBuffer.push(task);
|
|
31
|
+
if (taskBuffer.length > BUFFER_SIZE)
|
|
32
|
+
taskBuffer.shift();
|
|
33
|
+
analyzePatterns();
|
|
34
|
+
}
|
|
35
|
+
// ── analyzePatterns ───────────────────────────────────────────
|
|
36
|
+
// Looks for recurring multi-step tool sequences.
|
|
37
|
+
function analyzePatterns() {
|
|
38
|
+
// Throttle check
|
|
39
|
+
const now = Date.now();
|
|
40
|
+
if (now - lastProposalAt < THROTTLE_MS)
|
|
41
|
+
return;
|
|
42
|
+
// Max pending check
|
|
43
|
+
try {
|
|
44
|
+
const pending = (0, skillWriter_1.listPending)();
|
|
45
|
+
if (pending.length >= MAX_PENDING)
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
// Extract tool sequences (multi-step only)
|
|
52
|
+
const sequences = taskBuffer
|
|
53
|
+
.filter(t => t.toolCalls.length >= MIN_SEQUENCE)
|
|
54
|
+
.map(t => ({
|
|
55
|
+
key: sequenceKey(t.toolCalls),
|
|
56
|
+
prompt: t.userPrompt,
|
|
57
|
+
tools: t.toolCalls,
|
|
58
|
+
}));
|
|
59
|
+
if (sequences.length < PATTERN_HITS)
|
|
60
|
+
return;
|
|
61
|
+
// Count occurrences by sequence key
|
|
62
|
+
const counts = new Map();
|
|
63
|
+
for (const s of sequences) {
|
|
64
|
+
const arr = counts.get(s.key) ?? [];
|
|
65
|
+
arr.push(s);
|
|
66
|
+
counts.set(s.key, arr);
|
|
67
|
+
}
|
|
68
|
+
for (const [key, matches] of counts) {
|
|
69
|
+
if (matches.length < PATTERN_HITS)
|
|
70
|
+
continue;
|
|
71
|
+
if (proposedPatterns.has(key))
|
|
72
|
+
continue;
|
|
73
|
+
// Check prompt keyword overlap (user is doing similar things)
|
|
74
|
+
const prompts = matches.map(m => m.prompt.toLowerCase().split(/\s+/));
|
|
75
|
+
if (!hasKeywordOverlap(prompts))
|
|
76
|
+
continue;
|
|
77
|
+
// Draft the skill
|
|
78
|
+
const tools = matches[0].tools;
|
|
79
|
+
const skillName = inferSkillName(tools, matches.map(m => m.prompt));
|
|
80
|
+
proposedPatterns.add(key);
|
|
81
|
+
proposeDraft(skillName, tools, matches.map(m => m.prompt))
|
|
82
|
+
.then(() => { lastProposalAt = Date.now(); })
|
|
83
|
+
.catch(e => {
|
|
84
|
+
// Remove from proposed set so it can retry later
|
|
85
|
+
proposedPatterns.delete(key);
|
|
86
|
+
console.debug('[PassiveObserver] Draft failed:', e.message);
|
|
87
|
+
});
|
|
88
|
+
return; // one proposal per analyze cycle
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// ── sequenceKey ───────────────────────────────────────────────
|
|
92
|
+
// Creates a stable string key from a tool call sequence.
|
|
93
|
+
// Params are normalized to detect patterns even when values vary.
|
|
94
|
+
function sequenceKey(calls) {
|
|
95
|
+
return calls
|
|
96
|
+
.map(c => `${c.tool}(${Object.keys(c.params).sort().join(',')})`)
|
|
97
|
+
.join('→');
|
|
98
|
+
}
|
|
99
|
+
// ── hasKeywordOverlap ─────────────────────────────────────────
|
|
100
|
+
// Returns true if prompts share ≥2 significant words.
|
|
101
|
+
function hasKeywordOverlap(promptWords) {
|
|
102
|
+
if (promptWords.length < 2)
|
|
103
|
+
return true;
|
|
104
|
+
const STOP = new Set(['the', 'a', 'an', 'is', 'are', 'and', 'or', 'to', 'for', 'of', 'in', 'on', 'with', 'this', 'that', 'do', 'can', 'how']);
|
|
105
|
+
const firstSig = promptWords[0].filter(w => w.length > 3 && !STOP.has(w));
|
|
106
|
+
return promptWords.slice(1).some(words => {
|
|
107
|
+
const sig = new Set(words.filter(w => w.length > 3 && !STOP.has(w)));
|
|
108
|
+
return firstSig.filter(w => sig.has(w)).length >= 2;
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
// ── inferSkillName ────────────────────────────────────────────
|
|
112
|
+
// Generates a skill name from tool sequence + user prompts.
|
|
113
|
+
function inferSkillName(tools, prompts) {
|
|
114
|
+
const toolNames = [...new Set(tools.map(t => t.tool))];
|
|
115
|
+
// Pick the first two meaningful words from the most common prompt
|
|
116
|
+
const words = prompts[0]
|
|
117
|
+
.replace(/[^a-z0-9 ]/gi, ' ')
|
|
118
|
+
.split(/\s+/)
|
|
119
|
+
.filter(w => w.length > 3)
|
|
120
|
+
.slice(0, 3);
|
|
121
|
+
const base = words.length >= 2
|
|
122
|
+
? words.join(' ')
|
|
123
|
+
: toolNames.slice(0, 2).join(' + ');
|
|
124
|
+
return base.charAt(0).toUpperCase() + base.slice(1) + ' Workflow';
|
|
125
|
+
}
|
|
126
|
+
// ── templateParams ────────────────────────────────────────────
|
|
127
|
+
// Replaces highly-variable values with <placeholder> tokens.
|
|
128
|
+
function templateParams(tools) {
|
|
129
|
+
return tools
|
|
130
|
+
.map(c => {
|
|
131
|
+
const params = Object.entries(c.params)
|
|
132
|
+
.map(([k, v]) => {
|
|
133
|
+
const str = String(v);
|
|
134
|
+
// Long/URL/path values → placeholder
|
|
135
|
+
if (str.length > 40 || /^https?:\/\/|[\/\\]/.test(str)) {
|
|
136
|
+
return `${k}: <${k}>`;
|
|
137
|
+
}
|
|
138
|
+
return `${k}: ${str}`;
|
|
139
|
+
})
|
|
140
|
+
.join(', ');
|
|
141
|
+
return ` - ${c.tool}(${params})`;
|
|
142
|
+
})
|
|
143
|
+
.join('\n');
|
|
144
|
+
}
|
|
145
|
+
// ── proposeDraft ──────────────────────────────────────────────
|
|
146
|
+
// Writes a skill draft and logs a CLI notification.
|
|
147
|
+
async function proposeDraft(name, tools, prompts) {
|
|
148
|
+
const description = `Auto-detected workflow: ${tools.map(t => t.tool).join(' → ')}`;
|
|
149
|
+
const toolSection = templateParams(tools);
|
|
150
|
+
const examplePrompts = prompts.slice(0, 3)
|
|
151
|
+
.map(p => `- "${p.slice(0, 80)}"`)
|
|
152
|
+
.join('\n');
|
|
153
|
+
const content = `# ${name}
|
|
154
|
+
|
|
155
|
+
This workflow was automatically detected by Aiden's passive skill observer.
|
|
156
|
+
Review and edit before enabling.
|
|
157
|
+
|
|
158
|
+
## Tool Sequence
|
|
159
|
+
|
|
160
|
+
${toolSection}
|
|
161
|
+
|
|
162
|
+
## Example Prompts That Triggered This Pattern
|
|
163
|
+
|
|
164
|
+
${examplePrompts}
|
|
165
|
+
|
|
166
|
+
## Usage
|
|
167
|
+
|
|
168
|
+
When the user asks for a task similar to the examples above, follow the tool
|
|
169
|
+
sequence defined here. Adapt parameters as appropriate for the specific request.
|
|
170
|
+
`;
|
|
171
|
+
await (0, skillWriter_1.writeSkillDraft)({
|
|
172
|
+
name,
|
|
173
|
+
description,
|
|
174
|
+
category: 'productivity',
|
|
175
|
+
platform: 'any',
|
|
176
|
+
tags: [...new Set(tools.map(t => t.tool))].slice(0, 6),
|
|
177
|
+
version: '0.1.0',
|
|
178
|
+
content,
|
|
179
|
+
source: 'passive_observer',
|
|
180
|
+
sourceDetails: {
|
|
181
|
+
detectedAt: new Date().toISOString(),
|
|
182
|
+
toolSequence: tools.map(t => t.tool),
|
|
183
|
+
samplePrompts: prompts.slice(0, 3),
|
|
184
|
+
},
|
|
185
|
+
}, 'pending');
|
|
186
|
+
const id = (0, skillWriter_1.sanitizeSkillId)(name);
|
|
187
|
+
// Notify via stdout so the CLI can surface it
|
|
188
|
+
console.log(`\n 💡 Aiden proposed a new skill: ${name}`);
|
|
189
|
+
console.log(` Review: /skills review ${id}\n`);
|
|
190
|
+
}
|
|
191
|
+
// ── start ─────────────────────────────────────────────────────
|
|
192
|
+
// Wired by api/server.ts. No-op if AIDEN_PASSIVE_LEARNING=false.
|
|
193
|
+
function start() {
|
|
194
|
+
if (process.env.AIDEN_PASSIVE_LEARNING === 'false') {
|
|
195
|
+
console.log('[PassiveObserver] Disabled via AIDEN_PASSIVE_LEARNING=false');
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
console.log('[PassiveObserver] Started — watching for repeated tool patterns');
|
|
199
|
+
}
|
|
200
|
+
// ── getBuffer ─────────────────────────────────────────────────
|
|
201
|
+
// Exposed for testing.
|
|
202
|
+
function getBuffer() {
|
|
203
|
+
return [...taskBuffer];
|
|
204
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// core/paths.ts — Cross-platform user-data directory helpers.
|
|
3
|
+
//
|
|
4
|
+
// Windows : %APPDATA%\aiden (roaming)
|
|
5
|
+
// %LOCALAPPDATA%\aiden\cache
|
|
6
|
+
// macOS : ~/Library/Application Support/aiden
|
|
7
|
+
// ~/Library/Caches/aiden
|
|
8
|
+
// Linux : $XDG_DATA_HOME/aiden (default ~/.local/share/aiden)
|
|
9
|
+
// $XDG_CACHE_HOME/aiden (default ~/.cache/aiden)
|
|
10
|
+
// $XDG_CONFIG_HOME/aiden (default ~/.config/aiden)
|
|
11
|
+
//
|
|
12
|
+
// All paths can be overridden at runtime via AIDEN_USER_DATA / AIDEN_CONFIG_DIR.
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.getUserDataDir = getUserDataDir;
|
|
18
|
+
exports.getConfigDir = getConfigDir;
|
|
19
|
+
exports.getCacheDir = getCacheDir;
|
|
20
|
+
const os_1 = __importDefault(require("os"));
|
|
21
|
+
const path_1 = __importDefault(require("path"));
|
|
22
|
+
const APP_NAME = 'aiden';
|
|
23
|
+
/** Primary user-data root (config, workspace, logs). */
|
|
24
|
+
function getUserDataDir() {
|
|
25
|
+
if (process.env.AIDEN_USER_DATA)
|
|
26
|
+
return process.env.AIDEN_USER_DATA;
|
|
27
|
+
switch (process.platform) {
|
|
28
|
+
case 'win32':
|
|
29
|
+
return path_1.default.join(process.env.APPDATA || path_1.default.join(os_1.default.homedir(), 'AppData', 'Roaming'), APP_NAME);
|
|
30
|
+
case 'darwin':
|
|
31
|
+
return path_1.default.join(os_1.default.homedir(), 'Library', 'Application Support', APP_NAME);
|
|
32
|
+
default:
|
|
33
|
+
// Linux / FreeBSD / WSL
|
|
34
|
+
return path_1.default.join(process.env.XDG_DATA_HOME || path_1.default.join(os_1.default.homedir(), '.local', 'share'), APP_NAME);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** Config directory (separate from data on Linux/XDG). */
|
|
38
|
+
function getConfigDir() {
|
|
39
|
+
if (process.env.AIDEN_CONFIG_DIR)
|
|
40
|
+
return process.env.AIDEN_CONFIG_DIR;
|
|
41
|
+
if (process.platform === 'linux') {
|
|
42
|
+
return path_1.default.join(process.env.XDG_CONFIG_HOME || path_1.default.join(os_1.default.homedir(), '.config'), APP_NAME);
|
|
43
|
+
}
|
|
44
|
+
// Windows and macOS keep config inside the data dir
|
|
45
|
+
return path_1.default.join(getUserDataDir(), 'config');
|
|
46
|
+
}
|
|
47
|
+
/** Cache directory (safe to delete without data loss). */
|
|
48
|
+
function getCacheDir() {
|
|
49
|
+
switch (process.platform) {
|
|
50
|
+
case 'win32':
|
|
51
|
+
return path_1.default.join(process.env.LOCALAPPDATA || path_1.default.join(os_1.default.homedir(), 'AppData', 'Local'), APP_NAME, 'cache');
|
|
52
|
+
case 'darwin':
|
|
53
|
+
return path_1.default.join(os_1.default.homedir(), 'Library', 'Caches', APP_NAME);
|
|
54
|
+
default:
|
|
55
|
+
return path_1.default.join(process.env.XDG_CACHE_HOME || path_1.default.join(os_1.default.homedir(), '.cache'), APP_NAME);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
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.detectPatterns = detectPatterns;
|
|
8
|
+
exports.getPatternSummary = getPatternSummary;
|
|
9
|
+
// core/patternDetector.ts — Scans session history to surface
|
|
10
|
+
// recurring queries and usage patterns.
|
|
11
|
+
const fs_1 = require("fs");
|
|
12
|
+
const path_1 = require("path");
|
|
13
|
+
const SESSION_DIR = (0, path_1.join)(process.cwd(), 'workspace', 'sessions');
|
|
14
|
+
// ── Stop words ────────────────────────────────────────────────
|
|
15
|
+
const STOP_WORDS = new Set([
|
|
16
|
+
'what', 'that', 'this', 'with', 'from', 'have',
|
|
17
|
+
'been', 'will', 'they', 'your', 'about', 'would',
|
|
18
|
+
'there', 'their', 'which', 'could', 'other', 'just',
|
|
19
|
+
]);
|
|
20
|
+
// ── Helpers ───────────────────────────────────────────────────
|
|
21
|
+
function findCommonTopic(texts) {
|
|
22
|
+
const words = new Map();
|
|
23
|
+
for (const text of texts) {
|
|
24
|
+
new Set(text.toLowerCase().split(/\W+/).filter(w => w.length > 3)).forEach(w => words.set(w, (words.get(w) || 0) + 1));
|
|
25
|
+
}
|
|
26
|
+
for (const [word, count] of [...words.entries()].sort((a, b) => b[1] - a[1])) {
|
|
27
|
+
if (!STOP_WORDS.has(word) && count >= 3)
|
|
28
|
+
return word;
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
// ── Main detector ─────────────────────────────────────────────
|
|
33
|
+
async function detectPatterns() {
|
|
34
|
+
if (!(0, fs_1.existsSync)(SESSION_DIR))
|
|
35
|
+
return [];
|
|
36
|
+
const messages = [];
|
|
37
|
+
for (const file of (0, fs_1.readdirSync)(SESSION_DIR).slice(-30)) {
|
|
38
|
+
try {
|
|
39
|
+
const content = (0, fs_1.readFileSync)((0, path_1.join)(SESSION_DIR, file), 'utf8');
|
|
40
|
+
if (file.endsWith('.json')) {
|
|
41
|
+
const session = JSON.parse(content);
|
|
42
|
+
(session.messages ?? [])
|
|
43
|
+
.filter((m) => m.role === 'user')
|
|
44
|
+
.forEach((m) => messages.push({
|
|
45
|
+
text: m.content || '',
|
|
46
|
+
time: session.createdAt || file,
|
|
47
|
+
}));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch { }
|
|
51
|
+
}
|
|
52
|
+
if (messages.length === 0)
|
|
53
|
+
return [];
|
|
54
|
+
const patterns = [];
|
|
55
|
+
const queryMap = new Map();
|
|
56
|
+
for (const msg of messages) {
|
|
57
|
+
const norm = msg.text.toLowerCase()
|
|
58
|
+
.replace(/\d+/g, 'N')
|
|
59
|
+
.replace(/\b(today|yesterday|tomorrow)\b/g, 'DAY')
|
|
60
|
+
.trim()
|
|
61
|
+
.slice(0, 80);
|
|
62
|
+
if (norm.length > 5) {
|
|
63
|
+
queryMap.set(norm, (queryMap.get(norm) || 0) + 1);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
for (const [query, count] of queryMap) {
|
|
67
|
+
if (count >= 3) {
|
|
68
|
+
patterns.push({
|
|
69
|
+
type: 'recurring_query',
|
|
70
|
+
description: `Frequently asked: "${query}"`,
|
|
71
|
+
frequency: `${count} times`,
|
|
72
|
+
confidence: Math.min(count / 10, 1.0),
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return patterns.sort((a, b) => b.confidence - a.confidence);
|
|
77
|
+
}
|
|
78
|
+
function getPatternSummary(patterns) {
|
|
79
|
+
if (patterns.length === 0)
|
|
80
|
+
return '';
|
|
81
|
+
return 'Detected usage patterns:\n' +
|
|
82
|
+
patterns.slice(0, 3).map(p => `- ${p.description} (${p.frequency})`).join('\n');
|
|
83
|
+
}
|