Added ui/web/.npmrc with supportedArchitectures for musl+glibc/arm64+x64.
Updated Dockerfile to use --no-frozen-lockfile so pnpm fetches native rollup
binding compatible with Alpine's musl libc. Lockfile still pinned by copy order.
When parallel tool calls trigger loop detection warnings, the warning
messages (role="user") were inserted between tool result messages
(role="tool"). This breaks the Anthropic API when routed through
OpenAI-compatible proxies (e.g. LiteLLM): the proxy groups consecutive
tool messages into a single user message with tool_result blocks, but
an intervening user warning splits the group, causing orphaned
tool_results and HTTP 400 "tool_use ids without tool_result blocks".
Fix: accumulate warning messages during parallel result processing and
append them after all tool results, preserving the consecutive grouping.
Closes#642
LookupByBinary uses LEFT JOIN with secure_cli_user_credentials but
SELECT columns lacked table alias prefix, causing PostgreSQL error:
"column reference 'id' is ambiguous (SQLSTATE 42702)"
This silently broke ALL credentialed CLI exec — commands fell through
to regular shell exec without injected env vars.
Fix: use b.-prefixed column names for JOIN queries.
Also add diagnostic logging to lookupCredentialedBinary for future debugging.
Traces list Name column now displays agent display name, user label,
source type badge (Direct/Group/Cron/Team/Web), channel badge, and
truncated input preview — making it easy to identify which chat each
trace belongs to.
* feat(web): add Brave Search API key to tools config UI
Expose `web.brave.api_key` in the Web Search settings with password input,
strip masked values on save, and show the field only when Brave Search is
enabled. Add en/vi/zh strings for label, tooltip, placeholder, and managed key.
* refactor(web): extract isSecret to shared utility and fix mobile input font-size
DRY: move duplicated isSecret() from providers-section and tools-web-section
into lib/secret.ts. Add text-base md:text-sm to number inputs for iOS
Safari auto-zoom prevention.
---------
Co-authored-by: viettranx <viettranx@gmail.com>
Remap status reaction emojis for clarity (tool: 🔥→✍, error: 😱→💔)
and reduce overlap between statuses. Add /reactions command to show
emoji legend table to users.
fix(cli-credentials): show existing env keys on edit and support merge/remove
- Expose env_keys on secure CLI list/get and per-user credential list (values stay hidden)
- PUT merges env with stored secrets: empty value keeps existing, removed keys dropped
- Generic error messages to prevent env key enumeration
- Audit logging for user credential set/delete
- DRY: reuse envKeysFromDecryptedJSON helper
- Client-side env key name validation (en/vi/zh i18n)
- Filter Python stdlib modules at scan time to prevent false positives
when the runtime checker fails (e.g. pip:argparse, pip:sys)
- Install pip/npm packages one-by-one instead of batch so partial
success is preserved when one package fails
- Persist missing deps to DB after install via StoreMissingDeps() so
reload reflects actual state instead of stale data
- Use explicit master tenant context in handleInstallDeps for
consistency with rescanAndUpdate()
Previously, finishSummon() and RegenerateAgent() unconditionally overwrote
display_name with the LLM-extracted name from IDENTITY.md. Now if the user
already set a custom name, it is preserved and IDENTITY.md Name field is
synced to match — keeping UI label and agent self-identity consistent.
LLM @mentions are not necessarily Telegram usernames. Auto-wrapping
them in <a href="https://t.me/..."> caused unwanted profile cards.
Keep placeholder protection for italic conversion, restore as plain text.
Replace raw scope strings (e.g. group:nta7-goclaw:-5101523...) with
human-readable group names by fetching delivery targets from
channel_contacts via heartbeat.targets API. Scope labels are also
resolved in the permissions list display.
- Switch default Gemini video model to veo-3.1-lite-generate-preview (50% cheaper)
- Add image_path tool param for image-to-video generation (Gemini Veo only)
- Add resolution and generate_audio as per-provider chain params in UI
- Support dual response formats (Veo 3.1 generatedVideos + Veo 3.0 generatedSamples)
- Gracefully skip image-to-video on providers that don't support it (MiniMax, chat)
- Split create_video into per-provider files (gemini, minimax, chat) for maintainability
Post-merge cleanup for #634 channel health diagnostics:
Backend:
- Extract health types, ClassifyChannelError, mergeChannelHealth,
buildRemediation into internal/channels/health.go
- Fix case-true anti-pattern → default in Slack config
- Remove duplicate connection-refused case in ClassifyChannelError
- Remove unused _ bool param from BaseChannel.setHealth
- Fix snapshot.Enabled == false → !snapshot.Enabled
Web UI:
- Extract channel status utilities to channels-status-utils.ts
- Extract ChannelDiagnosticsCard from channel-detail-page.tsx
- Extract ChannelAttentionPanel from system-health-card.tsx
Desktop UI:
- Extract shared getChannelStatusDisplay() to utils/channel-status.ts
- Add explicit stopped state case for visual consistency with web UI
- Add missing vi/zh locale keys for new health status states
* feat: add channel health diagnostics
* fix(channels): harden startup failure reporting
- sanitize operator-facing failure details instead of exposing raw upstream errors
- keep registered channel instances failed during reload/startup errors and clean up pre-registration failure entries
- stop Telegram warning states from reporting running=true after polling or startup failures
* feat(channels-ui): surface actionable health diagnostics
- expand channel and overview views with richer health summaries, remediation hints, and failure history
- refine the channel dashboard layout so diagnostics are easier to scan instead of reading a wall of text
- keep shared web and desktop channel types aligned with the new health payload
* fix(web): harden channel health diagnostics states
- treat enabled channels without backend status as checking instead of stopped\n- align fallback remediation and overview attention synthesis with channel reality\n- localize diagnostics copy and reject invalid channel detail tabs\n\nRefs #628\nRefs #633
* docs(pr-assets): add channel diagnostics visual review pack
Remove blanket rejection of provider_type on update. Instead, when
provider_type changes, re-validate the existing api_base against the
new type to prevent SSRF via ACP→non-ACP type switch.
This enables provider type changes in onboarding/setup flows while
maintaining security: ACP providers skip URL validation, so switching
from ACP to another type now forces URL re-validation.
* fix(providers): recover Codex text from responses completion events
* fix(providers): honor Codex phase-aware response assembly
* refactor(providers): extract Codex stream state to separate file
Split codexMessageStreamState and related types/methods from codex.go
(457 lines) into codex_stream_state.go to comply with 200-line file
size guideline. Fix redundant nil check in registerMessageItem. Add
clarifying comment on reconcileCompleted edge case.
---------
Co-authored-by: viettranx <viettranx@gmail.com>
Refactor cron detail page to consolidate settings in overview tab.
Remove separate advanced dialog, simplifying navigation and reducing layout complexity.
Pass threadID and threadType to EnsureContact across all channel integrations:
- Discord, Feishu, Slack, Telegram, WhatsApp, Zalo
- Include General topic in contact collection
- Update UpsertContact to handle threadID and threadType
- Strip username from sender_id compound key
- Implement in both PostgreSQL and SQLite backends
- Replace free-text Input with Select for Channel + To fields
- Fetch delivery targets via HEARTBEAT_TARGETS RPC
- Populate To options based on selected Channel
- Fallback to Input when no targets available
- Use array_to_string([5:]) in PG to capture full chatId with topic:N suffix
- Add extractSessionKeyTail() for SQLite forum group support
- Join on base chatId for contact display name resolution
Model was delivering formatted "nothing new" status updates instead of using
HEARTBEAT_OK because instructions were ambiguous about what "nothing to deliver"
means. Now explicitly states: "A no news summary is NOT worth delivering."
- Fix workspace dir ownership in Docker entrypoint: chown dirs not owned
by goclaw on startup (handles dirs created by root in previous lifecycle)
- Add symlink check on .uploads/ via os.Lstat before file creation to
prevent symlink-based attacks replacing .uploads with link to sensitive dir
Summoning failures (e.g. provider timeout) left agents stuck in summoning because failure paths called setAgentStatus(context.Background(), ...) without tenant scope, causing agent not found on update. Pass tenantID to setAgentStatus and re-attach tenant context when missing.
- Add Tool Call Style section with narration minimalism + non-disclosure
rule (from TS reference): agents must never expose tool names to users
- Consolidate 3 redundant memory recall reminders into 1 dedicated section
- Remove "tell the user you checked but found nothing" instruction that
caused agents to describe internal tool mechanics in responses
- Remove 11 tool aliases from system prompt listing (~300 tokens saved);
aliases still work via provider definitions
- Filter alias tool names out of system prompt ToolNames in loop_history
- Update AGENTS.md: remove tool name references from Memory section,
add group chat framing from V1 ("participant, not their proxy")
- Fix race condition where session-change effect cleared runIdRef after
run.started already captured it, causing chunk events to be filtered
out (user saw "thinking" but no streamed tokens on new chats)
- Add SessionRunID to router + return runId in session status response
as backup restoration for event filtering
- Require explicit agent selection before chat input is shown
- Redesign ChatInput: attach icon inside input container, aligned send
- Port desktop UX: wobble animation for tool calls, auto-expand thinking
block on stream start, amber icon for streaming, iteration step count
- Add internal/webui/ package with //go:build embedui tag for optional
SPA embedding (handler.go serves static files with SPA fallback)
- Add internal/version/ shared semver comparison (DRY: extracted from
gateway/update_check.go and updater/updater.go)
- Enhance UpdateChecker: release notes, ETag caching, filter lite-v* tags
- Add web UI build stage to Dockerfile with ENABLE_EMBEDUI build arg
- Simplify CI: 7 Docker variants → 4 (base, latest, full, otel)
- Add SHA256 checksums job to release workflow
- Add Makefile build-full target (embeds web UI in Go binary)
- Default make up now embeds web UI (no separate nginx needed)
- Add WITH_WEB_NGINX=1 flag for optional nginx reverse proxy
- Update README + 30 translated READMEs: make up, port 18790
- Update docker-compose comments and prepare-env.sh
- About dialog: show release notes with markdown rendering
- Health card: amber badge for available updates
BREAKING: Default Docker setup no longer requires selfservice overlay.
Web dashboard served at :18790 (same port as API).