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,197 @@
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.getActiveSpawns = getActiveSpawns;
8
+ exports.killSpawn = killSpawn;
9
+ exports.spawnSubagent = spawnSubagent;
10
+ // core/spawnManager.ts — Spawn isolated subagent sessions.
11
+ //
12
+ // A spawned subagent gets:
13
+ // - Fresh conversation history (context isolation)
14
+ // - Half the parent's remaining iteration budget (budget inheritance)
15
+ // - Provider chain inherited from parent config via router
16
+ // - Memory writes that do NOT propagate to parent session
17
+ //
18
+ // Usage:
19
+ // const result = await spawnSubagent({ task, context, timeout, parentBudget })
20
+ const agentLoop_1 = require("./agentLoop");
21
+ const router_1 = require("../providers/router");
22
+ const index_1 = require("../providers/index");
23
+ const _activeSpawns = new Map();
24
+ /** Returns all active/recent spawns. */
25
+ function getActiveSpawns() {
26
+ return Array.from(_activeSpawns.values()).sort((a, b) => b.startedAt - a.startedAt);
27
+ }
28
+ /** Abort a running spawn by ID. Returns true if killed, false if not found. */
29
+ function killSpawn(id) {
30
+ const spawn = _activeSpawns.get(id);
31
+ if (!spawn)
32
+ return false;
33
+ if (spawn.status === 'running' || spawn.status === 'pending') {
34
+ spawn.abort?.();
35
+ spawn.status = 'aborted';
36
+ return true;
37
+ }
38
+ return false;
39
+ }
40
+ // ── Core spawn implementation ─────────────────────────────────
41
+ /**
42
+ * Spawns an isolated subagent to handle a sub-task.
43
+ *
44
+ * Budget inheritance: subagent gets at most floor(parentBudget.remaining / 2)
45
+ * iterations, capped at 10. This prevents runaway subagents from exhausting
46
+ * the parent's budget.
47
+ *
48
+ * Provider inheritance: uses the same provider chain (same config) so fallback
49
+ * behaviour is consistent with the parent.
50
+ */
51
+ async function spawnSubagent(opts) {
52
+ const spawnId = `spawn_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;
53
+ const t0 = Date.now();
54
+ // Budget inheritance: half of parent's remaining, max 10
55
+ const _subBudget = Math.max(1, Math.min(Math.floor(opts.parentBudget.remaining / 2), 10));
56
+ // Build task message with optional injected context
57
+ const taskMessage = opts.context
58
+ ? `${opts.task}\n\n--- Injected Context ---\n${opts.context}`
59
+ : opts.task;
60
+ // Abort flag for timeout / kill
61
+ let abortFlag = false;
62
+ const entry = {
63
+ id: spawnId,
64
+ task: opts.task.slice(0, 80),
65
+ startedAt: t0,
66
+ status: 'pending',
67
+ abort: () => { abortFlag = true; },
68
+ };
69
+ _activeSpawns.set(spawnId, entry);
70
+ // Collect provider names for the result (inherited from parent config)
71
+ const providerChain = (() => {
72
+ try {
73
+ const cfg = (0, index_1.loadConfig)();
74
+ return (cfg.providers?.apis ?? [])
75
+ .filter((a) => a.enabled)
76
+ .map((a) => String(a.provider));
77
+ }
78
+ catch {
79
+ return [];
80
+ }
81
+ })();
82
+ entry.status = 'running';
83
+ const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error(`Spawn timeout after ${opts.timeout}ms`)), opts.timeout));
84
+ const workPromise = (async () => {
85
+ if (abortFlag)
86
+ throw new Error('Spawn aborted before start');
87
+ // Resolve provider credentials via router (inherits parent chain)
88
+ const next = (0, router_1.getNextAvailableAPI)();
89
+ if (!next) {
90
+ return {
91
+ success: false,
92
+ error: 'No available API provider for subagent',
93
+ iterationsUsed: 0,
94
+ duration: Date.now() - t0,
95
+ providerChain,
96
+ };
97
+ }
98
+ const apiKey = next.entry.key.startsWith('env:')
99
+ ? (process.env[next.entry.key.replace('env:', '')] ?? '')
100
+ : next.entry.key;
101
+ // Plan in isolated context (empty history = no parent session context)
102
+ let plan;
103
+ try {
104
+ plan = await (0, agentLoop_1.planWithLLM)(taskMessage, [], // empty conversation history — context isolation
105
+ apiKey, next.entry.model, next.entry.provider);
106
+ }
107
+ catch (e) {
108
+ return {
109
+ success: false,
110
+ error: `Subagent planning failed: ${e?.message ?? String(e)}`,
111
+ iterationsUsed: 0,
112
+ duration: Date.now() - t0,
113
+ providerChain,
114
+ };
115
+ }
116
+ if (abortFlag)
117
+ throw new Error('Spawn aborted after planning');
118
+ // Direct answer — no tools needed
119
+ if (!plan.requires_execution || plan.plan.length === 0) {
120
+ const directAnswer = (plan.reason || plan.goal || 'Task complete.').trim();
121
+ return {
122
+ success: true,
123
+ result: directAnswer,
124
+ iterationsUsed: 0,
125
+ duration: Date.now() - t0,
126
+ providerChain,
127
+ };
128
+ }
129
+ // Execute plan (isolated — no workspace memory propagation)
130
+ let iterationsUsed = 0;
131
+ const stepResults = await (0, agentLoop_1.executePlan)(plan, (_step, _result) => { iterationsUsed++; });
132
+ if (abortFlag)
133
+ throw new Error('Spawn aborted during execution');
134
+ // Synthesize step outputs into a real LLM answer
135
+ const stepSummary = stepResults
136
+ .filter(r => r.success && r.output)
137
+ .map(r => `[${r.tool}]: ${String(r.output).slice(0, 2000)}`)
138
+ .join('\n\n');
139
+ if (!stepSummary.trim()) {
140
+ return {
141
+ success: false,
142
+ error: 'Subagent steps produced no output',
143
+ iterationsUsed,
144
+ duration: Date.now() - t0,
145
+ providerChain,
146
+ };
147
+ }
148
+ const synthesisPrompt = [
149
+ 'You are completing a sub-task. Synthesize the tool results into a clear, concise answer.',
150
+ '',
151
+ `Task: ${taskMessage}`,
152
+ '',
153
+ 'Tool Results:',
154
+ stepSummary,
155
+ '',
156
+ 'Provide a direct answer:',
157
+ ].join('\n');
158
+ let synthesized = '';
159
+ try {
160
+ synthesized = await (0, agentLoop_1.callLLM)(synthesisPrompt, apiKey, next.entry.model, next.entry.provider);
161
+ }
162
+ catch { }
163
+ return {
164
+ success: true,
165
+ result: synthesized.trim() || stepSummary,
166
+ iterationsUsed,
167
+ duration: Date.now() - t0,
168
+ providerChain,
169
+ };
170
+ })();
171
+ try {
172
+ const outcome = await Promise.race([workPromise, timeoutPromise]);
173
+ entry.status = 'done';
174
+ entry.result = outcome;
175
+ return outcome;
176
+ }
177
+ catch (err) {
178
+ const result = {
179
+ success: false,
180
+ error: err?.message ?? String(err),
181
+ iterationsUsed: 0,
182
+ duration: Date.now() - t0,
183
+ providerChain,
184
+ };
185
+ entry.status = abortFlag ? 'aborted' : 'done';
186
+ entry.result = result;
187
+ return result;
188
+ }
189
+ finally {
190
+ // Cap registry at 20 most recent
191
+ const all = Array.from(_activeSpawns.entries())
192
+ .sort((a, b) => b[1].startedAt - a[1].startedAt);
193
+ if (all.length > 20) {
194
+ all.slice(20).forEach(([id]) => _activeSpawns.delete(id));
195
+ }
196
+ }
197
+ }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ // core/statusVerbs.ts — Rotating verb vocabulary for streaming status events.
3
+ // Phase 2: same rotating-verb pattern as Claude Code — keeps Aiden feeling alive.
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.STATUS_VERBS = void 0;
6
+ exports.getVerb = getVerb;
7
+ exports.STATUS_VERBS = {
8
+ thinking: [
9
+ 'Pondering...', 'Thinking...', 'Mulling it over...', 'Figuring this out...',
10
+ 'Reasoning through...', 'Working it out...', 'On it...',
11
+ 'Processing...', 'Considering...'
12
+ ],
13
+ searching: [
14
+ 'Hunting...', 'Searching...', 'Digging...', 'Looking it up...',
15
+ 'Scouring the web...', 'On the hunt...', 'Tracking it down...',
16
+ 'Scanning...', 'Fetching...'
17
+ ],
18
+ reading: [
19
+ 'Reading...', 'Skimming...', 'Studying...', 'Going through this...',
20
+ 'Checking...', 'Scanning the page...', 'Absorbing...'
21
+ ],
22
+ coding: [
23
+ 'Coding...', 'Writing the script...', 'Crafting...', 'Building...',
24
+ 'Scripting...', 'Putting it together...', 'Tinkering...',
25
+ 'Hammering it out...'
26
+ ],
27
+ browsing: [
28
+ 'Opening...', 'Navigating...', 'Pulling up...', 'Launching...',
29
+ 'Loading the page...', 'Heading there now...'
30
+ ],
31
+ writing: [
32
+ 'Writing...', 'Composing...', 'Crafting your response...',
33
+ 'Putting this together...', 'Almost done...', 'Wrapping up...'
34
+ ],
35
+ tooling: [
36
+ 'Working on it...', 'Handling this...', 'Running the tool...',
37
+ 'Executing...', 'Taking care of it...'
38
+ ],
39
+ };
40
+ function getVerb(action) {
41
+ const verbs = exports.STATUS_VERBS[action] ?? exports.STATUS_VERBS.tooling;
42
+ return verbs[Math.floor(Math.random() * verbs.length)];
43
+ }
@@ -0,0 +1,109 @@
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.swarmSubagents = swarmSubagents;
8
+ // core/swarmManager.ts — Parallel subagent orchestration with voting/merge/best.
9
+ //
10
+ // Runs N isolated subagents concurrently via Promise.allSettled, then
11
+ // aggregates results using one of three strategies:
12
+ //
13
+ // vote — LLM judge picks the best single answer (default)
14
+ // merge — Synthesise all successful answers into one
15
+ // best — Return ranked list of all successful results
16
+ //
17
+ // Budget: each swarm agent gets floor(parentBudget.remaining / (2 * N)), min 1, max 5.
18
+ const spawnManager_1 = require("./spawnManager");
19
+ const router_1 = require("../providers/router");
20
+ const agentLoop_1 = require("./agentLoop");
21
+ // ── Core swarm implementation ─────────────────────────────────
22
+ /**
23
+ * Spawns N subagents in parallel for the same task, then aggregates.
24
+ *
25
+ * Budget inheritance: each agent gets floor(parentBudget.remaining / (2*N)),
26
+ * clamped to [1, 5]. Total budget consumed ≤ parentBudget.remaining / 2.
27
+ */
28
+ async function swarmSubagents(opts) {
29
+ const t0 = Date.now();
30
+ const n = Math.max(2, Math.min(opts.n, 5));
31
+ const agentBudget = Math.max(1, Math.min(Math.floor(opts.parentBudget.remaining / (2 * n)), 5));
32
+ const agentOpts = Array.from({ length: n }, (_, i) => ({
33
+ task: `[Swarm agent ${i + 1}/${n}] ${opts.task}`,
34
+ timeout: opts.timeout,
35
+ parentBudget: { ...opts.parentBudget, remaining: agentBudget * n },
36
+ }));
37
+ // Run all agents in parallel
38
+ const settled = await Promise.allSettled(agentOpts.map(o => (0, spawnManager_1.spawnSubagent)(o)));
39
+ const successes = settled
40
+ .filter((s) => s.status === 'fulfilled' && s.value.success)
41
+ .map(s => s.value.result ?? '')
42
+ .filter(r => r.length > 0);
43
+ const agentsRun = settled.length;
44
+ if (!successes.length) {
45
+ return {
46
+ success: false,
47
+ error: 'All swarm agents failed',
48
+ agentsRun,
49
+ strategy: opts.strategy,
50
+ duration: Date.now() - t0,
51
+ };
52
+ }
53
+ // ── Aggregation ───────────────────────────────────────────────
54
+ let finalResult = '';
55
+ if (opts.strategy === 'best') {
56
+ // Return all results ranked by length (proxy for completeness)
57
+ const ranked = [...successes].sort((a, b) => b.length - a.length);
58
+ finalResult = ranked
59
+ .map((r, i) => `### Agent ${i + 1}\n${r}`)
60
+ .join('\n\n---\n\n');
61
+ }
62
+ else if (opts.strategy === 'merge') {
63
+ // Ask an LLM to synthesise
64
+ finalResult = await aggregateWithLLM(opts.task, successes, 'merge') ?? successes.join('\n\n---\n\n');
65
+ }
66
+ else {
67
+ // vote — pick the single best answer
68
+ if (successes.length === 1) {
69
+ finalResult = successes[0];
70
+ }
71
+ else {
72
+ finalResult = await aggregateWithLLM(opts.task, successes, 'vote') ?? successes[0];
73
+ }
74
+ }
75
+ return {
76
+ success: true,
77
+ result: finalResult,
78
+ agentsRun,
79
+ strategy: opts.strategy,
80
+ duration: Date.now() - t0,
81
+ };
82
+ }
83
+ // ── LLM aggregation helper ────────────────────────────────────
84
+ async function aggregateWithLLM(originalTask, answers, mode) {
85
+ try {
86
+ const next = (0, router_1.getNextAvailableAPI)();
87
+ if (!next)
88
+ return null;
89
+ const apiKey = next.entry.key.startsWith('env:')
90
+ ? (process.env[next.entry.key.replace('env:', '')] ?? '')
91
+ : next.entry.key;
92
+ const numbered = answers.map((a, i) => `### Answer ${i + 1}\n${a}`).join('\n\n');
93
+ const prompt = mode === 'vote'
94
+ ? `You are a judge. The original task was:\n"${originalTask}"\n\nHere are ${answers.length} candidate answers:\n\n${numbered}\n\nSelect the single best answer. Respond with only that answer — no preamble.`
95
+ : `You are a synthesiser. The original task was:\n"${originalTask}"\n\nHere are ${answers.length} answers:\n\n${numbered}\n\nMerge them into one comprehensive answer. Respond with only the merged answer.`;
96
+ const budget = (0, agentLoop_1.getBudgetState)() ?? { current: 1, max: 10, remaining: 2 };
97
+ const plan = await (0, agentLoop_1.planWithLLM)(prompt, [], apiKey, next.entry.model, next.entry.provider);
98
+ // planWithLLM returns an AgentPlan — extract text from first respond step
99
+ if (plan?.plan?.length) {
100
+ const firstStep = plan.plan[0];
101
+ if (firstStep?.tool === 'respond')
102
+ return firstStep?.input?.message ?? null;
103
+ }
104
+ return null;
105
+ }
106
+ catch {
107
+ return null;
108
+ }
109
+ }
@@ -0,0 +1,119 @@
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.taskQueue = void 0;
8
+ // core/taskQueue.ts — Persistent async task queue.
9
+ // Tasks from API, Telegram, or the scheduler are enqueued here
10
+ // and processed sequentially by posting to the chat endpoint.
11
+ const fs_1 = require("fs");
12
+ const path_1 = require("path");
13
+ // ── TaskQueue class ───────────────────────────────────────────
14
+ class TaskQueue {
15
+ constructor(workspaceDir, chatEndpoint) {
16
+ this.queue = [];
17
+ this.isProcessing = false;
18
+ this.savePath = (0, path_1.join)(workspaceDir, 'task_queue.json');
19
+ this.chatEndpoint = chatEndpoint;
20
+ this.load();
21
+ // Re-queue any tasks that were mid-flight when process stopped
22
+ for (const task of this.queue) {
23
+ if (task.status === 'running') {
24
+ task.status = 'queued';
25
+ }
26
+ }
27
+ if (this.queue.some(t => t.status === 'queued')) {
28
+ console.log(`[Queue] Resuming ${this.queue.filter(t => t.status === 'queued').length} queued task(s) from previous session`);
29
+ setTimeout(() => this.processNext(), 2000); // short delay to let server finish starting
30
+ }
31
+ }
32
+ // ── Enqueue ───────────────────────────────────────────────
33
+ enqueue(task) {
34
+ const id = `task_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;
35
+ this.queue.push({
36
+ ...task,
37
+ id,
38
+ status: 'queued',
39
+ createdAt: new Date().toISOString(),
40
+ });
41
+ this.save();
42
+ console.log(`[Queue] Enqueued: ${id} from ${task.source}: "${task.message.substring(0, 50)}"`);
43
+ setTimeout(() => this.processNext(), 100);
44
+ return id;
45
+ }
46
+ // ── Process next queued task ──────────────────────────────
47
+ async processNext() {
48
+ if (this.isProcessing)
49
+ return;
50
+ const next = this.queue.find(t => t.status === 'queued');
51
+ if (!next)
52
+ return;
53
+ this.isProcessing = true;
54
+ next.status = 'running';
55
+ next.startedAt = new Date().toISOString();
56
+ this.save();
57
+ console.log(`[Queue] Processing: ${next.id}: "${next.message.substring(0, 50)}"`);
58
+ try {
59
+ const response = await fetch(this.chatEndpoint, {
60
+ method: 'POST',
61
+ headers: { 'Content-Type': 'application/json' },
62
+ body: JSON.stringify({
63
+ message: next.message,
64
+ sessionId: `dispatch_${next.id}`,
65
+ }),
66
+ signal: AbortSignal.timeout(120000), // 2 min cap per queued task
67
+ });
68
+ if (!response.ok)
69
+ throw new Error(`HTTP ${response.status} from chat endpoint`);
70
+ const data = await response.json();
71
+ next.status = 'completed';
72
+ next.completedAt = new Date().toISOString();
73
+ next.result = data.response || data.message || JSON.stringify(data).slice(0, 500);
74
+ console.log(`[Queue] Completed: ${next.id} — "${String(next.result).slice(0, 60)}"`);
75
+ }
76
+ catch (e) {
77
+ next.status = 'failed';
78
+ next.completedAt = new Date().toISOString();
79
+ next.error = e.message;
80
+ console.log(`[Queue] Failed: ${next.id}: ${e.message}`);
81
+ }
82
+ this.save();
83
+ this.isProcessing = false;
84
+ // Continue with next item if any
85
+ setTimeout(() => this.processNext(), 50);
86
+ }
87
+ // ── Query helpers ─────────────────────────────────────────
88
+ getStatus(id) {
89
+ return this.queue.find(t => t.id === id);
90
+ }
91
+ getPending() {
92
+ return this.queue.filter(t => t.status === 'queued' || t.status === 'running');
93
+ }
94
+ getRecent(n = 10) {
95
+ return [...this.queue]
96
+ .sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime())
97
+ .slice(0, n);
98
+ }
99
+ // ── Persistence ───────────────────────────────────────────
100
+ load() {
101
+ try {
102
+ if ((0, fs_1.existsSync)(this.savePath)) {
103
+ this.queue = JSON.parse((0, fs_1.readFileSync)(this.savePath, 'utf8'));
104
+ }
105
+ }
106
+ catch {
107
+ this.queue = [];
108
+ }
109
+ }
110
+ save() {
111
+ try {
112
+ (0, fs_1.mkdirSync)((0, path_1.dirname)(this.savePath), { recursive: true });
113
+ (0, fs_1.writeFileSync)(this.savePath, JSON.stringify(this.queue, null, 2));
114
+ }
115
+ catch { }
116
+ }
117
+ }
118
+ // ── Singleton — chat endpoint matches api/server.ts port default ──
119
+ exports.taskQueue = new TaskQueue((0, path_1.join)(process.cwd(), 'workspace'), 'http://localhost:4200/api/chat');
@@ -0,0 +1,128 @@
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.recoverTasks = recoverTasks;
11
+ const path_1 = __importDefault(require("path"));
12
+ const fs_1 = __importDefault(require("fs"));
13
+ const TASKS_DIR = path_1.default.join(process.cwd(), 'workspace', 'tasks');
14
+ const MAX_TASK_AGE_MS = 2 * 60 * 60 * 1000; // 2 hours
15
+ async function recoverTasks() {
16
+ if (!fs_1.default.existsSync(TASKS_DIR)) {
17
+ console.log('[Recovery] No task directory found — skipping');
18
+ return;
19
+ }
20
+ let taskDirs;
21
+ try {
22
+ taskDirs = fs_1.default.readdirSync(TASKS_DIR).filter(d => {
23
+ try {
24
+ return fs_1.default.statSync(path_1.default.join(TASKS_DIR, d)).isDirectory();
25
+ }
26
+ catch {
27
+ return false;
28
+ }
29
+ });
30
+ }
31
+ catch (e) {
32
+ console.error(`[Recovery] Cannot read tasks directory: ${e.message}`);
33
+ return;
34
+ }
35
+ let recovered = 0;
36
+ let cleaned = 0;
37
+ let corrupted = 0;
38
+ for (const taskId of taskDirs) {
39
+ const statePath = path_1.default.join(TASKS_DIR, taskId, 'state.json');
40
+ if (!fs_1.default.existsSync(statePath))
41
+ continue;
42
+ let state;
43
+ try {
44
+ state = JSON.parse(fs_1.default.readFileSync(statePath, 'utf-8'));
45
+ }
46
+ catch {
47
+ // Corrupt state file — overwrite with failed status
48
+ corrupted++;
49
+ try {
50
+ const tmp = statePath + '.tmp';
51
+ fs_1.default.writeFileSync(tmp, JSON.stringify({
52
+ id: taskId,
53
+ status: 'failed',
54
+ error: 'Corrupt state file — overwritten on startup',
55
+ createdAt: 0,
56
+ updatedAt: Date.now(),
57
+ }, null, 2));
58
+ // NTFS-safe rename attempt — fall back to direct write on error
59
+ try {
60
+ fs_1.default.renameSync(tmp, statePath);
61
+ }
62
+ catch {
63
+ fs_1.default.writeFileSync(statePath, fs_1.default.readFileSync(tmp, 'utf-8'));
64
+ try {
65
+ fs_1.default.unlinkSync(tmp);
66
+ }
67
+ catch { }
68
+ }
69
+ }
70
+ catch { }
71
+ continue;
72
+ }
73
+ // Skip already-terminal tasks
74
+ if (state.status === 'completed' || state.status === 'failed')
75
+ continue;
76
+ // Only act on tasks stuck in 'running'
77
+ if (state.status !== 'running')
78
+ continue;
79
+ const age = Date.now() - (state.createdAt || 0);
80
+ if (age > MAX_TASK_AGE_MS) {
81
+ // Expired — mark failed and move on
82
+ state.status = 'failed';
83
+ state.error = `Task expired — exceeded ${MAX_TASK_AGE_MS / 60000} minute limit`;
84
+ state.completedAt = Date.now();
85
+ cleaned++;
86
+ try {
87
+ const tmp = statePath + '.tmp';
88
+ fs_1.default.writeFileSync(tmp, JSON.stringify(state, null, 2));
89
+ try {
90
+ fs_1.default.renameSync(tmp, statePath);
91
+ }
92
+ catch {
93
+ fs_1.default.writeFileSync(statePath, JSON.stringify(state, null, 2));
94
+ try {
95
+ fs_1.default.unlinkSync(tmp);
96
+ }
97
+ catch { }
98
+ }
99
+ }
100
+ catch { }
101
+ console.log(`[Recovery] Expired task cleaned: ${taskId} (age: ${Math.round(age / 60000)}m)`);
102
+ }
103
+ else {
104
+ // Recent interrupted task — log it, don't auto-resume
105
+ // (User can retry via the API; auto-resume risks duplicate side effects)
106
+ recovered++;
107
+ const stepsDone = (state.steps || []).filter((s) => s.status === 'completed').length;
108
+ const totalSteps = state.totalSteps || 0;
109
+ console.log(`[Recovery] Interrupted task found: ${taskId}`);
110
+ console.log(` Goal: "${(state.goal || '').slice(0, 60)}"`);
111
+ console.log(` Progress: ${stepsDone}/${totalSteps} steps, age: ${Math.round(age / 60000)}m`);
112
+ console.log(` Status kept as 'running' — user can retry via the API`);
113
+ }
114
+ }
115
+ // Summary
116
+ if (recovered > 0) {
117
+ console.log(`[Recovery] ${recovered} interrupted task(s) available for retry`);
118
+ }
119
+ if (cleaned > 0) {
120
+ console.log(`[Recovery] Cleaned ${cleaned} expired/stale task(s)`);
121
+ }
122
+ if (corrupted > 0) {
123
+ console.log(`[Recovery] Reset ${corrupted} corrupt task state file(s)`);
124
+ }
125
+ if (recovered === 0 && cleaned === 0 && corrupted === 0) {
126
+ console.log('[Recovery] No interrupted tasks found');
127
+ }
128
+ }