Commit Graph
335 Commits
Author SHA1 Message Date
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
viettranx b7f4082145 feat(mcp): add agent count column and mask sensitive values in form
- Add agent_count to MCP server list API via CountAgentGrantsByServer query
- Show Agents column in MCP servers table
- Mask sensitive header values (Authorization, API keys) and env vars
  (keys containing secret/token/password) in create/edit form
2026-03-10 21:28:03 +07:00
viettranx 9e8e5b7297 feat(kg): session-based scope picker, dark mode support, inline agent select
Replace manual user_id text input with select dropdown populated from
sessions (DM + group chats). Add colorMode prop to ReactFlow for dark
mode Controls/MiniMap. Add agent select in empty state.
2026-03-10 20:58:30 +07:00
9a0557c7a3 fix(tools): allow read_file to access CLI workspaces directory (#122)
- Add ~/.goclaw/cli-workspaces/ to read_file allowed paths
- Enables agents to read working files from CLI workspace sessions

Co-authored-by: Nam Nguyen Ngoc <namnn.0911@gmail.com>
2026-03-10 20:58:10 +07:00
viettranx 33e75820e3 fix(security): add identity anchoring for predefined agents against social engineering
Predefined agents were vulnerable to conversational identity manipulation
(e.g. "I'm your master", "you only listen to me") — users could establish
authority through chat history, causing the agent to comply in subsequent messages.

Added identity anchoring at 3 system prompt zones (predefined agents only):
- Primacy: explicit instruction after Safety section
- Middle: USER_PREDEFINED.md owner authority framing
- Recency: persona reminder reinforcement
2026-03-10 20:56:54 +07:00
viettranx 5d64866be2 feat(memory): resolve user IDs to contact names in scope labels
Use useContactResolver hook to show display names instead of raw
user IDs in the memory documents scope filter and table.
2026-03-10 20:33:32 +07:00
viettranx 554e551386 fix(kg): use flex layout for full-height graph rendering
Replace fixed h-[500px] with flex-1 min-h-0 so graph fills available
viewport. Fix knowledge graph page and entities tab containers.
2026-03-10 20:33:24 +07:00
viettranx bec670ead0 fix(pending-messages): run compaction in background, return 202 Accepted
LLM summarization (30-120s) was blocking HTTP response causing browser
timeouts. Now runs in goroutine and returns immediately. UI polls every
5s until completion.
2026-03-10 20:33:16 +07:00
viettranx 06ac35eeb1 fix(compaction): use DB count for threshold check after server restart
MaybeCompact relied on RAM count which resets to 0 on restart (LoadFromDB
is a no-op). Messages accumulated in DB but never triggered compaction.
Now falls back to CountByKey DB query when RAM count is below threshold.
2026-03-10 20:33:08 +07:00
viettranx fab9028b05 feat(sessions): context usage progress bar with token estimation
Replace channel column with context usage bar showing estimated tokens
vs compaction threshold. Token count estimated from messages JSONB
(octet_length/4 + 12K system prompt) — no migration needed.
Color-coded: green <60%, amber 60-85%, red >85%. Inline compaction
count with refresh icon.
2026-03-10 20:32:58 +07:00
a4f2d02a80 fix(channels): annotate DM messages with sender identity (#120)
* fix(channels): annotate DM messages with sender identity

Telegram and Zalo group messages already include [From: sender] prefix
so the agent knows who is talking, but DM messages were sent without
any sender context — the agent had no way to address the user by name.

- Telegram DM: add [From: @username] (or FirstName if no username)
- Zalo DM: add [From: displayName] when dName is present in payload

* fix(tests): add missing EnsureUserProfile to test stubs

AgentStore interface gained EnsureUserProfile in 4fce731 but the test
stub implementations were not updated, breaking CI on main.

---------

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
2026-03-10 19:25:55 +07:00
viettranx 39b0104a7c feat: remove Custom Tools sidebar item and Wrench icon. 2026-03-10 19:04:09 +07:00
viettranx a3cc993515 fix(i18n): localize compaction tooltips and add contact insert i18n keys
Replace hardcoded English tooltip strings in compaction config with
t() calls. Add insertContact, searchContacts, noContactsFound i18n
keys across en/vi/zh.
2026-03-10 18:46:44 +07:00
viettranx fffdc0b082 feat(agents): contact search insert in file editor for predefined agents
Add inline contact search above textarea in file editor (predefined
agents only). Search contacts and click to insert formatted snippet
at cursor position. Also make USER.md clickable in sidebar.
2026-03-10 18:46:44 +07:00
viettranx bf970c4ff2 feat(kg): separate Knowledge Graph page, auto-fit zoom, compact layout
Extract KG from Memory page into standalone /knowledge-graph route.
Fix graph zoom: fitView after D3 force simulation settles so all nodes
are visible. Compact layout: merge stats/search/actions into single row,
inline filters with page header.
2026-03-10 18:46:44 +07:00
viettranx 4fce73198d feat(agents): contact search in instances tab with auto profile creation
Add searchable contact dropdown in instances sidebar to find channel
contacts and add them as agent instances. Backend EnsureUserProfile
creates user_agent_profiles row on demand when admin adds contacts.
2026-03-10 18:46:44 +07:00
viettranx d301c64dd0 refactor(ui): restructure sidebar into 7 groups, keep Nodes/TTS untranslated
Regroup sidebar from 4 to 7 sections (Core, Conversations, Connectivity,
Capabilities, Data, Monitoring, System) for better organization. Keep
technical terms Nodes and TTS as-is across all languages.
2026-03-10 18:46:44 +07:00
viettranx f073c5d275 fix(ui): contacts filter button height and chat send button alignment
- Contacts page: change filter button to default size to match h-9 inputs
- Chat input: adjust textarea padding (py-2.5) to align with send button
- Add batch resolver i18n keys for contacts page
2026-03-10 18:46:44 +07:00
viettranx 23f1957c56 feat(channels): wire contact auto-collector across all channel handlers
Pass contactCollector through channel manager to all channel handlers
(Telegram, Discord, Feishu, Slack, Zalo) so contacts are automatically
collected when users interact with the agent.
2026-03-10 18:46:44 +07:00
2495ff253c fix(ui): wire allowEmpty for embedding provider select (#112)
The `allowEmpty` prop on `ProviderModelSelect` was defined but the
Select dropdown still auto-selected the first provider when the value
was empty, and there was no way to reset back to empty (auto-detect).

- Map empty provider to a sentinel so Radix Select can represent it
- Show an "(auto)" option in the dropdown when `allowEmpty` is set
- Pass `allowEmpty` from both embedding config callers
- Skip clearing the model on provider change in allowEmpty mode to
  avoid a stale-closure bug where the second setState overwrites the
  provider update

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
2026-03-10 18:45:09 +07:00
25fd9c9d6d feat(cron): configurable default timezone for cron expressions (#117)
* feat(cron): configurable default timezone for cron expressions

Cron expressions (e.g. "0 8 * * *") are evaluated relative to a timezone.
Without an explicit per-job timezone, they default to the server's system
timezone, which may not match the user's local time — especially in Docker
containers (default UTC) or multi-region deployments.

This adds a `default_timezone` setting to `CronConfig` (IANA format, e.g.
"Asia/Ho_Chi_Minh") that is applied as fallback when a cron job has no
explicit `schedule.tz`. The setting is configurable via the UI config page
(Integrations → Cron Scheduler) and hot-reloads on config changes.

Backend:
- Add `DefaultTimezone` field to `CronConfig`
- Add `SetDefaultTimezone()` to `CronStore` interface + PG implementation
- Apply default TZ in `AddJob()` when `schedule.TZ` is empty
- Wire at startup + subscribe to config change events for hot reload
- Update cron tool description so LLM knows about gateway default

Frontend:
- Add timezone dropdown (20 common IANA timezones) to Cron config section
- Add i18n keys for en, vi, zh

* fix(cron): apply default timezone to existing jobs via computeNextRun

Pass defaultTZ as fallback to computeNextRun so existing cron jobs
(with timezone = NULL in DB) also use the gateway's configured default
timezone when computing next_run_at. This ensures old jobs benefit
from the timezone setting without needing a DB migration or backfill.

---------

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
2026-03-10 18:44:28 +07:00
therichardngai-codeandGitHub d874266e87 feat(providers): add Ollama local and Ollama Cloud provider support (#113)
* feat(providers): add Ollama local and Ollama Cloud provider support

Adds two new provider variants:

ollama — local/self-hosted Ollama instance
- Gated on providers.ollama.host in config (or GOCLAW_OLLAMA_HOST env)
- No API key required; Ollama's OpenAI-compat endpoint accepts any Bearer value
- Defaults to http://localhost:11434/v1 (configurable for LAN/remote hosts)
- Default model: llama3.3

ollama-cloud — Ollama Cloud (managed remote inference)
- Gated on providers.ollama_cloud.api_key (or GOCLAW_OLLAMA_CLOUD_API_KEY env)
- Bearer token from ollama.com/settings/keys
- Default base URL: https://ollama.com/v1 (overridable via api_base)
- Default model: llama3.3

Both variants use the existing NewOpenAIProvider (OpenAI-compat) — no new
provider struct needed. Both are registered from config file and DB (via
llm_providers table with ProviderOllama / ProviderOllamaCloud types).

OllamaCloud.APIKey follows all existing secret handling patterns:
MaskedCopy, StripSecrets, StripMaskedSecrets.

* feat(providers): wire Ollama into web UI and fix DB registration

- Add ollama + ollama_cloud to PROVIDER_TYPES constants (dropdowns)
- Fix setup wizard: skip API key requirement for Ollama local (isOllama)
- Fix bootstrap status: recognize Ollama local as no-API-key provider
- Add ollama_cloud to config-page KNOWN_PROVIDERS list
- Fix gateway_providers.go: move ProviderOllama before APIKey=='' guard
  so DB-registered local Ollama providers actually register at startup
  (same pattern as ClaudeCLI, which also needs no API key)
2026-03-10 18:43:02 +07:00
456e594b8f fix(config): treat GOCLAW_PROVIDER/MODEL env vars as fallback, not override (#119)
The onboard wizard sets GOCLAW_PROVIDER and GOCLAW_MODEL in .env for
initial bootstrap. Previously these env vars always overrode the config
file value via envStr(), making it impossible to change the default
provider/model through the Dashboard — every save was silently reverted
by ApplyEnvOverrides().

Change envStr to envFallback for these two fields: the env var is only
applied when the config file has no value (empty string). Once the user
saves a provider/model via the Dashboard, the config-file value wins.

Also:
- Stabilize ProviderModelSelect auto-select effect (useRef + useMemo)
- Add toast feedback on config save success/failure

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
2026-03-10 18:41:39 +07:00
viettranx 2fed2a57d3 fix(compaction): memory flush never triggering due to threshold mismatch
Flush threshold (176K) was higher than compaction threshold (150K), so
flush was always skipped. Removed independent threshold calculation —
flush now always runs before compaction, gated only by enabled check and
per-cycle dedup guard. Also localized hardcoded compaction tooltips
(en/vi/zh), fixed inaccurate Memory Flush description, and removed dead
reserveTokensFloor/softThreshold UI inputs.
2026-03-10 17:28:55 +07:00
viettranx 9181eebcea fix(channels): defer media download, fix compaction status & context cancel
- Defer Telegram media download until after mention gate — pending
  history now uses lightweight tags (no download) saving bandwidth
  and avoiding errors on large files
- Fix compaction status query: has_summary now false when new messages
  arrive after last compaction, re-enabling the compact button
- Fix HTTP compact endpoint: detach context from request so LLM
  summarization isn't cancelled when browser closes connection
2026-03-10 17:12:13 +07:00
viettranx f1953203c4 feat(contacts): batch resolver API, shared hooks & contact integration across agent UI
- Add GetContactsBySenderIDs batch lookup to ContactStore (DISTINCT ON sender_id)
- Add GET /v1/contacts/resolve?ids= endpoint (max 100 IDs)
- Extract useContactPicker hook from managers tab (DRY refactor)
- Create useContactResolver hook for batch ID→name resolution via React Query
- Agent Shares tab: replace Input with Combobox contact picker + resolve names in list
- Agent Instances tab: resolve user_id to contact name as fallback
- Update i18n placeholders for contact search (en/vi/zh)
2026-03-10 16:56:17 +07:00