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,212 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ============================================================
|
|
3
|
+
// DevOS — Autonomous AI Execution System
|
|
4
|
+
// Copyright (c) 2026 Shiva Deore. All rights reserved.
|
|
5
|
+
// ============================================================
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.memoryExtractor = void 0;
|
|
11
|
+
// core/memoryExtractor.ts — Post-conversation durable memory extraction.
|
|
12
|
+
// After every conversation ends, scans messages and writes facts to
|
|
13
|
+
// workspace/memory/ as typed frontmatter markdown files.
|
|
14
|
+
// Maintains workspace/memory/MEMORY_INDEX.md (max 100 entries).
|
|
15
|
+
const fs_1 = __importDefault(require("fs"));
|
|
16
|
+
const path_1 = __importDefault(require("path"));
|
|
17
|
+
const auxiliaryClient_1 = require("./auxiliaryClient");
|
|
18
|
+
const MEMORY_DIR = path_1.default.join(process.cwd(), 'workspace', 'memory');
|
|
19
|
+
const INDEX_PATH = path_1.default.join(MEMORY_DIR, 'MEMORY_INDEX.md');
|
|
20
|
+
const SESSIONS_DIR = path_1.default.join(process.cwd(), 'workspace', 'sessions');
|
|
21
|
+
const SOURCE_CONFIDENCE = {
|
|
22
|
+
user_stated: 1.0,
|
|
23
|
+
tool_result: 0.8,
|
|
24
|
+
llm_inferred: 0.5,
|
|
25
|
+
};
|
|
26
|
+
// ── Helpers ───────────────────────────────────────────────────
|
|
27
|
+
function memoryFilePath(filename) {
|
|
28
|
+
return path_1.default.join(MEMORY_DIR, filename);
|
|
29
|
+
}
|
|
30
|
+
function today() {
|
|
31
|
+
return new Date().toISOString().split('T')[0];
|
|
32
|
+
}
|
|
33
|
+
function readIndex() {
|
|
34
|
+
try {
|
|
35
|
+
if (!fs_1.default.existsSync(INDEX_PATH))
|
|
36
|
+
return [];
|
|
37
|
+
const content = fs_1.default.readFileSync(INDEX_PATH, 'utf-8');
|
|
38
|
+
return content.trim().split('\n')
|
|
39
|
+
.filter(l => l.startsWith('- ['))
|
|
40
|
+
.map(l => {
|
|
41
|
+
const m = l.match(/^- \[(.+?)\]\((.+?)\) — (.+)$/);
|
|
42
|
+
if (!m)
|
|
43
|
+
return null;
|
|
44
|
+
return { filename: m[2], title: m[1], type: 'project_fact', summary: m[3] };
|
|
45
|
+
})
|
|
46
|
+
.filter((e) => e !== null);
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
function writeIndex(entries) {
|
|
53
|
+
try {
|
|
54
|
+
const lines = entries.slice(0, 100).map(e => `- [${e.title}](${e.filename}) — ${e.summary}`);
|
|
55
|
+
fs_1.default.writeFileSync(INDEX_PATH, lines.join('\n') + '\n', 'utf-8');
|
|
56
|
+
}
|
|
57
|
+
catch (e) {
|
|
58
|
+
console.error('[MemoryExtractor] Index write failed:', e.message);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function buildExtractionPrompt(sessionContent, existingIndex) {
|
|
62
|
+
return `You are a memory extractor for DevOS. Read the session below and extract durable facts worth remembering.
|
|
63
|
+
|
|
64
|
+
EXISTING MEMORY INDEX:
|
|
65
|
+
${existingIndex || '(empty)'}
|
|
66
|
+
|
|
67
|
+
SESSION CONTENT:
|
|
68
|
+
${sessionContent.slice(0, 3000)}
|
|
69
|
+
|
|
70
|
+
Extract 1-5 memory items. For each one output JSON in this format:
|
|
71
|
+
[
|
|
72
|
+
{
|
|
73
|
+
"type": "user_preference|project_fact|tool_pattern|learned_behavior",
|
|
74
|
+
"filename": "user_name.md or project_architecture.md (use type prefix + snake_case descriptor)",
|
|
75
|
+
"title": "Short descriptive title",
|
|
76
|
+
"content": "Concise actionable fact. 1-4 sentences.",
|
|
77
|
+
"summary": "One-line summary for index",
|
|
78
|
+
"source": "user_stated|tool_result|llm_inferred",
|
|
79
|
+
"confidence": 0.5
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
Rules:
|
|
84
|
+
- Only extract facts that are genuinely useful in a future conversation
|
|
85
|
+
- Skip trivial or already-indexed facts
|
|
86
|
+
- learned_behavior: corrections, things to avoid
|
|
87
|
+
- tool_pattern: commands that work/fail, file paths
|
|
88
|
+
- project_fact: architecture, design decisions
|
|
89
|
+
- user_preference: communication style, preferences
|
|
90
|
+
- source rules:
|
|
91
|
+
- "user_stated": the user directly said/told this fact → confidence 1.0
|
|
92
|
+
- "tool_result": fact came from a tool's returned data → confidence 0.8
|
|
93
|
+
- "llm_inferred": you are summarizing or inferring from context → confidence 0.5
|
|
94
|
+
- Output ONLY valid JSON array, nothing else`;
|
|
95
|
+
}
|
|
96
|
+
// ── MemoryExtractor ───────────────────────────────────────────
|
|
97
|
+
class MemoryExtractor {
|
|
98
|
+
constructor() {
|
|
99
|
+
try {
|
|
100
|
+
fs_1.default.mkdirSync(MEMORY_DIR, { recursive: true });
|
|
101
|
+
}
|
|
102
|
+
catch { }
|
|
103
|
+
}
|
|
104
|
+
// ── Extract from session ───────────────────────────────────
|
|
105
|
+
async extractFromSession(sessionId) {
|
|
106
|
+
const sessionFile = path_1.default.join(SESSIONS_DIR, `${sessionId}.md`);
|
|
107
|
+
if (!fs_1.default.existsSync(sessionFile))
|
|
108
|
+
return;
|
|
109
|
+
try {
|
|
110
|
+
const sessionContent = fs_1.default.readFileSync(sessionFile, 'utf-8');
|
|
111
|
+
if (sessionContent.length < 100)
|
|
112
|
+
return; // too short
|
|
113
|
+
const existingIndex = fs_1.default.existsSync(INDEX_PATH)
|
|
114
|
+
? fs_1.default.readFileSync(INDEX_PATH, 'utf-8').slice(0, 2000)
|
|
115
|
+
: '';
|
|
116
|
+
const prompt = buildExtractionPrompt(sessionContent, existingIndex);
|
|
117
|
+
const raw = await auxiliaryClient_1.auxiliaryClient.complete(prompt, { task: 'memory_extraction', maxTokens: 300 });
|
|
118
|
+
if (!raw)
|
|
119
|
+
return;
|
|
120
|
+
// Parse JSON array from response
|
|
121
|
+
const jsonMatch = raw.replace(/```json\s*/g, '').replace(/```\s*/g, '').match(/\[[\s\S]*\]/);
|
|
122
|
+
if (!jsonMatch)
|
|
123
|
+
return;
|
|
124
|
+
const items = JSON.parse(jsonMatch[0]);
|
|
125
|
+
if (!Array.isArray(items) || items.length === 0)
|
|
126
|
+
return;
|
|
127
|
+
const existingEntries = readIndex();
|
|
128
|
+
for (const item of items) {
|
|
129
|
+
if (!item.filename || !item.title || !item.content)
|
|
130
|
+
continue;
|
|
131
|
+
const source = item.source || 'llm_inferred';
|
|
132
|
+
const confidence = item.confidence ?? SOURCE_CONFIDENCE[source];
|
|
133
|
+
await this.writeMemoryFile(item.filename, item.type, item.title, item.content, existingEntries, source, confidence, sessionId);
|
|
134
|
+
}
|
|
135
|
+
// Update index
|
|
136
|
+
writeIndex(existingEntries);
|
|
137
|
+
console.log(`[MemoryExtractor] Extracted ${items.length} memory item(s) from session ${sessionId}`);
|
|
138
|
+
}
|
|
139
|
+
catch (e) {
|
|
140
|
+
console.error('[MemoryExtractor] Extraction failed:', e.message);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// ── Write a single memory file ─────────────────────────────
|
|
144
|
+
async writeMemoryFile(filename, type, title, content, indexEntries, source = 'llm_inferred', confidence = 0.5, sessionId = '') {
|
|
145
|
+
const filePath = memoryFilePath(filename);
|
|
146
|
+
const now = today();
|
|
147
|
+
// Check if file already exists — update rather than duplicate
|
|
148
|
+
let created = now;
|
|
149
|
+
if (fs_1.default.existsSync(filePath)) {
|
|
150
|
+
try {
|
|
151
|
+
const existing = fs_1.default.readFileSync(filePath, 'utf-8');
|
|
152
|
+
const m = existing.match(/^created:\s*(.+)$/m);
|
|
153
|
+
if (m)
|
|
154
|
+
created = m[1].trim();
|
|
155
|
+
}
|
|
156
|
+
catch { }
|
|
157
|
+
}
|
|
158
|
+
const frontmatter = `---
|
|
159
|
+
title: ${title}
|
|
160
|
+
type: ${type}
|
|
161
|
+
created: ${created}
|
|
162
|
+
updated: ${now}
|
|
163
|
+
source: ${source}
|
|
164
|
+
confidence: ${confidence}
|
|
165
|
+
session: ${sessionId}
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
${content.trim()}
|
|
169
|
+
`;
|
|
170
|
+
try {
|
|
171
|
+
fs_1.default.writeFileSync(filePath, frontmatter, 'utf-8');
|
|
172
|
+
}
|
|
173
|
+
catch (e) {
|
|
174
|
+
console.error(`[MemoryExtractor] Write failed for ${filename}:`, e.message);
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
// Update or add index entry
|
|
178
|
+
const existing = indexEntries.findIndex(e => e.filename === filename);
|
|
179
|
+
const entry = { filename, title, type, summary: content.slice(0, 80).replace(/\n/g, ' ') };
|
|
180
|
+
if (existing >= 0) {
|
|
181
|
+
indexEntries[existing] = entry;
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
indexEntries.unshift(entry);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
// ── Load memory index for system prompt injection ──────────
|
|
188
|
+
loadMemoryIndex() {
|
|
189
|
+
try {
|
|
190
|
+
if (!fs_1.default.existsSync(INDEX_PATH))
|
|
191
|
+
return '';
|
|
192
|
+
return fs_1.default.readFileSync(INDEX_PATH, 'utf-8');
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
return '';
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// ── Load a specific memory file ────────────────────────────
|
|
199
|
+
loadMemoryFile(filename) {
|
|
200
|
+
try {
|
|
201
|
+
const p = memoryFilePath(filename);
|
|
202
|
+
if (!fs_1.default.existsSync(p))
|
|
203
|
+
return '';
|
|
204
|
+
return fs_1.default.readFileSync(p, 'utf-8');
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
return '';
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
// ── Singleton ──────────────────────────────────────────────────
|
|
212
|
+
exports.memoryExtractor = new MemoryExtractor();
|
|
@@ -0,0 +1,213 @@
|
|
|
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.nextId = nextId;
|
|
41
|
+
exports.appendRecord = appendRecord;
|
|
42
|
+
exports.loadAllRecords = loadAllRecords;
|
|
43
|
+
exports.loadRecordById = loadRecordById;
|
|
44
|
+
exports.assignId = assignId;
|
|
45
|
+
exports.runMigrationIfNeeded = runMigrationIfNeeded;
|
|
46
|
+
/**
|
|
47
|
+
* core/memoryIds.ts — Stable mem_NNNNNN IDs + append-only records.jsonl
|
|
48
|
+
*
|
|
49
|
+
* Sits on top of the existing 6-layer memory architecture.
|
|
50
|
+
* Does NOT touch conversationMemory, semanticMemory, knowledgeBase, etc.
|
|
51
|
+
*/
|
|
52
|
+
const fs = __importStar(require("fs"));
|
|
53
|
+
const path = __importStar(require("path"));
|
|
54
|
+
// ── Paths ──────────────────────────────────────────────────────────────────
|
|
55
|
+
const MEM_DIR = path.join(process.cwd(), 'workspace', 'memory');
|
|
56
|
+
const SEQUENCE_FILE = path.join(MEM_DIR, 'sequence.json');
|
|
57
|
+
const RECORDS_FILE = path.join(MEM_DIR, 'records.jsonl');
|
|
58
|
+
// ── Sequence counter ────────────────────────────────────────────────────────
|
|
59
|
+
function _ensureDir() {
|
|
60
|
+
fs.mkdirSync(MEM_DIR, { recursive: true });
|
|
61
|
+
}
|
|
62
|
+
function _readSeq() {
|
|
63
|
+
try {
|
|
64
|
+
if (!fs.existsSync(SEQUENCE_FILE))
|
|
65
|
+
return 0;
|
|
66
|
+
const d = JSON.parse(fs.readFileSync(SEQUENCE_FILE, 'utf-8'));
|
|
67
|
+
return typeof d.next === 'number' ? d.next : 0;
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return 0;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function _writeSeq(n) {
|
|
74
|
+
_ensureDir();
|
|
75
|
+
fs.writeFileSync(SEQUENCE_FILE, JSON.stringify({ next: n }), 'utf-8');
|
|
76
|
+
}
|
|
77
|
+
function nextId() {
|
|
78
|
+
const n = _readSeq();
|
|
79
|
+
_writeSeq(n + 1);
|
|
80
|
+
return `mem_${String(n + 1).padStart(6, '0')}`;
|
|
81
|
+
}
|
|
82
|
+
// ── Record persistence ──────────────────────────────────────────────────────
|
|
83
|
+
function appendRecord(record) {
|
|
84
|
+
_ensureDir();
|
|
85
|
+
fs.appendFileSync(RECORDS_FILE, JSON.stringify(record) + '\n', 'utf-8');
|
|
86
|
+
}
|
|
87
|
+
function loadAllRecords() {
|
|
88
|
+
try {
|
|
89
|
+
if (!fs.existsSync(RECORDS_FILE))
|
|
90
|
+
return [];
|
|
91
|
+
return fs.readFileSync(RECORDS_FILE, 'utf-8')
|
|
92
|
+
.split('\n')
|
|
93
|
+
.filter(l => l.trim())
|
|
94
|
+
.map(l => {
|
|
95
|
+
try {
|
|
96
|
+
return JSON.parse(l);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
})
|
|
102
|
+
.filter((r) => r !== null);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
return [];
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
function loadRecordById(id) {
|
|
109
|
+
const all = loadAllRecords();
|
|
110
|
+
return all.find(r => r.id === id) ?? null;
|
|
111
|
+
}
|
|
112
|
+
// ── ID assignment helper ────────────────────────────────────────────────────
|
|
113
|
+
function assignId(partial) {
|
|
114
|
+
const record = {
|
|
115
|
+
id: partial.id ?? nextId(),
|
|
116
|
+
timestamp: partial.timestamp ?? new Date().toISOString(),
|
|
117
|
+
type: partial.type ?? 'observation',
|
|
118
|
+
content: partial.content ?? '',
|
|
119
|
+
summary: partial.summary ?? _autoSummary(partial.content ?? ''),
|
|
120
|
+
sessionId: partial.sessionId,
|
|
121
|
+
tags: partial.tags,
|
|
122
|
+
entityRefs: partial.entityRefs,
|
|
123
|
+
};
|
|
124
|
+
appendRecord(record);
|
|
125
|
+
return record;
|
|
126
|
+
}
|
|
127
|
+
function _autoSummary(content) {
|
|
128
|
+
// Take first non-empty line, trim to 100 chars
|
|
129
|
+
const first = content.split('\n').find(l => l.trim()) ?? content;
|
|
130
|
+
return first.slice(0, 100).trim();
|
|
131
|
+
}
|
|
132
|
+
// ── One-time migration ──────────────────────────────────────────────────────
|
|
133
|
+
function runMigrationIfNeeded() {
|
|
134
|
+
if (fs.existsSync(RECORDS_FILE))
|
|
135
|
+
return 0; // already migrated
|
|
136
|
+
_ensureDir();
|
|
137
|
+
const records = [];
|
|
138
|
+
// Source 1: workspace/memory/memory.json (task/agent results)
|
|
139
|
+
try {
|
|
140
|
+
const raw = fs.readFileSync(path.join(MEM_DIR, 'memory.json'), 'utf-8');
|
|
141
|
+
const parsed = JSON.parse(raw);
|
|
142
|
+
const items = Array.isArray(parsed) ? parsed : (parsed.value ?? []);
|
|
143
|
+
for (const item of items) {
|
|
144
|
+
const v = item.value ?? {};
|
|
145
|
+
const content = [
|
|
146
|
+
v.goal ? `Goal: ${v.goal}` : '',
|
|
147
|
+
v.result ? `Result: ${String(v.result).slice(0, 800)}` : '',
|
|
148
|
+
v.role ? `Role: ${v.role}` : '',
|
|
149
|
+
].filter(Boolean).join('\n');
|
|
150
|
+
if (!content)
|
|
151
|
+
continue;
|
|
152
|
+
records.push({
|
|
153
|
+
timestamp: item.createdAt ?? new Date().toISOString(),
|
|
154
|
+
type: item.tags?.includes('task') ? 'interaction' : 'observation',
|
|
155
|
+
content,
|
|
156
|
+
summary: _autoSummary(v.goal ?? v.result ?? content),
|
|
157
|
+
tags: item.tags ?? [],
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
catch { /* non-fatal */ }
|
|
162
|
+
// Source 2: workspace/conversation-memory.json (conversation messages)
|
|
163
|
+
try {
|
|
164
|
+
const raw = fs.readFileSync(path.join(process.cwd(), 'workspace', 'conversation-memory.json'), 'utf-8');
|
|
165
|
+
const parsed = JSON.parse(raw);
|
|
166
|
+
const msgs = parsed.messages ?? [];
|
|
167
|
+
// Only migrate assistant messages that have meaningful content
|
|
168
|
+
for (const msg of msgs) {
|
|
169
|
+
if (msg.role !== 'assistant')
|
|
170
|
+
continue;
|
|
171
|
+
const content = String(msg.content ?? '').trim();
|
|
172
|
+
if (content.length < 20)
|
|
173
|
+
continue;
|
|
174
|
+
records.push({
|
|
175
|
+
timestamp: msg.timestamp ?? new Date().toISOString(),
|
|
176
|
+
type: 'interaction',
|
|
177
|
+
content: content.slice(0, 1000),
|
|
178
|
+
summary: _autoSummary(content),
|
|
179
|
+
sessionId: msg.sessionId,
|
|
180
|
+
tags: ['conversation'],
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
catch { /* non-fatal */ }
|
|
185
|
+
// Source 3: workspace/memory/MEMORY_INDEX.md (.md lines as facts)
|
|
186
|
+
try {
|
|
187
|
+
const raw = fs.readFileSync(path.join(MEM_DIR, 'MEMORY_INDEX.md'), 'utf-8');
|
|
188
|
+
const lines = raw.split('\n').filter(l => l.startsWith('- '));
|
|
189
|
+
for (const line of lines) {
|
|
190
|
+
const cleaned = line.replace(/^-\s*/, '').trim();
|
|
191
|
+
if (cleaned.length < 10)
|
|
192
|
+
continue;
|
|
193
|
+
records.push({
|
|
194
|
+
timestamp: new Date().toISOString(),
|
|
195
|
+
type: 'fact',
|
|
196
|
+
content: cleaned,
|
|
197
|
+
summary: cleaned.slice(0, 100),
|
|
198
|
+
tags: ['index'],
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
catch { /* non-fatal */ }
|
|
203
|
+
// Sort by timestamp ascending, assign IDs, write
|
|
204
|
+
records.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
|
|
205
|
+
let count = 0;
|
|
206
|
+
for (const rec of records) {
|
|
207
|
+
const id = nextId();
|
|
208
|
+
const record = { id, ...rec };
|
|
209
|
+
appendRecord(record);
|
|
210
|
+
count++;
|
|
211
|
+
}
|
|
212
|
+
return count;
|
|
213
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ============================================================
|
|
3
|
+
// DevOS — Autonomous AI Execution System
|
|
4
|
+
// Copyright (c) 2026 Shiva Deore. All rights reserved.
|
|
5
|
+
// ============================================================
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.buildGreetingPreamble = buildGreetingPreamble;
|
|
11
|
+
// core/memoryPreamble.ts — Phase 4: Greeting fast-path memory surface.
|
|
12
|
+
//
|
|
13
|
+
// When the user sends a greeting ("hi", "good morning", etc.) the semantic
|
|
14
|
+
// memory recall in streamChat produces no matches because there is no
|
|
15
|
+
// substantive query to match against. This module builds a compact
|
|
16
|
+
// "what I know right now" preamble from the live conversation facts so
|
|
17
|
+
// Aiden can open with context-aware continuity even on the very first
|
|
18
|
+
// sentence of a new session.
|
|
19
|
+
//
|
|
20
|
+
// Usage:
|
|
21
|
+
// const preamble = await buildGreetingPreamble()
|
|
22
|
+
// // => "GREETING CONTEXT:\nRecent files: report.py\nActive goals: ..." | null
|
|
23
|
+
const fs_1 = __importDefault(require("fs"));
|
|
24
|
+
const path_1 = __importDefault(require("path"));
|
|
25
|
+
const conversationMemory_1 = require("./conversationMemory");
|
|
26
|
+
const goalTracker_1 = require("./goalTracker");
|
|
27
|
+
const sessionMemory_1 = require("./sessionMemory");
|
|
28
|
+
const USER_MD = path_1.default.join(process.env.AIDEN_USER_DATA || process.cwd(), 'workspace', 'USER.md');
|
|
29
|
+
function readUserName() {
|
|
30
|
+
try {
|
|
31
|
+
if (!fs_1.default.existsSync(USER_MD))
|
|
32
|
+
return null;
|
|
33
|
+
const content = fs_1.default.readFileSync(USER_MD, 'utf-8');
|
|
34
|
+
const match = content.match(/^Name:\s*(.+)/m);
|
|
35
|
+
if (!match)
|
|
36
|
+
return null;
|
|
37
|
+
const name = match[1].trim();
|
|
38
|
+
if (!name || name.toLowerCase() === 'user')
|
|
39
|
+
return null;
|
|
40
|
+
return name;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function extractLastSessionSummary(raw) {
|
|
47
|
+
if (!raw)
|
|
48
|
+
return null;
|
|
49
|
+
const titleMatch = raw.match(/# Session Title\s*\n_?([^\n_#]+)/);
|
|
50
|
+
const stateMatch = raw.match(/# Current State\s*\n_?([\s\S]*?)(?=\n#|$)/);
|
|
51
|
+
const parts = [];
|
|
52
|
+
if (titleMatch?.[1]?.trim())
|
|
53
|
+
parts.push(`Last session: ${titleMatch[1].trim()}`);
|
|
54
|
+
if (stateMatch?.[1]?.trim()) {
|
|
55
|
+
const state = stateMatch[1].replace(/^_|_$/g, '').trim().slice(0, 120);
|
|
56
|
+
if (state)
|
|
57
|
+
parts.push(`State: ${state}`);
|
|
58
|
+
}
|
|
59
|
+
return parts.length > 0 ? parts.join(' — ') : null;
|
|
60
|
+
}
|
|
61
|
+
// ── Main export ───────────────────────────────────────────────────────────────
|
|
62
|
+
/**
|
|
63
|
+
* Build a compact preamble from live memory facts.
|
|
64
|
+
* Returns null when there is nothing meaningful to surface
|
|
65
|
+
* (e.g. a brand-new session with no prior history).
|
|
66
|
+
*/
|
|
67
|
+
async function buildGreetingPreamble(sessionId) {
|
|
68
|
+
try {
|
|
69
|
+
const facts = conversationMemory_1.conversationMemory.getFacts();
|
|
70
|
+
const goals = (0, goalTracker_1.getActiveGoalsSummary)();
|
|
71
|
+
const parts = [];
|
|
72
|
+
// User name from USER.md
|
|
73
|
+
const name = readUserName();
|
|
74
|
+
if (name)
|
|
75
|
+
parts.push(`User name: ${name}`);
|
|
76
|
+
// Last session context
|
|
77
|
+
if (sessionId) {
|
|
78
|
+
const lastCtx = sessionMemory_1.sessionMemory.getLastContext(sessionId);
|
|
79
|
+
const sessionSummary = extractLastSessionSummary(lastCtx);
|
|
80
|
+
if (sessionSummary)
|
|
81
|
+
parts.push(sessionSummary);
|
|
82
|
+
}
|
|
83
|
+
if (facts.lastFilesCreated.length > 0) {
|
|
84
|
+
parts.push(`Recent files: ${facts.lastFilesCreated.slice(-3).join(', ')}`);
|
|
85
|
+
}
|
|
86
|
+
if (facts.lastSearchQueries.length > 0) {
|
|
87
|
+
parts.push(`Recent searches: ${facts.lastSearchQueries.slice(-2).join(', ')}`);
|
|
88
|
+
}
|
|
89
|
+
if (facts.mentionedEntities.length > 0) {
|
|
90
|
+
parts.push(`Recent topics: ${facts.mentionedEntities.slice(-6).join(', ')}`);
|
|
91
|
+
}
|
|
92
|
+
if (facts.preferredPaths.length > 0) {
|
|
93
|
+
parts.push(`Frequent paths: ${facts.preferredPaths.slice(-2).join(', ')}`);
|
|
94
|
+
}
|
|
95
|
+
if (goals) {
|
|
96
|
+
// getActiveGoalsSummary() returns "Active goals:\n- title [status]: action\n..."
|
|
97
|
+
// Extract compact single-line titles to avoid double-labeling and regex capture bugs
|
|
98
|
+
const goalLines = goals.split('\n').filter((l) => l.trim().startsWith('- '));
|
|
99
|
+
const goalTitles = goalLines.map((l) => {
|
|
100
|
+
const m = l.match(/^-\s+(.+?)\s+\[/);
|
|
101
|
+
return m ? m[1] : l.replace(/^-\s+/, '').split('[')[0].trim();
|
|
102
|
+
}).filter(Boolean).join(', ');
|
|
103
|
+
if (goalTitles)
|
|
104
|
+
parts.push(`Active goals: ${goalTitles}`);
|
|
105
|
+
}
|
|
106
|
+
if (parts.length === 0)
|
|
107
|
+
return null;
|
|
108
|
+
return `GREETING CONTEXT (reference naturally if relevant — do not recite mechanically):\n${parts.join('\n')}`;
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
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.trackCitation = trackCitation;
|
|
8
|
+
exports.getSessionCitations = getSessionCitations;
|
|
9
|
+
exports.clearSessionCitations = clearSessionCitations;
|
|
10
|
+
exports.memsearch = memsearch;
|
|
11
|
+
exports.memtimeline = memtimeline;
|
|
12
|
+
exports.memget = memget;
|
|
13
|
+
/**
|
|
14
|
+
* core/memoryQuery.ts — 3-layer progressive disclosure memory query
|
|
15
|
+
*
|
|
16
|
+
* Layer 1 memsearch() — [{id, summary, type, date, score}] ~50 tok/hit
|
|
17
|
+
* Layer 2 memtimeline() — chronological ±window around a record ~200 tok
|
|
18
|
+
* Layer 3 memget() — full record bodies for selected IDs ~500-1000 tok each
|
|
19
|
+
*/
|
|
20
|
+
const memoryIds_1 = require("./memoryIds");
|
|
21
|
+
const _sessionCitations = new Map();
|
|
22
|
+
function trackCitation(id, summary) {
|
|
23
|
+
const c = _sessionCitations.get(id);
|
|
24
|
+
if (c) {
|
|
25
|
+
c.refs++;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
_sessionCitations.set(id, { id, summary, refs: 1 });
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function getSessionCitations() {
|
|
32
|
+
return Array.from(_sessionCitations.values());
|
|
33
|
+
}
|
|
34
|
+
function clearSessionCitations() {
|
|
35
|
+
_sessionCitations.clear();
|
|
36
|
+
}
|
|
37
|
+
async function memsearch(query, opts = {}) {
|
|
38
|
+
const limit = opts.limit ?? 10;
|
|
39
|
+
const records = (0, memoryIds_1.loadAllRecords)();
|
|
40
|
+
const words = query.toLowerCase().split(/\s+/).filter(w => w.length > 1);
|
|
41
|
+
if (words.length === 0) {
|
|
42
|
+
// No query words — return most recent
|
|
43
|
+
return records
|
|
44
|
+
.slice(-limit)
|
|
45
|
+
.reverse()
|
|
46
|
+
.map(r => _toHit(r, 0));
|
|
47
|
+
}
|
|
48
|
+
// Filter by type
|
|
49
|
+
let filtered = opts.type
|
|
50
|
+
? records.filter(r => r.type === opts.type)
|
|
51
|
+
: records;
|
|
52
|
+
// Filter by since
|
|
53
|
+
if (opts.since) {
|
|
54
|
+
const sinceMs = new Date(opts.since).getTime();
|
|
55
|
+
filtered = filtered.filter(r => new Date(r.timestamp).getTime() >= sinceMs);
|
|
56
|
+
}
|
|
57
|
+
// Score each record
|
|
58
|
+
const scored = filtered.map(r => {
|
|
59
|
+
const hay = (r.summary + ' ' + r.content).toLowerCase();
|
|
60
|
+
const hits = words.filter(w => hay.includes(w)).length;
|
|
61
|
+
const score = hits / words.length;
|
|
62
|
+
return { record: r, score };
|
|
63
|
+
});
|
|
64
|
+
// Filter zero-score, sort desc by score then recency
|
|
65
|
+
const hits = scored
|
|
66
|
+
.filter(x => x.score > 0)
|
|
67
|
+
.sort((a, b) => {
|
|
68
|
+
if (Math.abs(a.score - b.score) > 0.01)
|
|
69
|
+
return b.score - a.score;
|
|
70
|
+
return new Date(b.record.timestamp).getTime() - new Date(a.record.timestamp).getTime();
|
|
71
|
+
})
|
|
72
|
+
.slice(0, limit)
|
|
73
|
+
.map(x => _toHit(x.record, x.score));
|
|
74
|
+
// Track citations for pulse
|
|
75
|
+
for (const h of hits)
|
|
76
|
+
trackCitation(h.id, h.summary);
|
|
77
|
+
return hits;
|
|
78
|
+
}
|
|
79
|
+
function _toHit(r, score) {
|
|
80
|
+
return {
|
|
81
|
+
id: r.id,
|
|
82
|
+
summary: r.summary.slice(0, 120),
|
|
83
|
+
type: r.type,
|
|
84
|
+
date: r.timestamp.slice(0, 10),
|
|
85
|
+
score: Math.round(score * 100) / 100,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
async function memtimeline(centerId, opts = {}) {
|
|
89
|
+
const center = (0, memoryIds_1.loadRecordById)(centerId);
|
|
90
|
+
if (!center)
|
|
91
|
+
return null;
|
|
92
|
+
const windowMs = (opts.windowHours ?? 6) * 60 * 60 * 1000;
|
|
93
|
+
const centerMs = new Date(center.timestamp).getTime();
|
|
94
|
+
const allRecords = (0, memoryIds_1.loadAllRecords)();
|
|
95
|
+
const before = [];
|
|
96
|
+
const after = [];
|
|
97
|
+
for (const r of allRecords) {
|
|
98
|
+
if (r.id === centerId)
|
|
99
|
+
continue;
|
|
100
|
+
const t = new Date(r.timestamp).getTime();
|
|
101
|
+
const delta = t - centerMs;
|
|
102
|
+
if (Math.abs(delta) > windowMs)
|
|
103
|
+
continue;
|
|
104
|
+
const slim = {
|
|
105
|
+
id: r.id,
|
|
106
|
+
summary: r.summary.slice(0, 100),
|
|
107
|
+
type: r.type,
|
|
108
|
+
timestamp: r.timestamp,
|
|
109
|
+
};
|
|
110
|
+
if (delta < 0)
|
|
111
|
+
before.push(slim);
|
|
112
|
+
else
|
|
113
|
+
after.push(slim);
|
|
114
|
+
}
|
|
115
|
+
// Keep at most 5 before (most recent 5) and 5 after (earliest 5)
|
|
116
|
+
before.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime());
|
|
117
|
+
after.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
|
|
118
|
+
// Track citation
|
|
119
|
+
trackCitation(center.id, center.summary);
|
|
120
|
+
return {
|
|
121
|
+
center,
|
|
122
|
+
before: before.slice(0, 5),
|
|
123
|
+
after: after.slice(0, 5),
|
|
124
|
+
sessionContext: center.sessionId,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
async function memget(ids) {
|
|
128
|
+
const allRecords = (0, memoryIds_1.loadAllRecords)();
|
|
129
|
+
const byId = new Map(allRecords.map(r => [r.id, r]));
|
|
130
|
+
return ids.map(id => {
|
|
131
|
+
const record = byId.get(id) ?? null;
|
|
132
|
+
if (record)
|
|
133
|
+
trackCitation(id, record.summary);
|
|
134
|
+
return { id, record, found: record !== null };
|
|
135
|
+
});
|
|
136
|
+
}
|