Commit Graph
510 Commits
Author SHA1 Message Date
viettranx 23e34eec80 fix(ui): prevent white screen on usage page cross-filtering
Recharts Brush component crashes when data length changes after
cross-filtering because its internal indices go out of bounds.
Add key={chartData.length} to force re-mount on data change.
Add ErrorBoundary wrapper for resilience against future chart crashes.
2026-03-12 18:13:18 +07:00
GoonandGitHub 7a4a20b2e8 fix(discord): per-user memory scope in guild channels (#166)
* docs: add brainstorm report for discord guild-user memory

* docs: update brainstorm report with corrected root cause analysis

* feat(discord): per-user memory scope in guild channels

Fixes shared USER.md between guild members by scoping userID to
"guild:{guildID}:user:{senderID}" for Discord group messages.
Updates all group-context prefix checks (write permissions, writer
cache, cron peer kind, history filter) to include the new guild: prefix.

Closes #165
2026-03-12 16:45:30 +07:00
viettranx 495419b281 fix(ui): add pointer-events-auto to portal dropdowns inside dialogs
Radix Dialog sets pointer-events: none on document.body, making custom
Combobox and ToolNameSelect dropdowns (portaled to body) unclickable.
2026-03-12 16:32:54 +07:00
Winter279andGitHub 6629bdc56c feat(ui): add back button to setup wizard steps (#163)
* fix(cron): deliver reminders directly as bot messages instead of routing through agent

When deliver=true, send Payload.Message straight to the channel without
agent processing. This fixes reminders appearing as fake user messages
followed by an unnecessary agent reply.

Also auto-set deliver=true when cron jobs are created from chat context
(channel + chatID available), so reminders always deliver correctly
without requiring the LLM to explicitly set the deliver flag.

* feat(docker): add ENABLE_NODE build arg for MCP stdio servers

Optional Node.js/npm in Alpine runtime, default false.
Required for running MCP servers via npx inside container.

* feat(ui): add back button to setup wizard steps

Allow users to navigate back to previous steps during onboard setup.
Back button appears on steps 2-4, positioned left-aligned in the
action row with secondary (gray) styling.

* revert(cron): restore cron delivery to main version

* fix(ui): remove duplicate onBack in setup step interfaces
2026-03-12 16:10:30 +07:00
viettranx bece4525ba feat: share memory and KG across users when workspace sharing is enabled
Memory (MEMORY.md, memory/*) and knowledge graph are now shared when
workspace sharing is active, matching the filesystem sharing behavior.
Previously memory was always per-user isolated even with shared workspace,
causing inconsistencies when collaborating on the same files.

Adds MemoryUserID(ctx) helper that returns empty userID (global scope)
when shared memory flag is set, used by memory interceptor, memory tools,
and KG search. UI warning updated to note data is not migrated on toggle.
2026-03-12 12:09:38 +07:00
viettranx 25b24ebd50 feat: configurable workspace sharing with per-agent DM/group/user controls
Add workspace_sharing config in other_config JSONB to control per-user
workspace isolation. When enabled, users share the base workspace directory
instead of isolated subfolders — configurable separately for DMs and groups,
with a per-user allowlist override.

Backend: WorkspaceSharingConfig struct, ParseWorkspaceSharing(), conditional
isolation in loop.go/loop_history.go, 7 unit tests.
Frontend: prominent always-visible config section with contact search
combobox, sticky save bar layout fix, i18n (en/vi/zh).
2026-03-12 10:54:17 +07:00
viettranx a75e977dca fix(telegram): simplify pairing messages for friendlier UX
Remove verbose CLI instructions and Telegram user ID from pairing
replies. Show only the pairing code with a friendly message.
2026-03-12 10:46:32 +07:00
viettranx 225bd3d3b6 feat(ui): add agent and channel dropdown filters to traces page 2026-03-12 10:38:20 +07:00
viettranx 050de16aa2 feat(setup): add skip setup option with localStorage persistence
Users can skip the entire setup wizard via a link below the title.
Sets localStorage flag so refresh won't re-show the wizard.
2026-03-12 10:30:05 +07:00
viettranx 5ab4af415d feat(setup): add back navigation to onboard wizard
Steps 2-4 now have a Back button. Steps with DB resources
(provider, agent) support edit mode — pre-fill form and use
UPDATE instead of INSERT on re-submit.
2026-03-12 10:19:22 +07:00
viettranx dcf9ec4d49 fix: handle DB errors in credential merge to prevent silent data loss
loadExistingCreds now distinguishes sql.ErrNoRows (safe empty map) from
real DB errors (propagated to caller). Prevents transient DB failures
from silently wiping existing credentials during partial updates.
2026-03-12 10:19:13 +07:00
GoonandGitHub e2f0199d9e fix(ui): default agent mode to predefined (#147)
* fix(ui): default agent mode to predefined in create dialog

* fix(ui): swap agent type buttons, predefined first
2026-03-12 09:39:15 +07:00
b488ef44d6 fix: media tag enrichment, Gemini file polling, credential merge (#158)
1. Media tag enrichment (audio/video/document):
   - Add enrichVideoIDs() — video media_id was never injected into
     <media:video> tags, causing LLM to hallucinate UUIDs
   - Fix all enrich functions to replace the LAST bare tag instead of
     the first. When group history prepends older media tags, the first
     occurrence belongs to history — injecting the current turn's ID
     there causes the LLM to reference the wrong file

2. Gemini File API polling:
   - Upload response returns fileURI immediately but file may still be
     in PROCESSING state. Check state field; only skip polling when
     file is already ACTIVE. Fixes "not in an ACTIVE state" errors

3. Channel instance credential merge:
   - Partial credential updates (e.g. updating just token) now merge
     with existing credentials instead of wiping other fields
   - Loads, decrypts, merges, re-encrypts in a single Update() call

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
2026-03-12 09:35:04 +07:00
e5eca5d0f0 feat(telegram): support custom Bot API server URL (#157)
* feat(telegram): support custom Bot API server URL

Add api_server credential field for Telegram channels to allow
using a self-hosted Telegram Bot API server (e.g. for 2GB upload
limits). Uses telego.WithAPIServer() option.

* feat(telegram): local Bot API media download + config improvements

- Support local Bot API --local mode: detect absolute file paths and
  copy directly from filesystem (requires shared volume mount)
- Fall back to HTTP download via custom API server URL for non-local mode
- Move api_server/proxy from credentials to config (non-secret fields);
  credentials still accepted for backward compat
- Add media_max_mb config field (friendlier than media_max_bytes);
  deprecated media_max_bytes still works
- Default to 200 MB max when local Bot API is configured (vs 20 MB cloud)
- UI: move api_server/proxy to config section, use MB for media size

* fix: use 127.0.0.1 instead of localhost in API server placeholder

Docker containers cannot resolve localhost to the host machine.
127.0.0.1 works reliably with Docker's default bridge network.

---------

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
2026-03-12 09:29:14 +07:00
ace07509b7 feat(skills): system skills integration — toggle, dep checking, per-item install (#161)
* feat(infra): add runtime package support for skills

Install nodejs, npm, pandoc, github-cli + pre-install Python packages
(openpyxl, pandas, python-pptx, markitdown) and Node packages
(docx, pptxgenjs). Configure runtime dirs for agent pip/npm installs
with PIP_TARGET, NPM_CONFIG_PREFIX, NODE_PATH to enable dynamic
package installation in read-only container environment.

* feat(infra): add bundled skills with runtime package support

- Add 5 bundled skills: docx, pdf, pptx, xlsx, skill-creator from container skills-store
- Wire GOCLAW_BUILTIN_SKILLS_DIR env var in gateway and CLI
- Support optional runtime packages alongside dynamic skill loading
- Update Dockerfile to COPY bundled-skills at /app/bundled-skills/
- Add PIP_CACHE_DIR in docker-entrypoint.sh for clean pip installs
- Document bundled skills in 14-skills-runtime.md section 6

* feat(infra): remove ai-multimodal skill directory from bundled skills

Remove the ai-multimodal skill package as part of consolidating runtime
package support for bundled skills. This directory is no longer needed
in the bundled skills structure.

* feat(ci): add semantic release and Docker Hub publishing

Add go-semantic-release workflow to auto-create semver tags on merge to
main. Extend docker-publish to push all variants to both GHCR and
Docker Hub (digitop/goclaw).

* feat(skills): add system skills infrastructure with is_system column, dep scanning, and seeder

- Migration 000017: add is_system boolean column with partial index
- Store layer: UpsertSystemSkill, delete protection, IsSystemSkill
- ListAccessible auto-includes system skills (no grants needed)
- ListWithGrantStatus returns is_system field
- Dependency scanner: auto-detect deps from scripts/ or skill-manifest.json
- Dependency checker: verify system binaries, Python/Node packages
- Seeder: seed bundled skills into DB on startup (idempotent via hash)
- Gateway wiring: GOCLAW_BUNDLED_SKILLS_DIR env for bundled skills
- HTTP: delete guard (403), slug conflict check (409), rescan-deps endpoint
- UI: System badge, hide delete for system skills, rescan deps button
- Agent skills tab: "Always available" for system skills
- i18n: en/vi/zh keys for system skills, deps scanning

* feat(skills): conditional system prompt, skill manifests, and Zip Slip fix

- System prompt: only show package list when python3/node are available
- Add skill-manifest.json for pdf, docx, xlsx, pptx bundled skills
- Fix Zip Slip vulnerability in office/unpack.py (all 3 copies)

* refactor(skills): extract shared office code to _shared/ and deduplicate

Move office scripts (pack, unpack, validate, schemas, validators) from
duplicated copies in docx/xlsx/pptx to skills/_shared/office/ with
symlinks. Remove soffice.py (non-functional in containers) and update
SKILL.md references to use soffice binary directly. Update seeder
copyDir to follow symlinks.

Removes ~45K lines of duplicate code across 3 skills.

* fix(skills): address code review findings for system skills integration

- H1: Remove dead symlink branch in copyDir (filepath.Walk follows symlinks)
- H3: Fix rescan-deps to query ALL skills (including archived) and re-activate
  when deps become available; add ListAllSkills() + Status field to SkillInfo
- H4: Add Status field to SkillCreateParams, stop overloading Visibility
- M1: Batch Python/Node dep checks into single subprocess per runtime
- M4: Add rows.Err() check in ListSkills to prevent caching partial results

* feat(skills): async dep checking with realtime WS events

Split Seed() into sync DB upsert + async CheckDepsAsync() goroutine.
Gateway startup no longer blocks on Python/Node subprocess dep checks.

- Seed() returns seeded skills list, all initially status="active"
- CheckDepsAsync() runs in background, emits skill.deps.checked per-skill
- skill.deps.complete event emitted when all checks finish
- Each failed dep check: archives skill + BumpVersion() for immediate
  cache invalidation so next agent turn picks up the change
- UI: use-query-invalidation listens to skill.deps.* events → auto-refresh
  skills list in realtime

* feat(skills): system skills integration with toggle, dep checking, and per-item install

- Add is_system, deps, enabled columns to skills table (migration 017)
- Seed bundled core skills (pdf, docx, pptx, xlsx, skill-creator) on startup
- PYTHONPATH-based dep detection — eliminates false positives from local modules
- Per-item dep install UI with individual status (installing/success/error)
- Enable/disable toggle for core and custom skills (independent of dep status)
- Re-run dep check when skill is toggled back on
- Inline skill thresholds: 40 skills / 5000 tokens before switching to search mode
- Fix UpsertSystemSkill: backfill null file_hash without bumping DB version
- Remove redundant skill-manifest.json files (replaced by deps JSONB column)
- Show author from frontmatter in custom skills tab
- Runtime checker for python3/pip3/node/npm availability
- WS events for dep checking/installing progress
- docs: add 15-core-skills-system.md, 16-skill-publishing.md

---------

Co-authored-by: Goon <duy@wearetopgroup.com>
2026-03-12 09:20:41 +07:00
7386fc8ad7 fix: read_audio fails when LLM passes literal <media:audio> as media_id (#156)
The read_audio tool errors with "audio not found" because:
1. BuildMediaTags() creates bare <media:audio> tags without IDs
2. persistMedia() generates UUIDs stored in context, not in message content
3. LLM sees <media:audio> and passes it literally as media_id parameter
4. resolveAudioFile() tries to match "<media:audio>" against UUIDs — fails

Two-part fix:
- enrichAudioIDs(): embed persisted UUIDs into <media:audio> tags (like
  enrichDocumentPaths does for documents), so LLM sees actual IDs
- resolveAudioFile(): sanitize tag-like media_id values and fallback to
  most recent audio instead of hard error on unmatched IDs

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
2026-03-11 19:57:15 +07:00
b5b40e7d94 fix(cron): auto-default deliver=true when job created from channel chat (#155)
When users create cron jobs from channel chats (Zalo, Telegram, etc.),
the LLM often omits the `deliver` flag (defaults to false). This causes
cron jobs to run successfully but silently discard results — the response
never reaches the chat where the user requested it.

Auto-detect channel context and default deliver=true for real channels,
skipping internal channels (cli, system, subagent, cron, delegate).
The existing auto-fill logic then populates channel and chatID from
context, ensuring delivery info is always captured.

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
2026-03-11 19:56:46 +07:00
viettranx 6185948cb3 feat: add trace export as gzip with recursive sub-trace collection
Add GET /v1/traces/{traceID}/export endpoint that recursively collects
trace, spans, and child traces (delegations) up to depth 10, returning
gzip-compressed JSON. Add download button with icon+text in trace detail
dialog header.
2026-03-11 19:55:42 +07:00
viettranx 72779646c1 fix: complete media provider type routing for Suno and fix dbTypeToMediaType map
- Set providerType on Suno case in registerProvidersFromDB (was missing,
  causing misrouting for custom-named Suno providers)
- Fix dbTypeToMediaType: replace dead "openai" key with "openai_compat"
  to match actual store constant, add "bailian" → "dashscope" mapping
- Clone entry.Params before injecting _provider_type to avoid mutating
  the original chain config
2026-03-11 18:34:38 +07:00
405a753239 fix: resolve media provider type from DB instead of guessing from name (#154)
Media tools (create_image, create_video, create_audio, read_audio,
read_video, read_document) routed API calls based on provider name
pattern matching (e.g. strings.HasPrefix(name, "gemini")). This breaks
when users give custom names to DB providers — a Gemini provider named
"chatgpt-sap-het" would be misrouted to the OpenAI-compat endpoint,
causing 404 errors.

Fix: carry the DB provider_type through OpenAIProvider, resolve it via
typedProvider interface in ExecuteWithChain, and inject as _provider_type
param for callProvider routing. Name-based heuristic kept as fallback
for config-file providers that don't have a DB type.

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
2026-03-11 18:32:51 +07:00
viettranx d6f83afda5 fix(ui): use llm_call_count for provider/model distribution charts
Provider and Model donut charts showed 0 because they used request_count,
which is only populated on channel-level snapshot rows. LLM-level rows
store counts in llm_call_count instead.
2026-03-11 17:40:04 +07:00
viettranx eefc5ef4f2 fix(ui): preserve byProvider in tools_config whitelist on save
The PR #153 whitelist stripped byProvider on agent config save,
but byProvider is actively used in policy.go for per-provider
tool overrides. Add it to the whitelist and ToolPolicyConfig type.
2026-03-11 17:39:19 +07:00
0592be359d fix: remove legacy per-agent imageGen/vision override from tools_config (#153)
The per-agent `imageGen` and `vision` fields in `ToolPolicySpec` (stored
in agents.tools_config JSONB) were added in d5cc5a7 (Feb 26) as the
original way to configure image/vision providers. When the media provider
chain system was introduced in 5815437 (Mar 8), these fields were kept
"for backward compat" but became dead code with no UI to manage them.

This causes a hard-to-debug issue: if an agent's tools_config contains
stale imageGen/vision data (set via API or leftover from DB), it silently
overrides the global provider chain configured in the builtin tools UI.
Users see the correct chain in the UI but the tool calls a completely
different provider/model, with no indication of why.

Changes:
- Remove Vision and ImageGen fields + struct definitions from ToolPolicySpec
- Remove associated context helpers (WithVisionConfig, WithImageGenConfig, etc.)
- Remove per-agent override injection in agent loop
- Simplify create_image and read_image to use chain as sole source of truth
- UI: whitelist known tools_config fields on save to clean stale DB data

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
2026-03-11 17:37:55 +07:00
viettranx ec34f488df feat(tools): add tool alias registry for Claude Code skill compatibility
Add alias support to the tool Registry so Claude Code skills can reference
Anthropic tool names (Read, Write, Edit, Bash, etc.) and have them resolve
to GoClaw canonical tools (read_file, write_file, edit, exec, etc.).

- Registry: aliases map, RegisterAlias(), resolve(), Aliases()
- Policy engine: auto-includes alias defs when canonical tool passes filter
- System prompt: alias entries in coreToolSummaries + missing use_skill
- Legacy toolAliases migrated to Registry.RegisterAlias() at startup
2026-03-11 17:33:28 +07:00
GoonandGitHub c25e770d43 feat(ui): multi-skill upload with client-side validation (#149)
* feat(ui): multi-skill upload with client-side validation

Allow uploading multiple skill ZIP files at once with pre-upload
validation. JSZip parses each ZIP client-side to verify SKILL.md
presence, frontmatter format, and slug validity before upload.

- Add JSZip dependency (lazy-loaded, code-split ~30KB gzip)
- Create validate-skill-zip.ts mirroring server-side checks
- Rewrite skill-upload-dialog for multi-file with status badges
- Add concurrent validation, sequential upload with per-file progress
- Add empty SKILL.md check to backend upload handler
- Add i18n keys for all new UI strings (en/vi/zh)

* fix(ui): duplicate entries and validation hang in multi-skill upload

- Move pending list construction to assignment inside updater return
  to prevent StrictMode double-invoke from pushing duplicates
- Wrap per-file validateSkillZip in try/catch so one failure doesn't
  block Promise.all and leave entries stuck in "validating" state

* fix(ui): use static import for JSZip instead of dynamic import

Dynamic import("jszip") fails in browser - bare module specifiers
don't resolve at runtime. Use static import which Vite handles
via its module graph and code-splits automatically.

* feat(ui): add inline visibility toggle on skills table

Click the visibility badge on managed skills to cycle through
private → internal → public. File-based skills stay read-only.

* fix(ui): move dedup logic outside state updater in upload dialog

Avoids reading stale entries inside functional updater. Builds
pending list from current entries state before calling setEntries.

* fix(ui): auto-select first active agent when current agent unavailable

When agents load from API, if the current selected agent is not in the active agents list, automatically select the first available active agent instead of remaining unset. Prevents chat page from being unable to send messages when default agent selection is invalid.

* feat(ui): make agent display name editable in setup wizard

Allow users to customize the agent display name during onboarding instead of keeping it hardcoded to "GoClaw". Removed read-only state from the display name input and added a placeholder for guidance.

* feat: add document path enrichment and media filename support

Backend changes:
- enrichDocumentPaths() in agent/media.go: injects persisted file paths into <media:document> tags
- Document paths allow skills (e.g. pdf skill via exec) to access files directly
- chat.go: support new media format {path, filename} alongside legacy string paths
- Updated read_document tool description to guide agent on using path attribute
- Docker: add pypdf to Python dependencies for PDF processing
- Softened MUST language in read_* tool descriptions (changed to Call this)

Frontend changes:
- chat-input.tsx: attach filename with each uploaded file in media payload
- use-chat-send.ts: send media as {path, filename} objects instead of just paths
- i18n: add "uploaded_files" text in en, vi, zh locales
- chat-page.tsx: minor adjustment for media handling

Enables skills to process uploaded documents directly without intermediate copying.
2026-03-11 16:59:03 +07:00
pdtktsandGitHub 44e5d663af fix: respect API base when listing Anthropic models (#151) 2026-03-11 16:55:11 +07:00
viettranx 4f3664674b fix: add debug log when OAuth provider skips direct audio API path 2026-03-11 16:54:53 +07:00
viettranx 61e6ff2ab2 fix(ui): portal all custom dropdowns to document.body
Custom dropdowns using absolute positioning were clipped by parent
overflow containers (dialogs, scrollable sections). Fixed by rendering
via createPortal with fixed positioning:

- Combobox: default to body portal when no portalContainer prop
- ToolNameSelect: add createPortal + fixed positioning
- AgentSelector: replace overlay+absolute with portal
- ContactInsertSearch: add createPortal + fixed positioning
- ContactSearchBox (instances tab): add createPortal + fixed positioning
2026-03-11 16:54:33 +07:00
viettranx 771a6538c0 fix(ui): clear compact spinner when has_summary becomes true
Previously the spinner only cleared after a 120s timeout. Now a
useEffect watches the groups data and immediately clears the spinner
and polling when the compacting group's has_summary transitions to true.
2026-03-11 16:54:24 +07:00
viettranx b71e8abb5d fix: exclude inactive agents from team member listings
ListMembers() now filters by a.status = 'active' so inactive agents
no longer appear in TEAM.md or delegation prompts, preventing leaders
from attempting to delegate to unavailable agents.
2026-03-11 16:54:18 +07:00
viettranx e596d2b656 fix: invalidate TeamToolManager cache on team create
handleCreate() only invalidated agentRouter but missed emitting the
pub/sub event for TeamToolManager. Reuse invalidateTeamCaches() which
does both, matching the pattern used by all other team mutations.
2026-03-11 16:54:11 +07:00
fa5f51e72e fix: allow OAuth providers in media tool chain (read_audio, read_image, etc.) (#150)
ExecuteWithChain previously required all providers to implement
credentialProvider (APIKey/APIBase). OAuth-based providers like
CodexProvider (ChatGPT OAuth) don't expose static credentials,
causing all media tools to fail with "does not expose API credentials".

Make credentialProvider optional (nil when unsupported). Each
callProvider gracefully falls back to the provider's Chat() API
when credentials are unavailable. Generation tools (create_image,
create_video, create_audio) return a clear error since they require
direct API access with no Chat fallback.

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
2026-03-11 16:40:35 +07:00
2fdb791802 fix: honor per-agent DB settings for restrict, subagents, memory, sandbox (#145)
Four per-agent settings stored in the database (and configurable via UI)
were silently ignored at runtime because the tool/system layer always
used the global config defaults instead.

**restrict_to_workspace**: Tools used the global config default baked at
startup. Fix: pass per-agent value through context; tools check context
override before falling back to constructor default.

**subagents_config**: ParseSubagentsConfig() existed but was never called.
All agents shared one SubagentManager with global limits. Fix: resolve
per-agent config in the agent resolver, store it on each spawned task,
and use it for limit checks, deny lists, and system prompt generation.

**memory_config**: Only the enabled toggle was read per-agent; search
weights (vector_weight, text_weight, max_results, min_score) were
hardcoded from PGMemoryStore defaults. Fix: extend MemorySearchOptions
with weight overrides, read per-agent config from context in the
memory_search tool.

**sandbox_config**: Only workspace_access was extracted per-agent; mode,
image, memory, CPU, timeout, network settings were discarded. Fix: pass
full sandbox.Config through context; Manager.Get() accepts an optional
config override for new containers.

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
2026-03-11 16:05:56 +07:00
1b99406012 fix: resolve embedding provider from DB registry + per-agent config (#134)
The embedding provider resolution only matched 3 hardcoded names
(openai, openrouter, gemini), silently failing for DB-stored providers
like "openai-embedding". This caused memory chunks to be stored
without vectors even when a valid embedding provider was configured.

Changes:
- resolveEmbeddingProvider: fallback to provider registry for DB-stored
  provider names when hardcoded match fails
- gateway startup: read per-agent memory config from DB (priority over
  config file defaults) for embedding provider resolution
- memory IndexDocument: log embedding errors instead of swallowing them
- memory admin ListChunks: return full chunk text instead of truncating
  to 200 chars, avoiding confusing partial content in the UI

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
2026-03-11 14:31:00 +07:00
viettranx e9e0a4e813 feat(ui): mobile UX improvements for web dashboard (#141)
- Replace h-screen with h-dvh for correct mobile viewport height
- Fix input font-size to 16px on mobile preventing iOS Safari auto-zoom
- Add safe area padding for notched devices (Dynamic Island, home indicator)
- Expand touch targets for icon buttons to ≥44px on touch devices
- Make dialogs full-screen on mobile with slide-up animation
- Add virtual keyboard detection for chat input positioning
- Smooth auto-scroll for incoming messages, instant scroll on user send
- Add overflow-x-auto to table pages for mobile horizontal scroll
- Fix grid layouts to stack on mobile (grid-cols-1 sm:grid-cols-2)
- Safe-area-aware toast positioning
- Landscape compact mode for phone landscape orientation
2026-03-11 14:27:54 +07:00
viettranx ec11698fff docs: add mobile UI/UX rules to CLAUDE.md 2026-03-11 14:26:54 +07:00
Viet TranandGitHub 73389d2715 fix(ui): align usage data contracts, add timezone setting, and fix empty usage page (#146)
- Fix 6 data contract mismatches between Go backend JSON tags and React
  frontend TypeScript interfaces (field renames, response envelope changes)
- Add timezone selector to topbar with 12 common timezone options
- Replace date-fns formatting with native Intl.DateTimeFormat for
  timezone-aware chart labels (reduces bundle ~20KB)
- Add missing SnapshotTimeSeries fields (memory_docs, memory_chunks,
  kg_entities, kg_relations) that caused empty usage page
- Add error banner to usage page for API error visibility
- Sanitize backend error messages in usage HTTP handlers
- Add batch chunking (max 3000 rows) for snapshot upserts
- Remove userId display from topbar
- Add usage analytics i18n strings for en/vi/zh
2026-03-11 14:22:03 +07:00
Viet TranandGitHub 0926d053b0 feat: add token usage tracking, cost analytics, budget enforcement, wake API, and activity audit trail (#142)
- A1+C2: Include token usage in run.completed event payload for WS clients
- A2: Cost tracking with model pricing config, cost calculation, and cost summary API
- A3: Budget enforcement per agent with monthly budget limits (migration 000015)
- C1: External wake/trigger API (POST /v1/agents/{id}/wake) for orchestrators
- C3: Activity audit trail with structured logging and queryable API
- UI: Activity page, cost stat card on overview, budget section in agent detail
- i18n: Complete en/vi/zh translations for all new features
2026-03-11 12:52:12 +07:00
viettranx bef428c124 feat(ui): show webhook URL hint on Lark channel config
Display an info banner with the webhook endpoint path when Feishu/Lark
channel is configured in webhook mode, with a copy button for the path.
2026-03-11 12:20:54 +07:00
Viet TranandGitHub 6a51e8d7c4 fix(zalo): download CDN media to temp file and handle []byte credentials (#130)
Zalo CDN photo URLs are auth-restricted and expire quickly. Download
images to local temp files before passing to the agent, falling back
to the raw URL on failure. Also adds PhotoURL field support.

Credentials Update() now handles []byte type in the switch case,
preventing incorrect encryption when credentials arrive as raw bytes.
2026-03-11 07:58:05 +07:00
Viet TranandGitHub cd2e407b29 fix: auto-persist cleaned history when orphan tool messages detected (#128)
sanitizeHistory now returns dropped count so callers know when orphaned
tool_use/tool_result messages were removed. When orphans are found in
buildMessages, the full session history is sanitized and persisted,
preventing repeated warnings on every request.

- Add SetHistory() to SessionStore interface and both implementations
- Adapt memoryflush caller to new two-return signature
- Change sanitize log level from Warn to Debug
2026-03-11 07:57:54 +07:00
Viet TranandGitHub cc00a6f193 fix: route delegate session keys to correct agent loop (#127)
Delegate session keys (delegate:{uuid8}:{agentKey}:{delegationId}) were
not parsed by makeSchedulerRunFunc, causing fallback to default agent ID
which doesn't exist in managed-mode DBs. Add switch/case to handle both
agent: and delegate: prefixes.
2026-03-11 07:57:51 +07:00
Thieu NguyenandGitHub 8ad580521d refactor: deprecate standalone mode, managed mode is now default (#126)
* refactor: remove managed/standalone mode distinction from codebase

Standalone mode is deprecated; managed mode is now the only mode.
Remove redundant "managed mode" qualifiers from comments, docs,
and error messages. Error strings now reference "database stores"
instead of "managed mode" for clarity.

* improve(onboard): streamline onboard process and env setup

Simplify onboard wizard, extract helpers to dedicated file,
update env example and entrypoint for default managed mode,
clean up prepare-env script, update i18n catalogs.
2026-03-11 07:27:38 +07:00
viettranx c5b886048e fix(cron): inject delivery context into cron job system prompt
Cron jobs ran in isolated sessions with no context about who requested
them or where to deliver responses. The agent would misroute responses
(e.g., using team_message instead of replying to the original chat).

- Inject ExtraSystemPrompt with job name, requester ID, and delivery
  target so the agent knows to produce content directly
- Pass client.UserID() in Web UI cron.create instead of empty string
2026-03-11 07:26:43 +07:00
Nguyễn Hoàng ThứcandGitHub 13a3e25d40 feat(docker): update shared network configuration to specify name and driver (#125) 2026-03-11 07:26:03 +07:00
viettranx ee31387aa1 fix(security): disable config leak detection to prevent false positives
StripConfigLeak was blocking legitimate responses when predefined agents
mentioned SOUL.md/IDENTITY.md/AGENTS.md in architecture explanations.
Improved detection logic to exclude code blocks but disabled the gate
entirely for now until a more robust approach is designed.
2026-03-10 23:11:02 +07:00
viettranx b9e9e6e34a refactor(media): migrate builtin tool settings from legacy flat to chain format
- Update seed defaults to use chain format {"providers":[...]}
- Add startup auto-migration for existing legacy flat settings in DB
- Remove legacy flat format parsing from parseChainSettings()
2026-03-10 22:54:52 +07:00
viettranx fb309c3c2b perf(kg): sync force layout to eliminate render lag; redesign notifications section
Run d3-force simulation synchronously in useMemo (~300 ticks → 1 render
instead of 300). Redesign team notifications section with gradient bg,
Bell icon, and Switch toggle.
2026-03-10 22:31:17 +07:00
viettranx 9c593923a1 chore: Update gitignore to broadly exclude k8s-* directories. 2026-03-10 21:41:00 +07:00
viettranx 4ddbac5dd1 feat: enhance notification settings UI by replacing the checkbox with a Switch component and adding new styling. 2026-03-10 21:28:45 +07:00