Even with info/ok/warn fixed to stderr, raw command output
from git clone and cargo build was still leaking to stdout
through 2>&1 | tail -5.
Fix: added >&2 after tail -5 so ALL intermediate command output
goes to stderr, leaving only the final echo on stdout.
Same fix as gyandoot-release: ensure_gyandoot_binary() detects
whether we're in source repo, binary repo, or need to clone.
install_binary() now takes a path parameter.
The old banner was a handwritten ASCII art that didn't actually
spell 'GYANDOOT'. Replaced with proper figlet 'standard' font
output so the banner is readable and correct.
install_binary() now:
1. Automatically picks best location per platform:
- macOS: ~/.cargo/bin/ (no sudo, in PATH for Rust users)
- Linux: ~/.cargo/bin/ → /usr/local/bin → ~/.local/bin/
- Windows: /usr/local/bin (Git Bash/MSYS2)
2. Detects if old binary exists at a different PATH location
and warns the user: 'There is ANOTHER gyandoot at ...'
3. Verifies 'command -v gyandoot' resolves correctly after install
4. Shows shell profile instructions if PATH needs updating
Previous issue: always installed to /usr/local/bin with sudo,
overwriting the old binary from install.sh but not warning if
another copy existed elsewhere in PATH.
Root cause: camoufox-browser@0.1.0's CLI wrapper spawns the daemon
with stdio: 'ignore' and only waits 5 seconds. If the daemon crashes
(silent better-sqlite3 native binding error, etc.), the error is
swallowed and we see 'Failed to connect: No such file or directory'.
Fix:
1. find_daemon_js() — locates daemon.js in global node_modules via
'npm root -g' with fallbacks for common nvm/homebrew paths
2. trigger_daemon_start() — spawns daemon.js directly with 'node',
captures stderr to ~/.gyandoot/camoufox-daemon-stderr.log
3. Uses spawn() + std::mem::forget (background daemon) instead of
.output() (which would wait forever since daemon never exits)
4. kill_on_drop(false) — prevents killing daemon when child drops
5. Poll loop in wait_for_socket() still works as before (30s timeout)
Root cause: camoufox-js@0.11.0 fetch can exit 0 but silently fail
to download the browser binary when:
1. A partial/incomplete cache from a previous run exists
2. GitHub API rate-limits the unauthenticated release query
3. Network drops mid-download
Fix:
1. run_fetch() now DELETE incomplete cache (dir exists but no
version.json) before fetching — prevents 'already cached' no-op
2. After fetch, VERIFY version.json exists — if missing, RETRY once
3. After retry, verify Camoufox.app/Contents/MacOS/camoufox exists
4. Log stdout and stderr in INFO traces for debugging
Root cause: On Apple Silicon macOS, the Camoufox browser binary
inherits com.apple.quarantine from npm download. When camoufox-browser
launches it headlessly, Gatekeeper silently kills the process with
SIGKILL (exitCode=null, signal=SIGKILL) before it can run.
Fix:
1. remove_macos_quarantine() — runs 'xattr -dr com.apple.quarantine'
on the Camoufox cache directory after every fetch and on every
subsequent startup (in case cache was from a prior npx run)
2. check_known_errors() — detects 'sigkill' in daemon stderr and
shows the exact fix command to the user
3. Runs quarantine removal in TWO places:
- Immediately after camoufox-js fetch downloads the binary
- Always, even when binary already exists in cache
Root cause: 'npx camoufox-js@0.11.0 fetch' on a fresh install prompts
'Ok to proceed? (y/N)' and pipes it through 'tail -5', hiding it. User
sees nothing happening while script waits for input.
Fix:
1. npx --yes — auto-confirms the install prompt, no more silent hang
2. Removed | tail -5 — full output visible so user sees progress bar
3. macOS cache path (~/Library/Caches/) vs Linux (~/.cache/) in verify step
4. Also checks version.json as fallback (binary can be named differently)
Root cause on macOS: camoufox-browser@0.1.0 downloads an alpha binary
(v150.0.2-alpha.26) from daijro/camoufox that has a broken macOS build
(missing libmozglue.dylib). Binary crashes with SIGABRT/SIGKILL.
Changes:
1. gyandoot-browser client now supports TWO transports:
- Transport::UnixSocket (existing — daemon IPC)
- Transport::Http (new — Docker REST API on port 9377)
2. init_browser() tries Docker HTTP first, falls back to npx daemon
3. HTTP transport maps browser actions to Docker REST endpoints
(/navigate, /tabs, /health, etc.) with correct userId params
4. check_known_errors() detects libmozglue.dylib + SIGKILL patterns
5. Browser cache check works for both macOS and Linux paths
6. Error messages correctly say 'Use Docker' on corrupted binary
7. Added reqwest dep to gyandoot-agent for Docker health check
Clean build: 0 errors
Root cause on macOS: 'camoufox-browser install' downloaded v150.0.2-alpha.26
instead of the stable browser binary. This alpha version is missing
libmozglue.dylib, causing dyld to crash immediately.
Changes:
1. detect_os() — returns Mac/Linux/Wsl/Windows enum for platform-aware logic
2. check_known_errors() — parses daemon stderr for known failures (missing
libmozglue.dylib on macOS, missing libgtk/libnss on Linux, code-signing)
3. platform_fix_instructions() — returns OS-specific recovery steps:
- macOS: rm -rf ~/Library/Caches/camoufox, reinstall, or Docker fallback
- WSL/Linux: correct apt-get install commands (with t64 package variants)
4. Browser cache detection now checks Camoufox.app on macOS, camoufox on Linux
5. All error messages use detect_os() — no more Linux apt-get on macOS
6. Corrupted download detected automatically, user told to clear cache + retry
Clean build: 0 errors, 0 warnings
The Camoufox browser (Playwright-based) needs ~30 Linux system libraries
to run. On fresh WSL/Ubuntu, these are not pre-installed, causing the
browser daemon to crash silently with only a cryptic 'No such file or
directory' error.
Changes:
1. Add detect_wsl() — reads /proc/version for 'microsoft'/'wsl'
2. Add install_linux_deps() — installs all 30+ Playwright deps via
apt-get/dnf/yum before installing camoufox-browser
3. Handles t64 package name variants (libasound2t64 vs libasound2)
4. Shows WSL-specific note at end of install
5. npm install -g camoufox-browser + install now run with better output
6. Verifies browser binary exists at ~/.cache/camoufox/ post-install
7. Install now fully automatic on fresh WSL — no manual apt-get needed
- Add is_wsl() detection via /proc/version
- Add example_npx_path() returning platform-appropriate example path
- Replace all hardcoded macOS paths in error messages with dynamic ones
- Add WSL-specific hints: Node.js must be installed inside WSL, not Windows
- WSL hint includes nvm install instructions
- Clean build: 0 errors, 0 warnings
trigger_daemon_start now captures stdout/stderr and exit code instead
of silently redirecting to a log file. On failure it prints the actual
error, making it obvious what went wrong (npm install issue, node
version mismatch, etc.).
The setup wizard now auto-detects the npx/npx.cmd path via
`which npx` (Unix) or `where npx.cmd` (Windows) and writes it
to [browser].node_path in config.toml.
Changes:
- detect_npx_path(): cross-platform detection using which/where
- SerializedConfig now includes optional [browser] section
- Flat config parser (main.rs) handles [browser] section
- browser: BrowserSection threaded through AgentConfig everywhere
- init_browser() accepts node_path parameter with proper fallback
Adds [browser].node_path config option so camoufox-browser can use
an explicit npx path (essential for nvm/fnm/asdf users).
Resolution order (cross-platform):
1. config.browser.node_path — explicit user override
2. 'npx.cmd' on Windows, 'npx' on Linux/macOS — PATH lookup
Changes:
- BrowserSection config: added node_path: Option<String>
- AgentConfig: now carries browser section (was dropped in From<GyandootConfig>)
- browser_manager::init_browser(node_path): accepts optional path
- All call sites updated (run(), init_session(), subagents, tests)
- Error messages now hint at browser.node_path config
Two fixes for the TUI:
1. **Raw LLM responses** — was stateless, creating
fresh messages every turn. Added +
methods that accumulate conversation history, inject identity, load
past memory, run browser init, and compress context — identical to
the interactive loop but designed for external callers.
2. **Banner flash** — removed call that fired to stdout
*before* TUI entered alternate screen. TUI already shows the robot
head via as initial chat content.
Also added getter and field to AgentLoop.
Two bugs fixed:
1. Banner not shown: TUI default output was a plain welcome text
instead of the actual GyanDoot banner. Fixed by using
banner::banner_plain() as initial TUI output content.
2. No agent responses: TUI was a standalone shell with no connection
to the agent loop. Now uses mpsc channels:
- user_tx: TUI → agent (user sends messages)
- event_rx: agent → TUI (agent sends responses + telemetry)
- TuiEvent::Response / Status / Telemetry enum for structured
communication
- tokio::spawn runs agent in background processing messages
- poll_events() in render loop drains channel every frame tick
Also updated cmd_tui() in main to create channels + spawn agent.
Complete visual redesign of the TUI with a cyberpunk/holographic aesthetic:
Layout:
- Top header: GyanDoot logo (neon robot head) + 6 telemetry cards (3x2 grid)
- Middle: Chat interface area with message count
- Bottom: Mode-aware status bar (NORMAL/INPUT/CMD)
Telemetry Cards (live real-time dashboard):
1. PROVIDER — LLM provider name (neon cyan)
2. MODEL — Model name (neon green)
3. CLOCK — Live HH:MM:SS (neon amber)
4. TOKENS — Total/Max token count (neon magenta)
5. USAGE — Gauge bar with % (green→amber→red gradient)
6. MESSAGES — Total message count
Color Palette (holographic):
- BG: Deep violet-black (#0A0214)
- Cards: Neon cyan/magenta/green/amber/red
- Borders: Dim purple, rounded box-drawing
- Status bar: Glowing border per mode (cyan/green/amber)
Controls: / or : → command mode, i → input, q → quit
1. /quit and /help commands restored:
- /quit: exits the interactive loop
- /help: shows formatted help box with available commands & tips
- Unknown commands get a friendly error pointing to /help
- Slash commands intercepted before LLM processing (no token waste)
2. Zero warnings across entire workspace (13 files fixed):
- Fixed ambiguous glob re-exports in gyandoot-core
- Added #[allow(dead_code)] on intentional dead fields
- Fixed unused imports, variables, and macros
- Fixed unused assignments in subagents
- cleaned up service.rs, profile, kanban warnings
install.sh now produces a completely clean build with zero warnings.
Fixes the cramped terminal output. Two changes:
1. display_output: trailing \n after G> text for spacing
2. read_input: leading \n before » prompt + 30ms delay after spinner clear
to prevent \r overlap with prompt character
Before: G> response...» Hi (no gap, overlapping)
After: G> response...
(blank line)
» Hi (clean, separated)
Three UX improvements for interactive mode:
1. Input prompt: Shows '»' (bold cyan) on stdin before reading user input
2. Output prefix: Agent responses prefixed with 'G>' (bold green)
3. Thinking indicator: Animated spinner on stderr showing 'answering (N.Ns)'
with braille frame characters, auto-clears when response arrives
- Start/stop via tokio::sync::watch channel + tokio::spawn
- Only shows when interactive (atty detection)
- Does not affect gateway/sub-agent modes
- Create systemd + launchd service templates in resources/
- Add gyandoot-core/src/service.rs module with full lifecycle
- systemd: user service, daemon-reload, enable, start, stop, disable
- launchd: macOS plist, load/unload, start/stop (launchctl)
- Add 'gyandoot service install|remove|status' CLI subcommand
- Update setup wizard: prompts 'Install system service? [y/N]'
- Update install.sh: prompts user for service install after binary
- Browser auto-starts at runtime (browser_manager), no separate service needed
- Camoufox installed via npm, auto-started by GyanDoot agent loop
Full integration:
- install.sh now installs camoufox-browser via npm (preferred) or Docker
- install.sh creates systemd/launchd auto-start service on Linux/macOS
- New browser_manager.rs — health-check, auto-start, wait-for-ready
- AgentLoop::run() auto-inits Camoufox and registers web_search/web_browse
- System prompt tells LLM to use web_search/web_browse as PRIMARY tools
- Graceful fallback: if Camoufox unavailable, logs warning, uses bash tools
- ToolExecutor is now Arc<Mutex<>> for runtime tool registration
GyanDoot v2 now: install → Camoufox auto-starts → web tools available →
"search NSE India" uses Camoufox with anti-detection 🎯
Three fixes:
1. OllamaProvider now sends tools[] in native /api/chat requests
2. OllamaProvider parses tool_calls from response (OpenAI-compatible
format with function.name, function.arguments)
3. System prompt now lists available tools so LLM knows it can use
bash, curl, read/write files — stops saying "I cannot do that"
- Agent name now falls back to config.name if [identity] section is empty
- Agent role defaults to "AI Assistant built by Gyannetra"
- User name defaults to "the User" if not set
- Removes dependency on identity_setup being completed
- Every session gets identity+memory injected into system prompt
- Added [identity] config section (agent_name, agent_role, user_name,
user_role, setup_complete) to GyandootConfig and AgentConfig
- Agent loop now injects identity into system prompt on startup
- Agent loop injects past verbatim dialogue memory into system prompt
- Added dialogue_append() / dialogue_read() to MemPalace
- Word-by-word, line-by-line verbatim record in dialogue.md
- No compression, no truncation — every message preserved
- Agent loop writes to BOTH daily transcript AND verbatim dialogue
on every turn
- All config paths pass identity through (flat converter, subagents)
On macOS, dirs::config_dir() returns ~/Library/Application Support/,
NOT ~/.config/. This caused the loader to skip the actual config
file at ~/.config/gyandoot/config.toml and fall through to a stale
~/.gyandoot/config.yaml (which has no API keys).
Fix: Check ~/.config/gyandoot/config.toml explicitly FIRST via
home_dir(). This works identically on Linux and macOS.
BUGFIXES:
- Banner now displays on 'gyandoot run' via gyandoot_tui::banner::print_banner()
- Config now loads from ~/.config/gyandoot/config.toml with fallback chain
(XDG -> ~/.gyandoot/config.yaml -> hardcoded defaults), fixing 401 errors
- gyandoot init now writes visible placeholder api_key for users to edit
NEW PROVIDERS (4 added, now 7 total matching setup wizard):
- Google Gemini: Native API with x-goog-api-key auth, streamingGenerateContent
- DeepSeek: OpenAI-compatible wrapper at api.deepseek.com/v1
- OpenRouter: With HTTP-Referer/X-Title headers, model routing
- Groq: OpenAI-compatible wrapper at api.groq.com/openai/v1
All compile with 0 errors.