| 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 <query>\n/memory learn <name>: <description>\n/memory forget <name>\n" |
| "/memory count\n/memory export [path]\n/memory import <path>\n/memory compact [days]\n" |
| "/memory edit <name>: <new description>" |
| ) |
| 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 <situation> maps conflicting pulls, likely values, and one small next step." |
| if command == "focus": |
| return ( |
| "/focus <goal or mess> turns a fuzzy situation into a grounded next action." |
| ) |
| if command == "plan": |
| return "/plan <goal> 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 <title> | /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." |
| |
| 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 = {} |
| |
| 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 |
| 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: |
| |
| 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: |
| |
| 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: |
| |
| 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: |
| 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): |
| |
| 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}'." |
| |
| 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) |
|
|
| |
| 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: |
| |
| 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()}" |
|
|