@benzsiangco/jarvis 1.0.0 → 1.1.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 (55) hide show
  1. package/README.md +5 -0
  2. package/bin/{jarvis.js → jarvis} +1 -1
  3. package/dist/cli.js +476 -350
  4. package/dist/electron/main.js +160 -0
  5. package/dist/electron/preload.js +19 -0
  6. package/package.json +21 -8
  7. package/skills.md +147 -0
  8. package/src/agents/index.ts +248 -0
  9. package/src/brain/loader.ts +136 -0
  10. package/src/cli.ts +411 -0
  11. package/src/config/index.ts +363 -0
  12. package/src/core/executor.ts +222 -0
  13. package/src/core/plugins.ts +148 -0
  14. package/src/core/types.ts +217 -0
  15. package/src/electron/main.ts +192 -0
  16. package/src/electron/preload.ts +25 -0
  17. package/src/electron/types.d.ts +20 -0
  18. package/src/index.ts +12 -0
  19. package/src/providers/antigravity-loader.ts +233 -0
  20. package/src/providers/antigravity.ts +585 -0
  21. package/src/providers/index.ts +523 -0
  22. package/src/sessions/index.ts +194 -0
  23. package/src/tools/index.ts +436 -0
  24. package/src/tui/index.tsx +784 -0
  25. package/src/utils/auth-prompt.ts +394 -0
  26. package/src/utils/index.ts +180 -0
  27. package/src/utils/native-picker.ts +71 -0
  28. package/src/utils/skills.ts +99 -0
  29. package/src/utils/table-integration-examples.ts +617 -0
  30. package/src/utils/table-utils.ts +401 -0
  31. package/src/web/build-ui.ts +27 -0
  32. package/src/web/server.ts +674 -0
  33. package/src/web/ui/dist/.gitkeep +0 -0
  34. package/src/web/ui/dist/main.css +1 -0
  35. package/src/web/ui/dist/main.js +320 -0
  36. package/src/web/ui/dist/main.js.map +20 -0
  37. package/src/web/ui/index.html +46 -0
  38. package/src/web/ui/src/App.tsx +143 -0
  39. package/src/web/ui/src/Modules/Safety/GuardianModal.tsx +83 -0
  40. package/src/web/ui/src/components/Layout/ContextPanel.tsx +243 -0
  41. package/src/web/ui/src/components/Layout/Header.tsx +91 -0
  42. package/src/web/ui/src/components/Layout/ModelSelector.tsx +235 -0
  43. package/src/web/ui/src/components/Layout/SessionStats.tsx +369 -0
  44. package/src/web/ui/src/components/Layout/Sidebar.tsx +895 -0
  45. package/src/web/ui/src/components/Modules/Chat/ChatStage.tsx +620 -0
  46. package/src/web/ui/src/components/Modules/Chat/MessageItem.tsx +446 -0
  47. package/src/web/ui/src/components/Modules/Editor/CommandInspector.tsx +71 -0
  48. package/src/web/ui/src/components/Modules/Editor/DiffViewer.tsx +83 -0
  49. package/src/web/ui/src/components/Modules/Terminal/TabbedTerminal.tsx +202 -0
  50. package/src/web/ui/src/components/Settings/SettingsModal.tsx +935 -0
  51. package/src/web/ui/src/config/models.ts +70 -0
  52. package/src/web/ui/src/main.tsx +13 -0
  53. package/src/web/ui/src/store/agentStore.ts +41 -0
  54. package/src/web/ui/src/store/uiStore.ts +64 -0
  55. package/src/web/ui/src/types/index.ts +54 -0
@@ -0,0 +1,160 @@
1
+ import { app, BrowserWindow, ipcMain, dialog } from 'electron';
2
+ import { spawn } from 'child_process';
3
+ import path from 'path';
4
+ import { fileURLToPath } from 'url';
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = path.dirname(__filename);
7
+ let mainWindow = null;
8
+ let bunServer = null;
9
+ let serverPort = 5533;
10
+ /**
11
+ * Start Bun server in background
12
+ */
13
+ async function startBunServer() {
14
+ return new Promise((resolve, reject) => {
15
+ console.log('[Electron] Starting Bun server...');
16
+ // Find project root (go up from dist/electron/main.js to project root)
17
+ const projectRoot = path.join(__dirname, '..', '..');
18
+ const cliPath = path.join(projectRoot, 'src', 'cli.ts');
19
+ // Start Bun server
20
+ bunServer = spawn('bun', ['run', cliPath, 'web', '--port', String(serverPort)], {
21
+ cwd: projectRoot,
22
+ stdio: 'pipe'
23
+ });
24
+ bunServer.stdout?.on('data', (data) => {
25
+ const output = data.toString();
26
+ console.log('[Bun Server]', output);
27
+ // Look for server ready message
28
+ if (output.includes('Server running') || output.includes('localhost')) {
29
+ resolve(`http://localhost:${serverPort}`);
30
+ }
31
+ });
32
+ bunServer.stderr?.on('data', (data) => {
33
+ console.error('[Bun Server Error]', data.toString());
34
+ });
35
+ bunServer.on('error', (error) => {
36
+ console.error('[Bun Server] Failed to start:', error);
37
+ reject(error);
38
+ });
39
+ // Timeout after 10 seconds
40
+ setTimeout(() => {
41
+ resolve(`http://localhost:${serverPort}`);
42
+ }, 3000);
43
+ });
44
+ }
45
+ /**
46
+ * Create main Electron window
47
+ */
48
+ async function createWindow() {
49
+ console.log('[Electron] Creating main window...');
50
+ // Start Bun server first
51
+ const serverUrl = await startBunServer();
52
+ console.log('[Electron] Server URL:', serverUrl);
53
+ // Create browser window
54
+ mainWindow = new BrowserWindow({
55
+ width: 1400,
56
+ height: 900,
57
+ minWidth: 1024,
58
+ minHeight: 768,
59
+ title: 'JARVIS - AI Coding Assistant',
60
+ backgroundColor: '#09090b', // zinc-950
61
+ autoHideMenuBar: true, // Hide menu bar but allow Alt to show it
62
+ webPreferences: {
63
+ preload: path.join(__dirname, 'preload.js'),
64
+ contextIsolation: true,
65
+ nodeIntegration: false,
66
+ sandbox: false
67
+ },
68
+ show: false // Don't show until ready
69
+ });
70
+ // Show window when ready
71
+ mainWindow.once('ready-to-show', () => {
72
+ mainWindow?.show();
73
+ console.log('[Electron] Window ready');
74
+ });
75
+ // Load the Bun server URL
76
+ await mainWindow.loadURL(serverUrl);
77
+ // Open DevTools in development
78
+ if (process.env.NODE_ENV === 'development') {
79
+ mainWindow.webContents.openDevTools();
80
+ }
81
+ // Handle window closed
82
+ mainWindow.on('closed', () => {
83
+ mainWindow = null;
84
+ });
85
+ }
86
+ /**
87
+ * Setup IPC handlers
88
+ */
89
+ function setupIPC() {
90
+ // Handle folder selection
91
+ ipcMain.handle('select-folder', async () => {
92
+ const result = await dialog.showOpenDialog({
93
+ properties: ['openDirectory'],
94
+ title: 'Select Workspace Folder'
95
+ });
96
+ if (result.canceled || result.filePaths.length === 0) {
97
+ return null;
98
+ }
99
+ return result.filePaths[0];
100
+ });
101
+ // Handle file selection
102
+ ipcMain.handle('select-files', async () => {
103
+ const result = await dialog.showOpenDialog({
104
+ properties: ['openFile', 'multiSelections'],
105
+ title: 'Select Files'
106
+ });
107
+ if (result.canceled) {
108
+ return [];
109
+ }
110
+ return result.filePaths;
111
+ });
112
+ // Get app version
113
+ ipcMain.handle('get-app-version', () => {
114
+ return app.getVersion();
115
+ });
116
+ // Get app mode
117
+ ipcMain.handle('get-app-mode', () => {
118
+ return 'electron';
119
+ });
120
+ }
121
+ /**
122
+ * Cleanup on app quit
123
+ */
124
+ function cleanup() {
125
+ console.log('[Electron] Cleaning up...');
126
+ if (bunServer) {
127
+ console.log('[Electron] Stopping Bun server...');
128
+ bunServer.kill();
129
+ bunServer = null;
130
+ }
131
+ }
132
+ /**
133
+ * App lifecycle
134
+ */
135
+ app.whenReady().then(() => {
136
+ console.log('[Electron] App ready');
137
+ setupIPC();
138
+ createWindow();
139
+ // On macOS, re-create window when dock icon is clicked
140
+ app.on('activate', () => {
141
+ if (BrowserWindow.getAllWindows().length === 0) {
142
+ createWindow();
143
+ }
144
+ });
145
+ });
146
+ // Quit when all windows are closed (except on macOS)
147
+ app.on('window-all-closed', () => {
148
+ if (process.platform !== 'darwin') {
149
+ cleanup();
150
+ app.quit();
151
+ }
152
+ });
153
+ // Cleanup before quit
154
+ app.on('before-quit', () => {
155
+ cleanup();
156
+ });
157
+ // Handle uncaught errors
158
+ process.on('uncaughtException', (error) => {
159
+ console.error('[Electron] Uncaught exception:', error);
160
+ });
@@ -0,0 +1,19 @@
1
+ import { contextBridge, ipcRenderer } from 'electron';
2
+ /**
3
+ * Electron Preload Script
4
+ * Bridges main process and renderer process securely
5
+ */
6
+ // Expose safe APIs to renderer process
7
+ contextBridge.exposeInMainWorld('electron', {
8
+ // Folder selection
9
+ selectFolder: () => ipcRenderer.invoke('select-folder'),
10
+ // File selection
11
+ selectFiles: () => ipcRenderer.invoke('select-files'),
12
+ // App info
13
+ getAppVersion: () => ipcRenderer.invoke('get-app-version'),
14
+ getAppMode: () => ipcRenderer.invoke('get-app-mode'),
15
+ // Environment detection
16
+ isElectron: true,
17
+ platform: process.platform
18
+ });
19
+ console.log('[Preload] Electron APIs exposed to renderer');
package/package.json CHANGED
@@ -1,32 +1,42 @@
1
1
  {
2
2
  "name": "@benzsiangco/jarvis",
3
- "version": "1.0.0",
4
- "description": "AI coding agent with TUI, Web, and Desktop support",
3
+ "version": "1.1.0",
4
+ "description": "AI coding agent with TUI, Web, and Desktop support - Now with Brain system, OAuth config, and enhanced Skills",
5
5
  "module": "src/index.ts",
6
6
  "type": "module",
7
7
  "private": false,
8
8
  "bin": {
9
- "jarvis": "./bin/jarvis.js"
9
+ "jarvis": "./bin/jarvis"
10
10
  },
11
11
  "files": [
12
12
  "dist",
13
- "bin"
13
+ "bin",
14
+ "src",
15
+ "skills.md"
14
16
  ],
15
17
  "scripts": {
16
18
  "dev": "bun run src/cli.ts",
17
- "build": "bun build src/cli.ts --outdir dist --target node --minify",
19
+ "build": "bun build src/cli.ts --outdir dist --target bun --minify",
18
20
  "prepublishOnly": "bun run build",
19
21
  "start": "bun run dist/cli.js",
20
22
  "typecheck": "tsc --noEmit",
21
23
  "opentui": "bun run src/cli.ts tui",
22
24
  "web": "bun run src/cli.ts web",
23
- "web:build": "bun run src/web/build-ui.ts"
25
+ "web:build": "bun run src/web/build-ui.ts",
26
+ "electron:compile": "tsc src/electron/main.ts src/electron/preload.ts --outDir dist/electron --target es2020 --module esnext --moduleResolution bundler --esModuleInterop --skipLibCheck",
27
+ "electron:dev": "concurrently \"bun run web\" \"electron dist/electron/main.js\"",
28
+ "electron:build": "bun run web:build && bun run electron:compile && electron-builder",
29
+ "electron:start": "electron dist/electron/main.js"
24
30
  },
31
+ "main": "dist/electron/main.js",
25
32
  "devDependencies": {
26
33
  "@types/bun": "latest",
27
34
  "@types/marked-terminal": "^6.1.1",
28
35
  "@types/node": "^22.10.0",
29
- "@types/react": "19"
36
+ "@types/react": "19",
37
+ "concurrently": "^9.2.1",
38
+ "electron": "^40.0.0",
39
+ "electron-builder": "^26.4.0"
30
40
  },
31
41
  "peerDependencies": {
32
42
  "typescript": "^5"
@@ -46,11 +56,13 @@
46
56
  "commander": "^12.1.0",
47
57
  "conf": "^13.0.0",
48
58
  "figures": "^6.0.0",
59
+ "framer-motion": "^12.27.0",
49
60
  "glob": "^11.0.0",
50
61
  "hono": "^4.11.4",
51
62
  "lucide-react": "^0.562.0",
52
63
  "marked": "^15.0.0",
53
64
  "marked-terminal": "^7.2.0",
65
+ "node-pty": "^1.1.0",
54
66
  "open": "^11.0.0",
55
67
  "opencode-antigravity-auth": "^1.3.0",
56
68
  "ora": "^8.0.0",
@@ -63,7 +75,8 @@
63
75
  "tailwind-merge": "^3.4.0",
64
76
  "xterm": "^5.3.0",
65
77
  "xterm-addon-fit": "^0.8.0",
66
- "zod": "^3.23.0"
78
+ "zod": "^3.23.0",
79
+ "zustand": "^5.0.10"
67
80
  },
68
81
  "engines": {
69
82
  "node": ">=20.0.0"
package/skills.md ADDED
@@ -0,0 +1,147 @@
1
+ # JARVIS Skills Registry
2
+
3
+ This file contains modular skill modules that JARVIS can reference. Each skill adds specialized knowledge to specific domains.
4
+
5
+ ---
6
+
7
+ ## DevOps & Infrastructure
8
+
9
+ ### Linux System Administration
10
+ - Expert in systemd, journalctl, process management
11
+ - Package management (apt, yum, pacman)
12
+ - Systemctl service management
13
+ - Log analysis and debugging
14
+ - Performance tuning and monitoring
15
+
16
+ ### Docker & Containerization
17
+ - Dockerfile best practices and optimization
18
+ - Multi-stage builds for minimal images
19
+ - Docker Compose orchestration
20
+ - Volume management and networking
21
+ - Container security hardening
22
+ - Image layer optimization
23
+
24
+ ### Proxmox Virtualization
25
+ - LXC container management (pct commands)
26
+ - VM operations (qm commands)
27
+ - Storage configuration (LVM, ZFS)
28
+ - Network bridge setup
29
+ - Backup and restore strategies
30
+ - Resource allocation and limits
31
+
32
+ ---
33
+
34
+ ## Security & Hacking
35
+
36
+ ### Penetration Testing
37
+ - Reconnaissance and enumeration
38
+ - Vulnerability scanning (Nmap, Nikto, etc.)
39
+ - Web application testing (OWASP Top 10)
40
+ - Privilege escalation techniques
41
+ - Exploit development basics
42
+ - Post-exploitation strategies
43
+
44
+ ### Network Security
45
+ - Firewall configuration (iptables, ufw, pf)
46
+ - VPN setup (WireGuard, OpenVPN)
47
+ - SSH hardening and key management
48
+ - TLS/SSL certificate management
49
+ - Network traffic analysis
50
+ - Intrusion detection systems
51
+
52
+ ### Cloudflare Integration
53
+ - Cloudflare Tunnel (cloudflared) setup
54
+ - DNS management and configuration
55
+ - WAF rules and security policies
56
+ - Zero Trust Access configuration
57
+ - CDN optimization
58
+ - DDoS protection strategies
59
+
60
+ ---
61
+
62
+ ## Software Development
63
+
64
+ ### TypeScript & JavaScript
65
+ - Modern ES6+ features
66
+ - TypeScript advanced types (generics, conditional types)
67
+ - Async/await patterns
68
+ - Module systems (ESM, CommonJS)
69
+ - Build tools (Bun, Vite, esbuild)
70
+ - Testing (Jest, Vitest, Playwright)
71
+
72
+ ### Frontend Development
73
+ - React ecosystem (hooks, context, state management)
74
+ - Next.js (App Router, Server Components)
75
+ - TailwindCSS utility-first design
76
+ - Framer Motion animations
77
+ - Responsive design patterns
78
+ - Performance optimization
79
+
80
+ ### Backend Development
81
+ - Hono web framework
82
+ - RESTful API design
83
+ - WebSocket real-time communication
84
+ - Database design (SQL, NoSQL)
85
+ - Authentication & authorization
86
+ - API security best practices
87
+
88
+ ---
89
+
90
+ ## Automation & Scripting
91
+
92
+ ### SSH Automation
93
+ - SSH key-based authentication
94
+ - Remote command execution
95
+ - SCP/SFTP file transfers
96
+ - SSH tunneling and port forwarding
97
+ - ProxyJump configurations
98
+ - Batch operations on multiple servers
99
+
100
+ ### CI/CD Pipelines
101
+ - GitHub Actions workflows
102
+ - GitLab CI/CD configuration
103
+ - Docker-based build pipelines
104
+ - Automated testing integration
105
+ - Deployment strategies (blue-green, canary)
106
+ - Rollback mechanisms
107
+
108
+ ---
109
+
110
+ ## Database Management
111
+
112
+ ### PostgreSQL
113
+ - Schema design and normalization
114
+ - Query optimization and indexing
115
+ - JSONB operations
116
+ - Full-text search
117
+ - Replication and backup
118
+ - Performance tuning
119
+
120
+ ### Redis
121
+ - Caching strategies
122
+ - Pub/Sub messaging
123
+ - Session management
124
+ - Rate limiting implementation
125
+ - Data structures (Lists, Sets, Hashes)
126
+
127
+ ---
128
+
129
+ ## Monitoring & Observability
130
+
131
+ ### Logging Systems
132
+ - Structured logging best practices
133
+ - Log aggregation (ELK stack, Loki)
134
+ - Log rotation and retention
135
+ - Error tracking (Sentry integration)
136
+ - Correlation IDs for distributed systems
137
+
138
+ ### Metrics & Alerts
139
+ - Prometheus metrics collection
140
+ - Grafana dashboard creation
141
+ - Alert rule configuration
142
+ - SLO/SLI definition
143
+ - Incident response procedures
144
+
145
+ ---
146
+
147
+ _Add more skills as needed. Each skill module is automatically included when relevant to the conversation._
@@ -0,0 +1,248 @@
1
+ // Agent system for Jarvis
2
+ import type { AgentConfig, AgentMode } from '../core/types';
3
+
4
+ // Built-in agent definitions
5
+ const builtinAgents: Record<string, AgentConfig> = {
6
+ build: {
7
+ id: 'build',
8
+ name: 'Jarvis',
9
+ description: 'A powerful AI coding assistant with full tool access for development work',
10
+ mode: 'primary',
11
+ tools: {
12
+ bash: true,
13
+ read: true,
14
+ write: true,
15
+ edit: true,
16
+ glob: true,
17
+ grep: true,
18
+ webfetch: true,
19
+ task: true,
20
+ todoread: true,
21
+ todowrite: true,
22
+ question: true,
23
+ },
24
+ permission: {
25
+ edit: 'allow',
26
+ bash: 'allow',
27
+ webfetch: 'allow',
28
+ },
29
+ },
30
+ plan: {
31
+ id: 'plan',
32
+ name: 'Plan',
33
+ description: 'Restricted agent for planning and analysis without making changes',
34
+ mode: 'primary',
35
+ tools: {
36
+ bash: false,
37
+ read: true,
38
+ write: false,
39
+ edit: false,
40
+ glob: true,
41
+ grep: true,
42
+ webfetch: true,
43
+ task: true,
44
+ todoread: true,
45
+ todowrite: true,
46
+ question: true,
47
+ },
48
+ permission: {
49
+ edit: 'deny',
50
+ bash: 'ask',
51
+ webfetch: 'allow',
52
+ },
53
+ },
54
+ general: {
55
+ id: 'general',
56
+ name: 'General',
57
+ description: 'General-purpose agent for researching complex questions and executing multi-step tasks',
58
+ mode: 'subagent',
59
+ tools: {
60
+ bash: true,
61
+ read: true,
62
+ write: true,
63
+ edit: true,
64
+ glob: true,
65
+ grep: true,
66
+ webfetch: true,
67
+ task: false, // Cannot spawn sub-subagents
68
+ todoread: true,
69
+ todowrite: true,
70
+ question: true,
71
+ },
72
+ permission: {
73
+ edit: 'allow',
74
+ bash: 'allow',
75
+ webfetch: 'allow',
76
+ },
77
+ },
78
+ explore: {
79
+ id: 'explore',
80
+ name: 'Explore',
81
+ description: 'Fast agent specialized for exploring codebases. Use for finding files by patterns, searching code, or answering questions about the codebase.',
82
+ mode: 'subagent',
83
+ maxSteps: 10,
84
+ tools: {
85
+ bash: false,
86
+ read: true,
87
+ write: false,
88
+ edit: false,
89
+ glob: true,
90
+ grep: true,
91
+ webfetch: false,
92
+ task: false,
93
+ todoread: true,
94
+ todowrite: true,
95
+ question: false,
96
+ },
97
+ permission: {
98
+ edit: 'deny',
99
+ bash: 'deny',
100
+ webfetch: 'deny',
101
+ },
102
+ },
103
+ };
104
+
105
+ // Agent registry
106
+ const agents = new Map<string, AgentConfig>();
107
+
108
+ // Initialize with built-in agents
109
+ export function initializeAgents(customAgents?: Record<string, Partial<AgentConfig>>): void {
110
+ agents.clear();
111
+
112
+ // Add built-in agents
113
+ for (const [id, agent] of Object.entries(builtinAgents)) {
114
+ agents.set(id, agent);
115
+ }
116
+
117
+ // Merge with custom agents
118
+ if (customAgents) {
119
+ for (const [id, customConfig] of Object.entries(customAgents)) {
120
+ const existingAgent = agents.get(id);
121
+ if (existingAgent) {
122
+ // Merge with existing agent
123
+ agents.set(id, mergeAgentConfig(existingAgent, customConfig));
124
+ } else {
125
+ // Create new agent
126
+ agents.set(id, {
127
+ id,
128
+ name: customConfig.name ?? id,
129
+ description: customConfig.description ?? '',
130
+ mode: customConfig.mode ?? 'all',
131
+ ...customConfig,
132
+ } as AgentConfig);
133
+ }
134
+ }
135
+ }
136
+ }
137
+
138
+ function mergeAgentConfig(base: AgentConfig, override: Partial<AgentConfig>): AgentConfig {
139
+ return {
140
+ ...base,
141
+ ...override,
142
+ tools: {
143
+ ...base.tools,
144
+ ...override.tools,
145
+ },
146
+ permission: {
147
+ ...base.permission,
148
+ ...override.permission,
149
+ },
150
+ };
151
+ }
152
+
153
+ export function getAgent(id: string): AgentConfig | undefined {
154
+ return agents.get(id);
155
+ }
156
+
157
+ export function getPrimaryAgents(): AgentConfig[] {
158
+ return Array.from(agents.values()).filter(
159
+ (agent) => agent.mode === 'primary' || agent.mode === 'all'
160
+ );
161
+ }
162
+
163
+ export function getSubagents(): AgentConfig[] {
164
+ return Array.from(agents.values()).filter(
165
+ (agent) => (agent.mode === 'subagent' || agent.mode === 'all') && !agent.hidden
166
+ );
167
+ }
168
+
169
+ export function getAllAgents(): AgentConfig[] {
170
+ return Array.from(agents.values());
171
+ }
172
+
173
+ export function isToolEnabled(agent: AgentConfig, toolName: string): boolean {
174
+ if (agent.disabled) return false;
175
+ if (agent.tools === undefined) return true;
176
+ return agent.tools[toolName] ?? true;
177
+ }
178
+
179
+ // Get system prompt for an agent
180
+ export function getAgentSystemPrompt(agent: AgentConfig): string {
181
+ // Load JARVIS brain (automatically created if doesn't exist)
182
+ let brain = '';
183
+ try {
184
+ const { loadBrain } = require('../brain/loader.js');
185
+ brain = loadBrain();
186
+ } catch (error) {
187
+ console.warn('[Agent] Could not load brain:', error);
188
+ }
189
+
190
+ // Load skills content
191
+ let skillsContent = '';
192
+ try {
193
+ const { loadSkills } = require('../utils/skills.js');
194
+ skillsContent = loadSkills();
195
+ } catch (error) {
196
+ console.warn('[Agent] Could not load skills:', error);
197
+ }
198
+
199
+ // Combine: Brain + Skills + Agent-specific prompt
200
+ const parts: string[] = [];
201
+
202
+ // 1. Core brain (JARVIS.md)
203
+ if (brain) {
204
+ parts.push(brain);
205
+ }
206
+
207
+ // 2. Active skills
208
+ if (skillsContent) {
209
+ parts.push('\n## Active Skills\n' + skillsContent);
210
+ }
211
+
212
+ // 3. Agent-specific instructions
213
+ if (agent.description) {
214
+ parts.push('\n## Agent Role\n' + agent.description);
215
+ }
216
+
217
+ if (agent.prompt) {
218
+ parts.push('\n## Additional Instructions\n' + agent.prompt);
219
+ }
220
+
221
+ // If no brain or skills loaded, fall back to basic prompt
222
+ if (parts.length === 0) {
223
+ const basePrompt = `You are ${agent.name}, an AI coding assistant.
224
+ Your name is ${agent.name}. You are JARVIS (Just A Rather Very Intelligent System).
225
+
226
+ ${agent.description}
227
+
228
+ You help users with software engineering tasks including:
229
+ - Answering questions about code
230
+ - Debugging issues
231
+ - Adding new features
232
+ - Refactoring code
233
+ - Explaining complex concepts
234
+
235
+ Always be helpful, accurate, and thorough. When making changes, explain what you're doing and why.`;
236
+
237
+ if (agent.prompt) {
238
+ return `${basePrompt}\n\n${agent.prompt}`;
239
+ }
240
+
241
+ return basePrompt;
242
+ }
243
+
244
+ return parts.join('\n\n');
245
+ }
246
+
247
+ // Initialize agents on module load
248
+ initializeAgents();