* Add unfurl_links config for Slack channel
Add unfurl_links: bool (default true) to SlackConfig to control
Slack's automatic URL preview expansion. When set to false, links
in agent messages are not unfurled, keeping output compact.
Applied to SlackAdapter's chat.postMessage payload via unfurl_links
and unfurl_media parameters, affecting both real-time and cron
delivery paths.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Rename test per review: clarify it tests explicit true, not default
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add release-fast Cargo profile for faster dev builds
Introduces a `release-fast` profile that inherits from `release` but
uses thin LTO and 8 codegen units instead of full LTO + 1, cutting
link time significantly while remaining fast enough for integration
testing. Documents usage in CONTRIBUTING.md.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: allow renaming an agent to its current name
AgentRegistry::update_name was calling name_index.contains_key()
without excluding the agent being renamed. Renaming to the same name
always returned AgentAlreadyExists instead of succeeding silently.
Fix: only error when a *different* agent owns the target name.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: use fixed agent ID for hand agents based on hand_id
This ensures triggers and cron jobs continue to work after daemon restart,
as hand agents now have stable IDs instead of generating a new UUID each time.
Changes:
- Add AgentId::from_string() method for deterministic ID generation
- Modify spawn_agent_with_parent() to accept optional fixed_id
- Use hand_id-based fixed ID in activate_hand()
See: #519
* remove: remove serena local config from commit
* chore: ignore .serena directory
* fix: use async save_session to avoid blocking tokio runtime
save_session() was synchronous, holding a Mutex<Connection> on the
tokio worker thread during SQLite writes. On pods with 1 CPU core
(1 tokio worker thread), this starved the entire runtime — including
health check endpoints — causing K8s to mark the pod not-ready and
return 504 on all subsequent requests.
Add save_session_async() that wraps the SQLite write in
spawn_blocking, matching the pattern already used by other memory
operations (recall, remember, etc.). Update all 12 call sites in
the agent loop.
* fix: move health check DB query to spawn_blocking and add SSE keep_alive
The health endpoint called structured_get() synchronously on the tokio
async runtime, acquiring the shared std::sync::Mutex<Connection> on a
worker thread. When the agent loop held this mutex during session saves,
the health check blocked the tokio thread, starving the SSE stream and
causing Kubernetes probe timeouts.
- Health and health_detail now run the DB check via spawn_blocking
- SSE message/stream endpoint now includes keep_alive to flush periodic
heartbeats even during contention
* feat: add hands upsert API for idempotent hand definition updates
Add upsert_from_content() to HandRegistry that overwrites existing
definitions instead of rejecting duplicates. Exposed as POST
/api/hands/upsert for use by the shard manager to keep hand definitions
up to date across pod restarts.
* fix: websocket streaming delays
* fix: get response immediately
Adds LTO and CODEGEN_UNITS arguments that default to optimized prod settings but can be overridden (e.g., LTO=false, CODEGEN_UNITS=16) by developers for faster iteration.
The polling loop was updating last_notification_id on every iteration,
leaving it set to the oldest (smallest) ID in the batch after the loop
completed. On the next poll, since_id was set to that oldest ID, causing
Mastodon to return all previously seen notifications again.
Re-delivered notifications caused the bot to respond to the same user
mention repeatedly. Combined with api_post_status chaining each response
chunk as a reply to the previous chunk, this produced long self-reply
threads that appeared to be the bot conversing with itself.
Fix: capture the first (newest) notification ID before processing the
batch, so since_id always advances correctly on each poll cycle.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Introduces a `release-fast` profile that inherits from `release` but
uses thin LTO and 8 codegen units instead of full LTO + 1, cutting
link time significantly while remaining fast enough for integration
testing. Documents usage in CONTRIBUTING.md.
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Fix Claude Code provider setup flow: wizard now shows Detect button instead of API key input for keyless providers, TUI wizards include claude-code in provider list, credentials detection checks both .credentials.json paths, subprocess env_clear prevents API key leaks. Fixes#376#303.
Fix tool name mapping so LLM-hallucinated aliases (fs-write, fsRead, writeFile, etc.) normalize to canonical names before capability check and dispatch (#349). Fix provider keys not loading after dashboard save by creating fresh drivers that read current env vars instead of stale boot-time cache (#465, #458, #355). Fix Moonshot/kimi model IDs and provider inference (#428). Add Telegram message reactions for agent lifecycle feedback (#435). Add configurable api_url for Telegram proxy support (#477). Add Discord ignore_bots config option (#403). Fix openfang init EPERM crash with 7-browser fallback on Linux (#389). Add text-based tool call parsing for models without native function calling — [TOOL_CALL], <tool_call>, bare JSON patterns (#354, #332). Fix pre-existing Windows test failures with cross-platform paths. 1948 tests pass, 0 clippy warnings.
Fix 8 issues: empty LLM response after ~4 rounds by re-validating message pairs after history trim (#460), MCP tools permission denied by bypassing ToolInvoke capability filter for extension tools (#352), Telegram photos silently dropped now downloaded and passed as multimodal ContentBlock::Image (#362), workflow visual builder double-click editing and live property updates (#357), Claude Code provider card reflects actual install/auth status (#376), Python 3 detection runs actual command instead of path lookup (#405), hand agent_id persisted for cron job reassignment on restart (#402), CLI sends auth headers on all commands not just stop (#478). 1921 tests pass, 0 clippy warnings.
- Add stream_options (include_usage) for accurate token counts in streaming mode
- Add fallback for providers that don't support stream_options
- Add SSE stream diagnostic logging