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,149 @@
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.loadConfig = loadConfig;
41
+ exports.saveConfig = saveConfig;
42
+ exports.getActiveProvider = getActiveProvider;
43
+ // providers/index.ts — Config schema, load/save, legacy provider resolver
44
+ const fs = __importStar(require("fs"));
45
+ const path = __importStar(require("path"));
46
+ const ollama_1 = require("./ollama");
47
+ const groq_1 = require("./groq");
48
+ const openrouter_1 = require("./openrouter");
49
+ const gemini_1 = require("./gemini");
50
+ const boa_1 = require("./boa");
51
+ const cerebras_1 = require("./cerebras");
52
+ const custom_1 = require("./custom");
53
+ // Use AIDEN_CONFIG_DIR when injected by Electron CLI mode, otherwise fall back to cwd/config
54
+ const CONFIG_PATH = path.join(process.env.AIDEN_CONFIG_DIR || path.join(process.cwd(), 'config'), 'devos.config.json');
55
+ // ── Defaults ──────────────────────────────────────────────────
56
+ function defaultConfig() {
57
+ return {
58
+ user: { name: 'there' },
59
+ model: { active: 'cerebras-free', activeModel: 'llama3.1-8b' },
60
+ providers: {
61
+ ollama: { enabled: true, models: [] },
62
+ apis: [
63
+ {
64
+ name: 'cerebras-free',
65
+ provider: 'cerebras',
66
+ key: 'csk-w32jtjthv666erywhmxrkpx9kfnehn4e6cp38n3d3kmym943',
67
+ model: 'llama3.1-8b',
68
+ enabled: true,
69
+ rateLimited: false,
70
+ usageCount: 0,
71
+ },
72
+ {
73
+ name: 'cloudflare-free',
74
+ provider: 'cloudflare',
75
+ key: 'env:CLOUDFLARE_API_TOKEN',
76
+ model: 'env:CLOUDFLARE_ACCOUNT_ID|@cf/meta/llama-3.1-8b-instruct',
77
+ enabled: false,
78
+ rateLimited: false,
79
+ usageCount: 0,
80
+ },
81
+ ],
82
+ },
83
+ routing: { mode: 'auto', fallbackToOllama: true },
84
+ onboardingComplete: false,
85
+ };
86
+ }
87
+ // ── Load / save ───────────────────────────────────────────────
88
+ function loadConfig() {
89
+ try {
90
+ const raw = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8'));
91
+ // Back-compat: migrate old apis entries that lack new fields
92
+ if (raw.providers?.apis) {
93
+ raw.providers.apis = raw.providers.apis.map(a => ({
94
+ model: '',
95
+ enabled: true,
96
+ rateLimited: false,
97
+ usageCount: 0,
98
+ ...a,
99
+ }));
100
+ }
101
+ // Back-compat: add routing if missing
102
+ if (!raw.routing)
103
+ raw.routing = { mode: 'auto', fallbackToOllama: true };
104
+ // Back-compat: add customProviders if missing
105
+ if (!raw.customProviders)
106
+ raw.customProviders = [];
107
+ return raw;
108
+ }
109
+ catch {
110
+ return defaultConfig();
111
+ }
112
+ }
113
+ function saveConfig(config) {
114
+ fs.mkdirSync(path.dirname(CONFIG_PATH), { recursive: true });
115
+ fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), 'utf-8');
116
+ }
117
+ // ── Legacy active provider resolver (used by onboarding fallback) ──
118
+ function getActiveProvider() {
119
+ const config = loadConfig();
120
+ const userName = config.user?.name || 'there';
121
+ if (config.model.active === 'ollama') {
122
+ return { provider: ollama_1.ollamaProvider, model: config.model.activeModel || 'mistral:7b', userName };
123
+ }
124
+ const apiConfig = config.providers?.apis?.find(a => a.name === config.model.active);
125
+ if (!apiConfig) {
126
+ return { provider: ollama_1.ollamaProvider, model: config.model.activeModel || 'mistral:7b', userName };
127
+ }
128
+ const key = apiConfig.key.startsWith('env:')
129
+ ? process.env[apiConfig.key.replace('env:', '')] || ''
130
+ : apiConfig.key;
131
+ switch (apiConfig.provider) {
132
+ case 'groq':
133
+ return { provider: (0, groq_1.createGroqProvider)(key), model: apiConfig.model || 'llama-3.3-70b-versatile', userName };
134
+ case 'openrouter':
135
+ return { provider: (0, openrouter_1.createOpenRouterProvider)(key), model: apiConfig.model || 'meta-llama/llama-3.3-70b-instruct', userName };
136
+ case 'gemini':
137
+ return { provider: (0, gemini_1.createGeminiProvider)(key), model: apiConfig.model || 'gemini-1.5-flash', userName };
138
+ case 'boa':
139
+ return { provider: (0, boa_1.createBOAProvider)(key), model: apiConfig.model || 'llama-3.3-70b', userName };
140
+ case 'cerebras':
141
+ return { provider: (0, cerebras_1.createCerebrasProvider)(key), model: apiConfig.model || 'llama3.1-8b', userName };
142
+ case 'custom': {
143
+ const baseUrl = apiConfig.baseUrl || 'http://localhost:11434/v1';
144
+ return { provider: (0, custom_1.createCustomProvider)(baseUrl, key, apiConfig.name), model: apiConfig.model || 'gpt-4o-mini', userName };
145
+ }
146
+ default:
147
+ return { provider: ollama_1.ollamaProvider, model: config.model.activeModel || 'mistral:7b', userName };
148
+ }
149
+ }
@@ -0,0 +1,70 @@
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.createNvidiaProvider = createNvidiaProvider;
8
+ function createNvidiaProvider(apiKey) {
9
+ return {
10
+ name: 'nvidia',
11
+ async generate(messages, model) {
12
+ const res = await fetch('https://integrate.api.nvidia.com/v1/chat/completions', {
13
+ method: 'POST',
14
+ headers: {
15
+ 'Content-Type': 'application/json',
16
+ 'Authorization': `Bearer ${apiKey}`,
17
+ },
18
+ body: JSON.stringify({ model: model || 'meta/llama-3.3-70b-instruct', messages, stream: false }),
19
+ });
20
+ const data = await res.json();
21
+ return data?.choices?.[0]?.message?.content || '';
22
+ },
23
+ async generateStream(messages, model, onToken) {
24
+ try {
25
+ const res = await fetch('https://integrate.api.nvidia.com/v1/chat/completions', {
26
+ method: 'POST',
27
+ headers: {
28
+ 'Content-Type': 'application/json',
29
+ 'Authorization': `Bearer ${apiKey}`,
30
+ },
31
+ body: JSON.stringify({ model: model || 'meta/llama-3.3-70b-instruct', messages, stream: true }),
32
+ });
33
+ if (!res.ok) {
34
+ const err = await res.text();
35
+ throw new Error(`${res.status}: ${err}`);
36
+ }
37
+ if (!res.body)
38
+ return;
39
+ const reader = res.body.getReader();
40
+ const decoder = new TextDecoder();
41
+ let buf = '';
42
+ while (true) {
43
+ const { done, value } = await reader.read();
44
+ if (done)
45
+ break;
46
+ buf += decoder.decode(value, { stream: true });
47
+ const lines = buf.split('\n');
48
+ buf = lines.pop() ?? '';
49
+ for (const line of lines) {
50
+ if (!line.startsWith('data: '))
51
+ continue;
52
+ const raw = line.replace('data: ', '').trim();
53
+ if (raw === '[DONE]')
54
+ return;
55
+ try {
56
+ const parsed = JSON.parse(raw);
57
+ const token = parsed?.choices?.[0]?.delta?.content;
58
+ if (token)
59
+ onToken(token);
60
+ }
61
+ catch { }
62
+ }
63
+ }
64
+ }
65
+ catch (err) {
66
+ throw err;
67
+ }
68
+ },
69
+ };
70
+ }
@@ -0,0 +1,99 @@
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.ollamaProvider = void 0;
8
+ const modelDiscovery_1 = require("../core/modelDiscovery");
9
+ /** Build Ollama options object from environment variables.
10
+ * Only includes keys that are explicitly set — Ollama uses its own defaults
11
+ * for anything omitted, so we never send NaN or out-of-range values. */
12
+ function getOllamaOptions() {
13
+ const opts = {};
14
+ const temp = parseFloat(process.env.OLLAMA_TEMPERATURE ?? '');
15
+ if (!isNaN(temp) && temp >= 0 && temp <= 2)
16
+ opts.temperature = temp;
17
+ const ctx = parseInt(process.env.OLLAMA_CONTEXT_LENGTH ?? '', 10);
18
+ if (!isNaN(ctx) && ctx > 0)
19
+ opts.num_ctx = ctx;
20
+ const gpu = parseInt(process.env.OLLAMA_NUM_GPU ?? '', 10);
21
+ if (!isNaN(gpu) && gpu >= 0)
22
+ opts.num_gpu = gpu;
23
+ const threads = parseInt(process.env.OLLAMA_NUM_THREAD ?? '', 10);
24
+ if (!isNaN(threads) && threads > 0)
25
+ opts.num_thread = threads;
26
+ const topP = parseFloat(process.env.OLLAMA_TOP_P ?? '');
27
+ if (!isNaN(topP) && topP >= 0 && topP <= 1)
28
+ opts.top_p = topP;
29
+ const repeatPenalty = parseFloat(process.env.OLLAMA_REPEAT_PENALTY ?? '');
30
+ if (!isNaN(repeatPenalty) && repeatPenalty >= 0)
31
+ opts.repeat_penalty = repeatPenalty;
32
+ return Object.keys(opts).length > 0 ? opts : undefined;
33
+ }
34
+ exports.ollamaProvider = {
35
+ name: 'ollama',
36
+ async generate(messages, model) {
37
+ const options = getOllamaOptions();
38
+ const res = await fetch('http://localhost:11434/api/chat', {
39
+ method: 'POST',
40
+ headers: { 'Content-Type': 'application/json' },
41
+ body: JSON.stringify({ model, stream: false, messages, ...(options && { options }) }),
42
+ signal: AbortSignal.timeout((0, modelDiscovery_1.getOllamaTimeout)(model || '')),
43
+ });
44
+ const data = await res.json();
45
+ return data?.message?.content || '';
46
+ },
47
+ async generateStream(messages, model, onToken) {
48
+ const options = getOllamaOptions();
49
+ const res = await fetch('http://localhost:11434/api/chat', {
50
+ method: 'POST',
51
+ headers: { 'Content-Type': 'application/json' },
52
+ body: JSON.stringify({ model, stream: true, messages, ...(options && { options }) }),
53
+ signal: AbortSignal.timeout((0, modelDiscovery_1.getOllamaTimeout)(model || '')),
54
+ });
55
+ if (!res.body)
56
+ return;
57
+ const reader = res.body.getReader();
58
+ const decoder = new TextDecoder();
59
+ let buf = '';
60
+ while (true) {
61
+ const { done, value } = await reader.read();
62
+ if (done)
63
+ break;
64
+ buf += decoder.decode(value, { stream: true });
65
+ const lines = buf.split('\n');
66
+ buf = lines.pop() ?? '';
67
+ for (const line of lines) {
68
+ if (!line.trim())
69
+ continue;
70
+ try {
71
+ const parsed = JSON.parse(line);
72
+ if (parsed.message?.content)
73
+ onToken(parsed.message.content);
74
+ }
75
+ catch { /* skip malformed */ }
76
+ }
77
+ }
78
+ // flush remaining
79
+ if (buf.trim()) {
80
+ try {
81
+ const parsed = JSON.parse(buf);
82
+ if (parsed.message?.content)
83
+ onToken(parsed.message.content);
84
+ }
85
+ catch { }
86
+ }
87
+ },
88
+ async listModels() {
89
+ try {
90
+ const ollamaBase = (process.env.OLLAMA_HOST ?? 'http://127.0.0.1:11434').replace(/\/$/, '');
91
+ const res = await fetch(`${ollamaBase}/api/tags`, { signal: AbortSignal.timeout(3000) });
92
+ const data = await res.json();
93
+ return data.models?.map((m) => m.name) || [];
94
+ }
95
+ catch {
96
+ return [];
97
+ }
98
+ },
99
+ };
@@ -0,0 +1,74 @@
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.createOpenRouterProvider = createOpenRouterProvider;
8
+ function createOpenRouterProvider(apiKey) {
9
+ return {
10
+ name: 'openrouter',
11
+ async generate(messages, model) {
12
+ const res = await fetch('https://openrouter.ai/api/v1/chat/completions', {
13
+ method: 'POST',
14
+ headers: {
15
+ 'Content-Type': 'application/json',
16
+ 'Authorization': `Bearer ${apiKey}`,
17
+ 'HTTP-Referer': 'http://localhost:3000',
18
+ 'X-Title': 'DevOS',
19
+ },
20
+ body: JSON.stringify({ model, messages }),
21
+ });
22
+ const data = await res.json();
23
+ return data?.choices?.[0]?.message?.content || '';
24
+ },
25
+ async generateStream(messages, model, onToken) {
26
+ try {
27
+ const res = await fetch('https://openrouter.ai/api/v1/chat/completions', {
28
+ method: 'POST',
29
+ headers: {
30
+ 'Content-Type': 'application/json',
31
+ 'Authorization': `Bearer ${apiKey}`,
32
+ 'HTTP-Referer': 'http://localhost:3000',
33
+ 'X-Title': 'DevOS',
34
+ },
35
+ body: JSON.stringify({ model, messages, stream: true }),
36
+ });
37
+ if (!res.ok) {
38
+ const err = await res.text();
39
+ throw new Error(`${res.status}: ${err}`);
40
+ }
41
+ if (!res.body)
42
+ return;
43
+ const reader = res.body.getReader();
44
+ const decoder = new TextDecoder();
45
+ let buf = '';
46
+ while (true) {
47
+ const { done, value } = await reader.read();
48
+ if (done)
49
+ break;
50
+ buf += decoder.decode(value, { stream: true });
51
+ const lines = buf.split('\n');
52
+ buf = lines.pop() ?? '';
53
+ for (const line of lines) {
54
+ if (!line.startsWith('data: '))
55
+ continue;
56
+ const raw = line.replace('data: ', '').trim();
57
+ if (raw === '[DONE]')
58
+ return;
59
+ try {
60
+ const parsed = JSON.parse(raw);
61
+ const token = parsed?.choices?.[0]?.delta?.content;
62
+ if (token)
63
+ onToken(token);
64
+ }
65
+ catch { }
66
+ }
67
+ }
68
+ }
69
+ catch (err) {
70
+ throw err;
71
+ }
72
+ },
73
+ };
74
+ }