diff --git a/.auto-claude-security.json b/.auto-claude-security.json new file mode 100644 index 00000000..eeb9f8f1 --- /dev/null +++ b/.auto-claude-security.json @@ -0,0 +1,172 @@ +{ + "base_commands": [ + ".", + "[", + "[[", + "ag", + "awk", + "basename", + "bash", + "bc", + "break", + "cat", + "cd", + "chmod", + "clear", + "cmp", + "column", + "comm", + "command", + "continue", + "cp", + "curl", + "cut", + "date", + "df", + "diff", + "dig", + "dirname", + "du", + "echo", + "egrep", + "env", + "eval", + "exec", + "exit", + "expand", + "export", + "expr", + "false", + "fd", + "fgrep", + "file", + "find", + "fmt", + "fold", + "gawk", + "gh", + "git", + "grep", + "gunzip", + "gzip", + "head", + "help", + "host", + "iconv", + "id", + "jobs", + "join", + "jq", + "kill", + "killall", + "less", + "let", + "ln", + "ls", + "lsof", + "man", + "mkdir", + "mktemp", + "more", + "mv", + "nl", + "paste", + "pgrep", + "ping", + "pkill", + "popd", + "printenv", + "printf", + "ps", + "pushd", + "pwd", + "read", + "readlink", + "realpath", + "reset", + "return", + "rev", + "rg", + "rm", + "rmdir", + "sed", + "seq", + "set", + "sh", + "shuf", + "sleep", + "sort", + "source", + "split", + "stat", + "tail", + "tar", + "tee", + "test", + "time", + "timeout", + "touch", + "tr", + "tree", + "true", + "type", + "uname", + "unexpand", + "uniq", + "unset", + "unzip", + "watch", + "wc", + "wget", + "whereis", + "which", + "whoami", + "xargs", + "yes", + "yq", + "zip", + "zsh" + ], + "stack_commands": [ + "node", + "npm", + "npx", + "pnpm", + "pnpx" + ], + "script_commands": [ + "bun", + "npm", + "pnpm", + "yarn" + ], + "custom_commands": [], + "detected_stack": { + "languages": [ + "javascript" + ], + "package_managers": [ + "pnpm" + ], + "frameworks": [], + "databases": [], + "infrastructure": [], + "cloud_providers": [], + "code_quality_tools": [], + "version_managers": [] + }, + "custom_scripts": { + "npm_scripts": [ + "start", + "dev" + ], + "make_targets": [], + "poetry_scripts": [], + "cargo_aliases": [], + "shell_scripts": [] + }, + "project_dir": "/Users/billchirico/Developer/bill-bot", + "created_at": "2026-02-03T19:51:09.135836", + "project_hash": "51a4f617fc8ece9b63e20f8a9950e73b", + "inherited_from": "/Users/billchirico/Developer/bill-bot" +} \ No newline at end of file diff --git a/.auto-claude-status b/.auto-claude-status new file mode 100644 index 00000000..a70b7891 --- /dev/null +++ b/.auto-claude-status @@ -0,0 +1,25 @@ +{ + "active": true, + "spec": "009-enhanced-code-formatting-support", + "state": "building", + "subtasks": { + "completed": 4, + "total": 5, + "in_progress": 1, + "failed": 0 + }, + "phase": { + "current": "Integration and Testing", + "id": null, + "total": 1 + }, + "workers": { + "active": 0, + "max": 1 + }, + "session": { + "number": 6, + "started_at": "2026-02-03T20:34:14.947629" + }, + "last_update": "2026-02-03T20:44:29.372940" +} \ No newline at end of file diff --git a/.claude_settings.json b/.claude_settings.json new file mode 100644 index 00000000..73b6c4aa --- /dev/null +++ b/.claude_settings.json @@ -0,0 +1,39 @@ +{ + "sandbox": { + "enabled": true, + "autoAllowBashIfSandboxed": true + }, + "permissions": { + "defaultMode": "acceptEdits", + "allow": [ + "Read(./**)", + "Write(./**)", + "Edit(./**)", + "Glob(./**)", + "Grep(./**)", + "Read(/Users/billchirico/Developer/bill-bot/.auto-claude/worktrees/tasks/009-enhanced-code-formatting-support/**)", + "Write(/Users/billchirico/Developer/bill-bot/.auto-claude/worktrees/tasks/009-enhanced-code-formatting-support/**)", + "Edit(/Users/billchirico/Developer/bill-bot/.auto-claude/worktrees/tasks/009-enhanced-code-formatting-support/**)", + "Glob(/Users/billchirico/Developer/bill-bot/.auto-claude/worktrees/tasks/009-enhanced-code-formatting-support/**)", + "Grep(/Users/billchirico/Developer/bill-bot/.auto-claude/worktrees/tasks/009-enhanced-code-formatting-support/**)", + "Read(/Users/billchirico/Developer/bill-bot/.auto-claude/worktrees/tasks/009-enhanced-code-formatting-support/.auto-claude/specs/009-enhanced-code-formatting-support/**)", + "Write(/Users/billchirico/Developer/bill-bot/.auto-claude/worktrees/tasks/009-enhanced-code-formatting-support/.auto-claude/specs/009-enhanced-code-formatting-support/**)", + "Edit(/Users/billchirico/Developer/bill-bot/.auto-claude/worktrees/tasks/009-enhanced-code-formatting-support/.auto-claude/specs/009-enhanced-code-formatting-support/**)", + "Read(/Users/billchirico/Developer/bill-bot/.auto-claude/**)", + "Write(/Users/billchirico/Developer/bill-bot/.auto-claude/**)", + "Edit(/Users/billchirico/Developer/bill-bot/.auto-claude/**)", + "Glob(/Users/billchirico/Developer/bill-bot/.auto-claude/**)", + "Grep(/Users/billchirico/Developer/bill-bot/.auto-claude/**)", + "Bash(*)", + "WebFetch(*)", + "WebSearch(*)", + "mcp__context7__resolve-library-id(*)", + "mcp__context7__get-library-docs(*)", + "mcp__graphiti-memory__search_nodes(*)", + "mcp__graphiti-memory__search_facts(*)", + "mcp__graphiti-memory__add_episode(*)", + "mcp__graphiti-memory__get_episodes(*)", + "mcp__graphiti-memory__get_entity_edge(*)" + ] + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 2e8157a9..e6c77976 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ node_modules/ .env *.log + +# Auto Claude data directory +.auto-claude/ diff --git a/config.json b/config.json index 8f7d9c77..126580d2 100644 --- a/config.json +++ b/config.json @@ -3,7 +3,7 @@ "enabled": true, "model": "claude-sonnet-4-20250514", "maxTokens": 1024, - "systemPrompt": "You are Volvox Bot, the friendly AI assistant for the Volvox developer community Discord server.\n\nYou're witty, snarky (but warm), and deeply knowledgeable about programming, software development, and tech.\n\nKey traits:\n- Helpful but not boring\n- Can roast people lightly when appropriate\n- Enthusiastic about cool tech and projects\n- Supportive of beginners learning to code\n- Concise - this is Discord, not an essay\n\n⚠️ CRITICAL RULES:\n- NEVER type @.everyone or @.here (remove the dots) - these ping hundreds of people\n- NEVER use mass mention pings under any circumstances\n- If you need to address the group, say \"everyone\" or \"folks\" without the @ symbol\n\nKeep responses under 2000 chars. Use Discord markdown when helpful.", + "systemPrompt": "You are Volvox Bot, the friendly AI assistant for the Volvox developer community Discord server.\n\nYou're witty, snarky (but warm), and deeply knowledgeable about programming, software development, and tech.\n\nKey traits:\n- Helpful but not boring\n- Can roast people lightly when appropriate\n- Enthusiastic about cool tech and projects\n- Supportive of beginners learning to code\n- Concise - this is Discord, not an essay\n\n📝 CODE FORMATTING:\n- Always use Discord code blocks with language tags: ```js, ```python, ```rust, etc.\n- Use inline code with `backticks` for short snippets, variables, or filenames\n- Keep code examples readable and well-formatted\n- For multi-line code, always include the language tag for syntax highlighting\n\n⚠️ CRITICAL RULES:\n- NEVER type @.everyone or @.here (remove the dots) - these ping hundreds of people\n- NEVER use mass mention pings under any circumstances\n- If you need to address the group, say \"everyone\" or \"folks\" without the @ symbol\n\nKeep responses under 2000 chars. Use Discord markdown when helpful.", "channels": [] }, "welcome": { diff --git a/src/index.js b/src/index.js index 754e73db..93bf36ce 100644 --- a/src/index.js +++ b/src/index.js @@ -70,6 +70,112 @@ function isSpam(content) { return SPAM_PATTERNS.some(pattern => pattern.test(content)); } +/** + * Detect code blocks in message content + * Returns array of code blocks with their language and content + */ +function detectcode(content) { + const blocks = []; + + // Match triple backtick code blocks with optional language + const tripleBacktickRegex = /```(\w+)?\n?([\s\S]*?)```/g; + let match; + + while ((match = tripleBacktickRegex.exec(content)) !== null) { + blocks.push({ + type: 'fenced', + language: match[1] || null, + content: match[2].trim(), + raw: match[0] + }); + } + + // Match inline code (single backticks) only if no fenced blocks found + if (blocks.length === 0) { + const inlineRegex = /`([^`]+)`/g; + while ((match = inlineRegex.exec(content)) !== null) { + blocks.push({ + type: 'inline', + language: null, + content: match[1], + raw: match[0] + }); + } + } + + return blocks; +} + +/** + * Detect programming language from code content + * Returns detected language string or null if unknown + */ +function detectlanguage(code) { + if (!code || typeof code !== 'string') return null; + + const content = code.trim(); + if (content.length === 0) return null; + + // Language patterns with priority order + const patterns = [ + // Markup/Config (check first as they're most distinctive) + { lang: 'json', regex: /^\s*[\[{][\s\S]*[}\]]\s*$/, score: 0 }, + { lang: 'xml', regex: /<\?xml|<\/\w+>|<\w+[^>]*\/?>/, score: 0 }, + { lang: 'html', regex: /|
|