Commit Graph
570 Commits
Author SHA1 Message Date
viettranx dba3f4e4e6 fix(agent): prevent "..." fallback when iteration budget exhausted
Add early detection and graceful degradation when the model exhausts its
iteration budget without producing a text response:

- Inject 75% budget nudge telling model to start summarizing
- Strip all tool schemas on final iteration to force text-only response
- Adaptive web_fetch maxChars (60K→20K→10K) via iteration progress context
- Bump DefaultMaxIterations 20→30 for web-research workloads
2026-03-20 17:55:51 +07:00
Viet TranandGitHub 84650c5c14 feat(teams): attachments refactor, semantic search, improved prompting (#310)
* feat(teams): refactor attachments, remove team_message, add task comments UI

Major team system refactoring:

- Drop team_workspace_files, team_workspace_file_versions, team_workspace_comments,
  team_messages tables; replace team_task_attachments with path-based schema
- Add denormalized comment_count/attachment_count on team_tasks for dashboard perf
- Auto-track file writes as task attachments via WorkspaceInterceptor
- Remove team_message tool entirely (tool, store, i18n, builtin_tools, MCP bridge)
- Members communicate via task comments; approve/reject use comments for audit trail
- Add commented/new_task notification types to TeamNotifyConfig
- Enrich task completion announce with member comments
- User-created tasks stay pending (backlog) — no auto-assign to leader
- Configurable member request tasks (member_requests.enabled in team settings)
- Structured task description template in TEAM.md for v2 leads
- HTTP attachment download endpoint with IDOR + path traversal protection
- Web UI: count badges on task list, comments section with input, download button
- Team settings UI: completed/commented/new_task toggles, member requests section

* feat(teams): priority dispatch, compact prompting, realtime comments

- Priority dispatch: DispatchUnblockedTasks dispatches only 1 task per
  owner per round (highest priority first). Fixes cancel bug where
  CancelSession killed innocent queued tasks.
- Prompt rework: Replace verbose Task Decomposition (25 lines) with
  compact Task Planning (8 lines). Add explicit UUID warning and
  sequencing guidance for weak models (Qwen, MiniMax).
- Recent comments in dispatch: buildRecentCommentsSummary appends 3
  most recent comments to re-dispatched tasks (reject, retry, stale).
- Enrich comment event payload with TaskNumber, Subject, CommentText
  (truncated 500 runes, UTF-8 safe).
- UI: Board subscribes to TEAM_TASK_COMMENTED for realtime comment_count
  badge updates. Task detail dialog auto-refreshes comments on event.
- Tool description hint: guide models to write self-contained task
  descriptions with clear objectives and context.

* perf(teams): add ListRecentTaskComments with SQL LIMIT

Dispatch only needs 3 most recent comments — avoid fetching all.
New ListRecentTaskComments(ctx, taskID, limit) uses ORDER BY DESC
LIMIT N then reverses to chronological order.

* feat(teams): add subject embedding for semantic task search + improve prompting

- Add vector(1536) embedding column to team_tasks with HNSW index
- Implement hybrid search: FTS (0.3) + cosine similarity (0.7) with graceful fallback
- Auto-generate embeddings on task create/update, backfill existing tasks on startup
- Wire embedding provider into PGTeamStore via gateway_setup
- Change FTS from OR to AND with prefix matching for precise keyword search
- Reduce search page size from 30 to 5 to save tokens
- Rename migration 000023 → 000024, bump RequiredSchemaVersion to 24
- Update TEAM.md hints: prefer search over list, batch task creation with blocked_by
- Add anti-pattern examples to prevent sequential task creation
2026-03-20 17:51:40 +07:00
viettranx eb318ad8c3 feat(ui): add toast notifications and loading spinners to all save/mutation buttons
- Add userFriendlyError() helper to hide 5xx errors from users
- Add Loader2 animate-spin to all save/update/create/delete buttons
- Add useMinLoading(600ms) to StickySaveBar for visible feedback
- Move toast notifications from components into hooks (single source)
- Remove inline saved/saveError state in favor of toast system
- Add toast to all mutation hooks: agents, channels, skills, builtin-tools,
  sessions, teams, storage, tts, cron, providers, config
- Add i18n toast keys for en/vi/zh across all namespaces
- Deduplicate toast calls in team board components
2026-03-20 15:06:57 +07:00
viettranx 8a3bbab4aa fix(telegram): use bracket notation for media in group history context
Model confused context-history media tags (<media:image>) with current
message media, triggering read_image on non-existent images. Change
lightweightMediaTags() to use descriptive brackets (e.g. [sent an image])
so LLMs can distinguish history descriptions from actionable media tags.
2026-03-20 14:41:44 +07:00
viettranx 38dfcf8bb0 feat(tools): add Defuddle extractor chain for web_fetch (#296)
Add Cloudflare Worker (fetch.goclaw.sh) as primary markdown extractor
with waterfall fallback to built-in HTML→Markdown converter.

Architecture:
- ExtractorChain pattern with quality gate (min 100 chars, 10 words)
- Settings stored in builtin_tools DB table (not config.json5)
- ResolveExtractorChain reads chain from context per-request
- InProcessExtractor delegates to fetchRawContent (full SSRF + domain
  policy checks on redirects)
- DefuddleExtractor with configurable base_url + timeout
- Seed default chain [defuddle, html-to-markdown] for new deployments
- Backfill migration for existing deployments

Web UI:
- Dedicated DnD extractor chain form on builtin tools page
- Drag-and-drop ordering, enable/disable per extractor
- Timeout + base URL config for Defuddle
- i18n support (en/vi/zh)
2026-03-20 14:21:46 +07:00
viettranx b2330086ad fix(agent): harden intent classify — stricter quickClassify, steer vs newTask split
- Reduce quickClassify threshold from 60 bytes to 15 runes to prevent
  false positives (e.g. "làm đơn giản thôi" no longer matches "thôi")
- Use utf8.RuneCountInString for accurate Unicode length check
- Replace substring match with whole-word boundary check to avoid
  false positives like "nonstop" matching "stop"
- Remove statusKeywords; only exact "?" is fast-pathed as status query,
  all other status queries go through LLM classification
- Increase LLM classify timeout from 5s to 10s
- Differentiate steer (inject into running loop) from newTask (queue
  behind active run) instead of treating both as mid-run injection
2026-03-20 13:42:19 +07:00
viettranx f90a5f0974 feat(ui): refactor Provider, Cron, Channels pages with modern UX
- Add detail pages with sticky headers, bordered overview sections,
  and advanced config dialogs for Provider, Cron, and Channels
- Add list-row components for compact list views (no card view)
- Add Provider detail route (/providers/:id)
- Add cron job edit capability (updateJob via CRON_UPDATE RPC)
- Split Channel config into essential (Overview tab) vs advanced (dialog)
- Remove Channel Config tab, merge essential fields into General tab
- Add ViewModeToggle shared component (used by Agent/Team pages)
- Add i18n keys for all new UI elements (en/vi/zh)
- Simplify provider-form-dialog to create-only mode
2026-03-20 13:04:52 +07:00
viettranx 6e94c5fdf8 fix(agent): review fixes for tool call prefix stripping (#259)
- Fix TrimLeft → TrimPrefix to strip only one underscore separator
- Add registryName to indexedResult for parallel path cache
- Use registryName for bootstrapToolAllowlist and loopDetector checks
- Add server-side sanitization for ToolCallPrefix input
- Remove dead chatMessages alias and unrelated ParseStripAssistantPrefill
- Remove orphaned stripAssistantPrefill i18n keys
- Add 13 unit tests for StripToolPrefix
2026-03-20 09:14:28 +07:00
HXD.VNandGitHub ffb536861f feat(agent): tool call prefix stripping for proxy providers (#259)
* feat(agent): support tool call prefix stripping for proxy providers

Proxy providers like LiteLLM and OpenRouter may prepend a prefix to
tool call names returned by the model (e.g. "proxy_exec" instead of
"exec"). This broke tool policy validation, registry lookup, and
hardcoded name checks for "team_tasks" and "spawn" in both serial
and parallel execution paths.

Add per-agent toolCallPrefix configuration that strips the configured
prefix from incoming tool call names before registry resolution. The
stripping is applied at resolveToolCallName() which is called before
permission checks, registry execution, and spawn/team_tasks detection.

- Add StripToolPrefix() supporting literal ("proxy_") and template
  ("{tool_name}") patterns
- Add toolCallPrefix to ToolPolicySpec with backward compat from old
  "toolPrefix" JSON key
- Fix config save using spread operator to prevent dropping new fields
- Add UI input in Tool Policy section with i18n (en/vi/zh)

* chore: ignore AI tool config directories

Add .gemini/, .claude/, .opencode/ to .gitignore to prevent
committing user-specific AI tool configurations.
2026-03-20 09:10:06 +07:00
viettranx 89937edb22 fix(team): prevent task progress regression from model actions 2026-03-20 08:27:18 +07:00
viettranx 60995ff956 fix(skills): treat sibling .py files as local modules in dep scanner
The scanner only tracked subdirectories as local modules, so cross-file
imports like `from extract_form_field_info import ...` were incorrectly
reported as missing pip packages, causing install failures.
2026-03-20 08:26:52 +07:00
Thieu NguyenandGitHub 7f1f126091 fix(docker): make runtime dir creation non-fatal in entrypoint (#288)
On first start with a fresh Docker volume, mkdir for .runtime
subdirectories can fail due to a volume initialisation race condition,
causing the container to restart loop. The directories are only needed
for agent-installed packages (pip/npm), so the failure is non-fatal.
2026-03-20 07:53:29 +07:00
viettranx 9f80842bbc feat(telegram): add voiceguard error sanitization and STT concurrency control (#33)
Cherry-pick two features from PR #33:

- Voiceguard: intercept technical errors (rate limits, tool failures, exit codes)
  in voice agent replies and replace with user-friendly fallback messages.
  Configurable error markers and fallback templates via TelegramConfig.
- STT: shared HTTP client with connection pooling (sync.Once) and concurrency
  semaphore (max 4 concurrent calls) to prevent STT proxy overload.
2026-03-20 07:50:13 +07:00
viettranx a4a7a59b6a fix(sandbox): path isolation, DooD volume mounting, hints, and nginx DNS (#129, #136)
Address issues identified in PR #137 with a cleaner approach:

- Sandbox isolation: add SandboxCwd/ResolveSandboxPath helpers to map
  filesystem tool paths to agent-scoped container subdirectories,
  preventing cross-agent file access via read/write/edit/list tools
- DooD volume mounting: add resolveHostWorkspacePath with multi-strategy
  container ID detection (/proc/self/mountinfo, HOSTNAME, os.Hostname)
  and 5s timeout on docker inspect
- Sandbox hints: expand from 1 pattern (binary not found) to 6 patterns
  (permission denied, network disabled, read-only FS, missing file,
  resource limits) with MaybeFsBridgeHint for filesystem tools
- Nginx DNS: add Docker resolver (127.0.0.11) with dynamic upstream
  variable to handle backend container IP changes
- MCP args: switch from comma-separated to space-separated parsing
  with quote support for --flag="value with spaces" patterns
- Refactor: rename ExecTool.workingDir to workspace for consistency,
  extract sandbox.DefaultContainerWorkdir constant
2026-03-20 07:32:23 +07:00
viettranx a8fecfb3b1 refactor(ui): replace native window.confirm with ConfirmDialog for task deletion
Unify confirmation UX — task-list and board-container now use the shared
ConfirmDialog component instead of browser-native window.confirm().
2026-03-20 07:23:19 +07:00
d9dffc66e7 docs: restructure README — hub-and-spoke pattern, fix accuracy (#285)
* docs: restructure README with i18n, static diagrams, and accuracy fixes

Restructure:
- Reduce README from ~950 to ~280 lines (hub-and-spoke pattern)
- Move Project Status to CHANGELOG.md
- Add hero section: centered title, tagline, description, badges
- Add nav links: Documentation, Quick Start, Twitter/X (OpenFang pattern)
- Add Documentation table linking all docs.goclaw.sh sections
- Replace 3 mermaid diagrams with static images for consistent rendering

Accuracy fixes:
- Fix provider count: 13+ → 20+ (verified from gateway_providers.go)
- Fix "5-layer defense" → 5-layer permission system per policy.go
- Add missing features: Heartbeat, Scheduling/Cron, Observability
- Fix all docs URLs to docs.goclaw.sh hash routing
- Add VPS $5 minimum 2GB RAM note for Docker

Internationalization (30 languages, ZeroClaw coverage):
zh-CN, ja, ko, vi, tl, es, pt, it, de, fr, ar, hi, ru, bn, he,
pl, cs, nl, tr, uk, id, th, ur, ro, sv, el, hu, fi, da, nb
- Keep product feature names in English: Extended Thinking, Heartbeat
- Vietnamese README hand-tuned for natural phrasing

* docs: move translated READMEs to _readmes/ directory

Keep all 30 language translations but declutter the project root.
Fix relative links (_statics/, cross-language, main README) for new location.
Update main README language selector to point to _readmes/.

---------

Co-authored-by: viettranx <viettranx@gmail.com>
2026-03-20 07:10:47 +07:00
viettranx 71af1a6bdd fix(i18n): add missing zh locale keys for ChatGPT OAuth setup 2026-03-20 06:56:25 +07:00
Plateau NguyenandGitHub 43990c7e56 Fix ChatGPT OAuth setup wizard flow (#289) 2026-03-20 06:54:11 +07:00
Plateau NguyenandGitHub c1893c73d1 fix: normalize delete confirmation matching (#290) 2026-03-20 06:48:48 +07:00
viettranx cc43f78b4b fix(agent): correct within-turn duplicate tool call ID pairing in sanitizeHistory
Replace single-value idRemap with queue-based idQueue so multiple tool
results sharing the same original ID pair correctly in encounter order.
Previously the map overwrote on duplicates, causing the second result to
be dropped and a synthetic placeholder to be emitted instead.
2026-03-20 06:39:58 +07:00
55bc752773 fix(agent): handle duplicate tool call IDs in OpenAI-compatible transcripts (#283)
* fix(agent): handle duplicate tool call IDs with occurrence-aware sanitization

* refactor(agent): simplify duplicate tool call ID handling

Replace complex occurrence-aware queue system with simpler approach:
- uniquifyToolCallIDs: append runID+iteration+index to all IDs at
  response time, guaranteeing cross-turn uniqueness via UUID
- sanitizeHistory: simple seen-set dedup for legacy sessions with
  pre-existing duplicate IDs, no queue/counter logic needed
- Restore full problem description in sanitizeHistory docstring
- Add unit tests for both dedup paths and edge cases

---------

Co-authored-by: viettranx <viettranx@gmail.com>
2026-03-20 06:32:38 +07:00
viettranx eb39a46d57 fix: propagate IsError in parallel tool execution path
The squash merge of #291 missed the parallel tool execution path.
Tool errors running in parallel still displayed as "Done" instead
of "Failed" when reloading chat history.
2026-03-20 06:32:13 +07:00
18211154d0 fix: correct tool calling error status display in chat history (#291)
Co-authored-by: Chung Tran <chung.tran@diqit.io>
2026-03-20 06:28:34 +07:00
viettranx e13db25919 fix(ui): wire drag-and-drop file upload in chat view
Lift file state from ChatInput to ChatPage so DropZone.onDrop can
append dropped files to the shared state. Previously drag-and-drop
showed the overlay but never passed files to the input.
2026-03-20 00:27:14 +07:00
badgerbeesandGitHub 9100f981d7 fix(providers): robust Gemini thought_signature detection and history mapping
Improves supportsThoughtSignature with providerType and model normalization.
Strengthens collapseToolCallsWithoutSig with TrimSpace and camelCase support
to handle 'Thinking=OFF' whitespace signatures and proxy key translations.
2026-03-20 00:14:33 +07:00
badgerbeesandGitHub bc16af3797 fix(agent): handle duplicate tool call IDs in OpenAI-compatible transcripts
Simplified approach to fix duplicate tool_call_ids that cause HTTP 400 on OpenAI-compatible APIs (OpenRouter, vLLM, DeepSeek).

- uniquifyToolCallIDs: appends runID+iteration+index to all IDs at response time, guaranteeing cross-turn uniqueness via UUID
- sanitizeHistory: simple seen-set dedup for legacy sessions with pre-existing duplicate IDs
- Anthropic guard: skips ID rewriting when RawAssistantContent is present
- Unit tests for both paths + edge cases

Closes #283
2026-03-20 00:10:52 +07:00
viettranx cb93559154 fix(channels): allow config field in channel instance updates
Add "config" to channelInstanceAllowedFields so channel config changes
from the UI are actually persisted to the database instead of being
silently dropped by the allowlist filter.
2026-03-19 23:47:51 +07:00
GoonandGitHub 1454614ca8 feat: add MiniMax-M2.7 model, custom model input, combobox UX fix, mobile font-size audit (#282)
- Add MiniMax-M2.7 to minimax_native provider model list
- Fix combobox dropdown UX: show all options on re-focus instead of filtering by current selection
- Add allowCustom prop to combobox for typing custom model names not in the list
- Add i18n key useCustomModel for EN/VI/ZH
- Audit all raw input/select/textarea elements across web UI to use text-base (16px) on mobile, preventing iOS Safari auto-zoom on focus
2026-03-19 23:47:11 +07:00
viettranx 49540651af fix(ui): session title live update + solid card backgrounds
- Listen for session.updated event to update sidebar labels in-place
- Replace bg-muted/30 with bg-muted on chat cards so dotted background
  pattern does not bleed through
2026-03-19 23:34:57 +07:00
viettranx 4da85913a2 feat(chat): auto-generate conversation titles via lightweight LLM call
After the first agent run completes, generate a short title from the
user's message using a 10s/50-token LLM call. Title is stored in the
session label column and pushed to clients via session.updated event.
2026-03-19 23:34:45 +07:00
viettranx 24ad97af31 feat(agent): add read-only streak + same-result loop detection
Detect agents stuck in read-only loops (consecutive non-mutating tool
calls) and same-result patterns (identical outputs from different args).
Warns at threshold, force-stops at critical.
2026-03-19 23:34:34 +07:00
viettranx eec083c91a docs: add ErrorBoundary key + route params rules to CLAUDE.md 2026-03-19 22:39:41 +07:00
viettranx 886ef64aec feat(ui): delete chat conversation from sidebar
- Add deleteSession() to useChatSessions hook
- Trash icon on session rows (hover-reveal, always visible on mobile)
- Simple confirm dialog (no typing required)
- If active session deleted, switch to next or create new
- i18n strings for en/vi/zh
2026-03-19 22:39:34 +07:00
viettranx 45295bc75a fix(ui): eliminate full-page flash on chat session switch
Root cause: ErrorBoundary in AppLayout used key={location.pathname},
causing React to unmount/remount the entire page on every URL change.

- Add stableErrorBoundaryKey() that strips dynamic segments from pathname
- Merge /chat and /chat/:sessionKey into single /chat/:sessionKey? route
- Derive sessionKey from useParams() instead of duplicating into useState
  (dual state caused race condition: setState + navigate → B→A→B bounce)
- Move session reset from render-time setState to useEffect
- Only show loading spinner when messages array is empty
2026-03-19 22:38:06 +07:00
viettranx b80ee0ae43 feat(sandbox): hint LLM when tool/binary missing in sandbox container
Detect exit code 127 and "command not found" patterns in sandbox
execution paths and append a [SANDBOX] hint to the error output,
so the model can inform the user about sandbox environment limitations.

Only applies to sandbox execution — host paths are untouched.
2026-03-19 22:17:29 +07:00
viettranx 711395f81f fix(ui): chat polish — floating bar, dotted bg, tool icon, flash fix
- Chat input bar: floating with backdrop blur and rounded corners
- Chat thread: dotted background pattern matching kanban board
- Tool call cards: blue Wrench icon for completed (was green Check)
- Memo wrap ChatSidebar, SessionSwitcher, ChatThread to prevent re-renders
- Keep old messages visible during session switch to prevent flash
2026-03-19 21:47:46 +07:00
viettranx 8409db5890 feat(ui): adopt canonical WS session key format + channel filter
- buildNewSessionKey uses agent:{id}:ws:direct:{uuid} format
- sessions.list sends channel:"ws" to filter WS-only sessions
- isOwnSession supports both new and legacy key formats
- Read-only bar now floating with rounded corners
2026-03-19 21:47:35 +07:00
viettranx 6b747d7571 fix(sessions): auto-migrate legacy ws-{userId}-{ts} keys to ws:direct:{ts}
Runs idempotent regex migration at PGSessionStore init to convert
legacy WS session keys to canonical format. Handles multi-hyphen
userIDs (UUIDs) by matching last segment as timestamp.
2026-03-19 21:47:26 +07:00
viettranx 642797f079 feat(sessions): canonical WS session key format + channel/user filtering
- Add BuildWSSessionKey() and IsWSSession() helpers for ws:direct:{convId} format
- Change ChatID to userId (not clientID) for consistent team/workspace isolation
- Add Channel and UserID fields to SessionListOpts with dynamic WHERE builder
- Extract shared buildSessionFilter() for ListPaged and ListPagedRich
- Chat sidebar sends channel:"ws" to filter WS-only sessions per user
- Sessions admin page remains unfiltered (no channel param)
2026-03-19 21:47:15 +07:00
3f9401257c feat(telegram): networking isolation and sticky IPv4 fallback (#278)
* fix(telegram): isolated transport, sticky fallback, and overall timeouts

* fix(telegram): improve networking isolation for high-concurrency

- Tune MaxIdleConnsPerHost to 64 (default 2 starves concurrent sends)
- Fix data race in enableIPv4Only using sync.Once
- Add force_ipv4 config option for explicit IPv4-only mode
- Narrow auto-detect heuristic to "unreachable" only (avoid false-positive on timeouts)
- Use bot username instead of token prefix in logs
- Extract applyIPv4Dialer helper for reuse between config and runtime paths

---------

Co-authored-by: viettranx <viettranx@gmail.com>
2026-03-19 20:45:49 +07:00
viettranx 1452d9e8f3 docs: add solution design guideline to CLAUDE.md
Require root cause analysis and production scenario thinking
(high concurrency, multi-tenant, failure cascades) before designing
fixes or features. Prefer explicit config over runtime heuristics.
2026-03-19 20:39:44 +07:00
viettranx 15916823e0 feat(ui): integrate chat redesign + file preview modal
- ChatThread: merge consecutive tool-only messages, use ActiveRunZone
- ChatPage: add ChatTopBar, DropZone, pass new hook state
- MessageBubble: compact tool-only layout, block reply support
- ToolCallCard: compact mode with smaller padding
- AgentSelector: show emoji from other_config
- SessionSwitcher: friendly labels (Chat xxx instead of raw keys)
- FileBlock: click opens rich content modal with download button
- MarkdownRenderer: intercept /v1/files/ links as file chips with
  inline download icon, modal preview for md/code/audio/video/image
2026-03-19 19:01:51 +07:00
viettranx a9ec6302ca feat(ui): redesign chat with real-time event handling
Add 8 new chat components and extend use-chat-messages hook to handle
block.reply, activity, run.retrying, and team.task.* events.

New components: ActiveRunZone, ActivityIndicator, BlockReplyBubble,
SystemNotification, TeamActivityPanel, MediaGallery, ChatTopBar, DropZone.
2026-03-19 19:01:37 +07:00
viettranx b1b7bfbe69 fix(ws): detach agent runs from HTTP request context
Agent runs were tied to the HTTP request context, so navigating away
cancelled the LLM stream. Now uses context.WithoutCancel() to survive
page navigation while preserving explicit chat.abort support.
2026-03-19 19:01:19 +07:00
viettranx 78ffc57a8e fix(ws): propagate origin_session_key for team task announces
Team task announces rebuilt session keys via BuildScopedSessionKey(),
producing different format than WS sessions (ws:direct:uuid vs
ws-userId-ts). Now stores and forwards origin_session_key through
task metadata and dispatch, matching subagent announce pattern.

Also adds "ws" to InternalChannels to suppress spurious warnings.
2026-03-19 19:01:10 +07:00
2c1efa29ec fix(memory): prevent silent data loss on memory file overwrites (#279)
* fix(memory): auto-backup + overwrite warning for memory files

When an agent writes to a memory file that already has content:
1. Old content is backed up to memory/.prev/{filename} (best-effort)
2. Write succeeds normally (no blocking)
3. Tool result includes warning with previous content (truncated to
   4000 chars) so the agent can notice and merge if needed

Backup files are hidden from list_files and not indexed/embedded.
No database migration needed - uses existing PutDocument.

* fix(memory): support append mode + fix UTF-8 truncation in overwrite warning

- Add appendMode parameter to MemoryInterceptor.WriteFile() so
  write_file(append=true) actually appends to memory files instead
  of silently replacing content. Uses "\n\n---\n\n" separator.
- Fix UTF-8 truncation in overwrite warning: use []rune instead of
  byte slicing to avoid cutting multi-byte characters.
- Fix char count in warning message: use len([]rune()) not len().
- Remove .prev/ backup mechanism (prevBackupPath, isPrevPath, backup
  writes, ListFiles filter) in favor of simpler approach: append
  mode prevents data loss, warning enables self-correction.

---------

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
Co-authored-by: viettranx <viettranx@gmail.com>
2026-03-19 17:42:03 +07:00
bb783b952c feat(feishu): add list_group_members tool + native @mention support (#280)
* feat(feishu): add list_group_members tool + native @mention support

Add agent tool to list all members in a Lark group chat via
GET /open-apis/im/v1/chats/{chat_id}/members with auto-pagination.

- New tool `list_group_members`: returns member IDs + display names
- Native @mention conversion: @ou_xxx in outbound messages becomes
  real Lark mentions (post: "at" element, card: <at> markdown tag)
- Auto-sync discovered members into ContactStore
- GroupMemberProvider interface on Channel for extensibility
- Add im:chat.members:read scope to channel setup UI

Requires Lark app scope: im:chat.members:read

* fix(feishu): URL-encode API params + channel-aware tool filtering

- URL-encode chatID (PathEscape) and pageToken (QueryEscape) in
  ListChatMembers to prevent path traversal and query corruption
- Add slog.Warn when ListGroupMembers fails for observability
- Add ChannelAware interface so tools can declare required channel types
- ListGroupMembersTool now declares RequiredChannelTypes=["feishu"]
- loop.go filters out channel-specific tools when channel type mismatches,
  so list_group_members only appears for Feishu conversations

---------

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
Co-authored-by: viettranx <viettranx@gmail.com>
2026-03-19 17:21:38 +07:00
viettranx ec24b982f3 fix(subagent): replace bare count with deterministic roster in announce messages
Subagent announce messages told the parent LLM "There are still X active
runs" — a bare number. The LLM had to reconstruct which subagents were
done vs running from conversation history, causing hallucination when
results arrived out of order.

Replace with a full roster listing each subagent by label and status,
including per-agent config limits. Remove dead CountRunningForParent()
and unused rosterFunc field on AnnounceQueue.
2026-03-19 16:33:54 +07:00
viettranx 941a9657ca docs: add heartbeat system documentation
Document the agent heartbeat check-in mechanism covering architecture,
configuration, ticker loop, execution flow, suppression, delivery,
RPC methods, agent tool, frontend integration, and heartbeat vs cron
comparison.
2026-03-19 14:34:10 +07:00
efd3d15c70 fix: agent add cron within invalid params (#277)
Co-authored-by: Chung Tran <chung.tran@diqit.io>
2026-03-19 14:15:46 +07:00