Tags: ThuyTran07/goclaw
Tags
fix(cache): heartbeat/cron used UUID in session keys causing stale ca… …che after agent update Session keys must use agentKey (human-readable, e.g. "default") not UUID. Cache invalidation via InvalidateAgent(agentKey) only matches agentKey suffix, so UUID-keyed entries were never cleared — causing stale provider/model after agent updates from the web UI. - heartbeat: use agentKey (already resolved) instead of UUID for session key and HasActiveSessionsForAgent check - cron: resolve agentKey from UUID via agentStore before building session key - agents_update: also invalidate by UUID as safety net for legacy entries - startup migration: auto-fix existing UUID-based session keys in DB - tests: 7 new tests covering session key format and cache invalidation
fix(tools): harden session tools — phantom sessions, JSON injection, … …fail-closed checks - session_status: GetOrCreate → Get to prevent phantom session creation - sessions_history: replace string concat with json.Marshal (2 paths) to prevent JSON injection - sessions_send: use s.Label from List() directly (eliminates N+1 Get calls), add self-send protection, use json.Marshal for response - All tools: fail-closed agentID check (error when empty instead of skipping validation) - Add 22 unit tests covering all session tools
fix(bus,cron): panic recovery + deadlock fix + unit tests for 9 packages Bug fixes: - bus: add panic recovery in Broadcast() — panicking subscriber no longer crashes entire event bus goroutine - cron: fix deadlock in RunJob() — recordRun called while holding mutex, extracted recordRunLocked for callers already holding lock - cron: add run log recording to executeJobByID — automatic scheduler was not populating run log, only manual RunJob did New tests (~170 cases across 9 packages): - crypto: roundtrip, key derivation (hex/b64/raw), nonce uniqueness, backward compat, wrong key, corruption - permissions: role hierarchy, RoleFromScopes, CanAccess, scope precedence - bus: pub/sub delivery, buffer full, panic recovery, concurrent safety - providers/retry: IsRetryableError, backoff, jitter, Retry-After, context cancellation, hook callback - sessions: idempotency, concurrent writes, defensive copy, save/load roundtrip, metadata accumulation - scheduler: draining, drop policies, adaptive throttle, stale completion, lane concurrency, debounce, interrupt mode - config: JSON5 parsing, env overrides, FlexibleStringSlice, owner IDs - cron: schedule validation, computeNextRun, CRUD, job execution, failure tracking, persistence roundtrip - agent: history sanitization edge cases — all-tool history, partial results, cross-turn dedup, orphaned tools, 1000-msg performance
fix(tools): block message tool self-send to prevent duplicate media d… …elivery When a team member creates an image and completes a task, the announce flow already carries media to the leader agent, which dispatches it to the channel via ForwardMedia. If the leader also calls the message tool to send the same image to its own chat, the image appears twice. Block message tool calls where channel+target match the agent's own context, returning an error that guides the LLM to include content in its normal response instead.
refactor: decompose consumer, agent loop, team tools, and MCP manager 6-phase pure refactor — zero behavior change, all tests pass. Phase 1: DRY event payloads + metadata keys - BuildTaskEventPayload() helper with functional options replaces 24 inline constructions - 26 metadata string constants replace ~66 magic strings across dispatch/consumer Phase 2: Consumer handler decomposition - ConsumerDeps struct collapses 11-13 positional params to 3 per handler - Extract startTaskLockRenewal() and resolveTeamTaskOutcome() Phase 3: loop.go extraction (978→686 LOC) - enrichInputMedia(): media persistence, ref collection, tag enrichment - injectTeamTaskReminders(): leader/member task context injection - buildFilteredTools(): policy, bootstrap, channel, iteration filtering - collectRefsByKind() helper eliminates 3x copy-paste Phase 4: team_tasks_mutations split (630→318 LOC) - executeCreate extracted to team_tasks_create.go - resolveTeamAndTask() helper used by 13 execute* functions Phase 5: MCP LoadForAgent split (~90→~15 LOC body) - resolveServerCredentials() + connectAndFilter() helpers Phase 6: Comments + DI - 5 inaccurate comments fixed - ToolExecutor interface for dependency inversion (Loop.tools field) - FilterTools accepts ToolExecutor instead of concrete *Registry
fix(agent): uniqueness-aware loop detector + auto-fail killed team ta… …sks (nextlevelbuilder#506) Read-only streak detector was a dumb counter that killed agents exploring unique files (12 reads = kill regardless of uniqueness). Team tasks were then falsely auto-completed with the kill message as "result." Changes: - Add uniqueness ratio to read-only streak: exploration mode (>60% unique) uses relaxed thresholds (warn=24, kill=36) vs stuck mode (warn=8, kill=12) - Classify team_tasks by action: list/get/search=read-only, progress=neutral, create/complete/cancel/comment/etc.=mutating - Add LoopKilled flag to RunResult, propagated through all 3 kill paths - Consumer routes LoopKilled to FailTask (not CompleteTask) with clear signal - 40 tests covering uniqueness detection, team_tasks classification, exact nextlevelbuilder#506 trace replay, boundary values, and edge cases
fix(web): sign media_refs paths in session history delivery (nextleve… …lbuilder#519) (nextlevelbuilder#520) File downloads in web chat returned 401 when loading session history because MediaRefs paths were not signed with ?ft= HMAC tokens. - Add SignMediaPath() to clean legacy corrupted paths (stacked /v1/files/ prefixes, stale ?ft= tokens) and produce fresh signed URLs - Sign MediaRefs in chat.history and sessions.get WS handlers - Strip ?ft= from filename display in frontend - Add path traversal defense-in-depth check - Add unit tests for SignMediaPath legacy data healing Closes nextlevelbuilder#519
fix(docker): restore base capabilities in sandbox overlay (nextlevelb… …uilder#523) Sandbox overlay's cap_add replaces (not merges) the base compose, dropping SETUID, SETGID, CHOWN. This causes credential copy to fail with Permission denied when combining sandbox + claude-cli overlays. Changes: - Re-include base capabilities in sandbox overlay's cap_add - Use umask 077 for atomic permission-safe credential copy - Add ENABLE_CLAUDE_CLI build arg to pre-install Claude CLI in image - Add runtime warning when credentials mounted but CLI binary missing - Add WITH_CLAUDE_CLI to Makefile for overlay consistency - Add security warning comment for sandbox overlay attack surface
PreviousNext