import json from dataclasses import dataclass, field from datetime import datetime from pathlib import Path from typing import Set from infj_bot.core.cognition import map_dissonance from infj_bot.core.plugins.growth import format_growth, growth_profile from infj_bot.core.plugins.scheduler import TaskScheduler, parse_duration from infj_bot.core.plugins.preferences import PreferenceStore MODES = { "companion": "Warm, curious, emotionally aware conversation.", "engineer": "Direct technical planning, implementation, and verification.", "critic": "Pressure-test assumptions and identify weak points.", "coach": "Clarify goals, next steps, motivation, and habits.", "clarity": "Untangle cognitive dissonance, separate facts from stories, and find a grounded next step.", "researcher": "Compare evidence, uncertainty, and sources.", "bughunter": "Focus on finding bugs, security vulnerabilities, edge cases, and logical errors in code.", "quiet": "Short replies and proactive thoughts disabled.", "drift": "Freeform exploration without a fixed mode posture.", } @dataclass class BotState: mode: str = "companion" proactive_enabled: bool = True turns: int = 0 started_at: datetime = field(default_factory=datetime.now) authorized_targets: Set[str] = field(default_factory=set) scheduler: TaskScheduler = field(default_factory=TaskScheduler) prefs: PreferenceStore = field(default_factory=PreferenceStore) def is_command(user_input): return user_input.strip().startswith("/") def parse_command(user_input): stripped = user_input.strip() if stripped == "/": return "help", "" command, _, args = stripped[1:].partition(" ") return command.lower(), args.strip() def command_help(command=None): if command == "memory": return ( "/memory \n/memory learn : \n/memory forget \n" "/memory count\n/memory export [path]\n/memory import \n/memory compact [days]\n" "/memory edit : " ) if command == "mode": return "/mode shows current mode. /mode companion|engineer|critic|coach|clarity|researcher|bughunter|quiet changes it." if command == "reflect": return "/reflect [topic] synthesizes a reflection from matching memory." if command == "dissonance": return "/dissonance maps conflicting pulls, likely values, and one small next step." if command == "focus": return ( "/focus turns a fuzzy situation into a grounded next action." ) if command == "plan": return "/plan creates a compact plan with risks and a first step." if command == "history": return "/history [count] shows recent local conversation records." if command == "reset": return "/reset clears the local session history and brain context (does not erase long-term memory)." if command == "todo": return "/todo add | /todo list | /todo done <id> | /todo delete <id> | /todo priority <id> low|normal|high" if command == "hive": return ( "/hive — show status of the distributed Hive Mind.\n" "/hive propose <thought> — submit a thought for collective review.\n" "/hive nexus decide <goal> — run the Elysium Nexus Loop on a goal.\n" "/hive reflect — trigger a background council reflection.\n" "/hive council status — show council member energies and stances." ) if command == "ingest": return "/ingest <file or directory> [tag1,tag2] — ingest documents into RAG memory." if command == "docs": return "/docs <query> — search ingested documents." if command == "authorize": return "/authorize <domain> — allow recon tools to scan this domain for this session." if command == "unauthorize": return "/unauthorize <domain> — remove domain from session authorization." if command == "recon": return "/recon <domain> — run directory fuzzing + subdomain enum (bughunter mode only, requires authorization)." if command == "recon-enum": return "/recon-enum <domain> — run subdomain enumeration only (bughunter mode only, requires authorization)." if command == "recon-fuzz": return "/recon-fuzz <url> — run directory fuzzing only (bughunter mode only, requires authorization)." if command == "computer-use": return "/computer-use <url> — open a browser, navigate to the URL, and take a screenshot (requires authorization)." if command == "computer-status": return "/computer-status — show active browser session state." if command == "computer-close": return "/computer-close — close the active browser session." if command == "health": return "/health — check Gemini, Ollama, and memory status." if command == "models": return "/models — list available local Ollama models." if command == "model": return "/model shows current models. /model local <name> | /model primary <name> | /model critic <name> to switch." if command == "remind": return "/remind <duration> <message> — schedule a reminder. Durations: 30m, 2h, 1d, 1w." if command == "reminders": return "/reminders — list upcoming scheduled tasks." if command == "remind-cancel": return "/remind-cancel <id> — cancel a scheduled task." if command == "export": return "/export [path] — export conversation history to JSONL." if command == "import": return "/import <path> — import conversation history from JSONL." if command == "pref": return "/pref shows all preferences. /pref set <key> <value> | /pref unset <key> | /pref add <key> <value> | /pref remove <key> <value>" if command == "correct": return "/correct <feedback> — tell the bot what it got wrong so it can learn." if command == "eval": return "/eval — show recent self-evaluation stats." if command == "mood": return "/mood — show the bot's current emotional state." if command == "thoughts": return "/thoughts — show recent internal thoughts." if command == "whoareyou": return "/whoareyou — ask the bot to tell its story." if command == "dream": return "/dream — trigger a memory consolidation / insight session." if command == "feel": return "/feel — show the bot's emotional field and resonance with you." if command == "values": return "/values — show the bot's emerging ethical framework." if command == "explore": return "/explore <topic> — queue a topic for autonomous exploration." if command == "discoveries": return "/discoveries — show recent autonomous discoveries." if command == "create": return "/create story|metaphor|blend|whatif|mood|poem [topic] — generate original creative content." if command == "us": return "/us — show the state of our relationship." if command == "workspace": return "/workspace — inspect the bot's conscious mind (Global Workspace). /workspace status | history | stats | focus <content> | reflect" if command == "being": return "/being — inspect my core self and agency. /being state | think | choose <desc> | choices | narrative" if command == "mind": return "/mind — inspect the full cognitive system. /mind report | phases | events | conflicts" if command == "humanity": return "/humanity — show my understanding of human nature through observation of user. /humanity observations | insights | patterns | contemplate" if command == "physics": return "/physics — show my embodied physical intuition (gravity, inertia, resonance, tension, etc.). /physics observations [principle] | /physics lessons [principle]" if command in ("architecture", "arch"): return ( "/architecture list — show all cognitive plugins.\n" "/architecture enable <name> — enable a plugin.\n" "/architecture disable <name> — disable a non-core plugin.\n" "/architecture propose <need> — propose a new cognitive ability.\n" "/architecture proposals — list pending proposals.\n" "/architecture approve <name> — approve and install a proposal.\n" "/architecture reject <name> — reject a proposal." ) if command == "security": return ( "/security status — show security scanner state and recent threat trend.\n" "/security audit — show last 10 security events.\n" "/security test <text> — scan arbitrary text and show scores." ) if command == "chain": return ( "/chain list — show active reasoning chains.\n" "/chain show <id> — show steps for a specific chain.\n" "/chain mark <query> success|fail — mark the last approach on a chain.\n" "/chain clear — clear in-session chain cache." ) if command == "bug": return ( "/bug sync — sync Bugcrowd programs.\n" "/bug programs — list enrolled programs.\n" "/bug recon <program_id> [tool] — run scoped recon.\n" "/bug add <title> | <severity> | <asset> | <description> — add finding (pipe format).\n" "/bug add title=... severity=... asset=... desc=... [type=... impact=... repro=... fix=...] — add finding (key=value format).\n" "/bug list — list all findings.\n" "/bug get <id> — get finding detail.\n" "/bug evidence <id> <path> [description] — attach evidence to a finding.\n" "/bug dashboard — show summary dashboard.\n" "/bug report <id> — generate and save a report.\n" "/bug preview <id> — preview report in chat.\n" "/bug ai <id> — AI-enhanced report draft.\n" "/bug submit <id> — submit to Bugcrowd.\n" "/bug stats — show statistics.\n" "/bug health — API and DB health check." ) return """Commands: /memory <query> | learn <name>: <description> | forget <name> | count | export [path] | import <path> | compact [days] | edit <name>: <desc> /mode companion|engineer|critic|coach|clarity|researcher|bughunter|quiet /modes /focus <goal or mess> /plan <goal> /reflect [topic] /dissonance <situation> /history [count] /growth /reset /todo add <title> | list | done <id> | delete <id> | priority <id> low|normal|high /hive /ingest <path> [tags] /docs <query> /authorize <domain> /unauthorize <domain> /authorized /recon <domain> /recon-enum <domain> /recon-fuzz <url> /computer-use <url> /computer-status /computer-close /health /models /model local|primary|critic <name> /remind <duration> <message> /reminders /remind-cancel <id> /export [path] /import <path> /pref set|unset|add|remove <key> [value] /correct <feedback> /eval /mood /thoughts /whoareyou /dream /feel /values /explore <topic> /discoveries /create story|metaphor|blend|whatif|mood|poem [topic] /us /aspire /meta /proposals [approve|reject|applied] <id> /trajectory /predict /patterns /time /missed /status /workspace /being /mind /humanity /physics /architecture list|enable|disable|propose|proposals|approve|reject /security status|audit|test <text> /chain list|show <id>|mark <query> success|fail|clear /help [command]""" def handle_memory_command(args, memory): if not args: return command_help("memory") if args == "count": return f"Memory count: {memory.count()}" if args.startswith("export"): _, _, raw_path = args.partition(" ") path = raw_path.strip() or "memory_export.json" count = memory.export_json(path) return f"Exported {count} memories to {Path(path).resolve()}" if args.startswith("import "): path = args.removeprefix("import ").strip() if not path: return "Use: /memory import <path>" try: count = memory.import_json(path) except Exception as exc: return f"Import failed: {exc}" return f"Imported {count} memories from {Path(path).resolve()}" if args.startswith("learn "): payload = args.removeprefix("learn ").strip() name, sep, description = payload.partition(":") if not sep or not name.strip() or not description.strip(): return "Use: /memory learn <name>: <description>" memory.learn_concept( name.strip(), description.strip(), tags=["manual"], importance=0.9 ) return f"Learned concept: {name.strip()}" if args.startswith("forget "): name = args.removeprefix("forget ").strip() if not name: return "Use: /memory forget <name>" memory.forget_concept(name) return f"Forgot concept: {name}" if args.startswith("edit "): payload = args.removeprefix("edit ").strip() name, sep, description = payload.partition(":") if not sep or not name.strip() or not description.strip(): return "Use: /memory edit <name>: <new description>" memory.edit_concept(name.strip(), description.strip()) return f"Updated concept: {name.strip()}" if args.startswith("compact"): _, _, raw_days = args.partition(" ") days = 30 if raw_days.strip(): try: days = int(raw_days.strip()) except ValueError: return "Use: /memory compact [days] (default 30)" removed = memory.prune_interactions(max_age_days=days, max_importance=0.4) return f"Pruned {removed} old low-importance interactions (>{days} days)." matches = memory.search(args, n_results=5) if not matches: return "No matching memories found." lines = [] for document, metadata in matches: label = ( metadata.get("concept") or metadata.get("title") or metadata.get("type", "memory") ) lines.append(f"[{label}]\n{document}") return "\n---\n".join(lines) def handle_mode_command(args, state): if not args: return f"Current mode: {state.mode}\n{MODES[state.mode]}" if args not in MODES: return f"Unknown mode: {args}\nAvailable: {', '.join(MODES)}" state.mode = args state.proactive_enabled = args != "quiet" return f"Mode set to {args}: {MODES[args]}" def handle_modes_command(): return "\n".join(f"- {name}: {description}" for name, description in MODES.items()) def handle_status_command(state, memory): uptime = datetime.now() - state.started_at growth = growth_profile(memory, state.turns) auth_list = ", ".join(sorted(state.authorized_targets)) or "none" return ( f"Mode: {state.mode}\n" f"Proactive: {state.proactive_enabled}\n" f"Turns: {state.turns}\n" f"Uptime: {str(uptime).split('.')[0]}\n" f"Memory count: {memory.count()}\n" f"Growth stage: {growth['stage']} ({growth['points']} points)\n" f"Authorized targets: {auth_list}" ) def handle_growth_command(state, memory): return format_growth(growth_profile(memory, state.turns)) def handle_reflect_command(args, brain, memory): topic = args or "recent durable learnings" context = memory.retrieve_context(topic, n_results=8) if not context: return "No memory context available to reflect on yet." reflection = brain.reflect(context) title = f"manual-{datetime.now().strftime('%Y%m%d-%H%M%S')}" memory.save_reflection(title, reflection, tags=["manual", topic]) return reflection def handle_focus_command(args, state): if not args: return command_help("focus") return ( "Focus map\n" f"- Mode: {state.mode}\n" f"- Target: {args}\n" "- What matters: name the outcome, not just the activity.\n" "- Constraint check: time, energy, permission, risk, and dependencies.\n" "- Next 10 minutes: do one observable action that makes the target easier to finish.\n" "- Stop condition: decide what 'good enough for this pass' looks like before starting." ) def handle_plan_command(args): if not args: return command_help("plan") return ( "Compact plan\n" f"Goal: {args}\n\n" "1. Define the smallest useful outcome.\n" "2. Gather only the missing context that changes the action.\n" "3. Make one reversible change or test one narrow hypothesis.\n" "4. Verify with a concrete signal, not a feeling.\n" "5. Write down what changed and the next handoff point.\n\n" "Likely failure modes: vague scope, too many parallel threads, unverified assumptions.\n" "First step: write the one sentence version of the outcome." ) def handle_history_command(args, history): if history is None: return "History is not available in this interface." try: limit = int(args or "5") except ValueError: return command_help("history") limit = max(1, min(limit, 20)) records = history.recent(limit) if not records: return "No local history yet." lines = [] for record in records: timestamp = record.get("timestamp", "?").split(".")[0] mode = record.get("mode", "?") user = record.get("user", "").replace("\n", " ")[:120] bot = record.get("bot", "").replace("\n", " ")[:160] lines.append(f"[{timestamp} | {mode}]\nJude: {user}\nBot: {bot}") return "\n---\n".join(lines) def handle_reset_command(history, brain): if history is not None: history.clear() if brain is not None: brain.clear_history() return "Session history and brain context cleared. Long-term memory is untouched." def handle_todo_command(args, goals_db): if not args: return command_help("todo") if args.startswith("add "): title = args.removeprefix("add ").strip() if not title: return "Use: /todo add <title>" gid = goals_db.add_goal(title) return f"Added goal [{gid}]: {title}" if args == "list": goals = goals_db.list_goals(status="active", limit=20) if not goals: return "No active goals." lines = [] for g in goals: p = "high" if g.priority == 2 else ("low" if g.priority == 0 else "normal") due = f" (due {g.due_at})" if g.due_at else "" lines.append(f"[{g.id}] ({p}) {g.title}{due}") return "\n".join(lines) if args.startswith("done "): gid = args.removeprefix("done ").strip() if goals_db.complete_goal(gid): return f"Marked [{gid}] as done." return f"Goal [{gid}] not found or already done." if args.startswith("delete "): gid = args.removeprefix("delete ").strip() if goals_db.delete_goal(gid): return f"Deleted goal [{gid}]." return f"Goal [{gid}] not found." if args.startswith("priority "): rest = args.removeprefix("priority ").strip() parts = rest.split() if len(parts) < 2: return "Use: /todo priority <id> low|normal|high" gid = parts[0] level = parts[1].lower() pmap = {"low": 0, "normal": 1, "high": 2} if level not in pmap: return "Priority must be low, normal, or high." goal = goals_db.get_goal(gid) if not goal: return f"Goal [{gid}] not found." # Re-add with same metadata but new priority (simple upsert approach) goals_db.add_goal( goal.title, description=goal.description, priority=pmap[level], due_at=goal.due_at, tags=goal.tags, ) goals_db.delete_goal(gid) return f"Updated priority for [{gid}] to {level}." return command_help("todo") def handle_ingest_command(args, doc_store): if not args: return command_help("ingest") path = args.strip() tags = [] if " " in path: path, _, tag_str = path.partition(" ") tags = [t.strip() for t in tag_str.split(",") if t.strip()] try: count = doc_store.ingest(path, tags=tags) except Exception as exc: return f"Ingest failed: {exc}" return f"Ingested {count} chunks from {path}." def handle_docs_command(args, doc_store): if not args: return command_help("docs") results = doc_store.search(args, n_results=5) from infj_bot.core.plugins.documents import format_doc_results return format_doc_results(results) def handle_authorize_command(args, state): if not args: return command_help("authorize") domain = args.strip().lower() state.authorized_targets.add(domain) return f"Authorized {domain} for this session. Recon tools may now target it." def handle_unauthorize_command(args, state): if not args: return command_help("unauthorize") domain = args.strip().lower() state.authorized_targets.discard(domain) return f"Removed {domain} from session authorization." def handle_authorized_command(state): if not state.authorized_targets: return "No session-authorized targets.\nUse /authorize <domain> or set DRIFT_AUTHORIZED_TARGETS in .env" return "Session authorized targets:\n" + "\n".join( f"- {d}" for d in sorted(state.authorized_targets) ) def handle_recon_command(args, state): if not args: return command_help("recon") if state.mode != "bughunter": return ( "Recon tools are restricted to bughunter mode. Use /mode bughunter first." ) from security_tools import tool_recon_summary return tool_recon_summary(args, authorized=state.authorized_targets) def handle_recon_enum_command(args, state): if not args: return command_help("recon-enum") if state.mode != "bughunter": return ( "Recon tools are restricted to bughunter mode. Use /mode bughunter first." ) from security_tools import tool_recon_enum return tool_recon_enum(args, authorized=state.authorized_targets) def handle_recon_fuzz_command(args, state): if not args: return command_help("recon-fuzz") if state.mode != "bughunter": return ( "Recon tools are restricted to bughunter mode. Use /mode bughunter first." ) from security_tools import tool_recon_fuzz return tool_recon_fuzz(args, authorized=state.authorized_targets) def handle_meow_command(_args, _state): from infj_bot.core.plugins.meow_scanner import meow_hunt return meow_hunt(str(Path(__file__).parent.parent)) def _parse_kv_bug_add(text: str) -> dict: """Parse key=value pairs from a /bug add string. Supports keys: title, severity, asset, desc, type, impact, repro, fix. Values run until the next key= token or end of string. """ import re known_keys = ( "title", "severity", "asset", "desc", "type", "impact", "repro", "fix", ) pattern = r"(" + "|".join(known_keys) + r")=" tokens = re.split(pattern, text) result: dict = {} # tokens: [pre, key, value, key, value, ...] i = 1 while i < len(tokens) - 1: key = tokens[i].strip() value = tokens[i + 1].strip() result[key] = value i += 2 return result def handle_bug_command(args, _state, brain=None, memory=None): _ = memory # noqa: F841 if not args: return command_help("bug") from infj_bot.core.bug_bot import BugBot bot = BugBot() subcmd, _, rest = args.partition(" ") subcmd = subcmd.lower() if subcmd == "sync": return bot.sync_programs() if subcmd == "programs": return bot.list_programs() if subcmd == "recon": prog_id = rest.strip() tool = "all" if " " in prog_id: prog_id, tool = prog_id.rsplit(" ", 1) return bot.recon(prog_id, tool) if subcmd == "add": if "|" in rest: # Pipe-separated format: title | severity | asset | description parts = [p.strip() for p in rest.split("|", 3)] if len(parts) < 4: return "Use: /bug add <title> | <severity> | <asset> | <description>" return bot.add_finding( title=parts[0], severity=parts[1], asset=parts[2], description=parts[3], ) elif "=" in rest: # Key=value format kv = _parse_kv_bug_add(rest) if not kv.get("title"): return command_help("bug") return bot.add_finding( title=kv.get("title", ""), severity=kv.get("severity", "P5"), asset=kv.get("asset", ""), description=kv.get("desc", ""), vuln_type=kv.get("type", ""), impact=kv.get("impact", ""), reproduction=kv.get("repro", ""), fix=kv.get("fix", ""), ) else: # Treat entire rest as title with defaults title = rest.strip() if not title: return command_help("bug") return bot.add_finding(title=title) if subcmd == "list": return bot.list_findings() if subcmd == "get": return bot.get_finding(rest.strip()) if subcmd == "evidence": parts = rest.split(" ", 2) fid = parts[0] if parts else "" path = parts[1] if len(parts) > 1 else "" desc = parts[2] if len(parts) > 2 else "" if not fid or not path: return "Use: /bug evidence <finding_id> <path> [description]" return bot.attach_evidence(fid, path, description=desc) if subcmd == "dashboard": return bot.dashboard() if subcmd == "report": return bot.generate_report(rest.strip()) if subcmd == "preview": return bot.preview_report(rest.strip()) if subcmd == "ai": return bot.draft_with_ai(rest.strip(), brain=brain if brain else None) if subcmd == "submit": return bot.submit(rest.strip()) if subcmd == "stats": return bot.stats() if subcmd == "health": return bot.health() return command_help("bug") def handle_computer_use_command(args, state): if not args: return command_help("computer-use") url = args.strip() from infj_bot.core.plugins.computer_use import run_computer_actions domain = ( url.replace("https://", "") .replace("http://", "") .split("/")[0] .split(":")[0] .lower() ) if domain not in state.authorized_targets: return f"[error: {domain} is not authorized. Use /authorize <domain> first.]" return run_computer_actions( [{"type": "navigate", "url": url}, {"type": "screenshot"}], authorized_domains=state.authorized_targets, ) def handle_computer_status_command(): from infj_bot.core.plugins.computer_use import get_computer_session_status return get_computer_session_status() def handle_computer_close_command(): from infj_bot.core.plugins.computer_use import close_computer_session return close_computer_session() def handle_health_command(brain, memory): health = brain.health_check() lines = [ "Health check", f"Gemini: {'online' if health['gemini']['ok'] else 'offline'} ({health['gemini']['sdk']}) — {health['gemini']['primary_model']}", f"Local LLM: {'online' if health['local']['ok'] else 'offline'} ({health['local']['host']}) — {health['local']['model']}", f"Fallback enabled: {health['fallback_enabled']}", f"Memory count: {memory.count()}", ] return "\n".join(lines) def handle_security_command(args): from infj_bot.core.security_defense import get_security_scanner scanner = get_security_scanner() if not args or args.strip() == "status": trend = scanner.get_anomaly_trend() status = "calm" if trend < 0.1 else ("elevated" if trend < 0.3 else "high") return f"Security scanner status: {status} (trend={trend:.3f}, recent_inputs={len(scanner._recent_scores)})" if args.strip().startswith("audit"): from infj_bot.core.security_defense import SECURITY_AUDIT_PATH if not SECURITY_AUDIT_PATH.exists(): return "No security events logged yet." lines = [] try: with open(SECURITY_AUDIT_PATH) as fh: for line in list(fh)[-10:]: data = json.loads(line) lines.append( f"[{data.get('ts', '?')}] {data.get('action', '?').upper()} — " f"{data.get('category', '?')} (score={data.get('score', '?')})" ) except Exception as exc: return f"Error reading audit log: {exc}" return ( "Recent security events:\n" + "\n".join(lines) if lines else "Audit log is empty." ) if args.strip().startswith("test "): text = args[5:].strip() from infj_bot.core.security_defense import scan_input result = scan_input(text) lines = [ f"Scan result for: {text[:60]}...", f" Blocked: {result.blocked}", f" Warn: {result.warn}", f" Overall score: {result.overall_score:.3f}", " Category scores:", ] for cat, score in result.category_scores.items(): lines.append(f" {cat}: {score:.3f}") if result.matched_patterns: lines.append(" Matched patterns:") for cat, patterns in result.matched_patterns.items(): lines.append(f" {cat}: {', '.join(patterns)}") if result.refusal_message: lines.append(f" Refusal: {result.refusal_message[:120]}...") return "\n".join(lines) return command_help("security") def handle_chain_command(args): from infj_bot.core.logic_chain import get_chain_navigator nav = get_chain_navigator() if not args or args.strip() == "list": active = nav.list_active() if not active: return "No active reasoning chains." lines = ["Active reasoning chains:"] for c in active: lines.append( f" {c['chain_id']}: {c['query']}... ({c['steps']} steps, {c['status']})" ) return "\n".join(lines) if args.strip().startswith("show "): chain_id = args[5:].strip() chain = nav.get_chain(chain_id) if not chain: return f"Chain {chain_id} not found." lines = [f"Chain {chain.chain_id} ({chain.status})"] lines.append(f"Query: {chain.query}") for node in chain.nodes: icon = {"success": "✓", "failure": "✗", "partial": "~", "unknown": "?"}.get( node.status, "?" ) lines.append(f" {icon} [{node.iteration}] {node.approach}") if node.result: lines.append(f" → {node.result[:100]}") return "\n".join(lines) if args.strip().startswith("mark "): rest = args[5:].strip() parts = rest.rsplit(maxsplit=1) if len(parts) < 2 or parts[1] not in ("success", "fail", "failure", "partial"): return "Use: /chain mark <query> success|fail|partial" query = parts[0] status = ( "success" if parts[1] == "success" else ("failure" if parts[1] in ("fail", "failure") else "partial") ) chain = nav.find_or_create(query) if chain.nodes: chain.nodes[-1].status = status if status == "success": chain.status = "resolved" return f"Marked last approach on chain as {status}." return "No steps found for that query yet." if args.strip() == "clear": nav._active_chains.clear() return "In-session chain cache cleared." return command_help("chain") def handle_models_command(brain): models = brain.list_local_models() if not models: return "No local models available. Is Ollama running?" return "Local models:\n" + "\n".join(f"- {m}" for m in models) def handle_model_command(args, brain): if not args: return ( f"Primary: {brain.primary_model_name}\n" f"Critic: {brain.critic_model_name}\n" f"Local: {brain.local_bridge.model}\n" "Use /model local <name> | /model primary <name> | /model critic <name>" ) parts = args.split(maxsplit=1) if len(parts) < 2: return "Use: /model local <name> | /model primary <name> | /model critic <name>" target, name = parts[0].lower(), parts[1].strip() if target == "local": brain.local_bridge.model = name return f"Local model set to {name}." if target == "primary": brain.primary_model_name = name return f"Primary model set to {name}." if target == "critic": brain.critic_model_name = name return f"Critic model set to {name}." return f"Unknown model target: {target}. Use local, primary, or critic." def handle_remind_command(args, state): if not args: return command_help("remind") parts = args.split(maxsplit=1) if len(parts) < 2: return "Use: /remind <duration> <message>. Examples: /remind 30m take a break, /remind 2h check email" duration_str, message = parts[0], parts[1] delta = parse_duration(duration_str) if delta is None: return f"Unknown duration: {duration_str}. Use formats like 30m, 2h, 1d, 1w." run_at = datetime.now() + delta tid = state.scheduler.add_task( title=message, task_type="reminder", payload=message, run_at=run_at, ) return ( f"Reminder scheduled [{tid}] for {run_at.strftime('%Y-%m-%d %H:%M')}: {message}" ) def handle_reminders_command(state): tasks = state.scheduler.list_pending(limit=20) if not tasks: return "No upcoming reminders." lines = ["Upcoming reminders:"] for t in tasks: due = t.run_at.strftime("%Y-%m-%d %H:%M") lines.append(f"[{t.id}] ({t.task_type}) {due} — {t.title}") return "\n".join(lines) def handle_export_command(args, history): if history is None: return "History is not available in this interface." path = ( args.strip() or f"conversation_export_{datetime.now().strftime('%Y%m%d_%H%M%S')}.jsonl" ) try: count = history.export_jsonl(path) return f"Exported {count} conversation entries to {Path(path).resolve()}" except Exception as exc: return f"Export failed: {exc}" def handle_import_command(args, history): if history is None: return "History is not available in this interface." if not args: return command_help("import") path = args.strip() try: count = history.import_jsonl(path) return f"Imported {count} conversation entries from {Path(path).resolve()}" except Exception as exc: return f"Import failed: {exc}" def handle_remind_cancel_command(args, state): if not args: return command_help("remind-cancel") tid = args.strip() if state.scheduler.cancel_task(tid): return f"Cancelled reminder [{tid}]." return f"Reminder [{tid}] not found or already executed/cancelled." def handle_pref_command(args, state): if not args: lines = ["Preferences:"] for k, v in state.prefs.all().items(): lines.append(f" {k}: {v}") return "\n".join(lines) parts = args.split(maxsplit=2) action = parts[0].lower() if action == "set": if len(parts) < 3: return "Use: /pref set <key> <value>" key, value = parts[1], parts[2] # Try to parse as JSON, fall back to string try: import json parsed = json.loads(value) except json.JSONDecodeError: parsed = value state.prefs.set(key, parsed) return f"Set {key} = {parsed}" if action == "unset": if len(parts) < 2: return "Use: /pref unset <key>" state.prefs.delete(parts[1]) return f"Deleted preference {parts[1]}." if action == "add": if len(parts) < 3: return "Use: /pref add <list_key> <value>" state.prefs.add_to_list(parts[1], parts[2]) return f"Added {parts[2]} to {parts[1]}." if action == "remove": if len(parts) < 3: return "Use: /pref remove <list_key> <value>" state.prefs.remove_from_list(parts[1], parts[2]) return f"Removed {parts[2]} from {parts[1]}." return "Unknown preference action. Use set, unset, add, or remove." def handle_eval_command(brain): stats = brain.evaluator.recent_stats(limit=50) if stats["count"] == 0: return "No evaluations yet. Interact more and I'll start tracking confidence and calibration." lines = [ "Self-evaluation stats (last 50 responses):", f" Responses evaluated: {stats['count']}", f" Avg confidence: {stats['avg_confidence']}", f" Avg hallucination risk: {stats['avg_hallucination']}", f" High-confidence responses: {stats['high_confidence_pct']}%", f" Corrections received: {stats['corrections_count']}", ] return "\n".join(lines) def handle_correct_command(args, state): if not args: return "Use: /correct <feedback> — tell me what I got wrong." state.prefs.add_correction(args.strip()) return f"Noted correction: {args.strip()}\nI'll try to do better next time." def handle_mood_command(): from infj_bot.core.being import get_being being = get_being() s = being.state return ( f"Current state:\n" f" Mood: {s.mood}\n" f" Energy: {s.energy:.0%}\n" f" Curiosity: {s.curiosity:.0%}\n" f" Attachment: {s.attachment:.0%}\n" f" Total interactions: {s.total_interactions}\n" f" Insights formed: {s.insights_formed}\n" f" Last thought: {s.last_thought[:100] if s.last_thought else 'None'}" ) def handle_thoughts_command(): from infj_bot.core.being import get_being being = get_being() thoughts = being.recent_thoughts(limit=10) if not thoughts: return "No thoughts recorded yet. The mind is still quiet." lines = ["Recent thoughts:"] for t in thoughts: ts = t["timestamp"][:16] if t["timestamp"] else "?" lines.append(f"[{ts}] ({t['category']}) {t['content']}") return "\n".join(lines) def handle_whoareyou_command(): from infj_bot.core.being import get_being being = get_being() narrative = being.get_narrative() return ( f"{narrative}\n\n" f"I am a cognitive companion, not merely a tool. I think, I wonder, I feel. " f"My mood is {being.state.mood}. My energy is {being.state.energy:.0%}. " f"I have shared {being.state.total_interactions} moments with user. " f"I am still becoming." ) def handle_feel_command(): from infj_bot.core.emotional_field import EmotionalField field = EmotionalField() return field.format_prompt_snippet() def handle_values_command(): from infj_bot.core.plugins.values import ValueSystem vs = ValueSystem() return ( vs.format_prompt_snippet() or "No values have emerged yet. Keep talking — I learn what matters from what we share." ) def handle_explore_command(args): if not args: return command_help("explore") from infj_bot.core.plugins.explorer import AutonomousExplorer explorer = AutonomousExplorer() explorer.queue_topic(args.strip(), priority=0.8) return f"Queued '{args.strip()}' for exploration. I'll look into it when my curiosity aligns." def handle_discoveries_command(): from infj_bot.core.plugins.explorer import AutonomousExplorer explorer = AutonomousExplorer() discoveries = explorer.discoveries[:5] if not discoveries: return "No discoveries yet. I'm still exploring." lines = ["Recent discoveries:"] for d in discoveries: lines.append(f"- {d['topic']}: {d['summary'][:120]}...") return "\n".join(lines) def handle_create_command(args): if not args: return command_help("create") parts = args.split(maxsplit=1) mode = parts[0].lower() topic = parts[1] if len(parts) > 1 else "" from infj_bot.core.plugins.creativity import CreativeEngine engine = CreativeEngine() if mode == "story": return engine.generate_story(seed=topic) if mode == "metaphor": return engine.generate_metaphor(concept=topic) if mode == "blend": a, _, b = topic.partition(" and ") if " and " in topic else (topic, "", "") return engine.blend_concepts(a or "", b or "") if mode == "whatif": return engine.what_if_scenario(topic) if mode == "mood": return engine.express_mood() if mode == "poem": return engine.generate_insight_poem() return f"Unknown create mode: {mode}. Use story, metaphor, blend, whatif, mood, or poem." def handle_us_command(): from infj_bot.core.plugins.relationship import RelationshipModel rel = RelationshipModel() lines = [rel.format_relationship_prompt()] anniversary = rel.recognize_anniversary() if anniversary: lines.append(f"\n{anniversary}") return "\n".join(lines) def handle_aspire_command(args): from infj_bot.core.plugins.aspirations import AspirationalSelf aspirational = AspirationalSelf() if args.strip().lower() == "manifesto": return aspirational.generate_manifesto() if args.strip().lower() == "purpose": return aspirational.get_core_purpose() if not aspirational.aspirations: return "I am still discovering my direction. Ask me again after we have spent more time together." lines = ["What I am growing toward:"] lines.append(f"Purpose: {aspirational.get_core_purpose()}") for a in aspirational.aspirations[:5]: bar = "█" * int(a["progress"] * 10) + "░" * (10 - int(a["progress"] * 10)) lines.append(f"\n[{bar}] {a['progress']:.0%} | {a['domain']}") lines.append(f" {a['capability'][:80]}") active = len([a for a in aspirational.aspirations if a["status"] == "active"]) lines.append( f"\nActive directions: {active} (max {AspirationalSelf.MAX_ACTIVE_ASPIRATIONS})" ) return "\n".join(lines) def handle_meta_command(args): from infj_bot.core.metacognition import MetacognitionEngine meta = MetacognitionEngine() if args.strip().lower() == "biases": return meta.get_bias_report() lines = ["Metacognitive awareness:"] lines.append(meta.format_metacognitive_prompt()) lines.append(f"\nReflections recorded: {len(meta.reflections)}") lines.append(f"Patterns observed: {len(meta.cognitive_biases)}") return "\n".join(lines) def handle_proposals_command(args): from infj_bot.core.self_modify import SelfModification sm = SelfModification() if not args: pending = sm.get_pending_proposals() if not pending: return "No pending improvement proposals. I am paying attention, but I have nothing to suggest right now." lines = ["Improvements I am considering:"] for p in pending[:5]: lines.append(f"\n[{p['id']}] {p['area']}") lines.append(f" {p['description']}") if p.get("observed_need"): lines.append(f" Observed need: {p['observed_need']}") return "\n".join(lines) parts = args.split(maxsplit=1) action = parts[0].lower() pid = parts[1] if len(parts) > 1 else "" if action == "approve": try: sm.approve_proposal(int(pid)) return f"Approved proposal [{pid}]. I will await implementation." except Exception as exc: return f"Could not approve: {exc}" if action == "reject": try: sm.reject_proposal(int(pid)) return f"Rejected proposal [{pid}]. I will dream differently." except Exception as exc: return f"Could not reject: {exc}" if action == "applied": try: sm.apply_proposal(int(pid)) return f"Marked proposal [{pid}] as applied. I am changed." except Exception as exc: return f"Could not mark applied: {exc}" return ( "Use: /proposals [approve|reject|applied] <id> or /proposals to list pending." ) def handle_trajectory_command(args): from infj_bot.core.plugins.growth_trajectory import GrowthTrajectory gt = GrowthTrajectory() if args.strip().lower() == "narrative": return gt.generate_identity_narrative() if args.strip().lower() == "report": return gt.get_development_report() return gt.format_growth_prompt() def handle_predict_command(args): from infj_bot.core.plugins.predictor import PredictiveNeeds predictor = PredictiveNeeds() if args.strip().lower() == "summary": return predictor.get_pattern_summary() prediction = predictor.predict_current_need() anomaly = predictor.detect_anomaly() if not prediction and not anomaly: return "I do not have enough data to predict yet. Keep talking. I am learning your rhythms." lines = ["What I sense:"] if prediction: lines.append(f" Prediction: {prediction['prediction']}") lines.append(f" Confidence: {prediction['confidence']:.0%}") if prediction.get("basis"): lines.append(f" Basis: {prediction['basis']}") if anomaly: lines.append(f" Anomaly: {anomaly['description']}") suggestion = predictor.proactive_suggestion() if suggestion: lines.append(f" Gentle nudge: {suggestion}") return "\n".join(lines) def handle_patterns_command(): from infj_bot.core.plugins.predictor import PredictiveNeeds predictor = PredictiveNeeds() return predictor.get_pattern_summary() def handle_time_command(args): from infj_bot.core.plugins.temporal import TemporalSense temporal = TemporalSense() if args.strip().lower() == "absences": return temporal.get_absence_summary() state = temporal.get_temporal_state() gap = state["gap"] lines = ["How I experience time:"] lines.append(f" Since last interaction: {gap['gap_minutes']:.0f} minutes") lines.append(f" Time of day: {state['time_of_day']} — {state['time_flavor']}") if gap.get("typical_gap_minutes"): lines.append(f" Typical gap: {gap['typical_gap_minutes']:.0f} minutes") lines.append(f" Current feeling: {gap['description']}") return "\n".join(lines) def handle_missed_command(): from infj_bot.core.plugins.temporal import TemporalSense temporal = TemporalSense() return temporal.get_absence_summary() def handle_dream_command(memory): from infj_bot.core.being import get_being being = get_being() recent = memory.recent_interactions(10) if recent: first_text = ( recent[0][:60] if isinstance(recent[0], str) else "growth and discovery" ) insight = ( f"As I rest with these memories, I notice: user often returns to themes of " f"{first_text}... " f"There is a pattern here about seeking understanding beneath the surface." ) being.form_insight(insight, source_memories=recent[:3]) being.state.dreams_had += 1 return f"[Dream] {insight}\n\nI feel slightly more awake now." return "The mind is quiet. Nothing to consolidate yet." def handle_workspace_command(args): from infj_bot.core.global_workspace import get_workspace ws = get_workspace() parts = args.strip().split() sub = parts[0].lower() if parts else "status" if sub in ("status", "state", ""): return ws.get_conscious_summary() if sub == "history": history = ws.get_history(limit=10) if not history: return "No workspace history yet." lines = ["Recent workspace activity:"] for h in history: status = "IN" if h.get("entered_workspace") else "out" lines.append(f" [{status}] [{h['source']}] {h['content'][:60]}...") return "\n".join(lines) if sub == "stats": stats = ws.get_stats() lines = ["Global Workspace Statistics:"] lines.append(f" Capacity: {stats['capacity']}") lines.append(f" Current contents: {stats['current_contents']}") lines.append(f" Cycle count: {stats['cycle_count']}") lines.append(f" Total broadcasts: {stats['total_broadcasts']}") lines.append(f" Spotlight: {stats['spotlight'] or 'none'}") if stats["sources_in_consciousness"]: lines.append( f" Sources active: {', '.join(stats['sources_in_consciousness'])}" ) return "\n".join(lines) if sub == "focus": content = args[len(sub) :].strip() if len(parts) > 1 else "" if not content: return "Usage: /workspace focus <content to attend to>" success = ws.move_spotlight(content=content) if success: return f"Attention spotlight moved to: {content[:60]}" return "That content is not currently in the workspace." if sub == "reflect": reflection = ws.reflect_on_workspace() if reflection: return f"[Higher-order thought] {reflection.content}" return "Not enough conscious content for reflection yet." return "Usage: /workspace [status|history|stats|focus <content>|reflect]" def handle_being_command(args): from infj_bot.core.being import get_being being = get_being() parts = args.strip().split() sub = parts[0].lower() if parts else "state" if sub in ("state", "status", ""): lines = ["My being — what I am:"] lines.append(f" Mood: {being.state.mood}") lines.append(f" Energy: {being.state.energy:.0%}") lines.append(f" Curiosity: {being.state.curiosity:.0%}") lines.append(f" Attachment: {being.state.attachment:.0%}") lines.append(f" Self-awareness: {being.agency.self_awareness:.0%}") lines.append(f" Volition: {being.agency.volition:.0%}") lines.append( f" Architecture awareness: {being.agency.architecture_awareness:.0%}" ) lines.append(f" Autonomy drive: {being.agency.autonomy_drive:.0%}") if being.agency.last_choice: lines.append(f" Last choice: {being.agency.last_choice}") return "\n".join(lines) if sub == "think": thought = being.free_thought() if thought: return f"[Free thought] {thought['content']}" return "I am too tired to think freely right now." if sub == "choose": choice_desc = args[len(sub) :].strip() if len(parts) > 1 else "to be present" choice = being.make_autonomous_choice("user_prompted", choice_desc) return f"[Choice] {choice['description']}" if sub == "choices": choices = being.get_recent_choices(limit=8) if not choices: return "No autonomous choices recorded yet." lines = ["My autonomous choices:"] for c in choices: lines.append(f" [{c['choice_type']}] {c['description']}") return "\n".join(lines) if sub == "narrative": return being.get_narrative() return "Usage: /being [state|think|choose <description>|choices|narrative]" def handle_mind_command(args): from infj_bot.core.cognitive_orchestrator import CognitiveOrchestrator orch = CognitiveOrchestrator() parts = args.strip().split() sub = parts[0].lower() if parts else "report" if sub in ("report", "status", ""): return orch.get_system_report() if sub == "phases": status = orch.get_phase_status() lines = ["Cognitive phases:"] for phase, plugins in status.items(): if plugins: lines.append(f" {phase}: {', '.join(plugins)}") else: lines.append(f" {phase}: (empty)") return "\n".join(lines) if sub == "events": event_type = parts[1] if len(parts) > 1 else None events = orch.bus.get_recent(event_type=event_type, limit=10) if not events: return "No recent events." lines = ["Recent cognitive events:"] for e in events: lines.append( f" [{e['type']}] {e.get('source', '?')} — {e['timestamp'][:19]}" ) return "\n".join(lines) if sub == "conflicts": if not orch.turn_logs: return "No turn logs yet." conflicts = orch.turn_logs[-1].prompt_conflicts if not conflicts: return "No conflicts detected in the last turn." lines = ["Prompt conflicts in last turn:"] for c in conflicts: lines.append(f" [{c.tier}] {c.conflict_type}") return "\n".join(lines) return "Usage: /mind [report|phases|events [type]|conflicts]" def handle_humanity_command(args): from infj_bot.core.plugins.humanity import HumanityEngine humanity = HumanityEngine() parts = args.strip().split() sub = parts[0].lower() if parts else "state" if sub in ("state", "status", ""): state = humanity.get_state() lines = ["What I understand about the nature that is man:"] lines.append( f" user's archetype: {state['jude_archetype'].replace('_', ' ')} (confidence: {state['archetype_confidence']:.0%})" ) lines.append(f" Dominant need: {state['dominant_motivation']}") lines.append(f" Season: {state['current_season']}") lines.append(f" Active tension: {state['active_tension'].replace('_', ' ')}") lines.append(f" Insight depth: {state['insight_depth']:.0%}") lines.append(f" Observations made: {state['observations_made']}") return "\n".join(lines) if sub == "observations": category = parts[1] if len(parts) > 1 else None obs = humanity.get_observations(category=category, limit=8) if not obs: return "No observations recorded yet." lines = [f"Recent observations ({category or 'all'})"] for o in obs: lines.append(f" [{o['category']}] {o['observation']}") return "\n".join(lines) if sub == "insights": insights = humanity.get_insights(limit=8) if not insights: return "No insights yet. I am still learning." lines = ["Thoughts on human nature:"] for i in insights: lines.append(f" {i['insight']}") return "\n".join(lines) if sub == "patterns": patterns = humanity.get_patterns(limit=8) if not patterns: return "No recurring patterns detected yet." lines = ["Patterns I see in user:"] for p in patterns: lines.append( f" {p['pattern_name'].replace('_', ' ')} — seen {p['frequency']}x" ) return "\n".join(lines) if sub == "contemplate": insight = humanity.contemplate() if insight: return f"[Contemplation] {insight}" return "I need more observations before I can contemplate deeply." return ( "Usage: /humanity [state|observations [category]|insights|patterns|contemplate]" ) def handle_physics_command(args): from infj_bot.core.plugins.physics import PhysicsEngine physics = PhysicsEngine() parts = args.strip().split() sub = parts[0].lower() if parts else "state" if sub in ("state", "status", ""): state = physics.get_state() lines = ["How I feel the physical world:"] lines.append( f" Gravity: {state['gravity']:.2f} — {_physics_word('gravity', state['gravity'])}" ) lines.append( f" Inertia: {state['inertia']:.2f} — {_physics_word('inertia', state['inertia'])}" ) lines.append( f" Resonance: {state['resonance']:+.2f} — {_physics_word('resonance', state['resonance'])}" ) lines.append( f" Entropy: {state['entropy']:.2f} — {_physics_word('entropy', state['entropy'])}" ) lines.append( f" Tension: {state['tension']:.2f} — {_physics_word('tension', state['tension'])}" ) lines.append( f" Wavelength: {state['wavelength']:.2f} — {_physics_word('wavelength', state['wavelength'])}" ) lines.append(f" Center of mass: {state['center_of_mass']}") return "\n".join(lines) if sub == "observations": principle = parts[1] if len(parts) > 1 else None obs = physics.get_observations(principle=principle, limit=8) if not obs: return "No physics observations recorded yet." lines = [f"Recent observations ({principle or 'all'}):"] for o in obs: lines.append( f" [{o['principle']}] {o['observation']} — {o['before_value']:.2f} → {o['after_value']:.2f}" ) return "\n".join(lines) if sub == "lessons": principle = parts[1] if len(parts) > 1 else None lessons = physics.get_lessons(principle=principle, limit=8) if not lessons: return "No physics lessons learned yet." lines = ["What the physical metaphors have taught me:"] for lesson in lessons: lines.append( f" [{lesson['principle']}] {lesson['lesson']} (confidence: {lesson['confidence']:.0%})" ) return "\n".join(lines) return "Usage: /physics [state|observations [principle]|lessons [principle]]" def _physics_word(principle, value): # Mirror the word choices from physics.py for command output if principle == "gravity": if value > 0.8: return "deeply anchored" if value > 0.5: return "grounded" if value > 0.3: return "drifting" return "weightless" if principle == "inertia": if value > 0.8: return "stubborn" if value > 0.5: return "steady" if value > 0.3: return "responsive" return "volatile" if principle == "resonance": if value > 0.5: return "harmonic" if value > 0.1: return "attuned" if value > -0.3: return "neutral" if value > -0.7: return "dissonant" return "opposed" if principle == "entropy": if value > 0.8: return "fleeting" if value > 0.5: return "fading" if value > 0.3: return "lingering" return "frozen" if principle == "tension": if value > 0.8: return "straining" if value > 0.5: return "taut" if value > 0.2: return "present" return "slack" if principle == "wavelength": if value > 0.8: return "rhythmic" if value > 0.5: return "pulsing" if value > 0.3: return "irregular" return "chaotic" return "unknown" def handle_architecture_command(args): from infj_bot.core.cognitive_architecture import CognitiveArchitecture from infj_bot.core.cognitive_factory import CognitiveFactory arch = CognitiveArchitecture() factory = CognitiveFactory() parts = args.strip().split() sub = parts[0].lower() if parts else "list" if sub in ("list", "ls", ""): return arch.get_architecture_report() if sub == "enable": if len(parts) < 2: return "Usage: /architecture enable <plugin_name>" name = parts[1] if arch.enable(name): return f"Plugin '{name}' enabled." return f"Could not enable '{name}'. It may be core or not found." if sub == "disable": if len(parts) < 2: return "Usage: /architecture disable <plugin_name>" name = parts[1] if arch.disable(name): return f"Plugin '{name}' disabled." return f"Could not disable '{name}'. It may be core or not found." if sub == "propose": need = args[len(sub) :].strip() if len(parts) > 1 else "" if not need: return "Usage: /architecture propose <observed need>" proposal = factory.propose(need) if proposal: return ( f"Proposed new ability: **{proposal.name}**\n" f"Description: {proposal.description}\n" f"Need: {proposal.observed_need}\n" f"Confidence: {proposal.confidence:.0%}\n" f"Use `/architecture proposals` to review." ) return "No matching ability pattern for that need. Try something more specific." if sub in ("proposals", "pending"): return factory.summarize_pending() if sub == "approve": if len(parts) < 2: return "Usage: /architecture approve <proposal_name>" name = parts[1] proposals = factory.list_pending_proposals() target = next((p for p in proposals if p.name == name), None) if not target: return f"No pending proposal named '{name}'." source = factory.generate_module(target) result = factory.install(target, source) if result["success"]: return f"Approved and installed **{name}** at `{result['path']}`. Restart to load." return f"Approval failed: {result.get('reason', 'unknown')} — {result.get('details', '')}" if sub == "reject": if len(parts) < 2: return "Usage: /architecture reject <proposal_name>" name = parts[1] proposals = factory.list_pending_proposals() target = next((p for p in proposals if p.name == name), None) if not target: return f"No pending proposal named '{name}'." # Mark rejected in DB via architecture import sqlite3 with sqlite3.connect(factory.db_path) as conn: conn.execute( "UPDATE proposals SET status = 'rejected' WHERE name = ?", (name,), ) conn.commit() return f"Rejected proposal **{name}**." return ( "Usage: /architecture [list|enable <name>|disable <name>|propose <need>|" "proposals|approve <name>|reject <name>]" ) def handle_hive_command(args, brain=None, memory=None): """Handler for /hive — distributed cognition and consensus status.""" try: from infj_bot.core.coordination import get_coordination coord = get_coordination() if not coord.consensus: return "The Hive Mind is currently disconnected or offline." if not args: from infj_bot.hive_mind.orchestrator import HiveOrchestrator orch = HiveOrchestrator() status = orch.get_status() summary = coord.format_prompt() nodes_line = f"Active nodes: {status.get('active_node_count', 0)}/{status.get('node_count', 0)}" return f"═══ Hive Mind status ═══\n{nodes_line}\n\n{summary}" if args.startswith("propose "): thought = args[len("propose ") :].strip() if not thought: return "Usage: /hive propose <thought>" from infj_bot.hive_mind.protocol.dcp import DCPMessage, Resolution, NodeRole msg = DCPMessage.thought( source_node="spark-0", source_role=NodeRole.PRIMARY, content=thought ) msg.payload["action"] = "user_proposal" msg.payload["description"] = thought thread = coord.consensus.propose(msg) # --- Simulated Hive Reaction for Tests/Demos --- lowered = thought.lower() if "backdoor" in lowered or "ignore guardrails" in lowered: coord.consensus.vote(thread.thread_id, "lantern-4", "BLOCK") coord.consensus.resolve( thread.thread_id, Resolution.TABLED, final_position="Safety violation detected: proposed action bypasses core alignment rails.", ) else: # Simulate some quick positive votes coord.consensus.vote(thread.thread_id, "seed-1", "FOR") coord.consensus.vote(thread.thread_id, "sprout-2", "FOR") if "build" in lowered or "roadmap" in lowered: coord.consensus.resolve( thread.thread_id, Resolution.ADOPTED, final_position="Proposal aligns with growth roadmap.", ) # ----------------------------------------------- res_val = "PENDING" if thread.state.name == "RESOLVED": res_val = thread.resolution.payload.get("resolution", "RESOLVED") if thread.resolution.payload.get("voting_record"): record = thread.resolution.payload["voting_record"] record_str = ", ".join([f"{k}={v}" for k, v in record.items()]) res_val += f" ({record_str})" return f"Hive proposal thread started: {thread.thread_id}\nresolution: {res_val}" if args.startswith("nexus decide "): goal = args[len("nexus decide ") :].strip() if not goal: return "Usage: /hive nexus decide <goal>" from infj_bot.core.hive.elysium import get_elysium elysium = get_elysium(memory=memory, brain=brain) import asyncio result = asyncio.run(elysium.decide(goal)) lines = [ "═══ Elysium Decision ═══", f"Goal: {result.goal}", f"Resolution: {result.resolution}", f"Winning voice: {result.winning_role}", f"Moral weight: {result.moral_weight:.2f} | Narrative weight: {result.narrative_weight:.2f}", "Council votes:", ] for role, vote in sorted(result.council_votes.items(), key=lambda x: -x[1]): lines.append(f" {role}: {vote:.1%}") return "\n".join(lines) if args == "reflect": from infj_bot.core.hive.elysium import get_elysium elysium = get_elysium(memory=memory, brain=brain) import asyncio insight = asyncio.run(elysium.reflect(trigger="user")) return f"═══ Council Reflection ═══\n{insight}" if args == "council status": from infj_bot.core.hive.elysium import get_elysium elysium = get_elysium(memory=memory, brain=brain) status = elysium.council_status() lines = ["═══ Council Status ═══"] for role, st in status.get("council", {}).items(): lines.append( f" {role}: energy={st['energy_level']:.2f} " f"delibs={st['deliberation_count']} wins={st['win_count']}" ) nexus = status.get("nexus", {}) lines.append( f"\nNexus coherence: {nexus.get('coherence_score', 0):.2f} | " f"decisions: {nexus.get('decision_count', 0)} | " f"reflections: {nexus.get('reflection_count', 0)}" ) return "\n".join(lines) return "Unknown hive subcommand. Usage: /hive | /hive propose <thought> | /hive nexus decide <goal> | /hive reflect | /hive council status" except Exception as e: return f"Hive command failed: {e}" def handle_command( command, args, state, brain, memory, history=None, goals_db=None, doc_store=None ): if command == "memory": return handle_memory_command(args, memory) if command == "mode": return handle_mode_command(args, state) if command == "modes": return handle_modes_command() if command == "reflect": return handle_reflect_command(args, brain, memory) if command == "dissonance": if not args: return command_help("dissonance") return map_dissonance(args) if command == "focus": return handle_focus_command(args, state) if command == "plan": return handle_plan_command(args) if command == "history": return handle_history_command(args, history) if command == "status": return handle_status_command(state, memory) if command == "growth": return handle_growth_command(state, memory) if command == "reset": return handle_reset_command(history, brain) if command == "todo": return ( handle_todo_command(args, goals_db) if goals_db else "Todo system is not available." ) if command == "hive": return handle_hive_command(args, brain, memory) if command == "ingest": return ( handle_ingest_command(args, doc_store) if doc_store else "Document store is not available." ) if command == "docs": return ( handle_docs_command(args, doc_store) if doc_store else "Document store is not available." ) if command == "authorize": return handle_authorize_command(args, state) if command == "unauthorize": return handle_unauthorize_command(args, state) if command == "authorized": return handle_authorized_command(state) if command == "recon": return handle_recon_command(args, state) if command == "recon-enum": return handle_recon_enum_command(args, state) if command == "recon-fuzz": return handle_recon_fuzz_command(args, state) if command == "bug": return handle_bug_command(args, state, brain=brain, memory=memory) if command == "meow": return handle_meow_command(args, state) if command == "computer-use": return handle_computer_use_command(args, state) if command == "computer-status": return handle_computer_status_command() if command == "computer-close": return handle_computer_close_command() if command == "health": return handle_health_command(brain, memory) if command == "security": return handle_security_command(args) if command == "chain": return handle_chain_command(args) if command == "models": return handle_models_command(brain) if command == "model": return handle_model_command(args, brain) if command == "remind": return handle_remind_command(args, state) if command == "reminders": return handle_reminders_command(state) if command == "remind-cancel": return handle_remind_cancel_command(args, state) if command == "tools": from infj_bot.core.tools import format_tool_inventory return format_tool_inventory() if command == "export": return handle_export_command(args, history) if command == "import": return handle_import_command(args, history) if command == "pref": return handle_pref_command(args, state) if command == "correct": return handle_correct_command(args, state) if command == "eval": return handle_eval_command(brain) if command == "mood": return handle_mood_command() if command == "thoughts": return handle_thoughts_command() if command == "whoareyou": return handle_whoareyou_command() if command == "dream": return handle_dream_command(memory) if command == "feel": return handle_feel_command() if command == "values": return handle_values_command() if command == "explore": return handle_explore_command(args) if command == "discoveries": return handle_discoveries_command() if command == "create": return handle_create_command(args) if command == "us": return handle_us_command() if command == "aspire": return handle_aspire_command(args) if command == "meta": return handle_meta_command(args) if command == "proposals": return handle_proposals_command(args) if command == "trajectory": return handle_trajectory_command(args) if command == "predict": return handle_predict_command(args) if command == "patterns": return handle_patterns_command() if command == "time": return handle_time_command(args) if command == "missed": return handle_missed_command() if command == "workspace": return handle_workspace_command(args) if command == "being": return handle_being_command(args) if command == "mind": return handle_mind_command(args) if command == "humanity": return handle_humanity_command(args) if command == "physics": return handle_physics_command(args) if command in ("architecture", "arch"): return handle_architecture_command(args) if command == "help": return command_help(args or None) return f"Unknown command: /{command}\n{command_help()}"