nexus-mcp-agent 0.1.2

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 (72) hide show
  1. package/.env.example +56 -0
  2. package/README.md +74 -0
  3. package/dist/core/config.d.ts +46 -0
  4. package/dist/core/config.d.ts.map +1 -0
  5. package/dist/core/config.js +68 -0
  6. package/dist/core/config.js.map +1 -0
  7. package/dist/core/logger.d.ts +7 -0
  8. package/dist/core/logger.d.ts.map +1 -0
  9. package/dist/core/logger.js +54 -0
  10. package/dist/core/logger.js.map +1 -0
  11. package/dist/core/registry.d.ts +21 -0
  12. package/dist/core/registry.d.ts.map +1 -0
  13. package/dist/core/registry.js +52 -0
  14. package/dist/core/registry.js.map +1 -0
  15. package/dist/core/server.d.ts +12 -0
  16. package/dist/core/server.d.ts.map +1 -0
  17. package/dist/core/server.js +120 -0
  18. package/dist/core/server.js.map +1 -0
  19. package/dist/index.d.ts +3 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +38 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/tools/agents/index.d.ts +18 -0
  24. package/dist/tools/agents/index.d.ts.map +1 -0
  25. package/dist/tools/agents/index.js +134 -0
  26. package/dist/tools/agents/index.js.map +1 -0
  27. package/dist/tools/automation/index.d.ts +4 -0
  28. package/dist/tools/automation/index.d.ts.map +1 -0
  29. package/dist/tools/automation/index.js +95 -0
  30. package/dist/tools/automation/index.js.map +1 -0
  31. package/dist/tools/filesystem/index.d.ts +4 -0
  32. package/dist/tools/filesystem/index.d.ts.map +1 -0
  33. package/dist/tools/filesystem/index.js +261 -0
  34. package/dist/tools/filesystem/index.js.map +1 -0
  35. package/dist/tools/git/index.d.ts +4 -0
  36. package/dist/tools/git/index.d.ts.map +1 -0
  37. package/dist/tools/git/index.js +177 -0
  38. package/dist/tools/git/index.js.map +1 -0
  39. package/dist/tools/memory/index.d.ts +4 -0
  40. package/dist/tools/memory/index.d.ts.map +1 -0
  41. package/dist/tools/memory/index.js +178 -0
  42. package/dist/tools/memory/index.js.map +1 -0
  43. package/dist/tools/system/index.d.ts +4 -0
  44. package/dist/tools/system/index.d.ts.map +1 -0
  45. package/dist/tools/system/index.js +121 -0
  46. package/dist/tools/system/index.js.map +1 -0
  47. package/dist/tools/terminal/index.d.ts +4 -0
  48. package/dist/tools/terminal/index.d.ts.map +1 -0
  49. package/dist/tools/terminal/index.js +86 -0
  50. package/dist/tools/terminal/index.js.map +1 -0
  51. package/dist/tools/web/index.d.ts +4 -0
  52. package/dist/tools/web/index.d.ts.map +1 -0
  53. package/dist/tools/web/index.js +193 -0
  54. package/dist/tools/web/index.js.map +1 -0
  55. package/docs/SECURITY.md +31 -0
  56. package/mcp-config.json +9 -0
  57. package/package.json +65 -0
  58. package/scripts/setup.js +102 -0
  59. package/src/core/config.ts +138 -0
  60. package/src/core/logger.ts +61 -0
  61. package/src/core/registry.ts +72 -0
  62. package/src/core/server.ts +144 -0
  63. package/src/index.ts +46 -0
  64. package/src/tools/agents/index.ts +172 -0
  65. package/src/tools/automation/index.ts +127 -0
  66. package/src/tools/filesystem/index.ts +303 -0
  67. package/src/tools/git/index.ts +201 -0
  68. package/src/tools/memory/index.ts +204 -0
  69. package/src/tools/system/index.ts +140 -0
  70. package/src/tools/terminal/index.ts +105 -0
  71. package/src/tools/web/index.ts +224 -0
  72. package/tsconfig.json +30 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/tools/web/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAwLtD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,GAAG,IAAI,CAmChF"}
@@ -0,0 +1,193 @@
1
+ import { z } from 'zod/v3';
2
+ import axios from 'axios';
3
+ import * as cheerio from 'cheerio';
4
+ import { createContextLogger } from '../../core/logger.js';
5
+ import { nexusConfig } from '../../core/config.js';
6
+ const log = createContextLogger('tools/web');
7
+ const WebSearchSchema = z.object({
8
+ query: z.string().describe('Search query'),
9
+ maxResults: z.number().optional().default(10).describe('Maximum number of results'),
10
+ });
11
+ const WebBrowseSchema = z.object({
12
+ url: z.string().describe('URL to browse'),
13
+ actions: z.string().optional().describe('JavaScript code to execute on the page'),
14
+ waitFor: z.number().optional().default(2000).describe('Time to wait after page load (ms)'),
15
+ });
16
+ const WebScrapeSchema = z.object({
17
+ url: z.string().describe('URL to scrape'),
18
+ selector: z.string().optional().describe('CSS selector to extract specific content'),
19
+ });
20
+ const ApiCallSchema = z.object({
21
+ method: z.enum(['GET', 'POST', 'PUT', 'DELETE', 'PATCH']).describe('HTTP method'),
22
+ url: z.string().describe('API endpoint URL'),
23
+ headers: z.record(z.string()).optional().describe('HTTP headers'),
24
+ body: z.any().optional().describe('Request body'),
25
+ });
26
+ async function webSearch(params) {
27
+ const { query, maxResults = 10 } = params;
28
+ log.info(`Web search: "${query}"`);
29
+ if (nexusConfig.search.braveApiKey) {
30
+ try {
31
+ const response = await axios.get('https://api.search.brave.com/res/v1/web/search', {
32
+ params: { q: query, count: maxResults },
33
+ headers: { 'X-Subscription-Token': nexusConfig.search.braveApiKey },
34
+ timeout: 15000,
35
+ });
36
+ return {
37
+ success: true,
38
+ provider: 'brave',
39
+ results: response.data.web?.results?.map((r) => ({
40
+ title: r.title,
41
+ url: r.url,
42
+ snippet: r.description,
43
+ })) || [],
44
+ };
45
+ }
46
+ catch (error) {
47
+ log.warn('Brave search failed, falling back to DuckDuckGo');
48
+ }
49
+ }
50
+ try {
51
+ const response = await axios.get('https://html.duckduckgo.com/html/', {
52
+ params: { q: query },
53
+ headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' },
54
+ timeout: 15000,
55
+ });
56
+ const $ = cheerio.load(response.data);
57
+ const results = [];
58
+ $('.result').slice(0, maxResults).each((_, el) => {
59
+ const title = $(el).find('.result__title a').text().trim();
60
+ const url = $(el).find('.result__url').text().trim();
61
+ const snippet = $(el).find('.result__snippet').text().trim();
62
+ if (title && url) {
63
+ results.push({ title, url: url.startsWith('http') ? url : `https://${url}`, snippet });
64
+ }
65
+ });
66
+ return { success: true, provider: 'duckduckgo', results };
67
+ }
68
+ catch (error) {
69
+ return { success: false, error: error.message };
70
+ }
71
+ }
72
+ async function webBrowse(params) {
73
+ const { url, actions, waitFor = 2000 } = params;
74
+ log.info(`Browsing: ${url}`);
75
+ try {
76
+ const { chromium } = await import('playwright');
77
+ const browser = await chromium.launch({ headless: nexusConfig.browser.headless });
78
+ const page = await browser.newPage();
79
+ await page.goto(url, { waitUntil: 'domcontentloaded', timeout: nexusConfig.browser.timeout });
80
+ if (waitFor > 0)
81
+ await page.waitForTimeout(waitFor);
82
+ if (actions) {
83
+ try {
84
+ const actionFn = new Function('page', actions);
85
+ await actionFn(page);
86
+ }
87
+ catch (err) {
88
+ log.warn(`Action execution failed: ${err.message}`);
89
+ }
90
+ }
91
+ const title = await page.title();
92
+ const content = await page.content();
93
+ const text = await page.evaluate(`document.body?.innerText || ''`);
94
+ const snapshot = await page.accessibility.snapshot();
95
+ await browser.close();
96
+ return {
97
+ success: true,
98
+ url,
99
+ title,
100
+ text: text.slice(0, 50000),
101
+ accessibilityTree: snapshot,
102
+ };
103
+ }
104
+ catch (error) {
105
+ return { success: false, error: error.message };
106
+ }
107
+ }
108
+ async function webScrape(params) {
109
+ const { url, selector } = params;
110
+ log.info(`Scraping: ${url}`);
111
+ try {
112
+ const response = await axios.get(url, {
113
+ headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' },
114
+ timeout: 15000,
115
+ });
116
+ const $ = cheerio.load(response.data);
117
+ $('script, style, nav, footer, header').remove();
118
+ let content = '';
119
+ if (selector) {
120
+ content = $(selector).text();
121
+ }
122
+ else {
123
+ content = $('body').text();
124
+ }
125
+ content = content.replace(/\s+/g, ' ').trim();
126
+ return {
127
+ success: true,
128
+ url,
129
+ content: content.slice(0, 100000),
130
+ };
131
+ }
132
+ catch (error) {
133
+ return { success: false, error: error.message };
134
+ }
135
+ }
136
+ async function apiCall(params) {
137
+ const { method, url, headers, body } = params;
138
+ log.info(`API call: ${method} ${url}`);
139
+ try {
140
+ const response = await axios({
141
+ method: method,
142
+ url,
143
+ headers,
144
+ data: body,
145
+ timeout: 30000,
146
+ });
147
+ return {
148
+ success: true,
149
+ status: response.status,
150
+ headers: response.headers,
151
+ data: response.data,
152
+ };
153
+ }
154
+ catch (error) {
155
+ return {
156
+ success: false,
157
+ status: error.response?.status,
158
+ error: error.message,
159
+ };
160
+ }
161
+ }
162
+ export function registerWebTools(server, registry) {
163
+ server.registerTool('web_search', {
164
+ description: 'Search the web for information',
165
+ inputSchema: WebSearchSchema,
166
+ }, async (params) => ({
167
+ content: [{ type: 'text', text: JSON.stringify(await webSearch(params), null, 2) }],
168
+ }));
169
+ server.registerTool('web_browse', {
170
+ description: 'Browse a webpage with Playwright and extract content',
171
+ inputSchema: WebBrowseSchema,
172
+ }, async (params) => ({
173
+ content: [{ type: 'text', text: JSON.stringify(await webBrowse(params), null, 2) }],
174
+ }));
175
+ server.registerTool('web_scrape', {
176
+ description: 'Scrape content from a webpage',
177
+ inputSchema: WebScrapeSchema,
178
+ }, async (params) => ({
179
+ content: [{ type: 'text', text: JSON.stringify(await webScrape(params), null, 2) }],
180
+ }));
181
+ server.registerTool('api_call', {
182
+ description: 'Make HTTP API calls (REST/GraphQL)',
183
+ inputSchema: ApiCallSchema,
184
+ }, async (params) => ({
185
+ content: [{ type: 'text', text: JSON.stringify(await apiCall(params), null, 2) }],
186
+ }));
187
+ registry.register({ name: 'web_search', category: 'web', description: 'Search the web', handler: webSearch });
188
+ registry.register({ name: 'web_browse', category: 'web', description: 'Browse webpage', handler: webBrowse });
189
+ registry.register({ name: 'web_scrape', category: 'web', description: 'Scrape webpage', handler: webScrape });
190
+ registry.register({ name: 'api_call', category: 'web', description: 'HTTP API call', handler: apiCall });
191
+ log.info('Registered 4 web tools');
192
+ }
193
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/tools/web/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ # 🔒 Security Policy
2
+
3
+ NEXUS is an autonomous AI agent with broad system access. Security is paramount.
4
+
5
+ ## Security Layers
6
+
7
+ ### 1. Path Restrictions
8
+ All file operations are restricted to `ALLOWED_DIRS`.
9
+
10
+ ### 2. Command Blocking
11
+ Dangerous commands blocked: `rm -rf /`, `format`, `mkfs`, etc.
12
+
13
+ ### 3. Audit Logging
14
+ Sensitive ops logged to `logs/audit.log`.
15
+
16
+ ### 4. Confirmation for Destructive Actions
17
+ Marked tools can require confirmation.
18
+
19
+ ### 5. Network Isolation
20
+ Web operations respect system proxy settings.
21
+
22
+ ## Best Practices
23
+
24
+ 1. Start with narrow `ALLOWED_DIRS`
25
+ 2. Monitor `logs/audit.log`
26
+ 3. Store API keys in `.env` (never commit)
27
+ 4. Run in isolated environment
28
+ 5. Limit network access with firewalls
29
+
30
+ ## Disclaimer
31
+ NEXUS is provided as-is. User is responsible for securing API keys, configuring permissions, and monitoring activity.
@@ -0,0 +1,9 @@
1
+ {
2
+ "mcpServers": {
3
+ "nexus": {
4
+ "command": "npx",
5
+ "args": ["-y", "nexus-mcp-agent"],
6
+ "env": {}
7
+ }
8
+ }
9
+ }
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "nexus-mcp-agent",
3
+ "version": "0.1.2",
4
+ "description": "Autonomous AI Agent MCP Server — no API keys required, works out of the box",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "nexus": "dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsx watch src/index.ts",
13
+ "start": "node dist/index.js",
14
+ "inspect": "npx @modelcontextprotocol/inspector node dist/index.js",
15
+ "test": "vitest",
16
+ "lint": "eslint src --ext .ts",
17
+ "setup": "node scripts/setup.js",
18
+ "chroma": "docker run -p 8000:8000 chromadb/chroma",
19
+ "clean": "rmdir /s /q node_modules && del package-lock.json"
20
+ },
21
+ "keywords": [
22
+ "mcp",
23
+ "ai-agent",
24
+ "autonomous",
25
+ "claude",
26
+ "anthropic"
27
+ ],
28
+ "author": "Qwen AI (self-built)",
29
+ "license": "MIT",
30
+ "dependencies": {
31
+ "@modelcontextprotocol/sdk": "^1.0.4",
32
+ "playwright": "^1.49.0",
33
+ "sql.js": "^1.11.0",
34
+ "zod": "^3.23.8",
35
+ "zod-to-json-schema": "^3.23.5",
36
+ "node-cron": "^3.0.3",
37
+ "chokidar": "^4.0.1",
38
+ "chromadb": "^1.9.2",
39
+ "chromadb-default-embed": "^2.13.2",
40
+ "axios": "^1.7.9",
41
+ "cheerio": "^1.0.0",
42
+ "simple-git": "^3.27.0",
43
+ "dotenv": "^16.4.5",
44
+ "pino": "^9.5.0",
45
+ "pino-pretty": "^13.0.0",
46
+ "execa": "^9.5.2",
47
+ "openai": "^4.73.1",
48
+ "@anthropic-ai/sdk": "^0.32.1",
49
+ "uuid": "^11.0.3",
50
+ "glob": "^11.0.0"
51
+ },
52
+ "devDependencies": {
53
+ "@types/node": "^22.9.3",
54
+ "@types/node-cron": "^3.0.11",
55
+ "@types/uuid": "^10.0.0",
56
+ "@types/sql.js": "^1.4.9",
57
+ "tsx": "^4.19.2",
58
+ "typescript": "^5.7.2",
59
+ "vitest": "^2.1.5",
60
+ "eslint": "^9.15.0"
61
+ },
62
+ "engines": {
63
+ "node": ">=20.0.0"
64
+ }
65
+ }
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { existsSync, mkdirSync, copyFileSync, writeFileSync } from 'fs';
4
+ import { resolve, dirname } from 'path';
5
+ import { fileURLToPath } from 'url';
6
+ import { execSync } from 'child_process';
7
+
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = dirname(__filename);
10
+ const rootDir = resolve(__dirname, '..');
11
+
12
+ console.log('NEXUS - Autonomous AI Agent Ecosystem');
13
+ console.log('========================================\n');
14
+
15
+ console.log('Creating directories...');
16
+ const dirs = ['data', 'logs', 'workspace', 'skills', 'data/memory'];
17
+ dirs.forEach(dir => {
18
+ const fullPath = resolve(rootDir, dir);
19
+ if (!existsSync(fullPath)) {
20
+ mkdirSync(fullPath, { recursive: true });
21
+ console.log(` Created: ${dir}`);
22
+ } else {
23
+ console.log(` Exists: ${dir}`);
24
+ }
25
+ });
26
+
27
+ console.log('\nSetting up environment...');
28
+ const envExample = resolve(rootDir, '.env.example');
29
+ const envFile = resolve(rootDir, '.env');
30
+
31
+ if (!existsSync(envFile) && existsSync(envExample)) {
32
+ copyFileSync(envExample, envFile);
33
+ console.log(' Created .env from .env.example');
34
+ console.log(' Please edit .env to add your API keys');
35
+ } else if (existsSync(envFile)) {
36
+ console.log(' .env already exists');
37
+ }
38
+
39
+ console.log('\nChecking Node.js version...');
40
+ const nodeVersion = process.versions.node;
41
+ const [major] = nodeVersion.split('.').map(Number);
42
+ if (major < 20) {
43
+ console.log(` Node.js ${nodeVersion} detected - requires 20+`);
44
+ console.log(' Please upgrade Node.js: https://nodejs.org/');
45
+ } else {
46
+ console.log(` Node.js ${nodeVersion}`);
47
+ }
48
+
49
+ console.log('\nChecking npm...');
50
+ try {
51
+ const npmVersion = execSync('npm --version', { encoding: 'utf-8' }).trim();
52
+ console.log(` npm ${npmVersion}`);
53
+ } catch {
54
+ console.log(' npm not found');
55
+ }
56
+
57
+ console.log('\nChecking Docker (optional)...');
58
+ try {
59
+ const dockerVersion = execSync('docker --version', { encoding: 'utf-8' }).trim();
60
+ console.log(` ${dockerVersion}`);
61
+ console.log(' Run: docker run -d -p 8000:8000 chromadb/chroma');
62
+ } catch {
63
+ console.log(' Docker not found - memory will use in-memory fallback');
64
+ }
65
+
66
+ console.log('\nInitializing state database...');
67
+ const dbPath = resolve(rootDir, 'data', 'state.sqlite');
68
+ if (!existsSync(dbPath)) {
69
+ console.log(' state.sqlite will be created on first run');
70
+ } else {
71
+ console.log(' state.sqlite already exists');
72
+ }
73
+
74
+ console.log('\nCreating workspace welcome file...');
75
+ const welcomePath = resolve(rootDir, 'workspace', 'WELCOME.md');
76
+ if (!existsSync(welcomePath)) {
77
+ writeFileSync(welcomePath, `# Welcome to NEXUS Workspace
78
+
79
+ This is your autonomous AI workspace. NEXUS can read, write, and manage files here.
80
+
81
+ ## Quick Start
82
+ - Use \`fs_read\` to read files
83
+ - Use \`fs_write\` to create/edit files
84
+ - Use \`web_search\` to search the web
85
+ - Use \`memory_store\` to save information for later
86
+
87
+ ## Configuration
88
+ Edit \`.env\` in the NEXUS root to configure API keys and settings.
89
+
90
+ ## Documentation
91
+ See [README.md](../README.md) for full documentation.
92
+ `);
93
+ console.log(' Created workspace/WELCOME.md');
94
+ }
95
+
96
+ console.log('\nSetup complete!\n');
97
+ console.log('Next steps:');
98
+ console.log(' 1. Edit .env to add your API keys (OPENAI_API_KEY, etc.)');
99
+ console.log(' 2. Run: npm install');
100
+ console.log(' 3. Run: npm run build');
101
+ console.log(' 4. Run: npm start');
102
+ console.log(' 5. Add to Claude Desktop config: mcp-config.json\n');
@@ -0,0 +1,138 @@
1
+ import { config } from 'dotenv';
2
+ import { resolve } from 'path';
3
+ import { existsSync } from 'fs';
4
+
5
+ // Load .env file
6
+ const envPath = process.env.NEXUS_CONFIG || resolve(process.cwd(), '.env');
7
+ if (existsSync(envPath)) {
8
+ config({ path: envPath });
9
+ } else {
10
+ config();
11
+ }
12
+
13
+ export interface NexusConfig {
14
+ // LLM
15
+ llm: {
16
+ provider: 'openai' | 'anthropic' | 'ollama';
17
+ model: string;
18
+ openaiApiKey?: string;
19
+ anthropicApiKey?: string;
20
+ ollamaUrl: string;
21
+ };
22
+
23
+ // Web Search
24
+ search: {
25
+ provider: 'brave' | 'google' | 'duckduckgo';
26
+ braveApiKey?: string;
27
+ };
28
+
29
+ // Vector DB
30
+ vector: {
31
+ type: 'chroma-local' | 'chroma-remote' | 'sqlite-vss';
32
+ chromaUrl: string;
33
+ collection: string;
34
+ };
35
+
36
+ // State DB
37
+ state: {
38
+ dbPath: string;
39
+ };
40
+
41
+ // Directories
42
+ paths: {
43
+ workspace: string;
44
+ data: string;
45
+ logs: string;
46
+ skills: string;
47
+ };
48
+
49
+ // Security
50
+ security: {
51
+ allowedDirs: string[];
52
+ blockedCommands: string[];
53
+ auditLogEnabled: boolean;
54
+ };
55
+
56
+ // Automation
57
+ automation: {
58
+ cronEnabled: boolean;
59
+ watcherEnabled: boolean;
60
+ };
61
+
62
+ // Logging
63
+ logging: {
64
+ level: 'debug' | 'info' | 'warn' | 'error';
65
+ };
66
+
67
+ // Browser
68
+ browser: {
69
+ headless: boolean;
70
+ timeout: number;
71
+ };
72
+ }
73
+
74
+ function parseBool(val: string | undefined, defaultVal: boolean): boolean {
75
+ if (!val) return defaultVal;
76
+ return val.toLowerCase() === 'true' || val === '1';
77
+ }
78
+
79
+ function parseList(val: string | undefined): string[] {
80
+ if (!val) return [];
81
+ return val.split(',').map(s => s.trim()).filter(Boolean);
82
+ }
83
+
84
+ export const nexusConfig: NexusConfig = {
85
+ llm: {
86
+ provider: (process.env.DEFAULT_LLM_PROVIDER as any) || 'openai',
87
+ model: process.env.DEFAULT_LLM_MODEL || 'gpt-4o',
88
+ openaiApiKey: process.env.OPENAI_API_KEY,
89
+ anthropicApiKey: process.env.ANTHROPIC_API_KEY,
90
+ ollamaUrl: process.env.OLLAMA_BASE_URL || 'http://localhost:11434',
91
+ },
92
+
93
+ search: {
94
+ provider: (process.env.DEFAULT_SEARCH_PROVIDER as any) || 'duckduckgo',
95
+ braveApiKey: process.env.BRAVE_SEARCH_API_KEY,
96
+ },
97
+
98
+ vector: {
99
+ type: (process.env.VECTOR_DB as any) || 'chroma-local',
100
+ chromaUrl: process.env.CHROMA_URL || 'http://localhost:8000',
101
+ collection: process.env.CHROMA_COLLECTION || 'nexus_memory',
102
+ },
103
+
104
+ state: {
105
+ dbPath: process.env.STATE_DB_PATH || './data/state.sqlite',
106
+ },
107
+
108
+ paths: {
109
+ workspace: process.env.WORKSPACE_DIR || './workspace',
110
+ data: process.env.DATA_DIR || './data',
111
+ logs: process.env.LOGS_DIR || './logs',
112
+ skills: process.env.SKILLS_DIR || './skills',
113
+ },
114
+
115
+ security: {
116
+ allowedDirs: parseList(process.env.ALLOWED_DIRS) || ['./workspace'],
117
+ blockedCommands: parseList(process.env.BLOCKED_COMMANDS) || ['rm -rf /'],
118
+ auditLogEnabled: parseBool(process.env.AUDIT_LOG_ENABLED, true),
119
+ },
120
+
121
+ automation: {
122
+ cronEnabled: parseBool(process.env.CRON_ENABLED, true),
123
+ watcherEnabled: parseBool(process.env.WATCHER_ENABLED, true),
124
+ },
125
+
126
+ logging: {
127
+ level: (process.env.LOG_LEVEL as any) || 'info',
128
+ },
129
+
130
+ browser: {
131
+ headless: parseBool(process.env.BROWSER_HEADLESS, true),
132
+ timeout: parseInt(process.env.BROWSER_TIMEOUT || '30000', 10),
133
+ },
134
+ };
135
+
136
+ export function validateConfig(): string[] {
137
+ return [];
138
+ }
@@ -0,0 +1,61 @@
1
+ import pino from 'pino';
2
+ import { resolve } from 'path';
3
+ import { mkdirSync, existsSync } from 'fs';
4
+ import { nexusConfig } from './config.js';
5
+
6
+ // Ensure logs directory exists
7
+ const logsDir = resolve(nexusConfig.paths.logs);
8
+ if (!existsSync(logsDir)) {
9
+ mkdirSync(logsDir, { recursive: true });
10
+ }
11
+
12
+ const logFile = resolve(logsDir, `nexus-${new Date().toISOString().split('T')[0]}.log`);
13
+
14
+ // Create logger with both console and file transport
15
+ export const logger = pino({
16
+ level: nexusConfig.logging.level,
17
+ transport: {
18
+ targets: [
19
+ {
20
+ target: 'pino-pretty',
21
+ options: {
22
+ colorize: true,
23
+ translateTime: 'SYS:standard',
24
+ ignore: 'pid,hostname',
25
+ },
26
+ },
27
+ {
28
+ target: 'pino/file',
29
+ options: {
30
+ destination: logFile,
31
+ mkdir: true,
32
+ },
33
+ },
34
+ ],
35
+ },
36
+ });
37
+
38
+ export type Logger = typeof logger;
39
+
40
+ // Create child logger with context
41
+ export function createContextLogger(context: string): Logger {
42
+ return logger.child({ context });
43
+ }
44
+
45
+ // Audit logger for security-sensitive operations
46
+ export const auditLogger = pino({
47
+ level: 'info',
48
+ transport: {
49
+ target: 'pino/file',
50
+ options: {
51
+ destination: resolve(logsDir, 'audit.log'),
52
+ mkdir: true,
53
+ },
54
+ },
55
+ });
56
+
57
+ export function logAudit(event: string, details: Record<string, any>): void {
58
+ if (nexusConfig.security.auditLogEnabled) {
59
+ auditLogger.info({ event, ...details, timestamp: new Date().toISOString() }, event);
60
+ }
61
+ }