Consolidation was failing because max_tokens defaulted to 4096,
causing Haiku's response to be truncated mid-JSON (finish_reason=max_tokens).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Root cause: consolidation was calling Opus 4.6 with 10k thinking budget
on 50-80 message prompts. The 300s httpx timeout killed every request
(all failures were exactly 5 minutes after start). Consolidation is just
summarization — Haiku with no thinking handles it in seconds.
Also adds per-call thinking_budget override to the provider interface
so callers can disable thinking for lightweight tasks.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Auto-deploy is now handled by Watchtower on Unraid, which polls
for new images every 5 minutes for labeled containers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allows triggering a deploy via Gitea API. SSHes to Unraid to pull
latest image and restart the nanobot container.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
REGISTRY env var is just the hostname without scheme. Docker actions
handle this automatically, but curl needs the full URL.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Runs after push builds and daily at 03:00 UTC. Keeps :latest and
:buildcache, deletes old SHA-tagged images via Gitea packages API.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add pull_request trigger to build workflow
- Skip push and cache-to on PRs (build-only validation)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove "# nanobot" branding and "You are nanobot" from context.py
- Remove "You are a helpful AI assistant" personality line
- Remove fake "required" Claude Code system prefix from OAuth provider
- Identity is now fully customizable via IDENTITY.md in workspace
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Homebrew refuses to run as root in Docker containers.
Replace all brew installs with:
- GitHub release binaries (gogcli, goplaces, himalaya, obsidian-cli)
- go install (songsee)
- npm (gemini-cli)
- uv tool (openai-whisper)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Nanobot uses loguru, not stdlib logging. Switch to loguru so
thinking/usage logs actually appear in container output.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Logs thinking block presence, character count, and token usage
in API responses. Also logs request parameters including thinking
budget configuration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Anthropic API returns a signature field in thinking blocks that
must be replayed in subsequent turns. Store full thinking blocks
(including signatures) instead of just the text content.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Instead of maintaining a brittle alias dict mapping model names to
dated API IDs, simply normalize dots to hyphens. The Anthropic API
accepts both claude-sonnet-4-5 and dated variants like
claude-sonnet-4-5-20250929, so no alias table is needed. This lets
users write "claude-sonnet-4.5" or "claude-sonnet-4-5" interchangeably.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds configurable thinking_budget in agent defaults. When >0, sends
the thinking parameter to the API with the specified token budget.
Handles API constraints: forces temperature=1, auto-bumps max_tokens
if it's below the thinking budget, preserves thinking blocks in
message history for multi-turn conversations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The agent loop produces messages in OpenAI format (role:tool, tool_calls
array) but the Anthropic API expects its own format (tool_use content
blocks in assistant messages, tool_result blocks in user messages).
This caused 400 errors whenever the bot tried to use tools like
web_search, because the follow-up message with tool results was
malformed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allow "*" in the allowFrom list to explicitly permit all senders,
as an alternative to the empty-list-means-allow-all behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add .github/workflows/build.yml to auto-build and push to Gitea registry
- Change Dockerfile.oauth CMD from "status" to "gateway" for persistent container
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add MODEL_ALIASES dict to resolve short model names (e.g. claude-sonnet-4)
to dated API IDs (e.g. claude-sonnet-4-20250514). Includes claude-opus-4-6.
Add Dockerfile.oauth overlay extending birdxs/nanobot:latest for fast builds.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Markdown heading syntax (#) is not properly rendered in Feishu interactive
cards. Convert headings to div elements with lark_md format (bold text) for
proper display.
- Add _HEADING_RE regex to match markdown headings (h1-h6)
- Add _split_headings() method to parse and convert headings to div elements
- Update _build_card_elements() to process headings before markdown content