* fix: reduce log noise for node disconnect/late invoke errors
- Handle both 'node not connected' and 'node disconnected' errors at info level
- Return success with late:true for unknown invoke IDs instead of error
- Add 30-second throttle to skills change listener to prevent rapid-fire probes
- Add tests for isNodeUnavailableError and late invoke handling
* fix: clean up skills refresh timer and listener on shutdown
Store the return value from registerSkillsChangeListener() and call it
on gateway shutdown. Also clear any pending refresh timer. This follows
the same pattern used for agentUnsub and heartbeatUnsub.
* refactor: simplify KISS/YAGNI - inline checks, remove unit tests for internal utilities
* fix: reduce gateway log noise (#1607) (thanks @petter-b)
* test: align agent id casing expectations (#1607)
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
- Set inputTokens, outputTokens, totalTokens to 0 in sessions.reset
- Clear TUI sessionInfo tokens immediately before async reset
- Prevents stale token display after session reset
Fixes#1523
* fix(discord): gate autoThread by thread owner
* fix(discord): ack bot-owned autoThreads
* fix(discord): ack mentions in open channels
- Ack reactions in bot-owned autoThreads
- Ack reactions in open channels (no mention required)
- DRY: Pass pre-computed isAutoThreadOwnedByBot to avoid redundant checks
- Consolidate ack logic with explanatory comment
* fix: allow null values in exec.approval.request schema
The ExecApprovalRequestParamsSchema was rejecting null values for optional
fields like resolvedPath, but the calling code in bash-tools.exec.ts passes
null. This caused intermittent 'invalid exec.approval.request params'
validation errors.
Fix: Accept Type.Union([Type.String(), Type.Null()]) for all optional string
fields in the schema. Update test to reflect new behavior.
* fix: align discord ack reactions with mention gating (#1511) (thanks @pvoo)
---------
Co-authored-by: Wimmie <wimmie@tameson.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
The frontend fix alone wasn't enough because:
1. serveIndexHtml() was injecting the raw avatar filename into HTML
2. agent.identity.get RPC was returning raw filename, overwriting the
HTML-injected value
Now both paths resolve local file avatars (*.png, *.jpg, etc.) to the
/avatar/{agentId} endpoint URL.
TypeBox Type.Optional(Type.String()) accepts string|undefined but NOT null.
Discord exec was failing with 'resolvedPath must be string' because callers
passed null explicitly. Web UI worked because it skipped the approval request.
Fixes exec approval validation error in Discord-triggered sessions.