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.
Files changed (159) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +465 -0
  3. package/config/devos.config.json +186 -0
  4. package/config/hardware.json +9 -0
  5. package/config/model-selection.json +7 -0
  6. package/config/setup-complete.json +20 -0
  7. package/dist/api/routes/computerUse.js +112 -0
  8. package/dist/api/server.js +6870 -0
  9. package/dist/bin/npx-init.js +71 -0
  10. package/dist/coordination/commandGate.js +115 -0
  11. package/dist/coordination/livePulse.js +127 -0
  12. package/dist/core/agentLoop.js +2718 -0
  13. package/dist/core/agentShield.js +231 -0
  14. package/dist/core/aidenIdentity.js +215 -0
  15. package/dist/core/aidenPersonality.js +166 -0
  16. package/dist/core/aidenSdk.js +374 -0
  17. package/dist/core/asyncTasks.js +82 -0
  18. package/dist/core/auditTrail.js +61 -0
  19. package/dist/core/auxiliaryClient.js +114 -0
  20. package/dist/core/bgLLM.js +108 -0
  21. package/dist/core/bm25.js +68 -0
  22. package/dist/core/callbackSystem.js +64 -0
  23. package/dist/core/channels/adapter.js +6 -0
  24. package/dist/core/channels/discord.js +173 -0
  25. package/dist/core/channels/email.js +253 -0
  26. package/dist/core/channels/imessage.js +164 -0
  27. package/dist/core/channels/manager.js +96 -0
  28. package/dist/core/channels/signal.js +140 -0
  29. package/dist/core/channels/slack.js +139 -0
  30. package/dist/core/channels/twilio.js +144 -0
  31. package/dist/core/channels/webhook.js +186 -0
  32. package/dist/core/channels/whatsapp.js +185 -0
  33. package/dist/core/clarifyBus.js +75 -0
  34. package/dist/core/codeInterpreter.js +82 -0
  35. package/dist/core/computerControl.js +439 -0
  36. package/dist/core/conversationMemory.js +334 -0
  37. package/dist/core/costTracker.js +221 -0
  38. package/dist/core/cronManager.js +217 -0
  39. package/dist/core/deepKB.js +77 -0
  40. package/dist/core/doctor.js +279 -0
  41. package/dist/core/dreamEngine.js +334 -0
  42. package/dist/core/entityGraph.js +169 -0
  43. package/dist/core/eventBus.js +16 -0
  44. package/dist/core/evolutionAnalyzer.js +153 -0
  45. package/dist/core/executionLoop.js +309 -0
  46. package/dist/core/executor.js +224 -0
  47. package/dist/core/failureAnalyzer.js +166 -0
  48. package/dist/core/fastPathExpansion.js +82 -0
  49. package/dist/core/faultEngine.js +106 -0
  50. package/dist/core/featureGates.js +70 -0
  51. package/dist/core/fileIngestion.js +113 -0
  52. package/dist/core/gateway.js +97 -0
  53. package/dist/core/goalTracker.js +75 -0
  54. package/dist/core/growthEngine.js +168 -0
  55. package/dist/core/hardwareDetector.js +98 -0
  56. package/dist/core/hooks.js +45 -0
  57. package/dist/core/httpKeepalive.js +46 -0
  58. package/dist/core/hybridSearch.js +101 -0
  59. package/dist/core/importers.js +164 -0
  60. package/dist/core/instinctSystem.js +223 -0
  61. package/dist/core/knowledgeBase.js +351 -0
  62. package/dist/core/learningMemory.js +121 -0
  63. package/dist/core/lessonsBrowser.js +125 -0
  64. package/dist/core/licenseManager.js +399 -0
  65. package/dist/core/logBuffer.js +85 -0
  66. package/dist/core/machineId.js +87 -0
  67. package/dist/core/mcpClient.js +442 -0
  68. package/dist/core/memoryDistiller.js +165 -0
  69. package/dist/core/memoryExtractor.js +212 -0
  70. package/dist/core/memoryIds.js +213 -0
  71. package/dist/core/memoryPreamble.js +113 -0
  72. package/dist/core/memoryQuery.js +136 -0
  73. package/dist/core/memoryRecall.js +140 -0
  74. package/dist/core/memoryStrategy.js +201 -0
  75. package/dist/core/messageValidator.js +85 -0
  76. package/dist/core/modelDiscovery.js +108 -0
  77. package/dist/core/modelRouter.js +118 -0
  78. package/dist/core/morningBriefing.js +203 -0
  79. package/dist/core/multiGoalValidator.js +51 -0
  80. package/dist/core/parallelExecutor.js +43 -0
  81. package/dist/core/passiveSkillObserver.js +204 -0
  82. package/dist/core/paths.js +57 -0
  83. package/dist/core/patternDetector.js +83 -0
  84. package/dist/core/planResponseRepair.js +64 -0
  85. package/dist/core/planTool.js +111 -0
  86. package/dist/core/playwrightBridge.js +356 -0
  87. package/dist/core/pluginSystem.js +121 -0
  88. package/dist/core/privateMode.js +85 -0
  89. package/dist/core/reactLoop.js +156 -0
  90. package/dist/core/recipeEngine.js +166 -0
  91. package/dist/core/responseCache.js +128 -0
  92. package/dist/core/runSandbox.js +132 -0
  93. package/dist/core/sandboxRunner.js +200 -0
  94. package/dist/core/scheduler.js +543 -0
  95. package/dist/core/secretScanner.js +49 -0
  96. package/dist/core/semanticMemory.js +223 -0
  97. package/dist/core/sessionMemory.js +259 -0
  98. package/dist/core/sessionRouter.js +91 -0
  99. package/dist/core/sessionSearch.js +163 -0
  100. package/dist/core/setupWizard.js +225 -0
  101. package/dist/core/skillImporter.js +303 -0
  102. package/dist/core/skillLibrary.js +144 -0
  103. package/dist/core/skillLoader.js +471 -0
  104. package/dist/core/skillTeacher.js +352 -0
  105. package/dist/core/skillValidator.js +210 -0
  106. package/dist/core/skillWriter.js +384 -0
  107. package/dist/core/slashAsTool.js +226 -0
  108. package/dist/core/spawnManager.js +197 -0
  109. package/dist/core/statusVerbs.js +43 -0
  110. package/dist/core/swarmManager.js +109 -0
  111. package/dist/core/taskQueue.js +119 -0
  112. package/dist/core/taskRecovery.js +128 -0
  113. package/dist/core/taskState.js +168 -0
  114. package/dist/core/telegramBot.js +152 -0
  115. package/dist/core/todoManager.js +70 -0
  116. package/dist/core/toolNameRepair.js +71 -0
  117. package/dist/core/toolRegistry.js +2730 -0
  118. package/dist/core/tools/calendarTool.js +98 -0
  119. package/dist/core/tools/companyFilingsTool.js +98 -0
  120. package/dist/core/tools/gmailTool.js +87 -0
  121. package/dist/core/tools/marketDataTool.js +135 -0
  122. package/dist/core/tools/socialResearchTool.js +121 -0
  123. package/dist/core/truthCheck.js +57 -0
  124. package/dist/core/updateChecker.js +74 -0
  125. package/dist/core/userCognitionProfile.js +238 -0
  126. package/dist/core/userProfile.js +341 -0
  127. package/dist/core/version.js +5 -0
  128. package/dist/core/visionAnalyze.js +161 -0
  129. package/dist/core/voice/audio.js +187 -0
  130. package/dist/core/voice/stt.js +226 -0
  131. package/dist/core/voice/tts.js +310 -0
  132. package/dist/core/voiceInput.js +118 -0
  133. package/dist/core/voiceOutput.js +130 -0
  134. package/dist/core/webSearch.js +326 -0
  135. package/dist/core/workflowTracker.js +72 -0
  136. package/dist/core/workspaceMemory.js +54 -0
  137. package/dist/core/youtubeTranscript.js +224 -0
  138. package/dist/integrations/computerUse/apiRegistry.js +113 -0
  139. package/dist/integrations/computerUse/screenAgent.js +203 -0
  140. package/dist/integrations/computerUse/visionLoop.js +296 -0
  141. package/dist/memory/memoryLayers.js +143 -0
  142. package/dist/providers/boa.js +93 -0
  143. package/dist/providers/cerebras.js +70 -0
  144. package/dist/providers/custom.js +89 -0
  145. package/dist/providers/gemini.js +82 -0
  146. package/dist/providers/groq.js +92 -0
  147. package/dist/providers/index.js +149 -0
  148. package/dist/providers/nvidia.js +70 -0
  149. package/dist/providers/ollama.js +99 -0
  150. package/dist/providers/openrouter.js +74 -0
  151. package/dist/providers/router.js +497 -0
  152. package/dist/providers/types.js +6 -0
  153. package/dist/security/browserVault.js +129 -0
  154. package/dist/security/dataGuard.js +89 -0
  155. package/dist/tools/eonetTool.js +72 -0
  156. package/dist/types/computerUse.js +2 -0
  157. package/dist/types/executor.js +2 -0
  158. package/dist-bundle/cli.js +357859 -0
  159. package/package.json +256 -0
@@ -0,0 +1,303 @@
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.importFromUrl = importFromUrl;
11
+ exports.importFromGitHub = importFromGitHub;
12
+ exports.importFromLocal = importFromLocal;
13
+ exports.importSkill = importSkill;
14
+ // core/skillImporter.ts — agentskills.io-compatible skill importer.
15
+ //
16
+ // Supports importing skills from:
17
+ // - GitHub repos: importFromGitHub('owner/repo', [subpath])
18
+ // - HTTPS URLs: importFromUrl('https://...')
19
+ // - Local paths: importFromLocal('/path/to/skill-dir')
20
+ //
21
+ // Security gates (enforced unconditionally):
22
+ // 1. HTTPS only for remote imports (http:// blocked)
23
+ // 2. SKILL.md ≤ 100 KB
24
+ // 3. Total skill dir ≤ 10 MB
25
+ // 4. Scripts must live in scripts/ subdir
26
+ // 5. Script extensions: .py .sh .js .ts .mjs only
27
+ // 6. enabled: false always set on freshly imported skills
28
+ // 7. No existing skill overwrite without { force: true }
29
+ const fs_1 = __importDefault(require("fs"));
30
+ const path_1 = __importDefault(require("path"));
31
+ const skillLoader_1 = require("./skillLoader");
32
+ const skillValidator_1 = require("./skillValidator");
33
+ // ── Constants ──────────────────────────────────────────────────
34
+ const MAX_SKILL_MD_BYTES = 100 * 1024; // 100 KB
35
+ const MAX_TOTAL_BYTES = 10 * 1024 * 1024; // 10 MB
36
+ const ALLOWED_EXTS = new Set(['.py', '.sh', '.js', '.ts', '.mjs']);
37
+ const GITHUB_API_BASE = 'https://api.github.com';
38
+ // ── Security helpers ───────────────────────────────────────────
39
+ function assertHttps(url) {
40
+ if (!url.startsWith('https://')) {
41
+ throw new Error(`Security: only HTTPS imports are allowed (got: ${url.slice(0, 40)})`);
42
+ }
43
+ }
44
+ function assertSize(buf, max, label) {
45
+ const size = Buffer.isBuffer(buf) ? buf.length : Buffer.byteLength(buf, 'utf-8');
46
+ if (size > max) {
47
+ throw new Error(`Security: ${label} exceeds limit (${size} bytes > ${max} bytes)`);
48
+ }
49
+ }
50
+ function assertScriptExt(filename) {
51
+ const ext = path_1.default.extname(filename).toLowerCase();
52
+ if (ext && !ALLOWED_EXTS.has(ext)) {
53
+ throw new Error(`Security: script extension "${ext}" not allowed (permitted: .py .sh .js .ts .mjs)`);
54
+ }
55
+ }
56
+ // ── Fetch helper (Node 18 built-in fetch) ──────────────────────
57
+ async function fetchText(url, headers) {
58
+ assertHttps(url);
59
+ const resp = await fetch(url, {
60
+ headers: { 'User-Agent': 'Aiden/3.8.1 (agentskills-importer)', ...headers },
61
+ signal: AbortSignal.timeout(15000),
62
+ });
63
+ if (!resp.ok)
64
+ throw new Error(`HTTP ${resp.status} fetching ${url}`);
65
+ const text = await resp.text();
66
+ assertSize(text, MAX_SKILL_MD_BYTES, `response from ${url}`);
67
+ return text;
68
+ }
69
+ // ── Determine install destination ─────────────────────────────
70
+ function resolveDestDir(skillId, opts) {
71
+ if (opts.destDir)
72
+ return opts.destDir;
73
+ return path_1.default.join(process.cwd(), 'skills', 'installed', skillId);
74
+ }
75
+ // ── Inject/update import metadata in SKILL.md frontmatter ─────
76
+ function injectImportMeta(raw, source, importedFrom) {
77
+ // Always set enabled: false, source, imported-from in the frontmatter
78
+ const fmMatch = raw.match(/^(---\s*\n)([\s\S]*?)(\n---\s*\n)/);
79
+ if (!fmMatch) {
80
+ // No frontmatter — prepend one
81
+ return `---\nenabled: false\nsource: ${source}\nimported-from: ${importedFrom}\n---\n\n${raw}`;
82
+ }
83
+ let fm = fmMatch[2];
84
+ // Remove any existing enabled / source / imported-from lines
85
+ fm = fm.replace(/^enabled:.*$/m, '').replace(/^source:.*$/m, '').replace(/^imported-from:.*$/m, '');
86
+ // Add controlled fields
87
+ fm = fm.trimEnd();
88
+ fm += `\nenabled: false\nsource: ${source}\nimported-from: ${importedFrom}`;
89
+ return `${fmMatch[1]}${fm}${fmMatch[3]}${raw.slice(fmMatch[0].length)}`;
90
+ }
91
+ // ── Extract skill name from SKILL.md frontmatter ──────────────
92
+ function extractSkillName(raw, fallback) {
93
+ const m = raw.match(/^name:\s*(.+)$/m);
94
+ return m ? m[1].trim().replace(/^['"]|['"]$/g, '') : fallback;
95
+ }
96
+ // ── Write skill directory ──────────────────────────────────────
97
+ function writeSkillFiles(destDir, skillMdContent, extraFiles = []) {
98
+ // Check total size
99
+ let totalSize = Buffer.byteLength(skillMdContent, 'utf-8');
100
+ for (const f of extraFiles) {
101
+ totalSize += Buffer.isBuffer(f.content) ? f.content.length : Buffer.byteLength(f.content, 'utf-8');
102
+ }
103
+ assertSize(Buffer.alloc(totalSize), MAX_TOTAL_BYTES, 'total skill package');
104
+ // Validate script extensions in extra files
105
+ for (const f of extraFiles) {
106
+ const parts = f.relPath.split('/');
107
+ const inSub = parts.length > 1;
108
+ const subdir = parts[0];
109
+ if (!inSub)
110
+ continue;
111
+ if (subdir === 'scripts')
112
+ assertScriptExt(parts[parts.length - 1]);
113
+ // Files in non-standard subdirs are fine (references/, assets/, etc.)
114
+ }
115
+ fs_1.default.mkdirSync(destDir, { recursive: true });
116
+ fs_1.default.writeFileSync(path_1.default.join(destDir, 'SKILL.md'), skillMdContent, 'utf-8');
117
+ for (const f of extraFiles) {
118
+ const fullPath = path_1.default.join(destDir, f.relPath);
119
+ fs_1.default.mkdirSync(path_1.default.dirname(fullPath), { recursive: true });
120
+ if (Buffer.isBuffer(f.content)) {
121
+ fs_1.default.writeFileSync(fullPath, f.content);
122
+ }
123
+ else {
124
+ fs_1.default.writeFileSync(fullPath, f.content, 'utf-8');
125
+ }
126
+ }
127
+ }
128
+ // ── Import from HTTPS URL (single SKILL.md file) ──────────────
129
+ async function importFromUrl(url, opts = {}) {
130
+ try {
131
+ assertHttps(url);
132
+ const raw = await fetchText(url);
133
+ const fallbackId = url.split('/').pop()?.replace(/[^a-z0-9-]/gi, '-').toLowerCase() ?? 'imported';
134
+ const skillId = extractSkillName(raw, fallbackId);
135
+ const destDir = resolveDestDir(skillId, opts);
136
+ if (!opts.force && fs_1.default.existsSync(destDir)) {
137
+ return { success: false, error: `Skill "${skillId}" already exists. Use force:true to overwrite.` };
138
+ }
139
+ const patched = injectImportMeta(raw, opts.source ?? url, url);
140
+ writeSkillFiles(destDir, patched);
141
+ skillLoader_1.skillLoader.refresh();
142
+ const validation = (0, skillValidator_1.validateSkillDir)(destDir);
143
+ return { success: true, skillId, destPath: destDir, validation };
144
+ }
145
+ catch (e) {
146
+ return { success: false, error: e.message };
147
+ }
148
+ }
149
+ // ── Import from GitHub repo ────────────────────────────────────
150
+ // Fetches SKILL.md (and optionally scripts/, references/, assets/) via GitHub API.
151
+ async function importFromGitHub(ownerRepo, // "owner/repo"
152
+ opts = {}) {
153
+ try {
154
+ const [owner, repo] = ownerRepo.split('/');
155
+ if (!owner || !repo)
156
+ throw new Error(`Invalid owner/repo format: "${ownerRepo}"`);
157
+ const branch = opts.branch ?? 'main';
158
+ const subpath = opts.subpath ?? '';
159
+ // Try raw.githubusercontent.com first (no rate limit header required)
160
+ const basePath = subpath ? `${subpath}/` : '';
161
+ const rawBase = `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/${basePath}`;
162
+ const skillMdUrl = `${rawBase}SKILL.md`;
163
+ assertHttps(skillMdUrl);
164
+ let raw;
165
+ try {
166
+ raw = await fetchText(skillMdUrl);
167
+ }
168
+ catch {
169
+ // Try GitHub API as fallback (needed for non-default branch / private repos with token)
170
+ const apiUrl = `${GITHUB_API_BASE}/repos/${owner}/${repo}/contents/${basePath}SKILL.md?ref=${branch}`;
171
+ const apiRaw = await fetchText(apiUrl);
172
+ const parsed = JSON.parse(apiRaw);
173
+ if (parsed.encoding === 'base64' && parsed.content) {
174
+ raw = Buffer.from(parsed.content.replace(/\n/g, ''), 'base64').toString('utf-8');
175
+ }
176
+ else {
177
+ throw new Error('Could not decode SKILL.md from GitHub API response');
178
+ }
179
+ }
180
+ const fallbackId = repo.toLowerCase().replace(/[^a-z0-9-]/g, '-');
181
+ const skillId = extractSkillName(raw, fallbackId);
182
+ const destDir = resolveDestDir(skillId, opts);
183
+ if (!opts.force && fs_1.default.existsSync(destDir)) {
184
+ return { success: false, error: `Skill "${skillId}" already exists. Use force:true to overwrite.` };
185
+ }
186
+ // Also try to fetch scripts/ (best-effort — non-fatal if absent)
187
+ const extraFiles = [];
188
+ const EXTRA_SUBDIRS = ['scripts', 'references', 'assets'];
189
+ for (const subDir of EXTRA_SUBDIRS) {
190
+ const treeUrl = `${GITHUB_API_BASE}/repos/${owner}/${repo}/git/trees/${branch}?recursive=1`;
191
+ try {
192
+ const treeRaw = await fetchText(treeUrl);
193
+ const tree = JSON.parse(treeRaw);
194
+ const prefix = basePath + subDir + '/';
195
+ const entries = tree.tree.filter(e => e.type === 'blob' && e.path.startsWith(prefix));
196
+ for (const entry of entries) {
197
+ const relPath = entry.path.replace(basePath, ''); // e.g. "scripts/main.py"
198
+ const fileUrl = `${rawBase}${relPath}`;
199
+ // Security: enforce extension for scripts/
200
+ if (relPath.startsWith('scripts/'))
201
+ assertScriptExt(path_1.default.basename(relPath));
202
+ // Security: per-file size check (from tree metadata)
203
+ if ((entry.size ?? 0) > MAX_SKILL_MD_BYTES)
204
+ continue; // skip huge files silently
205
+ try {
206
+ const fileContent = await fetchText(fileUrl);
207
+ extraFiles.push({ relPath, content: fileContent });
208
+ }
209
+ catch {
210
+ // Non-fatal — skip this file
211
+ }
212
+ }
213
+ break; // Only need one tree fetch
214
+ }
215
+ catch {
216
+ // Tree API unavailable or repo private — skip extra files
217
+ break;
218
+ }
219
+ }
220
+ const sourceRef = `github:${ownerRepo}`;
221
+ const patched = injectImportMeta(raw, opts.source ?? sourceRef, sourceRef);
222
+ writeSkillFiles(destDir, patched, extraFiles);
223
+ skillLoader_1.skillLoader.refresh();
224
+ const validation = (0, skillValidator_1.validateSkillDir)(destDir);
225
+ return { success: true, skillId, destPath: destDir, validation };
226
+ }
227
+ catch (e) {
228
+ return { success: false, error: e.message };
229
+ }
230
+ }
231
+ // ── Import from local directory ────────────────────────────────
232
+ async function importFromLocal(srcDir, opts = {}) {
233
+ try {
234
+ if (!fs_1.default.existsSync(srcDir)) {
235
+ return { success: false, error: `Source directory not found: ${srcDir}` };
236
+ }
237
+ const skillMdPath = path_1.default.join(srcDir, 'SKILL.md');
238
+ if (!fs_1.default.existsSync(skillMdPath)) {
239
+ return { success: false, error: `No SKILL.md found in ${srcDir}` };
240
+ }
241
+ const raw = fs_1.default.readFileSync(skillMdPath, 'utf-8');
242
+ assertSize(raw, MAX_SKILL_MD_BYTES, 'SKILL.md');
243
+ const skillId = extractSkillName(raw, path_1.default.basename(srcDir));
244
+ const destDir = resolveDestDir(skillId, opts);
245
+ if (!opts.force && fs_1.default.existsSync(destDir)) {
246
+ return { success: false, error: `Skill "${skillId}" already exists. Use force:true to overwrite.` };
247
+ }
248
+ // Collect extra files (scripts/, references/, assets/)
249
+ const extraFiles = [];
250
+ let totalSize = Buffer.byteLength(raw, 'utf-8');
251
+ for (const subdir of ['scripts', 'references', 'assets']) {
252
+ const subdirPath = path_1.default.join(srcDir, subdir);
253
+ if (!fs_1.default.existsSync(subdirPath))
254
+ continue;
255
+ const files = fs_1.default.readdirSync(subdirPath);
256
+ for (const f of files) {
257
+ if (subdir === 'scripts')
258
+ assertScriptExt(f);
259
+ const fullPath = path_1.default.join(subdirPath, f);
260
+ const stat = fs_1.default.statSync(fullPath);
261
+ if (!stat.isFile())
262
+ continue;
263
+ totalSize += stat.size;
264
+ assertSize(Buffer.alloc(totalSize), MAX_TOTAL_BYTES, 'total skill package');
265
+ const content = fs_1.default.readFileSync(fullPath);
266
+ extraFiles.push({ relPath: `${subdir}/${f}`, content });
267
+ }
268
+ }
269
+ const patched = injectImportMeta(raw, opts.source ?? 'local', srcDir);
270
+ writeSkillFiles(destDir, patched, extraFiles);
271
+ skillLoader_1.skillLoader.refresh();
272
+ const validation = (0, skillValidator_1.validateSkillDir)(destDir);
273
+ return { success: true, skillId, destPath: destDir, validation };
274
+ }
275
+ catch (e) {
276
+ return { success: false, error: e.message };
277
+ }
278
+ }
279
+ // ── Smart import — detects type from source string ─────────────
280
+ async function importSkill(source, opts = {}) {
281
+ source = source.trim();
282
+ // Strip explicit github: prefix (e.g. "github:owner/repo")
283
+ if (source.startsWith('github:')) {
284
+ source = source.slice(7);
285
+ }
286
+ // GitHub shorthand: "owner/repo" or "owner/repo/subpath"
287
+ if (/^[a-z0-9_.-]+\/[a-z0-9_.-]+(\/.*)?$/i.test(source) && !source.startsWith('http')) {
288
+ const parts = source.split('/');
289
+ const ownerRepo = `${parts[0]}/${parts[1]}`;
290
+ const subpath = parts.slice(2).join('/');
291
+ return importFromGitHub(ownerRepo, { ...opts, subpath: subpath || undefined });
292
+ }
293
+ // HTTPS URL
294
+ if (source.startsWith('https://')) {
295
+ return importFromUrl(source, opts);
296
+ }
297
+ // http:// — blocked
298
+ if (source.startsWith('http://')) {
299
+ return { success: false, error: 'Security: only HTTPS imports are allowed (http:// blocked)' };
300
+ }
301
+ // Local path
302
+ return importFromLocal(source, opts);
303
+ }
@@ -0,0 +1,144 @@
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.fetchIndex = fetchIndex;
11
+ exports.fetchSkillMarkdown = fetchSkillMarkdown;
12
+ exports.scoreSkillsForTopic = scoreSkillsForTopic;
13
+ exports.installSkill = installSkill;
14
+ exports.invalidateCache = invalidateCache;
15
+ // core/skillLibrary.ts — Browser against the taracodlabs/aiden-skills
16
+ // library. Fetches INDEX.json, scores skills by topic relevance,
17
+ // and installs selected skills to skills/installed/<id>/.
18
+ const https_1 = __importDefault(require("https"));
19
+ const http_1 = __importDefault(require("http"));
20
+ const skillWriter_1 = require("./skillWriter");
21
+ // ── Constants ─────────────────────────────────────────────────
22
+ const LIBRARY_BASE_URL = process.env.AIDEN_SKILL_LIBRARY_URL ??
23
+ 'https://raw.githubusercontent.com/taracodlabs/aiden-skills/main';
24
+ const INDEX_CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour
25
+ // ── In-memory cache ───────────────────────────────────────────
26
+ let _indexCache = null;
27
+ let _indexCachedAt = 0;
28
+ // ── fetchText ─────────────────────────────────────────────────
29
+ // Minimal HTTPS/HTTP GET returning text. No external dependencies.
30
+ function fetchText(url) {
31
+ return new Promise((resolve, reject) => {
32
+ const client = url.startsWith('https') ? https_1.default : http_1.default;
33
+ const req = client.get(url, { timeout: 10000 }, res => {
34
+ if (res.statusCode === 301 || res.statusCode === 302) {
35
+ fetchText(res.headers.location).then(resolve, reject);
36
+ return;
37
+ }
38
+ if (res.statusCode !== 200) {
39
+ reject(new Error(`HTTP ${res.statusCode} fetching ${url}`));
40
+ return;
41
+ }
42
+ const chunks = [];
43
+ res.on('data', (c) => chunks.push(c));
44
+ res.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));
45
+ res.on('error', reject);
46
+ });
47
+ req.on('error', reject);
48
+ req.on('timeout', () => { req.destroy(); reject(new Error(`Timeout fetching ${url}`)); });
49
+ });
50
+ }
51
+ // ── fetchIndex ────────────────────────────────────────────────
52
+ // GET INDEX.json from library, with 1-hour in-memory cache.
53
+ async function fetchIndex() {
54
+ const now = Date.now();
55
+ if (_indexCache && now - _indexCachedAt < INDEX_CACHE_TTL_MS) {
56
+ return _indexCache;
57
+ }
58
+ const url = `${LIBRARY_BASE_URL}/INDEX.json`;
59
+ const text = await fetchText(url);
60
+ const idx = JSON.parse(text);
61
+ _indexCache = idx;
62
+ _indexCachedAt = now;
63
+ return idx;
64
+ }
65
+ // ── fetchSkillMarkdown ─────────────────────────────────────────
66
+ // Fetch raw SKILL.md content for a specific skill ID.
67
+ async function fetchSkillMarkdown(skillId) {
68
+ const idx = await fetchIndex();
69
+ const entry = idx.skills.find(s => s.id === skillId);
70
+ if (!entry)
71
+ throw new Error(`Skill "${skillId}" not found in library index`);
72
+ const url = `${LIBRARY_BASE_URL}/${entry.path}`;
73
+ return fetchText(url);
74
+ }
75
+ // ── scoreSkillsForTopic ────────────────────────────────────────
76
+ // Returns library skills scored by relevance to a topic string.
77
+ // Scoring: exact id/name match (+10), description word overlap (+3 each),
78
+ // category match (+6), tag match (+5 each).
79
+ function scoreSkillsForTopic(topic, index) {
80
+ const lower = topic.toLowerCase();
81
+ const words = lower.split(/\s+/).filter(w => w.length > 2);
82
+ return index.skills
83
+ .map(entry => {
84
+ let score = 0;
85
+ const name = entry.name.toLowerCase();
86
+ const desc = entry.description.toLowerCase();
87
+ const cat = entry.category.toLowerCase();
88
+ if (name.includes(lower) || lower.includes(name))
89
+ score += 10;
90
+ if (lower.includes(entry.id.toLowerCase()))
91
+ score += 10;
92
+ words.forEach(w => { if (desc.includes(w))
93
+ score += 3; });
94
+ if (cat.includes(lower) || lower.includes(cat))
95
+ score += 6;
96
+ entry.tags.forEach(tag => {
97
+ if (lower.includes(tag.toLowerCase()) || tag.toLowerCase().includes(lower))
98
+ score += 5;
99
+ });
100
+ words.forEach(w => {
101
+ entry.tags.forEach(tag => { if (tag.toLowerCase().includes(w))
102
+ score += 2; });
103
+ });
104
+ return { ...entry, score };
105
+ })
106
+ .filter(s => s.score > 0)
107
+ .sort((a, b) => b.score - a.score);
108
+ }
109
+ // ── installSkill ──────────────────────────────────────────────
110
+ // Fetches a skill from the library and writes it to skills/installed/<id>/.
111
+ // The skill is written with enabled: false — user must enable explicitly.
112
+ async function installSkill(skillId) {
113
+ const idx = await fetchIndex();
114
+ const entry = idx.skills.find(s => s.id === skillId);
115
+ if (!entry)
116
+ throw new Error(`Skill "${skillId}" not found in library`);
117
+ const markdown = await fetchSkillMarkdown(skillId);
118
+ // Strip existing frontmatter and let writeSkillDraft rebuild it cleanly
119
+ const bodyMatch = markdown.match(/^---[\s\S]*?---\s*([\s\S]*)$/);
120
+ const body = bodyMatch ? bodyMatch[1].trim() : markdown.trim();
121
+ const written = await (0, skillWriter_1.writeSkillDraft)({
122
+ name: entry.name,
123
+ description: entry.description,
124
+ category: entry.category,
125
+ platform: entry.platform ?? 'any',
126
+ tags: entry.tags,
127
+ version: entry.version,
128
+ content: body,
129
+ source: 'library_install',
130
+ sourceDetails: {
131
+ libraryId: entry.id,
132
+ libraryUrl: LIBRARY_BASE_URL,
133
+ installedAt: new Date().toISOString(),
134
+ envRequired: entry.env_required,
135
+ },
136
+ }, 'installed');
137
+ return written;
138
+ }
139
+ // ── invalidateCache ───────────────────────────────────────────
140
+ // Force-expire the index cache (e.g. after manual refresh).
141
+ function invalidateCache() {
142
+ _indexCache = null;
143
+ _indexCachedAt = 0;
144
+ }