mageagent-local 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/QUICK_START.md +255 -0
- package/README.md +453 -0
- package/bin/install-launchagent.js +135 -0
- package/bin/mageagent.js +255 -0
- package/bin/postinstall.js +43 -0
- package/config/com.adverant.mageagent.plist +38 -0
- package/config/config.example.json +41 -0
- package/docs/AUTOSTART.md +300 -0
- package/docs/MENUBAR_APP.md +238 -0
- package/docs/PATTERNS.md +501 -0
- package/docs/TROUBLESHOOTING.md +364 -0
- package/docs/VSCODE_SETUP.md +230 -0
- package/docs/assets/mageagent-logo.png +0 -0
- package/docs/assets/mageagent-logo.svg +57 -0
- package/docs/assets/menubar-screenshot.png +0 -0
- package/docs/diagrams/architecture.md +229 -0
- package/mageagent/__init__.py +4 -0
- package/mageagent/server.py +951 -0
- package/mageagent/tool_executor.py +453 -0
- package/menubar-app/MageAgentMenuBar/AppDelegate.swift +1337 -0
- package/menubar-app/MageAgentMenuBar/Info.plist +38 -0
- package/menubar-app/MageAgentMenuBar/main.swift +16 -0
- package/menubar-app/Package.swift +18 -0
- package/menubar-app/build/MageAgentMenuBar.app/Contents/Info.plist +38 -0
- package/menubar-app/build/MageAgentMenuBar.app/Contents/MacOS/MageAgentMenuBar +0 -0
- package/menubar-app/build/MageAgentMenuBar.app/Contents/PkgInfo +1 -0
- package/menubar-app/build/MageAgentMenuBar.app/Contents/Resources/icon.png +0 -0
- package/menubar-app/build.sh +96 -0
- package/package.json +81 -0
- package/scripts/build-dmg.sh +196 -0
- package/scripts/install.sh +641 -0
- package/scripts/mageagent-server.sh +218 -0
package/bin/mageagent.js
ADDED
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* MageAgent CLI
|
|
5
|
+
* Multi-Model AI Orchestration for Apple Silicon
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { spawn, execSync } from 'child_process';
|
|
9
|
+
import { existsSync, mkdirSync, copyFileSync, chmodSync } from 'fs';
|
|
10
|
+
import { homedir } from 'os';
|
|
11
|
+
import { join, dirname } from 'path';
|
|
12
|
+
import { fileURLToPath } from 'url';
|
|
13
|
+
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = dirname(__filename);
|
|
16
|
+
const packageRoot = join(__dirname, '..');
|
|
17
|
+
|
|
18
|
+
const CLAUDE_DIR = join(homedir(), '.claude');
|
|
19
|
+
const MAGEAGENT_DIR = join(CLAUDE_DIR, 'mageagent');
|
|
20
|
+
const SCRIPTS_DIR = join(CLAUDE_DIR, 'scripts');
|
|
21
|
+
const DEBUG_DIR = join(CLAUDE_DIR, 'debug');
|
|
22
|
+
const MODELS_DIR = join(homedir(), '.cache', 'mlx-models');
|
|
23
|
+
const SERVER_SCRIPT = join(SCRIPTS_DIR, 'mageagent-server.sh');
|
|
24
|
+
|
|
25
|
+
const COLORS = {
|
|
26
|
+
reset: '\x1b[0m',
|
|
27
|
+
red: '\x1b[31m',
|
|
28
|
+
green: '\x1b[32m',
|
|
29
|
+
yellow: '\x1b[33m',
|
|
30
|
+
blue: '\x1b[34m',
|
|
31
|
+
cyan: '\x1b[36m',
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
function log(message, color = 'reset') {
|
|
35
|
+
console.log(`${COLORS[color]}${message}${COLORS.reset}`);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function checkAppleSilicon() {
|
|
39
|
+
try {
|
|
40
|
+
const arch = execSync('uname -m').toString().trim();
|
|
41
|
+
if (arch !== 'arm64') {
|
|
42
|
+
log('Error: MageAgent requires Apple Silicon (M1/M2/M3/M4)', 'red');
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
} catch (e) {
|
|
46
|
+
log('Error: Could not detect system architecture', 'red');
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function checkPython() {
|
|
52
|
+
try {
|
|
53
|
+
execSync('python3 --version', { stdio: 'pipe' });
|
|
54
|
+
return true;
|
|
55
|
+
} catch (e) {
|
|
56
|
+
log('Error: Python 3 is required but not installed', 'red');
|
|
57
|
+
log('Install from: https://www.python.org/', 'yellow');
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function ensureDirectories() {
|
|
63
|
+
[CLAUDE_DIR, MAGEAGENT_DIR, SCRIPTS_DIR, DEBUG_DIR, MODELS_DIR].forEach(dir => {
|
|
64
|
+
if (!existsSync(dir)) {
|
|
65
|
+
mkdirSync(dir, { recursive: true });
|
|
66
|
+
log(`Created: ${dir}`, 'green');
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function copyServerFiles() {
|
|
72
|
+
const serverSrc = join(packageRoot, 'mageagent', 'server.py');
|
|
73
|
+
const serverDst = join(MAGEAGENT_DIR, 'server.py');
|
|
74
|
+
|
|
75
|
+
const scriptSrc = join(packageRoot, 'scripts', 'mageagent-server.sh');
|
|
76
|
+
const scriptDst = SERVER_SCRIPT;
|
|
77
|
+
|
|
78
|
+
if (existsSync(serverSrc)) {
|
|
79
|
+
copyFileSync(serverSrc, serverDst);
|
|
80
|
+
log(`Installed: ${serverDst}`, 'green');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (existsSync(scriptSrc)) {
|
|
84
|
+
copyFileSync(scriptSrc, scriptDst);
|
|
85
|
+
chmodSync(scriptDst, '755');
|
|
86
|
+
log(`Installed: ${scriptDst}`, 'green');
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function installPythonDeps() {
|
|
91
|
+
log('\nInstalling Python dependencies...', 'cyan');
|
|
92
|
+
try {
|
|
93
|
+
execSync('pip3 install --quiet mlx mlx-lm fastapi uvicorn pydantic huggingface_hub', {
|
|
94
|
+
stdio: 'inherit'
|
|
95
|
+
});
|
|
96
|
+
log('Python dependencies installed', 'green');
|
|
97
|
+
return true;
|
|
98
|
+
} catch (e) {
|
|
99
|
+
log('Failed to install Python dependencies', 'red');
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function runServerCommand(command) {
|
|
105
|
+
if (!existsSync(SERVER_SCRIPT)) {
|
|
106
|
+
log('Error: MageAgent not installed. Run: mageagent install', 'red');
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const child = spawn(SERVER_SCRIPT, [command], {
|
|
111
|
+
stdio: 'inherit',
|
|
112
|
+
shell: true
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
child.on('close', (code) => {
|
|
116
|
+
process.exit(code);
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function downloadModels() {
|
|
121
|
+
log('\nDownloading MLX models (~110GB total)...', 'cyan');
|
|
122
|
+
log('This will take 30-60 minutes depending on your connection.\n', 'yellow');
|
|
123
|
+
|
|
124
|
+
const models = [
|
|
125
|
+
{ name: 'Hermes-3-Llama-3.1-8B-8bit', size: '9GB', role: 'Tool calling' },
|
|
126
|
+
{ name: 'Qwen2.5-Coder-7B-Instruct-4bit', size: '5GB', role: 'Validation' },
|
|
127
|
+
{ name: 'Qwen2.5-Coder-32B-Instruct-4bit', size: '18GB', role: 'Code generation' },
|
|
128
|
+
{ name: 'Qwen2.5-72B-Instruct-8bit', size: '77GB', role: 'Primary reasoning' },
|
|
129
|
+
];
|
|
130
|
+
|
|
131
|
+
for (const model of models) {
|
|
132
|
+
const modelPath = join(MODELS_DIR, model.name);
|
|
133
|
+
if (existsSync(modelPath)) {
|
|
134
|
+
log(`Skipping ${model.name} (already exists)`, 'yellow');
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
log(`Downloading ${model.name} (${model.size}) - ${model.role}...`, 'blue');
|
|
139
|
+
|
|
140
|
+
try {
|
|
141
|
+
execSync(`python3 -c "
|
|
142
|
+
from huggingface_hub import snapshot_download
|
|
143
|
+
snapshot_download('mlx-community/${model.name}', local_dir='${modelPath}')
|
|
144
|
+
"`, { stdio: 'inherit' });
|
|
145
|
+
log(`Downloaded: ${model.name}`, 'green');
|
|
146
|
+
} catch (e) {
|
|
147
|
+
log(`Failed to download ${model.name}`, 'red');
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function showHelp() {
|
|
153
|
+
console.log(`
|
|
154
|
+
${COLORS.cyan}MageAgent - Multi-Model AI Orchestration for Apple Silicon${COLORS.reset}
|
|
155
|
+
|
|
156
|
+
${COLORS.yellow}Usage:${COLORS.reset}
|
|
157
|
+
mageagent <command>
|
|
158
|
+
|
|
159
|
+
${COLORS.yellow}Commands:${COLORS.reset}
|
|
160
|
+
install Install MageAgent server and dependencies
|
|
161
|
+
start Start the MageAgent server
|
|
162
|
+
stop Stop the MageAgent server
|
|
163
|
+
restart Restart the MageAgent server
|
|
164
|
+
status Check server status
|
|
165
|
+
logs View server logs
|
|
166
|
+
models Download required MLX models
|
|
167
|
+
test Test the API endpoint
|
|
168
|
+
help Show this help message
|
|
169
|
+
|
|
170
|
+
${COLORS.yellow}Examples:${COLORS.reset}
|
|
171
|
+
mageagent install # First-time setup
|
|
172
|
+
mageagent start # Start server on port 3457
|
|
173
|
+
mageagent status # Check if running
|
|
174
|
+
|
|
175
|
+
${COLORS.yellow}After installation:${COLORS.reset}
|
|
176
|
+
curl http://localhost:3457/health
|
|
177
|
+
|
|
178
|
+
${COLORS.yellow}More info:${COLORS.reset}
|
|
179
|
+
https://github.com/adverant/nexus-local-mageagent
|
|
180
|
+
`);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function testApi() {
|
|
184
|
+
log('\nTesting MageAgent API...', 'cyan');
|
|
185
|
+
try {
|
|
186
|
+
const result = execSync('curl -s http://localhost:3457/health').toString();
|
|
187
|
+
const health = JSON.parse(result);
|
|
188
|
+
log('\nServer Status: ' + health.status, 'green');
|
|
189
|
+
log('Loaded Models: ' + health.loaded_models.join(', '), 'blue');
|
|
190
|
+
log('Available Models: ' + health.available_models.join(', '), 'blue');
|
|
191
|
+
} catch (e) {
|
|
192
|
+
log('Error: Could not connect to MageAgent server', 'red');
|
|
193
|
+
log('Make sure the server is running: mageagent start', 'yellow');
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Main CLI
|
|
199
|
+
const command = process.argv[2] || 'help';
|
|
200
|
+
|
|
201
|
+
switch (command) {
|
|
202
|
+
case 'install':
|
|
203
|
+
log('\n=== MageAgent Installation ===\n', 'cyan');
|
|
204
|
+
checkAppleSilicon();
|
|
205
|
+
if (!checkPython()) process.exit(1);
|
|
206
|
+
ensureDirectories();
|
|
207
|
+
copyServerFiles();
|
|
208
|
+
installPythonDeps();
|
|
209
|
+
log('\nInstallation complete!', 'green');
|
|
210
|
+
log('\nNext steps:', 'yellow');
|
|
211
|
+
log(' 1. Download models: mageagent models', 'reset');
|
|
212
|
+
log(' 2. Start server: mageagent start', 'reset');
|
|
213
|
+
log(' 3. Test: mageagent test\n', 'reset');
|
|
214
|
+
break;
|
|
215
|
+
|
|
216
|
+
case 'models':
|
|
217
|
+
checkAppleSilicon();
|
|
218
|
+
downloadModels();
|
|
219
|
+
break;
|
|
220
|
+
|
|
221
|
+
case 'start':
|
|
222
|
+
runServerCommand('start');
|
|
223
|
+
break;
|
|
224
|
+
|
|
225
|
+
case 'stop':
|
|
226
|
+
runServerCommand('stop');
|
|
227
|
+
break;
|
|
228
|
+
|
|
229
|
+
case 'restart':
|
|
230
|
+
runServerCommand('restart');
|
|
231
|
+
break;
|
|
232
|
+
|
|
233
|
+
case 'status':
|
|
234
|
+
runServerCommand('status');
|
|
235
|
+
break;
|
|
236
|
+
|
|
237
|
+
case 'logs':
|
|
238
|
+
runServerCommand('logs');
|
|
239
|
+
break;
|
|
240
|
+
|
|
241
|
+
case 'test':
|
|
242
|
+
testApi();
|
|
243
|
+
break;
|
|
244
|
+
|
|
245
|
+
case 'help':
|
|
246
|
+
case '--help':
|
|
247
|
+
case '-h':
|
|
248
|
+
showHelp();
|
|
249
|
+
break;
|
|
250
|
+
|
|
251
|
+
default:
|
|
252
|
+
log(`Unknown command: ${command}`, 'red');
|
|
253
|
+
showHelp();
|
|
254
|
+
process.exit(1);
|
|
255
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* MageAgent Post-Install Script
|
|
5
|
+
* Shows helpful information after npm install
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const COLORS = {
|
|
9
|
+
reset: '\x1b[0m',
|
|
10
|
+
green: '\x1b[32m',
|
|
11
|
+
yellow: '\x1b[33m',
|
|
12
|
+
cyan: '\x1b[36m',
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
console.log(`
|
|
16
|
+
${COLORS.cyan}═══════════════════════════════════════════════════════════════${COLORS.reset}
|
|
17
|
+
${COLORS.green} MageAgent installed successfully!${COLORS.reset}
|
|
18
|
+
${COLORS.cyan}═══════════════════════════════════════════════════════════════${COLORS.reset}
|
|
19
|
+
|
|
20
|
+
${COLORS.yellow}Quick Start:${COLORS.reset}
|
|
21
|
+
|
|
22
|
+
1. Complete installation:
|
|
23
|
+
${COLORS.green}mageagent install${COLORS.reset}
|
|
24
|
+
|
|
25
|
+
2. Download MLX models (~110GB):
|
|
26
|
+
${COLORS.green}mageagent models${COLORS.reset}
|
|
27
|
+
|
|
28
|
+
3. Start the server:
|
|
29
|
+
${COLORS.green}mageagent start${COLORS.reset}
|
|
30
|
+
|
|
31
|
+
4. Test it:
|
|
32
|
+
${COLORS.green}mageagent test${COLORS.reset}
|
|
33
|
+
|
|
34
|
+
${COLORS.yellow}Requirements:${COLORS.reset}
|
|
35
|
+
- Apple Silicon Mac (M1/M2/M3/M4)
|
|
36
|
+
- 64GB+ unified memory (128GB recommended)
|
|
37
|
+
- Python 3.9+
|
|
38
|
+
|
|
39
|
+
${COLORS.yellow}Documentation:${COLORS.reset}
|
|
40
|
+
https://github.com/adverant/nexus-local-mageagent
|
|
41
|
+
|
|
42
|
+
${COLORS.cyan}═══════════════════════════════════════════════════════════════${COLORS.reset}
|
|
43
|
+
`);
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>Label</key>
|
|
6
|
+
<string>com.adverant.mageagent</string>
|
|
7
|
+
|
|
8
|
+
<key>ProgramArguments</key>
|
|
9
|
+
<array>
|
|
10
|
+
<string>/usr/bin/python3</string>
|
|
11
|
+
<string>/Users/don/.claude/mageagent/server.py</string>
|
|
12
|
+
</array>
|
|
13
|
+
|
|
14
|
+
<key>RunAtLoad</key>
|
|
15
|
+
<true/>
|
|
16
|
+
|
|
17
|
+
<key>KeepAlive</key>
|
|
18
|
+
<true/>
|
|
19
|
+
|
|
20
|
+
<key>StandardOutPath</key>
|
|
21
|
+
<string>/Users/don/.claude/debug/mageagent.log</string>
|
|
22
|
+
|
|
23
|
+
<key>StandardErrorPath</key>
|
|
24
|
+
<string>/Users/don/.claude/debug/mageagent.error.log</string>
|
|
25
|
+
|
|
26
|
+
<key>WorkingDirectory</key>
|
|
27
|
+
<string>/Users/don/.claude/mageagent</string>
|
|
28
|
+
|
|
29
|
+
<key>EnvironmentVariables</key>
|
|
30
|
+
<dict>
|
|
31
|
+
<key>PATH</key>
|
|
32
|
+
<string>/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin</string>
|
|
33
|
+
</dict>
|
|
34
|
+
|
|
35
|
+
<key>ThrottleInterval</key>
|
|
36
|
+
<integer>30</integer>
|
|
37
|
+
</dict>
|
|
38
|
+
</plist>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"providers": [
|
|
3
|
+
{
|
|
4
|
+
"name": "mageagent",
|
|
5
|
+
"api_base_url": "http://localhost:3457/v1/chat/completions",
|
|
6
|
+
"api_key": "local",
|
|
7
|
+
"models": [
|
|
8
|
+
"mageagent:auto",
|
|
9
|
+
"mageagent:hybrid",
|
|
10
|
+
"mageagent:validated",
|
|
11
|
+
"mageagent:compete",
|
|
12
|
+
"mageagent:tools",
|
|
13
|
+
"mageagent:primary",
|
|
14
|
+
"mageagent:validator",
|
|
15
|
+
"mageagent:competitor"
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"name": "ollama",
|
|
20
|
+
"api_base_url": "http://localhost:11434/v1/chat/completions",
|
|
21
|
+
"api_key": "ollama",
|
|
22
|
+
"models": [
|
|
23
|
+
"qwen2.5:72b",
|
|
24
|
+
"qwen2.5-coder:32b",
|
|
25
|
+
"qwen2.5-coder:1.5b"
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"name": "anthropic",
|
|
30
|
+
"api_base_url": "https://api.anthropic.com",
|
|
31
|
+
"api_key": "${ANTHROPIC_API_KEY}",
|
|
32
|
+
"models": [
|
|
33
|
+
"claude-opus-4-5-20251101",
|
|
34
|
+
"claude-sonnet-4-5-20250929"
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
"Router": {
|
|
39
|
+
"default": "mageagent,mageagent:hybrid"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
# Auto-Start Configuration
|
|
2
|
+
|
|
3
|
+
> Configure MageAgent to start automatically on macOS boot
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
MageAgent can be configured to start automatically when your Mac boots using macOS LaunchAgents. This ensures the server is always available without manual intervention.
|
|
8
|
+
|
|
9
|
+
## Quick Setup
|
|
10
|
+
|
|
11
|
+
The install script can set this up for you:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
./scripts/install.sh
|
|
15
|
+
# Answer "y" when prompted about auto-start
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Manual Setup
|
|
19
|
+
|
|
20
|
+
### Step 1: Create the LaunchAgent
|
|
21
|
+
|
|
22
|
+
Create the plist file at `~/Library/LaunchAgents/com.adverant.mageagent.plist`:
|
|
23
|
+
|
|
24
|
+
```xml
|
|
25
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
26
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
27
|
+
<plist version="1.0">
|
|
28
|
+
<dict>
|
|
29
|
+
<key>Label</key>
|
|
30
|
+
<string>com.adverant.mageagent</string>
|
|
31
|
+
|
|
32
|
+
<key>ProgramArguments</key>
|
|
33
|
+
<array>
|
|
34
|
+
<string>/usr/bin/python3</string>
|
|
35
|
+
<string>/Users/YOUR_USERNAME/.claude/mageagent/server.py</string>
|
|
36
|
+
</array>
|
|
37
|
+
|
|
38
|
+
<key>RunAtLoad</key>
|
|
39
|
+
<true/>
|
|
40
|
+
|
|
41
|
+
<key>KeepAlive</key>
|
|
42
|
+
<true/>
|
|
43
|
+
|
|
44
|
+
<key>StandardOutPath</key>
|
|
45
|
+
<string>/Users/YOUR_USERNAME/.claude/debug/mageagent.log</string>
|
|
46
|
+
|
|
47
|
+
<key>StandardErrorPath</key>
|
|
48
|
+
<string>/Users/YOUR_USERNAME/.claude/debug/mageagent.error.log</string>
|
|
49
|
+
|
|
50
|
+
<key>WorkingDirectory</key>
|
|
51
|
+
<string>/Users/YOUR_USERNAME/.claude/mageagent</string>
|
|
52
|
+
|
|
53
|
+
<key>EnvironmentVariables</key>
|
|
54
|
+
<dict>
|
|
55
|
+
<key>PATH</key>
|
|
56
|
+
<string>/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin</string>
|
|
57
|
+
</dict>
|
|
58
|
+
</dict>
|
|
59
|
+
</plist>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Important**: Replace `YOUR_USERNAME` with your actual username (e.g., `/Users/don/`).
|
|
63
|
+
|
|
64
|
+
### Step 2: Load the LaunchAgent
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# Unload if already loaded
|
|
68
|
+
launchctl unload ~/Library/LaunchAgents/com.adverant.mageagent.plist 2>/dev/null
|
|
69
|
+
|
|
70
|
+
# Load the agent
|
|
71
|
+
launchctl load ~/Library/LaunchAgents/com.adverant.mageagent.plist
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Step 3: Verify It's Running
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Check if loaded
|
|
78
|
+
launchctl list | grep mageagent
|
|
79
|
+
|
|
80
|
+
# Check if server is responding
|
|
81
|
+
curl http://localhost:3457/health
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## LaunchAgent Options Explained
|
|
85
|
+
|
|
86
|
+
| Key | Value | Description |
|
|
87
|
+
|-----|-------|-------------|
|
|
88
|
+
| `Label` | `com.adverant.mageagent` | Unique identifier for this service |
|
|
89
|
+
| `ProgramArguments` | Array | Command to run (python3 + script path) |
|
|
90
|
+
| `RunAtLoad` | `true` | Start when agent is loaded (at boot) |
|
|
91
|
+
| `KeepAlive` | `true` | Restart if process exits |
|
|
92
|
+
| `StandardOutPath` | Path | Where to write stdout logs |
|
|
93
|
+
| `StandardErrorPath` | Path | Where to write stderr logs |
|
|
94
|
+
| `WorkingDirectory` | Path | Working directory for the process |
|
|
95
|
+
| `EnvironmentVariables` | Dict | Environment variables to set |
|
|
96
|
+
|
|
97
|
+
## Managing the Service
|
|
98
|
+
|
|
99
|
+
### Start the Service
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
launchctl start com.adverant.mageagent
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Stop the Service
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
launchctl stop com.adverant.mageagent
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Restart the Service
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
launchctl stop com.adverant.mageagent
|
|
115
|
+
launchctl start com.adverant.mageagent
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Disable Auto-Start
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
launchctl unload ~/Library/LaunchAgents/com.adverant.mageagent.plist
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Re-Enable Auto-Start
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
launchctl load ~/Library/LaunchAgents/com.adverant.mageagent.plist
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Remove Auto-Start Completely
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
launchctl unload ~/Library/LaunchAgents/com.adverant.mageagent.plist
|
|
134
|
+
rm ~/Library/LaunchAgents/com.adverant.mageagent.plist
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Viewing Logs
|
|
138
|
+
|
|
139
|
+
### Real-time Server Logs
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
tail -f ~/.claude/debug/mageagent.log
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Error Logs
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
tail -f ~/.claude/debug/mageagent.error.log
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### System Logs (launchd)
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
log show --predicate 'subsystem == "com.apple.launchd"' --last 5m | grep mageagent
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## Troubleshooting
|
|
158
|
+
|
|
159
|
+
### Service Won't Start
|
|
160
|
+
|
|
161
|
+
1. **Check the plist syntax**:
|
|
162
|
+
```bash
|
|
163
|
+
plutil -lint ~/Library/LaunchAgents/com.adverant.mageagent.plist
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
2. **Verify paths exist**:
|
|
167
|
+
```bash
|
|
168
|
+
ls -la ~/.claude/mageagent/server.py
|
|
169
|
+
ls -la ~/.claude/debug/
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
3. **Check Python is accessible**:
|
|
173
|
+
```bash
|
|
174
|
+
/usr/bin/python3 --version
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
4. **Check error logs**:
|
|
178
|
+
```bash
|
|
179
|
+
cat ~/.claude/debug/mageagent.error.log
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Service Keeps Restarting
|
|
183
|
+
|
|
184
|
+
If `KeepAlive` is true and the service crashes, launchd will restart it. Check logs for crash reasons:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
# View recent crashes
|
|
188
|
+
cat ~/.claude/debug/mageagent.error.log | tail -100
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Common causes:
|
|
192
|
+
- Missing Python dependencies
|
|
193
|
+
- Port 3457 already in use
|
|
194
|
+
- Insufficient memory for models
|
|
195
|
+
|
|
196
|
+
### Port Already in Use
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
# Find what's using port 3457
|
|
200
|
+
lsof -i :3457
|
|
201
|
+
|
|
202
|
+
# Kill the process if needed
|
|
203
|
+
kill -9 <PID>
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Memory Issues
|
|
207
|
+
|
|
208
|
+
If the server crashes due to memory, you may need to:
|
|
209
|
+
|
|
210
|
+
1. Close other applications
|
|
211
|
+
2. Use smaller models (edit server.py)
|
|
212
|
+
3. Increase swap space
|
|
213
|
+
|
|
214
|
+
Check memory usage:
|
|
215
|
+
```bash
|
|
216
|
+
# Current memory pressure
|
|
217
|
+
memory_pressure
|
|
218
|
+
|
|
219
|
+
# Top memory consumers
|
|
220
|
+
top -l 1 -o mem | head -20
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Advanced Configuration
|
|
224
|
+
|
|
225
|
+
### Delay Start Until Network Ready
|
|
226
|
+
|
|
227
|
+
Add these keys to wait for network:
|
|
228
|
+
|
|
229
|
+
```xml
|
|
230
|
+
<key>NetworkState</key>
|
|
231
|
+
<true/>
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### Run Only When Logged In
|
|
235
|
+
|
|
236
|
+
The default configuration in `~/Library/LaunchAgents/` only runs when you're logged in. For system-wide (all users), use `/Library/LaunchDaemons/` instead (requires admin).
|
|
237
|
+
|
|
238
|
+
### Resource Limits
|
|
239
|
+
|
|
240
|
+
Add resource limits if needed:
|
|
241
|
+
|
|
242
|
+
```xml
|
|
243
|
+
<key>HardResourceLimits</key>
|
|
244
|
+
<dict>
|
|
245
|
+
<key>NumberOfFiles</key>
|
|
246
|
+
<integer>1024</integer>
|
|
247
|
+
</dict>
|
|
248
|
+
|
|
249
|
+
<key>SoftResourceLimits</key>
|
|
250
|
+
<dict>
|
|
251
|
+
<key>NumberOfFiles</key>
|
|
252
|
+
<integer>1024</integer>
|
|
253
|
+
</dict>
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Throttle Restarts
|
|
257
|
+
|
|
258
|
+
Prevent rapid restart loops:
|
|
259
|
+
|
|
260
|
+
```xml
|
|
261
|
+
<key>ThrottleInterval</key>
|
|
262
|
+
<integer>30</integer>
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
This waits 30 seconds between restart attempts.
|
|
266
|
+
|
|
267
|
+
## Verification Checklist
|
|
268
|
+
|
|
269
|
+
After setup, verify everything works:
|
|
270
|
+
|
|
271
|
+
- [ ] LaunchAgent file exists at correct path
|
|
272
|
+
- [ ] File syntax is valid (`plutil -lint`)
|
|
273
|
+
- [ ] Agent is loaded (`launchctl list | grep mageagent`)
|
|
274
|
+
- [ ] Server responds (`curl http://localhost:3457/health`)
|
|
275
|
+
- [ ] Logs are being written (`ls -la ~/.claude/debug/`)
|
|
276
|
+
- [ ] Service survives reboot (restart and check)
|
|
277
|
+
|
|
278
|
+
## Alternative: Using the Management Script
|
|
279
|
+
|
|
280
|
+
Instead of launchctl directly, you can use the provided script:
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
# Start server
|
|
284
|
+
~/.claude/scripts/mageagent-server.sh start
|
|
285
|
+
|
|
286
|
+
# Stop server
|
|
287
|
+
~/.claude/scripts/mageagent-server.sh stop
|
|
288
|
+
|
|
289
|
+
# Check status
|
|
290
|
+
~/.claude/scripts/mageagent-server.sh status
|
|
291
|
+
|
|
292
|
+
# View logs
|
|
293
|
+
~/.claude/scripts/mageagent-server.sh logs
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
The management script provides a simpler interface but doesn't persist across reboots unless combined with LaunchAgents.
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
*Made with care by [Adverant](https://github.com/adverant)*
|