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,186 @@
|
|
|
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.WebhookAdapter = void 0;
|
|
41
|
+
// core/channels/webhook.ts — Generic HMAC-signed HTTP webhook adapter.
|
|
42
|
+
//
|
|
43
|
+
// Config (env vars):
|
|
44
|
+
// WEBHOOK_SECRET — required; HMAC-SHA256 signing key
|
|
45
|
+
// WEBHOOK_ALLOWED_ORIGINS — optional comma-separated IP prefixes/addresses
|
|
46
|
+
//
|
|
47
|
+
// Registers endpoint: POST /api/webhook
|
|
48
|
+
//
|
|
49
|
+
// Request format:
|
|
50
|
+
// Headers: X-Aiden-Signature: sha256=<HMAC-SHA256 of raw body using WEBHOOK_SECRET>
|
|
51
|
+
// Body: { "message": "string", "context": {...}, "callbackUrl": "https://..." }
|
|
52
|
+
//
|
|
53
|
+
// Response modes:
|
|
54
|
+
// Sync (no callbackUrl): waits for agent response, returns { response: "..." }
|
|
55
|
+
// Async (callbackUrl set): responds { status: "queued" } then POSTs result to callbackUrl
|
|
56
|
+
//
|
|
57
|
+
// Security:
|
|
58
|
+
// - HMAC-SHA256 signature required on every request (timing-safe compare)
|
|
59
|
+
// - Optional origin IP allowlist (WEBHOOK_ALLOWED_ORIGINS)
|
|
60
|
+
// - No WEBHOOK_SECRET → 503 "Webhook disabled"
|
|
61
|
+
//
|
|
62
|
+
// No external SDK — uses Node.js built-in crypto only.
|
|
63
|
+
const crypto = __importStar(require("crypto"));
|
|
64
|
+
const gateway_1 = require("../gateway");
|
|
65
|
+
class WebhookAdapter {
|
|
66
|
+
constructor(app) {
|
|
67
|
+
this.name = 'webhook';
|
|
68
|
+
this.healthy = false;
|
|
69
|
+
this.secret = process.env.WEBHOOK_SECRET ?? '';
|
|
70
|
+
const rawOrigins = process.env.WEBHOOK_ALLOWED_ORIGINS ?? '';
|
|
71
|
+
this.allowedOrigins = rawOrigins
|
|
72
|
+
? rawOrigins.split(',').map(s => s.trim()).filter(Boolean)
|
|
73
|
+
: [];
|
|
74
|
+
this.app = app ?? null;
|
|
75
|
+
}
|
|
76
|
+
// ── Lifecycle ──────────────────────────────────────────────
|
|
77
|
+
async start() {
|
|
78
|
+
if (!this.app) {
|
|
79
|
+
console.warn('[Webhook] No Express app provided — endpoint not registered');
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (!this.secret) {
|
|
83
|
+
console.log('[Webhook] Disabled — set WEBHOOK_SECRET to enable');
|
|
84
|
+
// Register the route but return 503 so callers get a clear error
|
|
85
|
+
this.app.post('/api/webhook', (_req, res) => {
|
|
86
|
+
res.status(503).json({ error: 'Webhook disabled — set WEBHOOK_SECRET to enable' });
|
|
87
|
+
});
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
// ── POST /api/webhook ──────────────────────────────────
|
|
91
|
+
this.app.post('/api/webhook', async (req, res) => {
|
|
92
|
+
// 1. Origin check
|
|
93
|
+
if (this.allowedOrigins.length > 0) {
|
|
94
|
+
const forwarded = req.headers['x-forwarded-for'];
|
|
95
|
+
const remote = Array.isArray(forwarded) ? forwarded[0] : (forwarded ?? req.socket.remoteAddress ?? '');
|
|
96
|
+
if (!this.isAllowedOrigin(remote)) {
|
|
97
|
+
return res.status(403).json({ error: 'Origin not in WEBHOOK_ALLOWED_ORIGINS' });
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// 2. Signature verification
|
|
101
|
+
const signature = req.headers['x-aiden-signature'];
|
|
102
|
+
if (!this.verifySignature(req.body, signature)) {
|
|
103
|
+
return res.status(401).json({ error: 'Invalid or missing X-Aiden-Signature' });
|
|
104
|
+
}
|
|
105
|
+
// 3. Parse body
|
|
106
|
+
const { message, context, callbackUrl } = (req.body ?? {});
|
|
107
|
+
if (!message || typeof message !== 'string') {
|
|
108
|
+
return res.status(400).json({ error: '"message" field is required and must be a string' });
|
|
109
|
+
}
|
|
110
|
+
const contextNote = context
|
|
111
|
+
? `\nContext: ${JSON.stringify(context)}`
|
|
112
|
+
: '';
|
|
113
|
+
const fullMessage = message + contextNote;
|
|
114
|
+
if (callbackUrl) {
|
|
115
|
+
// ── Async mode ─────────────────────────────────────
|
|
116
|
+
res.json({ status: 'queued' });
|
|
117
|
+
this.runAndCallback(fullMessage, callbackUrl, context).catch(() => { });
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
// ── Sync mode ──────────────────────────────────────
|
|
121
|
+
try {
|
|
122
|
+
const response = await gateway_1.gateway.routeMessage({
|
|
123
|
+
channel: 'api',
|
|
124
|
+
channelId: 'webhook',
|
|
125
|
+
userId: 'webhook',
|
|
126
|
+
text: fullMessage,
|
|
127
|
+
timestamp: Date.now(),
|
|
128
|
+
});
|
|
129
|
+
res.json({ response });
|
|
130
|
+
}
|
|
131
|
+
catch (e) {
|
|
132
|
+
res.status(500).json({ error: e.message ?? 'Internal error' });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
this.healthy = true;
|
|
137
|
+
console.log('[Webhook] Enabled — POST /api/webhook (HMAC-SHA256 required)');
|
|
138
|
+
}
|
|
139
|
+
async stop() {
|
|
140
|
+
this.healthy = false;
|
|
141
|
+
// Express routes cannot be unregistered at runtime; we simply mark unhealthy
|
|
142
|
+
console.log('[Webhook] Stopped');
|
|
143
|
+
}
|
|
144
|
+
/** Not applicable — webhook is request-response, not push-based */
|
|
145
|
+
async send(_target, _message) { }
|
|
146
|
+
isHealthy() { return this.healthy; }
|
|
147
|
+
// ── Helpers ────────────────────────────────────────────────
|
|
148
|
+
verifySignature(body, signature) {
|
|
149
|
+
if (!signature)
|
|
150
|
+
return false;
|
|
151
|
+
const payload = typeof body === 'string' ? body : JSON.stringify(body);
|
|
152
|
+
const expected = 'sha256=' + crypto.createHmac('sha256', this.secret).update(payload).digest('hex');
|
|
153
|
+
try {
|
|
154
|
+
// timing-safe comparison — both buffers must be same length
|
|
155
|
+
if (signature.length !== expected.length)
|
|
156
|
+
return false;
|
|
157
|
+
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
isAllowedOrigin(origin) {
|
|
164
|
+
return this.allowedOrigins.some(allowed => origin === allowed || origin.startsWith(allowed));
|
|
165
|
+
}
|
|
166
|
+
async runAndCallback(message, callbackUrl, context) {
|
|
167
|
+
try {
|
|
168
|
+
const response = await gateway_1.gateway.routeMessage({
|
|
169
|
+
channel: 'api',
|
|
170
|
+
channelId: 'webhook',
|
|
171
|
+
userId: 'webhook',
|
|
172
|
+
text: message,
|
|
173
|
+
timestamp: Date.now(),
|
|
174
|
+
});
|
|
175
|
+
await fetch(callbackUrl, {
|
|
176
|
+
method: 'POST',
|
|
177
|
+
headers: { 'Content-Type': 'application/json' },
|
|
178
|
+
body: JSON.stringify({ response, context }),
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
catch (e) {
|
|
182
|
+
console.error('[Webhook] Async callback failed:', e.message);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
exports.WebhookAdapter = WebhookAdapter;
|
|
@@ -0,0 +1,185 @@
|
|
|
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.WhatsAppAdapter = void 0;
|
|
44
|
+
// core/channels/whatsapp.ts — WhatsApp channel adapter.
|
|
45
|
+
//
|
|
46
|
+
// Uses whatsapp-web.js (WebSocket-based, no business API required).
|
|
47
|
+
// On first run, a QR code is printed to the terminal — scan it with
|
|
48
|
+
// the WhatsApp mobile app. The session is then persisted so subsequent
|
|
49
|
+
// launches connect automatically.
|
|
50
|
+
//
|
|
51
|
+
// ⚠️ TERMS OF SERVICE NOTE:
|
|
52
|
+
// WhatsApp web automation is for personal use only.
|
|
53
|
+
// For production or commercial scale, use WhatsApp Business API
|
|
54
|
+
// (set WHATSAPP_BUSINESS_API_KEY) which is fully compliant with
|
|
55
|
+
// WhatsApp's terms. Web scraping at scale violates their ToS.
|
|
56
|
+
//
|
|
57
|
+
// Config (env vars):
|
|
58
|
+
// WHATSAPP_SESSION_PATH — path to persist session data
|
|
59
|
+
// (default: workspace/.whatsapp_session)
|
|
60
|
+
// WHATSAPP_ALLOWED_NUMBERS — optional comma-separated allowlist
|
|
61
|
+
// (+919812345678 format)
|
|
62
|
+
// WHATSAPP_BUSINESS_API_KEY — optional; if set, use official Business API
|
|
63
|
+
// instead of web automation
|
|
64
|
+
const path_1 = __importDefault(require("path"));
|
|
65
|
+
const gateway_1 = require("../gateway");
|
|
66
|
+
class WhatsAppAdapter {
|
|
67
|
+
constructor() {
|
|
68
|
+
this.name = 'whatsapp';
|
|
69
|
+
this.client = null;
|
|
70
|
+
this.healthy = false;
|
|
71
|
+
this.sessionPath = process.env.WHATSAPP_SESSION_PATH ?? path_1.default.join(process.cwd(), 'workspace', '.whatsapp_session');
|
|
72
|
+
const raw = process.env.WHATSAPP_ALLOWED_NUMBERS ?? '';
|
|
73
|
+
this.allowedNumbers = raw ? new Set(raw.split(',').map(s => s.trim()).filter(Boolean)) : new Set();
|
|
74
|
+
this.businessApiKey = process.env.WHATSAPP_BUSINESS_API_KEY ?? '';
|
|
75
|
+
}
|
|
76
|
+
// ── Lifecycle ──────────────────────────────────────────────
|
|
77
|
+
async start() {
|
|
78
|
+
// Opt-in guard — silent unless WHATSAPP_ENABLED=true
|
|
79
|
+
if (!process.env.WHATSAPP_ENABLED || process.env.WHATSAPP_ENABLED.toLowerCase() !== 'true') {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
// Attempt dynamic import — graceful degradation if module not available
|
|
83
|
+
let Client, LocalAuth;
|
|
84
|
+
try {
|
|
85
|
+
const wwebjs = await Promise.resolve().then(() => __importStar(require('whatsapp-web.js')));
|
|
86
|
+
Client = wwebjs.Client;
|
|
87
|
+
LocalAuth = wwebjs.LocalAuth;
|
|
88
|
+
}
|
|
89
|
+
catch (e) {
|
|
90
|
+
console.log('[WhatsApp] Disabled — whatsapp-web.js not available:', e.message);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
this.client = new Client({
|
|
94
|
+
authStrategy: new LocalAuth({ dataPath: this.sessionPath }),
|
|
95
|
+
puppeteer: {
|
|
96
|
+
headless: true,
|
|
97
|
+
args: ['--no-sandbox', '--disable-setuid-sandbox'],
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
// QR code for first-time auth
|
|
101
|
+
this.client.on('qr', (qr) => {
|
|
102
|
+
console.log('[WhatsApp] Scan this QR code with your WhatsApp mobile app:');
|
|
103
|
+
try {
|
|
104
|
+
const qrcode = require('qrcode-terminal');
|
|
105
|
+
qrcode.generate(qr, { small: true });
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
console.log('[WhatsApp] QR (raw):', qr);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
this.client.on('authenticated', () => {
|
|
112
|
+
console.log('[WhatsApp] Session authenticated — session persisted at', this.sessionPath);
|
|
113
|
+
});
|
|
114
|
+
this.client.on('ready', () => {
|
|
115
|
+
this.healthy = true;
|
|
116
|
+
console.log('[WhatsApp] Client ready');
|
|
117
|
+
gateway_1.gateway.registerChannel('whatsapp', async (msg) => {
|
|
118
|
+
await this.send(msg.channelId, msg.text);
|
|
119
|
+
return true;
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
this.client.on('disconnected', (reason) => {
|
|
123
|
+
this.healthy = false;
|
|
124
|
+
console.log('[WhatsApp] Disconnected:', reason);
|
|
125
|
+
});
|
|
126
|
+
this.client.on('message', async (msg) => {
|
|
127
|
+
// Skip non-text messages and group messages (from field ends with @g.us)
|
|
128
|
+
if (msg.from.endsWith('@g.us'))
|
|
129
|
+
return;
|
|
130
|
+
if (msg.type !== 'chat')
|
|
131
|
+
return;
|
|
132
|
+
const senderNumber = msg.from.replace('@c.us', '').replace(/^0/, '+');
|
|
133
|
+
if (!this.isAllowed(senderNumber))
|
|
134
|
+
return;
|
|
135
|
+
const response = await this.processMessage(msg.from, senderNumber, msg.body);
|
|
136
|
+
await msg.reply(response).catch((e) => console.error('[WhatsApp] reply error:', e.message));
|
|
137
|
+
});
|
|
138
|
+
try {
|
|
139
|
+
await this.client.initialize();
|
|
140
|
+
}
|
|
141
|
+
catch (e) {
|
|
142
|
+
console.log('[WhatsApp] Disabled — check WHATSAPP_SESSION_PATH:', e.message);
|
|
143
|
+
this.healthy = false;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
async stop() {
|
|
147
|
+
this.healthy = false;
|
|
148
|
+
if (this.client) {
|
|
149
|
+
gateway_1.gateway.unregisterChannel('whatsapp');
|
|
150
|
+
await this.client.destroy().catch(() => { });
|
|
151
|
+
this.client = null;
|
|
152
|
+
}
|
|
153
|
+
console.log('[WhatsApp] Disconnected');
|
|
154
|
+
}
|
|
155
|
+
async send(target, message) {
|
|
156
|
+
if (!this.client || !this.healthy)
|
|
157
|
+
return;
|
|
158
|
+
// Ensure target has @c.us suffix
|
|
159
|
+
const chatId = target.includes('@') ? target : `${target.replace('+', '')}@c.us`;
|
|
160
|
+
await this.client.sendMessage(chatId, message).catch((e) => console.error('[WhatsApp] send error:', e.message));
|
|
161
|
+
}
|
|
162
|
+
isHealthy() { return this.healthy; }
|
|
163
|
+
// ── Helpers ────────────────────────────────────────────────
|
|
164
|
+
isAllowed(number) {
|
|
165
|
+
if (this.allowedNumbers.size === 0)
|
|
166
|
+
return true;
|
|
167
|
+
return this.allowedNumbers.has(number);
|
|
168
|
+
}
|
|
169
|
+
async processMessage(chatId, userId, text) {
|
|
170
|
+
try {
|
|
171
|
+
return await gateway_1.gateway.routeMessage({
|
|
172
|
+
channel: 'whatsapp',
|
|
173
|
+
channelId: chatId,
|
|
174
|
+
userId,
|
|
175
|
+
text,
|
|
176
|
+
timestamp: Date.now(),
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
catch (e) {
|
|
180
|
+
console.error('[WhatsApp] routeMessage error:', e.message);
|
|
181
|
+
return '❌ Something went wrong. Try again.';
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
exports.WhatsAppAdapter = WhatsAppAdapter;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ============================================================
|
|
3
|
+
// DevOS — Autonomous AI Execution System
|
|
4
|
+
// Copyright (c) 2026 Shiva Deore. All rights reserved.
|
|
5
|
+
// ============================================================
|
|
6
|
+
//
|
|
7
|
+
// core/clarifyBus.ts — Global event bus for mid-task clarification questions.
|
|
8
|
+
//
|
|
9
|
+
// When the `clarify` tool fires:
|
|
10
|
+
// 1. It posts a ClarifyRequest to this bus.
|
|
11
|
+
// 2. The CLI (or any registered handler) picks it up, shows the question,
|
|
12
|
+
// collects an answer, and resolves the pending promise.
|
|
13
|
+
// 3. If no handler is registered, the bus auto-resolves with the first option
|
|
14
|
+
// (or free-text fallback) after a short timeout so headless runs never hang.
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.registerClarifyHandler = registerClarifyHandler;
|
|
17
|
+
exports.answer = answer;
|
|
18
|
+
exports.ask = ask;
|
|
19
|
+
const events_1 = require("events");
|
|
20
|
+
const bus = new events_1.EventEmitter();
|
|
21
|
+
bus.setMaxListeners(20);
|
|
22
|
+
// Pending requests keyed by id
|
|
23
|
+
const pending = new Map();
|
|
24
|
+
let handlerRegistered = false;
|
|
25
|
+
/**
|
|
26
|
+
* Called by the CLI (or any TUI layer) to claim clarify questions.
|
|
27
|
+
* The handler receives a ClarifyRequest and must call `answer(id, text)`
|
|
28
|
+
* when the user responds.
|
|
29
|
+
*/
|
|
30
|
+
function registerClarifyHandler(handler) {
|
|
31
|
+
bus.on('request', handler);
|
|
32
|
+
handlerRegistered = true;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Provide the user's answer to a pending clarify request.
|
|
36
|
+
* Called by the CLI handler after the user types their response.
|
|
37
|
+
*/
|
|
38
|
+
function answer(id, text) {
|
|
39
|
+
const resolve = pending.get(id);
|
|
40
|
+
if (resolve) {
|
|
41
|
+
pending.delete(id);
|
|
42
|
+
resolve(text);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
let seq = 1;
|
|
46
|
+
/**
|
|
47
|
+
* Ask a clarification question and wait for the answer.
|
|
48
|
+
* Resolves immediately with the first option (or empty string) if no
|
|
49
|
+
* TUI handler is registered (headless / API mode).
|
|
50
|
+
*/
|
|
51
|
+
async function ask(question, options, allowFreeText = true) {
|
|
52
|
+
const id = `clarify_${seq++}`;
|
|
53
|
+
const promise = new Promise(resolve => {
|
|
54
|
+
pending.set(id, resolve);
|
|
55
|
+
if (!handlerRegistered) {
|
|
56
|
+
// Headless fallback: use first option, or acknowledge text
|
|
57
|
+
const fallback = options?.[0] ?? 'yes';
|
|
58
|
+
pending.delete(id);
|
|
59
|
+
resolve(fallback);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
// Emit to registered TUI handler
|
|
63
|
+
bus.emit('request', { id, question, options, allowFreeText });
|
|
64
|
+
// Safety timeout — never hang the agent for more than 5 minutes
|
|
65
|
+
const timer = setTimeout(() => {
|
|
66
|
+
if (pending.has(id)) {
|
|
67
|
+
pending.delete(id);
|
|
68
|
+
resolve(options?.[0] ?? '');
|
|
69
|
+
}
|
|
70
|
+
}, 5 * 60 * 1000);
|
|
71
|
+
if (typeof timer.unref === 'function')
|
|
72
|
+
timer.unref();
|
|
73
|
+
});
|
|
74
|
+
return promise;
|
|
75
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
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.runInSandbox = runInSandbox;
|
|
11
|
+
// core/codeInterpreter.ts — Isolated code execution sandbox.
|
|
12
|
+
// Runs Python or Node.js scripts in per-session subdirectories under
|
|
13
|
+
// workspace/sandbox/interpreter/. Each session gets a clean directory;
|
|
14
|
+
// generated files are reported back and the directory is cleaned up
|
|
15
|
+
// automatically after 5 minutes.
|
|
16
|
+
const child_process_1 = require("child_process");
|
|
17
|
+
const fs_1 = __importDefault(require("fs"));
|
|
18
|
+
const path_1 = __importDefault(require("path"));
|
|
19
|
+
const SANDBOX_DIR = path_1.default.join(process.cwd(), 'workspace', 'sandbox', 'interpreter');
|
|
20
|
+
async function runInSandbox(code, language, packages) {
|
|
21
|
+
const start = Date.now();
|
|
22
|
+
fs_1.default.mkdirSync(SANDBOX_DIR, { recursive: true });
|
|
23
|
+
const sessionId = `session_${Date.now()}`;
|
|
24
|
+
const sessionDir = path_1.default.join(SANDBOX_DIR, sessionId);
|
|
25
|
+
fs_1.default.mkdirSync(sessionDir, { recursive: true });
|
|
26
|
+
// Schedule cleanup after 5 minutes regardless of outcome
|
|
27
|
+
const scheduleCleanup = () => {
|
|
28
|
+
setTimeout(() => {
|
|
29
|
+
try {
|
|
30
|
+
fs_1.default.rmSync(sessionDir, { recursive: true, force: true });
|
|
31
|
+
}
|
|
32
|
+
catch { }
|
|
33
|
+
}, 5 * 60 * 1000);
|
|
34
|
+
};
|
|
35
|
+
try {
|
|
36
|
+
if (language === 'python') {
|
|
37
|
+
// Install packages if requested
|
|
38
|
+
if (packages && packages.length > 0) {
|
|
39
|
+
try {
|
|
40
|
+
(0, child_process_1.execSync)(`pip install ${packages.join(' ')} --quiet --break-system-packages 2>&1`, { timeout: 30000 });
|
|
41
|
+
}
|
|
42
|
+
catch { }
|
|
43
|
+
}
|
|
44
|
+
const scriptPath = path_1.default.join(sessionDir, 'script.py');
|
|
45
|
+
fs_1.default.writeFileSync(scriptPath, code);
|
|
46
|
+
return new Promise((resolve) => {
|
|
47
|
+
(0, child_process_1.exec)(`python "${scriptPath}"`, { timeout: 30000, cwd: sessionDir }, (error, stdout, stderr) => {
|
|
48
|
+
scheduleCleanup();
|
|
49
|
+
const files = fs_1.default.readdirSync(sessionDir).filter(f => f !== 'script.py');
|
|
50
|
+
const duration = Date.now() - start;
|
|
51
|
+
if (error && !stdout) {
|
|
52
|
+
resolve({ success: false, output: stderr || error.message, error: stderr || error.message, files, duration });
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
resolve({ success: true, output: stdout || '(no output)', files, duration });
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
const scriptPath = path_1.default.join(sessionDir, 'script.js');
|
|
62
|
+
fs_1.default.writeFileSync(scriptPath, code);
|
|
63
|
+
return new Promise((resolve) => {
|
|
64
|
+
(0, child_process_1.exec)(`node "${scriptPath}"`, { timeout: 30000, cwd: sessionDir }, (error, stdout, stderr) => {
|
|
65
|
+
scheduleCleanup();
|
|
66
|
+
const files = fs_1.default.readdirSync(sessionDir).filter(f => f !== 'script.js');
|
|
67
|
+
const duration = Date.now() - start;
|
|
68
|
+
if (error && !stdout) {
|
|
69
|
+
resolve({ success: false, output: stderr || error.message, error: stderr || error.message, files, duration });
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
resolve({ success: true, output: stdout || '(no output)', files, duration });
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch (e) {
|
|
79
|
+
scheduleCleanup();
|
|
80
|
+
return { success: false, output: e.message, error: e.message, duration: Date.now() - start };
|
|
81
|
+
}
|
|
82
|
+
}
|