* fix(channels): annotate DM messages with sender identity
Telegram and Zalo group messages already include [From: sender] prefix
so the agent knows who is talking, but DM messages were sent without
any sender context — the agent had no way to address the user by name.
- Telegram DM: add [From: @username] (or FirstName if no username)
- Zalo DM: add [From: displayName] when dName is present in payload
* fix(tests): add missing EnsureUserProfile to test stubs
AgentStore interface gained EnsureUserProfile in 4fce731 but the test
stub implementations were not updated, breaking CI on main.
---------
Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
Self-Evolution: predefined agents can now optionally evolve their SOUL.md
(communication style/tone only) when self_evolve is enabled in other_config.
Identity, name, and operating instructions remain locked. Context propagation
flows through LoopConfig → Loop → context.WithValue → interceptor carve-out.
System prompt guides the agent on what it can/cannot evolve.
Instances Tab: new HTTP endpoints and UI tab for viewing/editing per-user
USER.md files on predefined agents. Includes owner-only access checks,
fileName validation (USER.md only), and cache invalidation.
UI: self-evolve toggle in General tab, create dialog, and setup wizard.
Agent type and evolve/static badges with tooltip explanations on cards
and detail header. TooltipProvider added to agents list and detail pages.
Add optional Redis cache support via `go build -tags redis`, following
the same paired-stub pattern as OTel and Tailscale. The Cache[V] interface
is unchanged; Redis and in-memory implementations are injected at startup
without altering usage logic.
- Add RedisCache[V] implementation with JSON serialization, fail-open on errors
- Add gateway_redis.go / gateway_redis_noop.go paired wiring files
- Refactor GroupWriterCache and ContextFileInterceptor to accept injected caches
- Add GOCLAW_REDIS_DSN env var, docker-compose.redis.yml overlay
- Update Dockerfile and GitHub Actions with ENABLE_REDIS build arg
- Add Redis variant to CI matrix (5 variants: latest, otel, tsnet, redis, full)
When LLMs call team_tasks create + spawn in parallel, the spawn
tool receives a hallucinated task_id that fails uuid.Parse, causing
a misleading error and bypassing orphan detection.
- Include pending task IDs in spawn error message so LLM can retry
with the correct UUID
- Move spawn counting to post-execution so failed spawns don't
increment teamTaskSpawns, allowing orphan detection to fire
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix resolvePath for nested non-existent dirs (use resolveThroughExistingAncestors)
- Channel-isolated workspace: user_agent_profiles.workspace stores channel prefix,
used as source of truth with backward compat for existing users
- Loop caches workspace per-user with CacheKindUserWorkspace invalidation via pubsub
- ContractHome/ExpandHome for portable ~-based paths in DB
- create_image saves to workspace/generated/YYYY-MM-DD/ instead of OS temp dir
- SOUL.md template: add ## Expertise section for domain knowledge
- Summoner buildEditPrompt: section guide, complete file output, frontmatter update
- Bus: Topic* constants for Subscribe/Broadcast keys, CacheKind* for payload kinds
- Teams, delegates, sessions, agent links: various enhancements
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: invalidate ContextFileInterceptor cache on agents.files.set
When agents.files.set (or agents.update) wrote context files to
agent_context_files in Postgres, only the agent router cache was
invalidated via agents.InvalidateAgent(). The ContextFileInterceptor
maintains its own separate in-memory cache with a 5-minute TTL which
was never cleared, causing the agent to serve stale file content
(e.g. wizard-written SOUL.md/IDENTITY.md) for up to 5 minutes.
Fix: inject *tools.ContextFileInterceptor into AgentsMethods and call
intc.InvalidateAgent(ag.ID) immediately after each successful DB write
in handleFilesSet and handleUpdate.
Wire path: wireManagedExtras now returns the interceptor it creates;
gateway.go captures it and passes it through registerAllMethods →
NewAgentsMethods. The interceptor is nil in standalone mode so all
nil guards are in place.
* test: add unit tests for ContextFileInterceptor cache invalidation
Covers:
- Cache hit: second read does not call store again
- InvalidateAgent clears agent cache → fresh content served from store
- InvalidateAgent clears user cache for that agent
- InvalidateAgent does not affect other agents' cache entries
- TTL expiry causes re-fetch from store