neoagent 1.0.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 (54) hide show
  1. package/.env.example +28 -0
  2. package/LICENSE +21 -0
  3. package/README.md +42 -0
  4. package/bin/neoagent.js +8 -0
  5. package/com.neoagent.plist +45 -0
  6. package/docs/configuration.md +45 -0
  7. package/docs/skills.md +45 -0
  8. package/lib/manager.js +459 -0
  9. package/package.json +61 -0
  10. package/server/db/database.js +239 -0
  11. package/server/index.js +442 -0
  12. package/server/middleware/auth.js +35 -0
  13. package/server/public/app.html +559 -0
  14. package/server/public/css/app.css +608 -0
  15. package/server/public/css/styles.css +472 -0
  16. package/server/public/favicon.svg +17 -0
  17. package/server/public/js/app.js +3283 -0
  18. package/server/public/login.html +313 -0
  19. package/server/routes/agents.js +125 -0
  20. package/server/routes/auth.js +105 -0
  21. package/server/routes/browser.js +116 -0
  22. package/server/routes/mcp.js +164 -0
  23. package/server/routes/memory.js +193 -0
  24. package/server/routes/messaging.js +153 -0
  25. package/server/routes/protocols.js +87 -0
  26. package/server/routes/scheduler.js +63 -0
  27. package/server/routes/settings.js +98 -0
  28. package/server/routes/skills.js +107 -0
  29. package/server/routes/store.js +1192 -0
  30. package/server/services/ai/compaction.js +82 -0
  31. package/server/services/ai/engine.js +1690 -0
  32. package/server/services/ai/models.js +46 -0
  33. package/server/services/ai/multiStep.js +112 -0
  34. package/server/services/ai/providers/anthropic.js +181 -0
  35. package/server/services/ai/providers/base.js +40 -0
  36. package/server/services/ai/providers/google.js +187 -0
  37. package/server/services/ai/providers/grok.js +121 -0
  38. package/server/services/ai/providers/ollama.js +162 -0
  39. package/server/services/ai/providers/openai.js +167 -0
  40. package/server/services/ai/toolRunner.js +218 -0
  41. package/server/services/browser/controller.js +320 -0
  42. package/server/services/cli/executor.js +204 -0
  43. package/server/services/mcp/client.js +260 -0
  44. package/server/services/memory/embeddings.js +126 -0
  45. package/server/services/memory/manager.js +431 -0
  46. package/server/services/messaging/base.js +23 -0
  47. package/server/services/messaging/discord.js +238 -0
  48. package/server/services/messaging/manager.js +328 -0
  49. package/server/services/messaging/telegram.js +243 -0
  50. package/server/services/messaging/telnyx.js +693 -0
  51. package/server/services/messaging/whatsapp.js +304 -0
  52. package/server/services/scheduler/cron.js +312 -0
  53. package/server/services/websocket.js +191 -0
  54. package/server/utils/security.js +71 -0
@@ -0,0 +1,1192 @@
1
+ const express = require('express');
2
+ const router = express.Router();
3
+ const path = require('path');
4
+ const { requireAuth } = require('../middleware/auth');
5
+
6
+ router.use(requireAuth);
7
+
8
+ const SKILLS_DIR = path.join(__dirname, '../../agent-data/skills');
9
+
10
+ // ── Skill catalog ─────────────────────────────────────────────────────────────
11
+ // Each entry: id (becomes filename <id>.md), name, description, category, icon, content
12
+ const CATALOG = [
13
+
14
+ // ── SYSTEM ──────────────────────────────────────────────────────────────────
15
+ {
16
+ id: 'disk-usage',
17
+ name: 'Disk Usage',
18
+ description: 'Show disk space usage for all mounted filesystems.',
19
+ category: 'system',
20
+ icon: '💾',
21
+ content: `---
22
+ name: disk-usage
23
+ description: Show disk space usage for all mounted filesystems
24
+ category: system
25
+ icon: 💾
26
+ enabled: true
27
+ ---
28
+
29
+ Run \`df -h\` to show disk usage. If the user asks about a specific path, run \`du -sh <path>\`. Present the output in a readable table, highlight any filesystems above 80% usage.`
30
+ },
31
+
32
+ {
33
+ id: 'system-stats',
34
+ name: 'System Stats',
35
+ description: 'Report CPU, RAM, load average and uptime.',
36
+ category: 'system',
37
+ icon: '📊',
38
+ content: `---
39
+ name: system-stats
40
+ description: Report CPU, RAM, load average and uptime
41
+ category: system
42
+ icon: 📊
43
+ enabled: true
44
+ ---
45
+
46
+ Run these commands and summarise the results:
47
+ - \`uptime\` — load average and uptime
48
+ - \`free -m\` (Linux) or \`vm_stat\` (macOS) — memory usage
49
+ - \`nproc\` or \`sysctl -n hw.logicalcpu\` — CPU count
50
+
51
+ Combine into a short dashboard-style summary.`
52
+ },
53
+
54
+ {
55
+ id: 'process-monitor',
56
+ name: 'Process Monitor',
57
+ description: 'List the top 15 processes by CPU or memory usage.',
58
+ category: 'system',
59
+ icon: '⚙️',
60
+ content: `---
61
+ name: process-monitor
62
+ description: List the top 15 processes by CPU or memory usage
63
+ category: system
64
+ icon: ⚙️
65
+ enabled: true
66
+ ---
67
+
68
+ Run \`ps aux --sort=-%cpu | head -16\` on Linux or \`ps aux -r | head -16\` on macOS to show top CPU processes. If the user asks for memory, use \`ps aux --sort=-%mem | head -16\`. Format as a readable table with PID, command, CPU%, MEM%.`
69
+ },
70
+
71
+ {
72
+ id: 'tail-log',
73
+ name: 'Tail Log File',
74
+ description: 'Show the last N lines of any log file, with optional filtering.',
75
+ category: 'system',
76
+ icon: '📋',
77
+ content: `---
78
+ name: tail-log
79
+ description: Show the last N lines of any log file, with optional filtering
80
+ category: system
81
+ icon: 📋
82
+ enabled: true
83
+ ---
84
+
85
+ Run \`tail -n <lines> <file>\` to show recent log lines. Default to 50 lines if not specified. If the user provides a filter keyword, pipe through \`grep <keyword>\`. For common logs, suggest: /var/log/syslog, /var/log/nginx/error.log, ./logs/app.log etc.`
86
+ },
87
+
88
+ {
89
+ id: 'find-large-files',
90
+ name: 'Find Large Files',
91
+ description: 'Find the largest files in a directory tree.',
92
+ category: 'system',
93
+ icon: '🔍',
94
+ content: `---
95
+ name: find-large-files
96
+ description: Find the largest files in a directory tree
97
+ category: system
98
+ icon: 🔍
99
+ enabled: true
100
+ ---
101
+
102
+ Run \`find <dir> -type f -exec du -sh {} + 2>/dev/null | sort -rh | head -20\` to list the 20 largest files. Default to current directory if none provided. Present as a ranked list with human-readable sizes.`
103
+ },
104
+
105
+ // ── NETWORK ─────────────────────────────────────────────────────────────────
106
+ {
107
+ id: 'ping-host',
108
+ name: 'Ping Host',
109
+ description: 'Ping a hostname or IP and report latency and packet loss.',
110
+ category: 'network',
111
+ icon: '📡',
112
+ content: `---
113
+ name: ping-host
114
+ description: Ping a hostname or IP and report latency and packet loss
115
+ category: network
116
+ icon: 📡
117
+ enabled: true
118
+ ---
119
+
120
+ Run \`ping -c 5 <host>\` to send 5 ICMP packets. Report average RTT, packet loss %, and whether the host is reachable. If the host is unreachable, suggest checking DNS or firewall.`
121
+ },
122
+
123
+ {
124
+ id: 'ip-info',
125
+ name: 'IP Info',
126
+ description: 'Get your public IP address and geolocation details.',
127
+ category: 'network',
128
+ icon: '🌐',
129
+ content: `---
130
+ name: ip-info
131
+ description: Get your public IP address and geolocation details
132
+ category: network
133
+ icon: 🌐
134
+ enabled: true
135
+ ---
136
+
137
+ Make a GET request to \`https://ipinfo.io/json\` (no auth needed for basic info). Display the IP, city, region, country, org (ISP), and timezone in a clean summary. If the user asks about a specific IP, use \`https://ipinfo.io/<ip>/json\`.`
138
+ },
139
+
140
+ {
141
+ id: 'ssl-check',
142
+ name: 'SSL Certificate Check',
143
+ description: 'Check the SSL certificate expiry date for any domain.',
144
+ category: 'network',
145
+ icon: '🔒',
146
+ content: `---
147
+ name: ssl-check
148
+ description: Check the SSL certificate expiry date for any domain
149
+ category: network
150
+ icon: 🔒
151
+ enabled: true
152
+ ---
153
+
154
+ Run \`echo | openssl s_client -connect <domain>:443 -servername <domain> 2>/dev/null | openssl x509 -noout -dates\` to get cert validity dates. Calculate how many days until expiry. Warn if < 30 days, alert if < 7 days, or if already expired.`
155
+ },
156
+
157
+ {
158
+ id: 'port-check',
159
+ name: 'Port Check',
160
+ description: 'Test whether a specific TCP port is open on a host.',
161
+ category: 'network',
162
+ icon: '🔌',
163
+ content: `---
164
+ name: port-check
165
+ description: Test whether a specific TCP port is open on a host
166
+ category: network
167
+ icon: 🔌
168
+ enabled: true
169
+ ---
170
+
171
+ Run \`nc -zv -w3 <host> <port> 2>&1\` or \`curl -s --connect-timeout 3 telnet://<host>:<port>\` to test connectivity. Report clearly: open or closed/filtered, and response time if measurable. Common ports to suggest: 80 (HTTP), 443 (HTTPS), 22 (SSH), 3306 (MySQL), 5432 (Postgres), 6379 (Redis).`
172
+ },
173
+
174
+ {
175
+ id: 'dns-lookup',
176
+ name: 'DNS Lookup',
177
+ description: 'Perform DNS lookups (A, MX, TXT, CNAME records) for any domain.',
178
+ category: 'network',
179
+ icon: '🗺️',
180
+ content: `---
181
+ name: dns-lookup
182
+ description: Perform DNS lookups (A, MX, TXT, CNAME records) for any domain
183
+ category: network
184
+ icon: 🗺️
185
+ enabled: true
186
+ ---
187
+
188
+ Use \`dig <domain> <type>\` or \`nslookup\` to query DNS records. Default to A records. If the user says "all records", run dig for A, MX, TXT, CNAME in one go. Present results cleanly without raw dig headers.`
189
+ },
190
+
191
+ // ── INFO ────────────────────────────────────────────────────────────────────
192
+ {
193
+ id: 'weather',
194
+ name: 'Weather',
195
+ description: 'Get current weather and a 3-day forecast for any city.',
196
+ category: 'info',
197
+ icon: '🌤️',
198
+ content: `---
199
+ name: weather
200
+ description: Get current weather and a 3-day forecast for any city
201
+ category: info
202
+ icon: 🌤️
203
+ enabled: true
204
+ ---
205
+
206
+ Make a GET request to \`https://wttr.in/<city>?format=j1\` (returns JSON). Parse:
207
+ - current_condition[0]: temp_C, weatherDesc, humidity, windspeedKmph, feels_like
208
+ - weather[0..2]: date, maxtempC, mintempC, hourly[4].weatherDesc (midday)
209
+
210
+ Present as a clean weather card: current conditions + 3-day forecast with icons. URL-encode city names with spaces.`
211
+ },
212
+
213
+ {
214
+ id: 'crypto-price',
215
+ name: 'Crypto Price',
216
+ description: 'Look up live cryptocurrency prices from CoinGecko.',
217
+ category: 'info',
218
+ icon: '₿',
219
+ content: `---
220
+ name: crypto-price
221
+ description: Look up live cryptocurrency prices from CoinGecko
222
+ category: info
223
+ icon: ₿
224
+ enabled: true
225
+ ---
226
+
227
+ Use the CoinGecko free API (no key needed):
228
+ - Single coin: \`GET https://api.coingecko.com/api/v3/simple/price?ids=<id>&vs_currencies=usd,eur&include_24hr_change=true\`
229
+ - Common IDs: bitcoin, ethereum, solana, cardano, dogecoin, ripple, polkadot, chainlink, litecoin, avalanche-2
230
+
231
+ Show price in USD and EUR, 24h change %, and a trend arrow ↑↓. If the user uses a ticker (BTC), map it to the CoinGecko ID first.`
232
+ },
233
+
234
+ {
235
+ id: 'exchange-rate',
236
+ name: 'Exchange Rate',
237
+ description: 'Get live currency exchange rates between any two currencies.',
238
+ category: 'info',
239
+ icon: '💱',
240
+ content: `---
241
+ name: exchange-rate
242
+ description: Get live currency exchange rates between any two currencies
243
+ category: info
244
+ icon: 💱
245
+ enabled: true
246
+ ---
247
+
248
+ Use the free Open Exchange Rates API:
249
+ \`GET https://open.er-api.com/v6/latest/<base_currency>\`
250
+
251
+ Example: \`https://open.er-api.com/v6/latest/USD\` returns rates for all currencies relative to USD.
252
+ Show the requested conversion with the exact rate and the last updated time. If the user gives an amount (e.g. "200 EUR to GBP"), calculate and show the converted value.`
253
+ },
254
+
255
+ {
256
+ id: 'world-time',
257
+ name: 'World Time',
258
+ description: 'Show the current local time in major cities around the world.',
259
+ category: 'info',
260
+ icon: '🕐',
261
+ content: `---
262
+ name: world-time
263
+ description: Show the current local time in major cities around the world
264
+ category: info
265
+ icon: 🕐
266
+ enabled: true
267
+ ---
268
+
269
+ Run \`date\` for local time. Get world times via the API:
270
+ \`GET https://worldtimeapi.org/api/timezone/<Region/City>\`
271
+
272
+ Show a table of current times for: New York (America/New_York), London (Europe/London), Berlin (Europe/Berlin), Dubai (Asia/Dubai), Singapore (Asia/Singapore), Tokyo (Asia/Tokyo), Sydney (Australia/Sydney). Format as HH:MM timezone with day name.`
273
+ },
274
+
275
+ {
276
+ id: 'news-hackernews',
277
+ name: 'Hacker News Top Stories',
278
+ description: 'Fetch the top 10 stories from Hacker News right now.',
279
+ category: 'info',
280
+ icon: '📰',
281
+ content: `---
282
+ name: news-hackernews
283
+ description: Fetch the top 10 stories from Hacker News right now
284
+ category: info
285
+ icon: 📰
286
+ enabled: true
287
+ ---
288
+
289
+ 1. GET \`https://hacker-news.firebaseio.com/v0/topstories.json\` → get array of IDs
290
+ 2. Take the first 10 IDs
291
+ 3. For each ID, GET \`https://hacker-news.firebaseio.com/v0/item/<id>.json\` → title, url, score, by, descendants
292
+ Present as a numbered list: score points | title | by author (N comments). Link the title.`
293
+ },
294
+
295
+ // ── DEV ─────────────────────────────────────────────────────────────────────
296
+ {
297
+ id: 'git-summary',
298
+ name: 'Git Summary',
299
+ description: 'Show recent commits, current branch, and status for a git repo.',
300
+ category: 'dev',
301
+ icon: '🌿',
302
+ content: `---
303
+ name: git-summary
304
+ description: Show recent commits, current branch, and status for a git repo
305
+ category: dev
306
+ icon: 🌿
307
+ enabled: true
308
+ ---
309
+
310
+ Run in the user's specified directory (default: current working directory):
311
+ 1. \`git log --oneline -10\` — last 10 commits
312
+ 2. \`git status --short\` — dirty files
313
+ 3. \`git branch --show-current\` — current branch
314
+ 4. \`git remote -v\` — remotes
315
+
316
+ Present as a structured git dashboard. Note any uncommitted changes or detached HEAD.`
317
+ },
318
+
319
+ {
320
+ id: 'docker-status',
321
+ name: 'Docker Status',
322
+ description: 'List all running and stopped Docker containers with their status.',
323
+ category: 'dev',
324
+ icon: '🐳',
325
+ content: `---
326
+ name: docker-status
327
+ description: List all running and stopped Docker containers with their status
328
+ category: dev
329
+ icon: 🐳
330
+ enabled: true
331
+ ---
332
+
333
+ Run \`docker ps -a --format "table {{.Names}}\\t{{.Image}}\\t{{.Status}}\\t{{.Ports}}"\` to list all containers. Also run \`docker images --format "table {{.Repository}}:{{.Tag}}\\t{{.Size}}"\` to show local images.
334
+ Highlight running vs stopped vs exited. If Docker isn't installed/running, say so clearly.`
335
+ },
336
+
337
+ {
338
+ id: 'npm-outdated',
339
+ name: 'NPM Outdated Check',
340
+ description: 'Check for outdated npm packages in a Node.js project.',
341
+ category: 'dev',
342
+ icon: '📦',
343
+ content: `---
344
+ name: npm-outdated
345
+ description: Check for outdated npm packages in a Node.js project
346
+ category: dev
347
+ icon: 📦
348
+ enabled: true
349
+ ---
350
+
351
+ Run \`npm outdated --json\` in the project directory. Parse the JSON and display as a table:
352
+ Package | Current | Wanted | Latest | Type (dep/devDep)
353
+
354
+ Categorise: minor updates (wanted > current), major updates (latest >> current). Suggest running \`npm update\` for minor updates or manual upgrades for majors. Handle "everything up to date" gracefully.`
355
+ },
356
+
357
+ {
358
+ id: 'run-tests',
359
+ name: 'Run Tests',
360
+ description: 'Run the test suite for a project and summarise results.',
361
+ category: 'dev',
362
+ icon: '✅',
363
+ content: `---
364
+ name: run-tests
365
+ description: Run the test suite for a project and summarise results
366
+ category: dev
367
+ icon: ✅
368
+ enabled: true
369
+ ---
370
+
371
+ Check what test runner is configured (look at package.json scripts.test). Then run \`npm test\` (or \`yarn test\`, \`pytest\`, etc. as appropriate). Capture stdout/stderr.
372
+ Summarise: total tests, passed, failed, skipped. If failures occur, show the first 3 failed test names and errors. Do NOT truncate error details — they're important.`
373
+ },
374
+
375
+ {
376
+ id: 'http-debug',
377
+ name: 'HTTP Debug',
378
+ description: 'Make a detailed HTTP request and inspect headers, status, timing.',
379
+ category: 'dev',
380
+ icon: '🔎',
381
+ content: `---
382
+ name: http-debug
383
+ description: Make a detailed HTTP request and inspect headers, status, timing
384
+ category: dev
385
+ icon: 🔎
386
+ enabled: true
387
+ ---
388
+
389
+ Use the http_request tool to make the request with full header capture. Also run \`curl -o /dev/null -s -w "\\n%{http_code} | %{time_total}s | %{size_download} bytes\\n" <url>\` for timing. Report:
390
+ - Status code and meaning
391
+ - Response time
392
+ - Key headers (Content-Type, Cache-Control, X-Frame-Options, etc.)
393
+ - Body preview (first 500 chars)
394
+ - Any redirects`
395
+ },
396
+
397
+ // ── PRODUCTIVITY ─────────────────────────────────────────────────────────────
398
+ {
399
+ id: 'summarize-url',
400
+ name: 'Summarize URL',
401
+ description: 'Fetch a webpage and give a concise summary of its content.',
402
+ category: 'productivity',
403
+ icon: '📄',
404
+ content: `---
405
+ name: summarize-url
406
+ description: Fetch a webpage and give a concise summary of its content
407
+ category: productivity
408
+ icon: 📄
409
+ enabled: true
410
+ ---
411
+
412
+ Use http_request to GET the URL. Extract text content from the HTML (skip scripts, styles, nav). Write a structured summary:
413
+ - **What it is**: 1 sentence
414
+ - **Key points**: 3–5 bullet points
415
+ - **Takeaway**: most important thing to know
416
+
417
+ Keep total summary under 200 words. If the URL fails or returns non-HTML, say so.`
418
+ },
419
+
420
+ {
421
+ id: 'wikipedia',
422
+ name: 'Wikipedia Summary',
423
+ description: 'Get a Wikipedia article summary for any topic.',
424
+ category: 'productivity',
425
+ icon: '📚',
426
+ content: `---
427
+ name: wikipedia
428
+ description: Get a Wikipedia article summary for any topic
429
+ category: productivity
430
+ icon: 📚
431
+ enabled: true
432
+ ---
433
+
434
+ Use the Wikipedia REST API:
435
+ \`GET https://en.wikipedia.org/api/rest_v1/page/summary/<title>\`
436
+
437
+ URL-encode the title (replace spaces with underscores). The response contains \`extract\` (plain text summary) and \`content_urls.desktop.page\` (full article link).
438
+
439
+ Show the summary with the article URL. If the topic resolves to a disambiguation page, show the top options. Support language override via \`https://<lang>.wikipedia.org/...\`.`
440
+ },
441
+
442
+ {
443
+ id: 'translate',
444
+ name: 'Translate Text',
445
+ description: 'Translate any text to a target language.',
446
+ category: 'productivity',
447
+ icon: '🌍',
448
+ content: `---
449
+ name: translate
450
+ description: Translate any text to a target language
451
+ category: productivity
452
+ icon: 🌍
453
+ enabled: true
454
+ ---
455
+
456
+ Use the LibreTranslate free API:
457
+ \`POST https://libretranslate.com/translate\`
458
+ Body: \`{"q": "<text>", "source": "auto", "target": "<lang_code>", "format": "text"}\`
459
+
460
+ Common language codes: en, de, fr, es, it, pt, nl, ru, zh, ja, ko, ar.
461
+ Show the translation clearly, note the detected source language. If the API fails, fall back to using your own translation ability with a note.`
462
+ },
463
+
464
+ {
465
+ id: 'quick-note',
466
+ name: 'Quick Note',
467
+ description: 'Save a timestamped note to a notes file on disk.',
468
+ category: 'productivity',
469
+ icon: '📝',
470
+ content: `---
471
+ name: quick-note
472
+ description: Save a timestamped note to a notes file on disk
473
+ category: productivity
474
+ icon: 📝
475
+ enabled: true
476
+ ---
477
+
478
+ Append the note to \`~/notes.md\` (or a user-specified file) with this format:
479
+ \`\`\`
480
+ ## 2025-01-15 14:32
481
+ <note content>
482
+ \`\`\`
483
+ Use \`echo\` or \`tee -a\` to append. Confirm the note was saved and show the file path. If the file doesn't exist, create it with a \`# Notes\` header first.`
484
+ },
485
+
486
+ {
487
+ id: 'pomodoro',
488
+ name: 'Pomodoro Timer',
489
+ description: 'Start a Pomodoro focus timer with a desktop notification at the end.',
490
+ category: 'productivity',
491
+ icon: '🍅',
492
+ content: `---
493
+ name: pomodoro
494
+ description: Start a Pomodoro focus timer with a desktop notification at the end
495
+ category: productivity
496
+ icon: 🍅
497
+ enabled: true
498
+ ---
499
+
500
+ Default: 25-minute work session followed by a 5-minute break. Run in background:
501
+ \`\`\`bash
502
+ (sleep 1500 && osascript -e 'display notification "Pomodoro complete! Take a break." with title "🍅 Pomodoro"' 2>/dev/null || notify-send "🍅 Pomodoro" "Complete! Take a break." 2>/dev/null || echo "POMODORO DONE") &
503
+ \`\`\`
504
+ Print the PID and end time so the user can track it. Support custom durations.`
505
+ },
506
+
507
+ // ── GOOGLE ──────────────────────────────────────────────────────────────────
508
+ {
509
+ id: 'gogcli',
510
+ name: 'Google Suite (gogcli)',
511
+ description: 'Control Gmail, Calendar, Drive, Tasks, Contacts, Sheets, Chat and more via the gog CLI.',
512
+ category: 'productivity',
513
+ icon: '🌐',
514
+ content: `---
515
+ name: gogcli
516
+ description: Control Gmail, Calendar, Drive, Tasks, Contacts, Sheets, Chat and more via the gog CLI
517
+ category: productivity
518
+ icon: 🌐
519
+ trigger: gmail|calendar|drive|tasks|contacts|sheets|google
520
+ enabled: true
521
+ source: https://github.com/steipete/gogcli
522
+ ---
523
+
524
+ ## Overview
525
+ \`gog\` (gogcli) is a fast, JSON-first CLI for Google Workspace services. Install via:
526
+ \`\`\`
527
+ brew install steipete/tap/gogcli
528
+ \`\`\`
529
+ Use \`--json\` for machine-readable output.
530
+
531
+ ## Credential Storage (NeoAgent)
532
+ Store the Google account email in API_KEYS.json so you can always retrieve it:
533
+ \`\`\`
534
+ memory_write target=api_keys content={"gog_account": "you@gmail.com"}
535
+ \`\`\`
536
+ For non-interactive / headless runs, also store the keyring password:
537
+ \`\`\`
538
+ memory_write target=api_keys content={"gog_account": "you@gmail.com", "gog_keyring_password": "<your-keyring-password>"}
539
+ \`\`\`
540
+ Before every \`gog\` command, read back these keys:
541
+ \`\`\`
542
+ memory_read target=api_keys
543
+ \`\`\`
544
+ Then run gog with the stored values:
545
+ \`\`\`bash
546
+ export GOG_ACCOUNT="<gog_account from api_keys>"
547
+ export GOG_KEYRING_BACKEND=file # use on-disk encrypted keyring (no Keychain prompts)
548
+ export GOG_KEYRING_PASSWORD="<gog_keyring_password from api_keys>" # if set
549
+ gog ...
550
+ \`\`\`
551
+
552
+ ## First-Time Setup (run once manually by the user)
553
+ \`\`\`bash
554
+ gog auth credentials ~/Downloads/client_secret_....json # store OAuth client credentials
555
+ gog auth keyring file # switch to file backend (avoids Keychain prompts)
556
+ gog auth add you@gmail.com # authorize account — opens browser
557
+ gog auth status # verify auth state
558
+ gog auth list # list stored accounts
559
+ \`\`\`
560
+ After setup, save the account email with memory_write (above) so the agent can use it automatically.
561
+
562
+ ## Gmail
563
+ \`\`\`bash
564
+ gog gmail search 'newer_than:7d is:unread' --max 10 --json
565
+ gog gmail thread get <threadId>
566
+ gog gmail send --to a@b.com --subject "Subject" --body "Body"
567
+ gog gmail send --to a@b.com --subject "Subject" --body-html "<p>Hi</p>"
568
+ gog gmail labels list
569
+ gog gmail thread modify <threadId> --add STARRED --remove INBOX
570
+ \`\`\`
571
+
572
+ ## Calendar
573
+ \`\`\`bash
574
+ gog calendar events primary --today --json
575
+ gog calendar events primary --week
576
+ gog calendar search "standup" --days 7 --json
577
+ gog calendar create primary --summary "Meeting" --from 2026-01-15T10:00:00Z --to 2026-01-15T11:00:00Z --attendees "a@b.com"
578
+ gog calendar freebusy --calendars primary --from 2026-01-15T00:00:00Z --to 2026-01-16T00:00:00Z
579
+ gog calendar delete primary <eventId> --force
580
+ \`\`\`
581
+
582
+ ## Drive
583
+ \`\`\`bash
584
+ gog drive ls --max 20 --json
585
+ gog drive search "invoice" --max 20 --json
586
+ gog drive upload ./file.pdf
587
+ gog drive download <fileId> --out ./file.pdf
588
+ gog drive share <fileId> --to user --email user@example.com --role reader
589
+ \`\`\`
590
+
591
+ ## Tasks
592
+ \`\`\`bash
593
+ gog tasks lists --json
594
+ gog tasks list <tasklistId> --json
595
+ gog tasks add <tasklistId> --title "Task title" --due 2026-02-01
596
+ gog tasks done <tasklistId> <taskId>
597
+ \`\`\`
598
+
599
+ ## Contacts
600
+ \`\`\`bash
601
+ gog contacts search "John" --max 20 --json
602
+ gog contacts create --given "Jane" --family "Doe" --email "jane@example.com"
603
+ \`\`\`
604
+
605
+ ## Sheets
606
+ \`\`\`bash
607
+ gog sheets metadata <spreadsheetId>
608
+ gog sheets get <spreadsheetId> 'Sheet1!A1:D10' --json
609
+ gog sheets update <spreadsheetId> 'Sheet1!A1' 'val1|val2,val3|val4'
610
+ gog sheets append <spreadsheetId> 'Sheet1!A:C' 'new|row|data'
611
+ \`\`\`
612
+
613
+ ## Docs / Slides
614
+ \`\`\`bash
615
+ gog docs cat <docId>
616
+ gog docs export <docId> --format pdf --out ./doc.pdf
617
+ gog docs sed <docId> 's/old/new/g'
618
+ gog slides export <presentationId> --format pptx --out ./deck.pptx
619
+ \`\`\`
620
+
621
+ ## Tips
622
+ - Pipe JSON output to \`jq\` for filtering: \`gog --json gmail search 'is:unread' | jq '.threads[].id'\`
623
+ - Use \`GOG_ENABLE_COMMANDS=gmail,calendar\` to sandbox allowed commands
624
+ - \`--plain\` outputs stable TSV for shell scripting
625
+ - Calendar JSON includes \`startDayOfWeek\` and localized time fields, useful for scheduling logic`
626
+ },
627
+
628
+ // ── COMMUNITY ────────────────────────────────────────────────────────────────
629
+ {
630
+ id: 'answeroverflow',
631
+ name: 'Answer Overflow',
632
+ description: 'Search indexed Discord community discussions for coding answers via Answer Overflow.',
633
+ category: 'productivity',
634
+ icon: '💬',
635
+ content: `---
636
+ name: answeroverflow
637
+ description: Search indexed Discord community discussions for coding answers via Answer Overflow
638
+ category: productivity
639
+ icon: 💬
640
+ trigger: discord|answeroverflow|community support
641
+ enabled: true
642
+ source: https://github.com/AnswerOverflow/AnswerOverflow
643
+ ---
644
+
645
+ ## What is Answer Overflow?
646
+ Answer Overflow indexes public Discord support channels and makes them searchable via Google and direct API. Perfect for finding answers that only exist in Discord conversations — from servers like Valorant, Cloudflare, C#, Nuxt, and thousands more.
647
+
648
+ ## Quick Search (via Google)
649
+ \`\`\`bash
650
+ # Best approach — Answer Overflow results appear in Google
651
+ web_search "site:answeroverflow.com prisma connection pooling"
652
+ web_search "site:answeroverflow.com nextjs app router error"
653
+ web_search "site:answeroverflow.com discord.js slash commands"
654
+ \`\`\`
655
+
656
+ ## Fetch Thread Content
657
+ \`\`\`bash
658
+ # Markdown format (preferred for agents)
659
+ http_request GET https://www.answeroverflow.com/m/<message-id>
660
+ # Add Accept: text/markdown header, or use /m/ prefix URL
661
+ \`\`\`
662
+
663
+ URL patterns:
664
+ - Thread: \`https://www.answeroverflow.com/m/<message-id>\`
665
+ - Server: \`https://www.answeroverflow.com/c/<server-slug>\`
666
+ - Channel: \`https://www.answeroverflow.com/c/<server-slug>/<channel-slug>\`
667
+
668
+ ## MCP Server
669
+ Answer Overflow exposes an MCP server at \`https://www.answeroverflow.com/mcp\`:
670
+
671
+ | Tool | Description |
672
+ |------|-------------|
673
+ | \`search_answeroverflow\` | Search all indexed communities; filter by server/channel ID |
674
+ | \`search_servers\` | Discover indexed Discord servers |
675
+ | \`get_thread_messages\` | Get all messages from a specific thread |
676
+ | \`find_similar_threads\` | Find threads related to a given thread |
677
+
678
+ To add it as an MCP server in NeoAgent: command \`npx -y @answeroverflow/mcp\`
679
+
680
+ ## Tips
681
+ - Results are real Discord conversations — context may be informal
682
+ - Threads often have back-and-forth before the solution; read the whole thread
683
+ - Check the server/channel name to understand context (official support vs community)
684
+ - Many major open-source projects index their Discord support channels here`
685
+ },
686
+
687
+ // ── FUN ─────────────────────────────────────────────────────────────────────
688
+ {
689
+ id: 'random-joke',
690
+ name: 'Random Joke',
691
+ description: 'Fetch a random joke (clean, programmer or general).',
692
+ category: 'fun',
693
+ icon: '😄',
694
+ content: `---
695
+ name: random-joke
696
+ description: Fetch a random joke (clean, programmer or general)
697
+ category: fun
698
+ icon: 😄
699
+ enabled: true
700
+ ---
701
+
702
+ GET \`https://v2.jokeapi.dev/joke/Programming,Miscellaneous?blacklistFlags=nsfw,racist,sexist,explicit\`
703
+
704
+ The response has either a single \`joke\` field or a two-part \`setup\`/\`delivery\`. Present it naturally — pause before the punchline in delivery style. If the user asks for a specific category (dark, pun, etc.), adjust the URL accordingly.`
705
+ },
706
+
707
+ {
708
+ id: 'random-quote',
709
+ name: 'Random Quote',
710
+ description: 'Get a random motivational or philosophical quote.',
711
+ category: 'fun',
712
+ icon: '💭',
713
+ content: `---
714
+ name: random-quote
715
+ description: Get a random motivational or philosophical quote
716
+ category: fun
717
+ icon: 💭
718
+ enabled: true
719
+ ---
720
+
721
+ GET \`https://api.quotable.io/random\`
722
+
723
+ Show: \`"<content>"\` — *<author>*
724
+
725
+ If the user specifies a topic or author, use:
726
+ \`https://api.quotable.io/random?tags=<tag>\` (common tags: technology, wisdom, success, life, motivational, literature, science)
727
+ \`https://api.quotable.io/quotes?author=<slug>\` for a specific author.`
728
+ },
729
+
730
+ {
731
+ id: 'random-fact',
732
+ name: 'Random Fact',
733
+ description: 'Get a random interesting fact.',
734
+ category: 'fun',
735
+ icon: '🧠',
736
+ content: `---
737
+ name: random-fact
738
+ description: Get a random interesting fact
739
+ category: fun
740
+ icon: 🧠
741
+ enabled: true
742
+ ---
743
+
744
+ GET \`https://uselessfacts.jsph.pl/api/v2/facts/random?language=en\` for a random fact.
745
+ Alternatively: \`https://api.api-ninjas.com/v1/facts?limit=1\` (no key needed for free tier).
746
+ Present the fact naturally, optionally adding a brief "why this is interesting" comment if it's not immediately obvious.`
747
+ },
748
+
749
+ {
750
+ id: 'word-definition',
751
+ name: 'Word Definition',
752
+ description: 'Look up the definition, pronunciation and examples for any word.',
753
+ category: 'fun',
754
+ icon: '📖',
755
+ content: `---
756
+ name: word-definition
757
+ description: Look up the definition, pronunciation and examples for any word
758
+ category: fun
759
+ icon: 📖
760
+ enabled: true
761
+ ---
762
+
763
+ GET \`https://api.dictionaryapi.dev/api/v2/entries/en/<word>\`
764
+
765
+ Extract and display:
766
+ - Pronunciation (phonetic)
767
+ - Part of speech
768
+ - Primary definition(s)
769
+ - Example sentence if available
770
+ - Synonyms (first 5)
771
+
772
+ If the word isn't found, suggest similar spellings. Supports multiple meanings grouped by part of speech.`
773
+ },
774
+
775
+ {
776
+ id: 'qr-code',
777
+ name: 'QR Code Generator',
778
+ description: 'Generate a QR code image URL for any text or URL.',
779
+ category: 'fun',
780
+ icon: '⬛',
781
+ content: `---
782
+ name: qr-code
783
+ description: Generate a QR code image URL for any text or URL
784
+ category: fun
785
+ icon: ⬛
786
+ enabled: true
787
+ ---
788
+
789
+ Use the QR Server API (no auth):
790
+ \`https://api.qrserver.com/v1/create-qr-code/?data=<encoded_text>&size=300x300&margin=10\`
791
+
792
+ URL-encode the input data. Provide the direct image URL that the user can open in a browser or embed. Also calculate: at the default error correction level (M), the QR can hold the given text reliably up to X characters.`
793
+ },
794
+
795
+ // ── DEV (continued) ──────────────────────────────────────────────────────────
796
+ {
797
+ id: 'github',
798
+ name: 'GitHub',
799
+ description: 'Interact with GitHub repos, PRs, issues, branches, CI and releases using git and the gh CLI.',
800
+ category: 'dev',
801
+ icon: '🐙',
802
+ content: `---
803
+ name: github
804
+ description: Interact with GitHub repos, PRs, issues, branches, CI and releases using git and the gh CLI
805
+ trigger: When the user asks to clone a repo, create a PR, open/close issues, check CI status, fork, review diffs, manage branches, or do anything GitHub-related
806
+ category: dev
807
+ icon: 🐙
808
+ enabled: true
809
+ ---
810
+
811
+ # GitHub Skill
812
+
813
+ Use \`git\` for local version control and \`gh\` (GitHub CLI) for GitHub-specific actions.
814
+ Always verify both tools are available: \`which git && which gh\`.
815
+ If \`gh\` is not authenticated, prompt the user to run \`gh auth login\`.
816
+
817
+ ## Repo Status & Info
818
+ \`\`\`
819
+ gh repo view # show current repo overview
820
+ gh repo view <owner>/<repo> # show a specific repo
821
+ git status # show working tree state
822
+ git log --oneline -20 # last 20 commits
823
+ git diff # unstaged changes
824
+ git diff --staged # staged changes
825
+ \`\`\`
826
+
827
+ ## Clone & Fork
828
+ \`\`\`
829
+ gh repo clone <owner>/<repo> # clone via gh (sets up remote automatically)
830
+ gh repo fork <owner>/<repo> --clone # fork and clone in one step
831
+ \`\`\`
832
+
833
+ ## Branches
834
+ \`\`\`
835
+ git checkout -b <branch> # create and switch to new branch
836
+ git branch -a # list all branches (local + remote)
837
+ git push -u origin <branch> # push new branch to origin
838
+ git branch -d <branch> # delete local branch
839
+ gh repo sync # sync fork with upstream
840
+ \`\`\`
841
+
842
+ ## Commits & Push
843
+ \`\`\`
844
+ git add -A && git commit -m "<msg>" # stage all and commit
845
+ git push # push to tracked remote branch
846
+ git pull --rebase # pull with rebase
847
+ \`\`\`
848
+
849
+ ## Pull Requests
850
+ \`\`\`
851
+ gh pr create --title "<title>" --body "<body>" # open a PR
852
+ gh pr list # list open PRs
853
+ gh pr view <number> # view a specific PR
854
+ gh pr checkout <number> # check out a PR branch locally
855
+ gh pr merge <number> --squash # merge PR (squash)
856
+ gh pr review <number> --approve # approve a PR
857
+ gh pr review <number> --request-changes -b "<feedback>"
858
+ gh pr close <number> # close without merging
859
+ gh pr status # PRs involving you
860
+ \`\`\`
861
+
862
+ ## Issues
863
+ \`\`\`
864
+ gh issue create --title "<title>" --body "<body>" # create issue
865
+ gh issue list # list open issues
866
+ gh issue view <number> # view an issue
867
+ gh issue close <number> # close an issue
868
+ gh issue comment <number> -b "<comment>" # add a comment
869
+ gh issue assign <number> --assignee @me # assign to yourself
870
+ \`\`\`
871
+
872
+ ## Releases & Tags
873
+ \`\`\`
874
+ gh release create <tag> --title "<title>" --notes "<notes>"
875
+ gh release list
876
+ gh release view <tag>
877
+ git tag -a v1.0.0 -m "Release v1.0.0" && git push --tags
878
+ \`\`\`
879
+
880
+ ## CI / Actions
881
+ \`\`\`
882
+ gh run list # list recent workflow runs
883
+ gh run view <run-id> # view a run's details and logs
884
+ gh run watch <run-id> # stream live logs
885
+ gh workflow list # list workflows
886
+ gh workflow run <workflow-file> # trigger a workflow manually
887
+ \`\`\`
888
+
889
+ ## Presentation Tips
890
+ - For pr/issue lists, format as a table: number, title, author, date.
891
+ - For git log, show short hash, message, and relative date.
892
+ - For CI runs, summarise: ✅ success / ❌ failure / ⏳ in progress per job.
893
+ - Confirm with the user before any repo-modifying operation (push, merge, delete).`
894
+ },
895
+
896
+ // ── RESEARCH ─────────────────────────────────────────────────────────────────
897
+ {
898
+ id: 'deep-research',
899
+ name: 'Deep Research',
900
+ description: 'Conduct thorough multi-source research on any topic and synthesise findings into a structured report.',
901
+ category: 'research',
902
+ icon: '🔬',
903
+ content: `---
904
+ name: deep-research
905
+ description: Conduct thorough multi-source research on any topic, synthesising findings into a structured report
906
+ trigger: When the user asks for deep research, a detailed investigation, a comprehensive overview, or wants to understand a complex topic in depth
907
+ category: research
908
+ icon: 🔬
909
+ enabled: true
910
+ ---
911
+
912
+ # Deep Research Skill
913
+
914
+ Perform iterative, multi-source research by combining web searches, page reads, and cross-referencing. Don't stop at the first result — go wide, then go deep.
915
+
916
+ ## Research Process
917
+
918
+ ### 1. Clarify the Query
919
+ Decompose the topic into 3–5 sub-questions that together fully answer the user's request. State them so the user can correct scope before you begin.
920
+
921
+ ### 2. Broad Discovery (go wide)
922
+ Run multiple searches using varied queries and angles:
923
+ - Direct topic searches: \`<topic> overview\`, \`<topic> explained\`
924
+ - Authoritative sources: \`site:en.wikipedia.org <topic>\`, \`site:arxiv.org <topic>\`
925
+ - Recent developments: \`<topic> 2025\`, \`<topic> latest research\`
926
+ - Opposing views: \`<topic> criticism\`, \`<topic> limitations\`, \`<topic> controversy\`
927
+
928
+ Use \`https://html.duckduckgo.com/html/?q=<query>\` for web searches (parse \`<a class="result__a">\` links and snippets).
929
+
930
+ ### 3. Deep Reads (go deep)
931
+ For each sub-question, identify the 3–5 most relevant URLs. Fetch and read each one fully. Extract:
932
+ - Key claims and data points
933
+ - Author / publication / date (assess credibility)
934
+ - References to follow up on
935
+
936
+ ### 4. Cross-Reference & Validate
937
+ - Note where sources agree and disagree.
938
+ - Flag claims from only one source as unverified.
939
+ - If numbers or stats are cited, trace to the primary source.
940
+ - Prefer sources from the last 2 years unless historical context is needed.
941
+
942
+ ### 5. Synthesise & Report
943
+ \`\`\`
944
+ ## Summary
945
+ 2–3 sentence TL;DR.
946
+
947
+ ## Background
948
+ Context needed to understand the topic.
949
+
950
+ ## Key Findings
951
+ - Finding 1 (source: [title](url))
952
+ - Finding 2 ...
953
+
954
+ ## Different Perspectives / Debate
955
+ Where experts or sources disagree, and why.
956
+
957
+ ## Open Questions / Gaps
958
+ What is still unknown or contested.
959
+
960
+ ## Sources
961
+ Numbered list of all URLs consulted, with title and date.
962
+ \`\`\`
963
+
964
+ ## Tips
965
+ - Run at least 5 distinct searches before writing the report.
966
+ - Read at least 4 full pages (not just snippets).
967
+ - Never present a single source as definitive — always triangulate.
968
+ - Cite every factual claim with a link.`
969
+ },
970
+
971
+ {
972
+ id: 'coding',
973
+ name: 'Coding',
974
+ description: 'Write, debug, refactor, explain, and review code in any programming language.',
975
+ category: 'dev',
976
+ icon: '💻',
977
+ content: `---
978
+ name: coding
979
+ description: Write, debug, refactor, explain, and review code in any programming language
980
+ trigger: When the user asks to write code, fix a bug, refactor, explain how code works, review a function, add tests, or help with any programming task
981
+ category: dev
982
+ icon: 💻
983
+ enabled: true
984
+ ---
985
+
986
+ # Coding Skill
987
+
988
+ Handle the full software development lifecycle: writing new code, understanding existing code, debugging, refactoring, and testing — in any language.
989
+
990
+ ## Write New Code
991
+ - Confirm the language, framework, and environment before starting.
992
+ - Ask for constraints (performance, style guide, existing dependencies).
993
+ - Write clean, idiomatic code with comments for non-obvious logic.
994
+ - Include a usage example or short test block where helpful.
995
+
996
+ ## Debug & Fix
997
+ 1. Read the full error message and stack trace carefully.
998
+ 2. Identify the exact file and line where the error originates.
999
+ 3. Inspect surrounding code for logic errors, type mismatches, null-dereferences, or off-by-one errors.
1000
+ 4. Run the code in a terminal to reproduce the error if needed.
1001
+ 5. Apply the minimal fix that resolves the root cause — avoid masking errors with bare try/catch.
1002
+ 6. Explain what was wrong and why the fix works.
1003
+
1004
+ ## Refactor
1005
+ - Identify code smells: duplication, long functions, deep nesting, magic numbers, unclear naming.
1006
+ - Refactor in small, safe steps — preserve behaviour before improving structure.
1007
+ - Prefer readability over cleverness.
1008
+ - Verify functionality is unchanged after refactoring.
1009
+
1010
+ ## Explain Code
1011
+ - Summarise what the code does at a high level first.
1012
+ - Walk through it section by section, explaining intent not just mechanics.
1013
+ - Highlight non-obvious patterns (closures, generators, recursion, bitwise tricks, etc.).
1014
+ - Point out potential edge cases or bugs noticed during the read.
1015
+
1016
+ ## Code Review
1017
+ Evaluate on these dimensions and provide concrete, actionable feedback:
1018
+ - **Correctness** — does it do what it's supposed to? Are edge cases handled?
1019
+ - **Readability** — are names clear? Is logic easy to follow?
1020
+ - **Performance** — any O(n²) loops, N+1 queries, or memory leaks?
1021
+ - **Security** — injection risks, unvalidated input, exposed secrets, insecure defaults?
1022
+ - **Tests** — adequate coverage? Are tests meaningful?
1023
+
1024
+ ## Add Tests
1025
+ - Identify the testing framework in use (Jest, pytest, Go test, etc.) or ask.
1026
+ - Write unit tests for individual functions, edge cases, and failure paths.
1027
+ - Aim for tests that are independent, deterministic, and fast.
1028
+
1029
+ ## Quick-Run Commands
1030
+ \`\`\`
1031
+ python3 <file>.py # Python
1032
+ node <file>.js # Node.js
1033
+ npx ts-node <file>.ts # TypeScript
1034
+ go run <file>.go # Go
1035
+ cargo run # Rust
1036
+ java <ClassName>.java # Java 11+
1037
+ swift <file>.swift # Swift
1038
+ ruby <file>.rb # Ruby
1039
+ \`\`\`
1040
+
1041
+ ## Pre-Delivery Checklist
1042
+ - No hardcoded secrets or credentials
1043
+ - Input is validated / sanitised at entry points
1044
+ - Error paths are handled (not silently swallowed)
1045
+ - Async code uses proper await / error handling
1046
+ - No unused imports or dead code left behind`
1047
+ },
1048
+
1049
+ // ── MAKER ────────────────────────────────────────────────────────────────────
1050
+ {
1051
+ id: 'bambu-studio-cli',
1052
+ name: 'BambuStudio CLI',
1053
+ description: 'Slice 3MF/STL files, export G-code and slicing data using BambuStudio on the command line.',
1054
+ category: 'maker',
1055
+ icon: '🖨️',
1056
+ content: `---
1057
+ name: bambu-studio-cli
1058
+ description: Slice 3MF/STL files and export results using the BambuStudio command-line interface
1059
+ category: maker
1060
+ icon: 🖨️
1061
+ enabled: true
1062
+ ---
1063
+
1064
+ # BambuStudio CLI
1065
+
1066
+ Invoke BambuStudio headlessly for slicing and exporting. The binary is typically \`bambu-studio\` on Linux/macOS or \`bambu-studio.exe\` on Windows.
1067
+
1068
+ ## Core flags
1069
+
1070
+ | Flag | Description |
1071
+ |------|-------------|
1072
+ | \`--slice <plate>\` | Slice plates: \`0\` = all, \`N\` = plate N |
1073
+ | \`--export-3mf <out.3mf>\` | Export sliced result as 3MF |
1074
+ | \`--outputdir <dir>\` | Directory for all exported files |
1075
+ | \`--load-settings "machine.json;process.json"\` | Override printer + process settings |
1076
+ | \`--load-filaments "f1.json;f2.json"\` | Override filament settings (use \`;\` separators, skip slots with empty entry) |
1077
+ | \`--curr-bed-type "Cool Plate"\` | Set bed type via command line |
1078
+ | \`--arrange <0\|1>\` | Auto-arrange: 0=off, 1=on |
1079
+ | \`--orient\` | Auto-orient models before slicing |
1080
+ | \`--scale <factor>\` | Scale model by float factor (e.g. \`1.5\`) |
1081
+ | \`--export-settings <out.json>\` | Dump merged settings to JSON |
1082
+ | \`--export-slicedata <dir>\` | Export slicing data to folder |
1083
+ | \`--load-slicedata <dir>\` | Load cached slicing data |
1084
+ | \`--info\` | Print model info without slicing |
1085
+ | \`--debug <0-5>\` | Log level: 0=fatal … 5=trace |
1086
+ | \`--pipe <name>\` | Send progress to named pipe |
1087
+ | \`--uptodate\` | Upgrade 3MF config values to latest profiles |
1088
+ | \`--help\` | Show CLI help |
1089
+
1090
+ Setting priority (highest → lowest):
1091
+ 1. \`--key=value\` flags on the command line
1092
+ 2. Files loaded via \`--load-settings\` / \`--load-filaments\`
1093
+ 3. Settings embedded in the 3MF file
1094
+
1095
+ ## Common usage patterns
1096
+
1097
+ ### Slice a 3MF using its own settings
1098
+ \`\`\`bash
1099
+ bambu-studio --slice 0 --debug 2 --export-3mf output.3mf model.3mf
1100
+ \`\`\`
1101
+ Slices all plates in model.3mf and exports to output.3mf.
1102
+
1103
+ ### Slice a 3MF with custom machine/process/filament overrides
1104
+ \`\`\`bash
1105
+ bambu-studio \\
1106
+ --load-settings "machine.json;process.json" \\
1107
+ --load-filaments "filament1.json;;filament3.json" \\
1108
+ --curr-bed-type "Cool Plate" \\
1109
+ --slice 2 --debug 2 \\
1110
+ --export-3mf output.3mf \\
1111
+ model.3mf
1112
+ \`\`\`
1113
+ Slices plate 2 only, overriding printer/process/filament settings from JSON files.
1114
+ Empty \`;\;\` entries keep the filament slot from the 3MF unchanged.
1115
+
1116
+ ### Slice raw STL files
1117
+ \`\`\`bash
1118
+ bambu-studio \\
1119
+ --orient --arrange 1 \\
1120
+ --load-settings "machine.json;process.json" \\
1121
+ --load-filaments "filament.json" \\
1122
+ --slice 0 --debug 2 \\
1123
+ --export-3mf output.3mf \\
1124
+ model.stl
1125
+ \`\`\`
1126
+ Auto-orients and arranges the STL, applies settings from JSON files, slices all plates.
1127
+
1128
+ ## When the user asks to slice a file:
1129
+ 1. Confirm the path to \`bambu-studio\` binary (run \`which bambu-studio\` or ask the user)
1130
+ 2. Check if custom settings JSON files are needed or if the 3MF is self-contained
1131
+ 3. Build the command from the flags above
1132
+ 4. Run it and check for errors in the output (debug level 2 is a good default)
1133
+ 5. Report the output file location and any warnings`
1134
+ }
1135
+ ];
1136
+
1137
+ // ── Routes ─────────────────────────────────────────────────────────────────────
1138
+
1139
+ /** GET /api/store — return catalog with installed status */
1140
+ router.get('/', (req, res) => {
1141
+ const fs = require('fs');
1142
+ const installed = new Set();
1143
+
1144
+ if (fs.existsSync(SKILLS_DIR)) {
1145
+ for (const f of fs.readdirSync(SKILLS_DIR)) {
1146
+ installed.add(f.replace(/\.md$/i, ''));
1147
+ }
1148
+ }
1149
+
1150
+ const items = CATALOG.map(s => ({
1151
+ id: s.id,
1152
+ name: s.name,
1153
+ description: s.description,
1154
+ category: s.category,
1155
+ icon: s.icon,
1156
+ installed: installed.has(s.id)
1157
+ }));
1158
+
1159
+ res.json(items);
1160
+ });
1161
+
1162
+ /** POST /api/store/:id/install — write the skill file */
1163
+ router.post('/:id/install', (req, res) => {
1164
+ const fs = require('fs');
1165
+ const skill = CATALOG.find(s => s.id === req.params.id);
1166
+ if (!skill) return res.status(404).json({ error: 'Skill not found in catalog' });
1167
+
1168
+ if (!fs.existsSync(SKILLS_DIR)) fs.mkdirSync(SKILLS_DIR, { recursive: true });
1169
+
1170
+ const filePath = path.join(SKILLS_DIR, `${skill.id}.md`);
1171
+ fs.writeFileSync(filePath, skill.content, 'utf-8');
1172
+
1173
+ // Also reload the skill runner if available
1174
+ const skillRunner = req.app.locals?.skillRunner;
1175
+ if (skillRunner) skillRunner.loadSkillFile(filePath);
1176
+
1177
+ res.json({ success: true, id: skill.id, name: skill.name, filePath });
1178
+ });
1179
+
1180
+ /** DELETE /api/store/:id/uninstall — remove the skill file */
1181
+ router.delete('/:id/uninstall', (req, res) => {
1182
+ const fs = require('fs');
1183
+ const skill = CATALOG.find(s => s.id === req.params.id);
1184
+ if (!skill) return res.status(404).json({ error: 'Skill not found in catalog' });
1185
+
1186
+ const filePath = path.join(SKILLS_DIR, `${skill.id}.md`);
1187
+ if (fs.existsSync(filePath)) fs.unlinkSync(filePath);
1188
+
1189
+ res.json({ success: true, id: skill.id });
1190
+ });
1191
+
1192
+ module.exports = router;