Commit Graph
945 Commits
Author SHA1 Message Date
viettranx ecf6463d98 fix(summon): preserve user's custom display_name during summon/regenerate
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.
2026-04-02 11:04:56 +07:00
viettranx 9d74e39625 fix(telegram): stop auto-linking @mentions to t.me profile URLs
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.
2026-04-02 10:55:41 +07:00
viettranx 1a2d5789d3 fix(ui): show group names in permission scope dropdown
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.
2026-04-02 10:37:19 +07:00
viettranx 3e4d614aa1 feat(media): add Veo 3.1 Lite video generation with image-to-video support (#638)
- 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
2026-04-02 10:33:35 +07:00
viettranx 14c375e33b fix(media): update native provider API defaults and UI schema
- OpenAI image default: dall-e-3 → gpt-image-1.5 (dall-e-3 deprecated May 12)
- DashScope: add missing 4:3 and 3:4 aspect ratio mappings
- UI: remove stale MiniMax size/prompt_optimizer params (backend uses aspect_ratio since #630)
2026-04-02 09:53:01 +07:00
viettranx 83bcb16597 refactor(channels): extract health model and modularize UI components
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
2026-04-02 09:45:41 +07:00
Tai Nguyen b5c4d1de2a fix bug can not create image with minimax provider (#630) 2026-04-02 09:35:21 +07:00
Kai (Tam Nhu) Tran 4cd7b0a8d4 feat: add actionable channel health diagnostics and remediation (#634)
* 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
2026-04-02 09:30:11 +07:00
viettranx abcb9614bc feat(providers): allow provider_type changes on update with SSRF re-validation
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.
2026-04-02 08:49:54 +07:00
Kai (Tam Nhu) Tranandviettranx 9fd9e1f47b fix(providers): recover Codex text from responses completion events (#631)
* 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>
2026-04-02 08:47:26 +07:00
Thieu Nguyen c84f4ac905 docs: sync API endpoint documentation with codebase (#632)
Add ~55 undocumented REST endpoints and ~30 undocumented WS methods.
Remove 14 stale entries (custom tools HTTP, sessions HTTP, delegations WS).
New sections: tenants, system-configs, edition, TTS, browser, zalo, export/import.
2026-04-02 08:24:08 +07:00
viettranx 3266a66299 feat(workspace): split sharing UI - separate Memory & KG from Workspace
Reorganize workspace sharing section to distinguish shared workspace
from memory/knowledge graph sharing controls.
2026-04-02 08:23:19 +07:00
viettranx fbcff96a49 feat(pending-messages): add topic suffix to group titles
Show topic/thread context in pending messages group titles for clarity.
2026-04-02 08:23:17 +07:00
viettranx 99f4679876 feat(contacts-page): add topic badge, filter, and thread_id display
Add topic filtering and display thread_id column on contacts page.
Show topic badge in contact listing for better organization.
2026-04-02 08:23:16 +07:00
viettranx 7291f31364 feat(cron-ui): move advanced settings inline to overview tab
Refactor cron detail page to consolidate settings in overview tab.
Remove separate advanced dialog, simplifying navigation and reducing layout complexity.
2026-04-02 08:23:14 +07:00
viettranx ab0e2051a6 refactor(heartbeat): simplify and optimize heartbeat store operations
Clean up heartbeat query logic and improve query efficiency across
PostgreSQL and SQLite implementations.
2026-04-02 08:23:11 +07:00
viettranx e682c53f73 feat(heartbeat): reformat delivery layout with channel and chat ID
Improve layout in heartbeat delivery list with 140px channel column
and flexible chat ID column for better readability.
2026-04-02 08:23:09 +07:00
viettranx b663d92fa4 fix(cron): skip loadClaimedJob for manual runs
Allow manual job runs even when job is disabled by checking job ID before
claiming. Prevents skipping manually triggered executions.
2026-04-02 08:23:07 +07:00
viettranx c48639369b fix(cron): apply timezone to all schedule kinds, not just cron
Move TZ application before schedule kind switch in MergeCronSchedule.
Ensure timezone applies consistently to cron, every, and at expressions.
2026-04-02 08:23:05 +07:00
viettranx 7d5c670708 feat(channels): add thread support to all channel handlers
Pass threadID and threadType to EnsureContact across all channel integrations:
- Discord, Feishu, Slack, Telegram, WhatsApp, Zalo
- Include General topic in contact collection
2026-04-02 08:23:03 +07:00
viettranx ac3af93df5 feat(contacts): implement thread_id persistence in PG and SQLite stores
- Update UpsertContact to handle threadID and threadType
- Strip username from sender_id compound key
- Implement in both PostgreSQL and SQLite backends
2026-04-02 08:23:01 +07:00
viettranx bf98a32e9b feat(store): add thread support to contact model and collector
- Add threadID and threadType to ContactCollector.EnsureContact
- Update ContactStore.UpsertContact signature
- Update Contact type in web UI
2026-04-02 08:22:57 +07:00
viettranx 670000651d feat(sqlite): add thread_id columns to contacts schema
Update SQLite schema to include thread_id and thread_type columns.
2026-04-02 08:22:54 +07:00
viettranx 5d632a522e feat(db): add migration 35 for contact thread_id columns
Add thread_id, thread_type columns to track forum topics and threaded conversations.
2026-04-02 08:22:53 +07:00
viettranx 28aa667c77 refactor(cron): redesigned run history with cleaner layout + status icons
- StatusIcon component with CheckCircle2/XCircle for visual feedback
- Compact timeline layout: icon, timestamp, duration badge, summary, tokens, status
- Error messages in monospace <pre> blocks with error-specific styling
- Mobile: duration + tokens move to expanded section
- Hide pagination when single page
2026-04-01 23:24:48 +07:00
viettranx cac3974e7c feat(cron): delivery UI with Select dropdowns + targets fetching
- 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
2026-04-01 23:24:44 +07:00
viettranx 4a0d938452 fix(ui): combobox dropdown auto-focus only on user interaction
- Check relatedTarget and document.hasFocus() to distinguish user-initiated focus
- Prevent programmatic focus from opening dropdown unintentionally
2026-04-01 23:24:40 +07:00
viettranx 523b084478 fix(telegram): retry pairing message without thread ID on hidden topic
- Handle 'thread not found' error when forum General topic is hidden/deleted
- Retry without messageThreadID for graceful fallback to main chat
2026-04-01 23:24:38 +07:00
viettranx 2f97d58c83 feat(heartbeat): support topic suffix in delivery targets
- 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
2026-04-01 23:24:36 +07:00
viettranx 8ba4bd7c4a fix(cron): RunJob NULL-safe comparison and timezone persistence
- Use IS DISTINCT FROM instead of != for NULL handling in RunJob claim
- Always apply patch TZ (empty = UTC default). Callers send full schedule
2026-04-01 23:24:33 +07:00
viettranx 04dc34e32c fix(schema): exempt multi-action tools from OpenAI strict mode
Strict mode forces ALL properties to be required, causing models to
send ~13 empty params per tool call on multi-action tools like
team_tasks (17 actions, 16 params). This wastes ~200-300 output tokens
per call.

- Add IsMultiActionSchema() to detect tools with action+enum pattern
- Per-tool strict decision in CleanToolSchemas (exempt multi-action)
- Extract normalizeWithProfile() for per-tool profile overrides
- Add per-action param guide to team_tasks description
- Fix schema/impl mismatches: file_id→path, add task_type property
- Gate param guide on policy (lite edition only sees allowed actions)
2026-04-01 22:00:05 +07:00
viettranx 43232c6189 fix(heartbeat): clarify HEARTBEAT_OK decision criteria to suppress "no news" responses
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."
2026-04-01 21:16:44 +07:00
viettranx da240a5e09 fix: pool validation false positive + OAuth step advancement + pool routing sync (#583, #594)
- Skip disabled providers in pool graph validation to prevent false
  "member already exists" errors when stale pool configs linger (#583)
- Add retry logic (3 attempts, 1s delay) in setup wizard OAuth flow
  to handle backend commit race condition (#594)
- Reset chatgpt_oauth_routing in agent other_config when provider
  changes, with amber warning in UI (#583)
- Add 3 pool validation tests for disabled provider scenarios
- Add providerChangedWarning i18n key (en/vi/zh)
2026-04-01 19:31:02 +07:00
MK d334a2082f fix(pg): align SearchByEmbedding SQL placeholders with scope args (#623) 2026-04-01 18:28:56 +07:00
viettranx d819e08071 fix(security): fix media upload permission denied + symlink protection
- 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
2026-04-01 18:11:42 +07:00
Huy Doan 41c827c65f fix(agent): update setAgentStatus to include tenantID parameter (#621)
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.
2026-04-01 18:07:43 +07:00
viettranx 1b190fa0bb fix(prompt): reduce mechanical chat behavior + optimize system prompt
- 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")
2026-04-01 16:27:41 +07:00
viettranx c388364d2c fix(ui): fix chat streaming race condition + require agent selection + improve chat UX
- 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
2026-04-01 16:12:44 +07:00
Plateau Nguyen 066c61f09a fix(ui): improve event detail dialog layout and scroll behavior (#619)
* fix(ui): improve event detail dialog layout and scroll behavior

* fix(ui): apply review suggestions for event detail dialog
2026-04-01 15:26:15 +07:00
Viet Tran 52c67d6d92 feat(build): embed web UI in backend binary + simplify Docker variants (#620)
- 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).
2026-04-01 15:25:59 +07:00
viettranx 39bb90bd60 refactor(permissions): remove auto-add file writer, add config type constants
- Remove auto-add logic that granted file_writer permission to the first
  group/guild member who chatted with the bot
- Add ConfigTypeFileWriter and ConfigTypeHeartbeat constants, replace all
  hardcoded config_type strings across callers
- Add bootstrap exception: /addwriter and !addwriter allow first writer
  to be added when no writers exist yet
- Optimize writer commands: reuse cached ListFileWriters result for both
  permission check and last-writer guard, reducing DB queries per command
- Add freshness directive to file writer system prompt so bot prioritizes
  current list over stale references in conversation history
2026-04-01 13:59:56 +07:00
viettranx f4369c51e4 fix(providers): make provider_type immutable + add argString tests
Prevent SSRF bypass via provider_type change on update — ACP skips URL
validation, so changing type post-creation could circumvent the check.
Add table-driven unit tests for argString() covering all JSON type
coercion paths (float64, int, NaN, json.Number, nil).
2026-04-01 11:59:21 +07:00
Huy Doan 238d639de7 fix(providers): skip URL validation for ACP provider api_base (#610)
* fix(providers): skip URL validation for ACP provider api_base

ACP uses api_base to store agent command/binary, so enforcing http/https URL validation rejects valid ACP configs. Bypass provider URL checks for ACP while keeping URL validation for HTTP-based providers.

* fix(message): enhance target handling in message tool to support numeric chat IDs

- Introduced argString function to correctly parse numeric chat IDs from tool arguments, ensuring they are treated as strings when necessary.
- Added a new test case to verify that numeric targets are correctly processed and sent via the Telegram channel.
2026-04-01 11:55:48 +07:00
Duc Nguyen 983f6184d9 fix(ui): dynamic searchable timezone picker with validation (#614)
Replace hardcoded 20-entry IANA_TIMEZONES with getAllIanaTimezones()
using Intl.supportedValuesOf (~400 zones). Switch Select dropdowns
to searchable Combobox in cron, heartbeat, and system config.

Add defense-in-depth timezone validation:
- Backend: validate in heartbeat.set handler and SetDefaultTimezone()
- Frontend: isValidIanaTimezone() guard before save in all 3 dialogs

Closes #614
2026-04-01 11:12:35 +07:00
viettranx 9c2b4cbf0f fix(agent): improve memory recall accuracy and flush safety
- Add "low confidence" instruction to memory_search tool description
  to prevent models from fabricating memories when no results found
- Add dedicated ## Memory Recall section in system prompt (supplements
  recency reminder) with clear instructions for memory_search/memory_get
- Update flush prompts: replace YYYY-MM-DD with actual date at runtime,
  cleaner append-only wording
- Update AGENTS.md memory privacy section for multi-tenant: remove
  implementation details (per-user scoping), keep group chat output
  guardrails that work for both shared and isolated memory configs
2026-04-01 09:16:16 +07:00
viettranx 5b66d64545 fix(ui): decouple Edit with AI from SummoningModal, improve agent create UX
- RegenerateDialog now handles its own progress via WS events instead of
  opening SummoningModal (inline spinner + auto-close on completion)
- Clean up SummoningModal: remove mode/isRegenerate prop, summon-only
- Agent create: default to Predefined, collapse Open type behind toggle
  with warning banner explaining per-user context trade-off
- Add 4 new agent presets: Coder, Support, Writer, Translator (en/vi/zh)
- Remove 15 dead summoning.regenerate* i18n keys
2026-04-01 09:06:41 +07:00
viettranx 2092c50a04 fix(agent): use DB provider_type for SOUL echo and strict mode detection
- Add providerTypeOf() to extract provider_type via type assertion
  (e.g. "chatgpt_oauth") instead of config name (user-set "openai")
- Exclude "compat" providers (openai_compat → OpenRouter/DeepSeek/Groq)
  from strict mode and SOUL echo — they proxy to non-OpenAI models
- Fix isOpenAIStrict matching openai_compat incorrectly
2026-03-31 23:38:48 +07:00
viettranx 2a9400949b fix(agent): SOUL echo in recency zone for OpenAI/Codex providers
GPT models have strong recency bias and lose persona in long prompts.
Extract Style/Vibe sections from SOUL.md and echo them at the end of
the system prompt (~200 chars each) so GPT sees personality traits right
before generating. Only applies to OpenAI/Codex — Claude respects early
system prompt instructions well and doesn't need this.
2026-03-31 23:32:21 +07:00
viettranx ff4d370d27 fix(mcp): require 3 consecutive ping failures before marking server disconnected
Single transient errors (e.g. 504 from upstream proxy) no longer
instantly disconnect MCP servers. Requires healthFailThreshold (3)
consecutive failures before setting connected=false and triggering
reconnect. Applies to both Manager.healthLoop and poolHealthLoop.
2026-03-31 23:15:59 +07:00
viettranx e48ba1df7f fix(mcp): prevent LLM hallucination of optional tool parameters
3-layer defense against GPT-5.4 filling all optional MCP tool params
with fabricated values (e.g. api_key:"optional", proxyUrl:"http://example.com"):

Layer 1 — bridge_tool.go: expand placeholder detection to catch "optional",
"skip", example URLs; type-aware empty string handling (keep for string-typed,
strip for non-string); add propertyType() helper.

Layer 2 — schema_strict.go: OpenAI strict mode transform — optional props
become nullable unions, all props required, additionalProperties:false.
Constrained decoding prevents invalid output. Only enabled for first-party
OpenAI/Codex providers.

Layer 3 — systemprompt_sections.go: concrete WRONG/RIGHT examples in MCP
optional param instruction.
2026-03-31 23:15:59 +07:00