Commit Graph
601 Commits
Author SHA1 Message Date
Tyler VoandClaude Opus 4.6 ab09deecd7 perf: wire embedding_cache table into IndexDocument hot path
The embedding_cache table existed in the schema but was never queried.
IndexDocument() now batch-checks the cache before calling the embedding
API, writes fresh results back, and merges cached + fresh vectors.

Graceful fallback: if cache lookup fails, falls through to full API call.

Closes #326

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 13:11:24 +07:00
viettranx c50ce7c48e fix(ui): usage tab crash, chat layout overflow, marker color
- Fix ErrorBoundary retry to remount children via Fragment key counter
- Guard PieChart against zero-total slices and single-slice paddingAngle
- Disable Recharts animations to prevent state corruption on rapid filter
- Add per-section ErrorBoundary in usage page and per-donut isolation
- Fix Brush key to be content-aware for proper reset on filter change
- Fix chat page flex containment chain (overflow-hidden, min-h-0, shrink-0)
- Fix list marker color: use currentColor instead of hardcoded foreground
2026-03-21 12:55:16 +07:00
viettranx e2c131c57d feat(ui): add image download overlay, improve agent selector defaults
- Add hover download button with filename/size on chat image thumbnails
- Add download button and file info bar to image lightbox overlay
- Add hover download button on inline markdown images
- Increase agent selector dropdown height on desktop (sm:max-h-80)
- Select default agent (is_default) instead of first in list
- Increase session title generation timeout to 120s
2026-03-21 12:01:04 +07:00
394ded7836 fix(skills): parse YAML multiline blocks and lists in skill frontmatter (#325)
* fix(skills): parse YAML multiline blocks and lists in skill frontmatter

parseSimpleYAML and ParseSkillFrontmatter only handled single-line
key: value pairs. YAML multiline block scalars (|, >) and list values
(- item) were parsed incorrectly:

  description: |
    Multi-line text here...

was stored as description="|" (literal pipe character), and indented
continuation lines were misinterpreted as new key-value pairs.

Fix: parseSimpleYAML now tracks indented continuation lines after
block scalar indicators (|, >, |-, >-) and empty-value keys (for
list blocks). Continuation lines are joined with spaces. List items
(- value) have the prefix stripped.

ParseSkillFrontmatter now delegates to parseSimpleYAML instead of
duplicating the parsing logic.

* fix(skills): preserve empty-value keys in parseSimpleYAML

When a key has no value and no indented continuation (e.g. "slug:"),
flushBlock now stores "" instead of silently dropping the key.
Maintains backward compatibility with the previous parser behavior.

---------

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
Co-authored-by: viettranx <viettranx@gmail.com>
2026-03-21 08:58:21 +07:00
Luan VuandLuvu182 f3b344d731 fix(pkg-helper): fix apk-packages persist file not writable in Docker (#324)
The .runtime directory on the data volume may be owned by goclaw:goclaw
(from older images or Docker volume initialization). pkg-helper runs as
root but without CAP_DAC_OVERRIDE, so it cannot create files in
goclaw-owned directories. This caused persistAdd() to fail silently —
runtime-installed system packages (bash, pandoc, etc.) were lost on
container recreate.

Fix: set .runtime directory ownership to root:goclaw (mode 0750) so
pkg-helper can write apk-packages while goclaw can still traverse.
Three layers for robustness:

- Dockerfile: pre-create .runtime with correct split ownership in image
- docker-entrypoint.sh: fix ownership on existing volumes (upgrade path)
- pkg-helper: self-healing ensurePersistDir() at startup as defense-in-depth

Subdirs (pip/, npm-global/, pip-cache/) remain goclaw-owned since those
are written by the app process, not pkg-helper.

Fixes #323

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
2026-03-21 08:35:31 +07:00
ebc4a22fd2 fix(skills): use DB file_path for directory resolution + list archived skills (#322)
* fix(skills): use DB file_path for skill directory resolution + list archived skills

Two fixes:

1. Skills store methods (ListSkills, ListAllSkills, GetSkill, GetSkillByID,
   LoadSkill) constructed BaseDir from s.baseDir + slug + version, ignoring
   the file_path column stored in the database. When GOCLAW_DATA_DIR differs
   from the directory used during initial skill seeding, this caused
   dependency rescans to look in the wrong directory, find no scripts, and
   silently skip — leaving missing_deps stale in the database even after
   successful pip/npm installs.

   Fix: buildSkillInfo now accepts an optional filePath parameter from the
   DB and uses it as the authoritative BaseDir when set.

2. ListSkills only returned skills with status='active', hiding archived
   skills from the admin UI. Skills with missing dependencies are archived
   on seed, making them invisible — admins couldn't see them to install
   deps and reactivate. Now includes archived skills in the listing.

* fix(skills): use 'deleted' status for soft-delete, distinct from 'archived'

DeleteSkill previously set status='archived', which is also used for skills
with missing dependencies. Now that ListSkills includes archived skills
(so admins can see and fix missing deps), soft-deleted skills were
reappearing after page refresh.

Use status='deleted' for user-deleted skills to keep them hidden while
allowing archived (missing deps) skills to remain visible in the admin UI.

* fix(skills): complete file_path resolution + exclude deleted from rescan

- ListAllSkills: add `status != 'deleted'` to prevent rescan from
  resurrecting user-deleted skills
- ListAccessible: add file_path to SELECT so runtime skill resolution
  uses DB path instead of stale baseDir
- SearchByEmbedding: use DB file_path when available for path resolution
- CreateSkillManaged: ON CONFLICT visibility reset now matches both
  'archived' and 'deleted' statuses
- Update delete result message and status comment

---------

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
Co-authored-by: viettranx <viettranx@gmail.com>
2026-03-21 08:00:39 +07:00
Luan VuandLuvu182 19d34aacec fix(mcp): add empty properties to object schemas for OpenAI compatibility (#321)
MCP tools that accept no parameters return {type: "object"} without a
properties field, which is valid per JSON Schema spec. However, OpenAI
API strictly requires "properties" on object schemas and rejects
requests with HTTP 400: "object schema missing properties".

Add default empty properties map when type is "object" and the MCP
server provides none.

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
2026-03-21 07:35:24 +07:00
badgerbees 7200ecb7fe feat(providers): add native Azure OpenAI and Foundry header support (#319) 2026-03-21 07:33:18 +07:00
badgerbeesandviettranx 551b6670d5 fix(tools): resolve Windows build errors and harden filesystem security (#318)
* fix(tools): resolve Windows build errors and harden filesystem security

* fix(tools): remove stale Windows skip in hardlink test

Now that checkHardlink uses GetFileInformationByHandle on Windows,
the test should run on all platforms.

---------

Co-authored-by: viettranx <viettranx@gmail.com>
2026-03-21 07:29:48 +07:00
badgerbees adb81d1069 feat(channels): enforce MediaMaxBytes for outbound media uploads in Telegram and Discord (#317) 2026-03-21 07:14:58 +07:00
viettranx 66a8029d26 fix(teams): wire post-turn processor for HTTP API and wake endpoints
Post-turn team task dispatch was only wired for WS chat.send path.
Now also wired for /v1/chat/completions, /v1/responses, and
/v1/agents/{id}/wake HTTP endpoints so team tasks dispatch correctly
from all API entry points.
2026-03-20 23:18:58 +07:00
viettranx be770252e6 fix(teams): inject PendingTeamDispatch in WS chat.send path
WS handleSend called loop.Run() directly without injecting
PendingTeamDispatch into context, bypassing the gate that requires
search/list before team task creation (ptd was nil → gate skipped).

- Add InjectTeamDispatch helper: creates ptd, returns drain func
  that dispatches pending tasks + releases team lock (panic-safe)
- Wire PostTurnProcessor to ChatMethods via setter
- defer drainTeamDispatch() in handleSend goroutine
2026-03-20 23:03:59 +07:00
viettranx 32ced98f6a fix(tools): add extractor chain retry/timeout, fix openai_compat media routing
- ExtractorChain now supports per-entry retry (max_retries) and chain-level
  timeout (context.WithTimeout), matching MediaProviderChain pattern
- Low quality content breaks out of retry (not transient), errors retry
- Fix ResolveProviderType: skip generic "openai_compat" DB type so
  OpenRouter routes via name-based inference to correct /chat/completions
  endpoint instead of falling through to /images/generations (caused 404)
- Remove dead "openai_compat" entry from dbTypeToMediaType map
- Seed data: defuddle default max_retries=2
2026-03-20 22:26:48 +07:00
viettranx 9ad3043fe9 feat(ui): team leader processing indicator and announce run streaming
- Add team.leader.processing backend event (emitted from onDrain before
  announce run starts) so all WS clients show processing status
- Capture announce run.started events to stream leader's summarization
  in real-time (thinking, tool calls, text)
- Add leader_processing phase to ActivityIndicator and ChatTopBar
- isBusy stays true during leader processing → stop button visible
2026-03-20 22:26:22 +07:00
c6bab9a059 fix(codex,memory): sanitize tool call IDs, fix memory delete, add GPT-5.4 (#313)
* fix(codex,memory): sanitize tool call IDs, fix memory delete, add GPT-5.4

- codex_build: sanitize colons in tool call IDs before sending to
  Responses API (OpenAI rejects non-alphanumeric chars except _ and -)
- memory_docs: check RowsAffected on delete — return error instead of
  silent 200 when no document matched
- memory UI: pass document's agent_id to delete call so deletion works
  from the "all agents" view (previously sent undefined as agent ID)
- codex models: add GPT-5.4 and GPT-5.4 Mini, update default model

* fix(codex): update default model assertion in test to gpt-5.4

* fix(codex): regex sanitize all invalid chars in tool call IDs, restore GPT-5.1 models

- toFcID: replace all non-alphanumeric/underscore/dash chars (not just
  colons) to prevent future Responses API rejections
- Restore GPT-5.1 Codex Max and Codex Mini in model dropdown to avoid
  breaking existing user configurations

---------

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
Co-authored-by: viettranx <viettranx@gmail.com>
2026-03-20 21:57:30 +07:00
viettranx e4770956cb fix(security): replace stdlib xml.etree.ElementTree with defusedxml
Mitigate XXE Billion Laughs (entity expansion DoS) in DOCX parsing.
5 ET.parse() calls used vulnerable stdlib parser instead of defusedxml
which was already a project dependency.
2026-03-20 21:55:24 +07:00
viettranx 107140b32c feat(ui): kanban board improvements, comment event subscription 2026-03-20 21:46:44 +07:00
viettranx 6fe59faa0c feat(ui): media gallery, file helpers, chat message improvements 2026-03-20 21:46:39 +07:00
viettranx 6275117dbd feat(teams): improved task prompting for weak models, file serving fix
- Rework lead prompt: anti-pattern examples, batch task creation
  emphasis, explicit UUID guidance for Qwen/MiniMax
- Enriched tool description hint for task descriptions
- Fix workspace file serving fallback
2026-03-20 21:46:32 +07:00
viettranx 0cffbf5bfa fix(agent): loop improvements, history compaction, config tweaks 2026-03-20 21:46:22 +07:00
viettranx 001fe2721c fix(files): fallback workspace search for generated file links
LLMs hallucinate file paths in responses (e.g. ./system/generated/file.png)
when the actual file is at /app/workspace/teams/.../generated/file.png.

Backend: /v1/files/ now falls back to searching the workspace directory
tree by basename when exact path isn't found. Generated filenames
(goclaw_gen_*) include nanosecond timestamps and are globally unique.

Frontend: relative file paths now use just the basename in the /v1/files/
URL, letting the backend fallback find the actual file. Auth token
appended as ?token= query param for authenticated file access.
2026-03-20 19:57:39 +07:00
viettranx ca6ec0bf9f fix(ui): add auth token to /v1/files/ requests in markdown file links
File preview dialog was showing {"error":"unauthorized"} because
fetch() calls to /v1/files/ lacked the Bearer token. Now appends
?token= query param (accepted by the files endpoint) to all resolved
file URLs including relative path detection.
2026-03-20 19:49:52 +07:00
Goonandviettranx 7040081756 feat(discord): add writer management commands (#309)
* feat(discord): add writer management commands (!addwriter, !removewriter, !writers)

Port Telegram's file writer commands to Discord with guild-wide scope.
Uses wildcard scope (guild:{guildID}:*) to match per-user contexts.
Also fixes system prompt injection to find guild-wide writers.

* fix(discord): use per-user scope for writer self-check

CheckPermission with guild-wide wildcard scope (guild:{guildID}:*)
fails to match auto-bootstrapped per-user perms. Use per-user scope
(guild:{guildID}:user:{senderID}) which matches both per-user exact
and guild-wide wildcard stored patterns via matchWildcard.

* fix(discord): deduplicate writers in prompt injection, add context timeout

- Deduplicate writers by UserID after merging guild-wide and per-user
  scope results in buildGroupWriterPrompt to prevent duplicates when a
  user has both grant types.
- Add 10s context timeout to Discord writer command handlers instead of
  using context.Background() to prevent DB calls from hanging.

---------

Co-authored-by: viettranx <viettranx@gmail.com>
2026-03-20 19:44:31 +07:00
viettranx cab9338f14 fix(ui): chat running status, streaming layout, file links, scroll jitter
- Add isBusy derived state (isRunning || teamTasks active) for stop button
  and top bar status — reflects team task activity after main agent completes
- Align ActiveRunZone with MessageBubble layout: bubble wrapper for streaming
  text, compact tool cards with divide-y borders
- Detect relative file paths (./path) in markdown and render as file chips
  routed through /v1/files/ endpoint
- Fix auto-scroll jitter during streaming by using instant scroll and
  ignoring programmatic scroll events in the near-bottom check
2026-03-20 19:27:51 +07:00
Le Dat c9a484d5d7 fix: Windows deployment — broken symlinks, missing packages, dep scanner false positives (#292)
fix: Windows deployment — broken symlinks, missing packages, dep scanner false positives

- Dockerfile: add pdfplumber, pdf2image, anthropic, poppler-utils, bash to ENABLE_FULL_SKILLS
- Dockerfile: resolve broken git symlinks from Windows clone (core.symlinks=false)
- Dockerfile: strip CRLF from docker-entrypoint.sh at build time
- .gitattributes: enforce LF line endings for shell scripts
- dep_scanner.go: track nested subdirectories + scripts dir basename as local modules
2026-03-20 18:54:45 +07:00
viettranx 11673dabf1 fix(agent): prevent trailing assistant messages for proxy provider compat
Reorder team task reminders to inject before the user message instead of
after, ensuring the user's message is always the last in the messages
array. Proxy providers (LiteLLM, OpenRouter) reject requests ending with
an assistant-role message (unsupported prefill).

Also add a safety net in the OpenAI provider to strip any trailing
assistant message that might slip through in the future.
2026-03-20 18:46:27 +07:00
viettranx 0415052872 fix(tools): strip tab indent from cron description, restore lost context
Remove leading tabs that wasted tokens in LLM system prompt.
Restore timezone example (Asia/Ho_Chi_Minh) and channel auto-fill info
that were dropped in #307.
2026-03-20 18:27:18 +07:00
chungtran4078andChung Tran 8b44c01627 Fix: agent call cron tool within invalid params (#307)
* fix: agent add cron within invalid params

* fix: sometime cron tool calling fail

---------

Co-authored-by: Chung Tran <chung.tran@diqit.io>
2026-03-20 18:24:37 +07:00
viettranx 7634bb7834 fix(telegram): use typed error checks for 5xx detection in retry/dedup logic
Replace loose string matching ("502", "503", "504") with telegoapi.Error
type assertion — prevents false positives from error messages that
happen to contain these substrings. Also classifies 5xx as
post-connect errors since the server received the request.
2026-03-20 18:24:00 +07:00
badgerbees 874923d44b fix(telegram): suppress duplicate messages on high-latency streaming connections (#286)
fix(telegram): suppress duplicate messages on high-latency streaming connections
2026-03-20 18:21:46 +07:00
viettranx 670b295851 fix(telegram): bounded concurrent handlers, stall-aware downloads, media error feedback
- Replace sequential polling dispatch with semaphore-bounded goroutines
  (max 20 concurrent handlers) to prevent polling hangs from slow media
  downloads without risking unbounded goroutine growth
- Add sync.WaitGroup for graceful shutdown — Stop() waits for in-flight
  handlers with a 15s timeout
- Add progressReader that aborts downloads stalled for 60s (no data)
- Return MediaError from resolveMedia so callers know what failed and why
- Annotate model content with error context when media is skipped
  (e.g. "[sent media (image) — skipped: exceeds 20 MB limit]")
- Send Telegram reply to user when their file is too large or download fails
- Use errMediaTooLarge sentinel in all size-check paths for consistent
  error classification
2026-03-20 18:18:51 +07:00
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 Tran 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.VN 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 Nguyen 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
Thieu Nguyenandviettranx 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 Nguyen 43990c7e56 Fix ChatGPT OAuth setup wizard flow (#289) 2026-03-20 06:54:11 +07:00
Plateau Nguyen c1893c73d1 fix: normalize delete confirmation matching (#290) 2026-03-20 06:48:48 +07:00