Commit Graph
389 Commits
Author SHA1 Message Date
viettranx bc9ebaa2d0 refactor(channels): unify tab layout widths and schema-driven group overrides
- Remove redundant max-w-* constraints from General, Credentials, Groups,
  and Managers tabs so all tabs fill the parent container equally
- Refactor TelegramGroupFields to use ChannelFields with groupOverrideSchema
  instead of manually rendered form fields
- Add tristate, textarea, tool-select, and skill-select field types to
  ChannelFields renderer
- Create SkillNameSelect multi-select component (mirrors ToolNameSelect)
- Wire listManagerGroups into Groups tab for quick-add known groups
- Add i18n keys for knownGroups and selectOrTypeSkills (en/vi/zh)
2026-03-14 15:09:17 +07:00
Goon b9b8c8f8aa Merge pull request #191 from nextlevelbuilder/add-claude-github-actions-1773474803484
Add Claude Code GitHub Workflow
2026-03-14 14:53:45 +07:00
Goon 51677b8ff7 "Claude Code Review workflow" 2026-03-14 14:53:30 +07:00
Goon de03bc79b2 "Claude PR Assistant workflow" 2026-03-14 14:53:25 +07:00
viettranx 08823c057e fix(agent): prevent team V2 leads from manually creating tasks before spawn
Strengthen TEAM.md prompt with WRONG/CORRECT examples and NEVER wording
to stop models from calling `team_tasks create` before `spawn` in V2.

Prompt changes:
- V2 leads: explicit WRONG/CORRECT pattern, NEVER create before spawn
- V1 leads: separate workflow with manual create→spawn instructions
- team_tasks summary: de-emphasize "create", highlight auto-creation
- spawn team_task_id: clarify "omit to auto-create (recommended)"

Backend guards:
- Reject spawn with in-progress team_task_id (prevents reuse)
- Log warning on early claim race instead of silently ignoring
2026-03-14 14:23:15 +07:00
viettranx 8ad425f5f8 fix: use resolved workspace dir for StorageHandler in Docker deployments
StorageHandler was hardcoded to browse ~/.goclaw/, which is empty in
Docker where volumes mount to separate paths (GOCLAW_WORKSPACE).
Use the already-resolved workspace variable so the Storage page
correctly shows workspace files regardless of deployment layout.
2026-03-14 14:21:59 +07:00
viettranx 06b4eb912e feat(channels): add i18n for channel config fields and enable DM streaming by default
Add complete i18n support for channel config tab — field labels, help text,
and select option translations for en/vi/zh. Enable DM streaming by default
for Telegram and Slack channels.
2026-03-14 13:08:57 +07:00
viettranx b6df6c9286 refactor(agent): consolidate system prompt sections into AGENTS.md template
Merge §5 (Memory Recall), §9 (Messaging), §12 (Silent Replies) from
hardcoded system prompt into AGENTS.md — single source of truth.
Add recency reinforcement at §16 to compensate for mid-prompt position.
Clean up SOUL.md and IDENTITY.md template duplication.

Saves ~175 tokens/turn across all LLM calls.
2026-03-14 10:30:35 +07:00
viettranx e485549407 Refactor: Simplify runtime package installation hints by removing dynamic detection and providing a static message. 2026-03-14 10:00:17 +07:00
Nam Nguyen NgocandNam Nguyen Ngoc 1543b7a7a3 fix(ui): improve markdown renderer styling and code block typography (#184)
- Add VS Code/GitHub-inspired typography styles for markdown renderer
- Use JetBrains Mono/Fira Code font stack for code blocks and inline code
- Refine code block headers with uppercase labels and subtle borders
- Improve table styling with bordered cells and alternating row colors
- Add custom blockquote, heading, list, and horizontal rule styles
- Polish CSV viewer with consistent border and spacing treatments

Co-authored-by: Nam Nguyen Ngoc <namnn.0911@gmail.com>
2026-03-14 07:33:15 +07:00
19786166c1 fix(agent): enrich <media:image> tags with persisted media IDs for Discord image attachments (#179)
* fix(agent): enrich <media:image> tags with persisted media IDs for Discord image attachments

Discord image attachments were downloaded and persisted correctly, but
<media:image> tags in the message content remained bare (no ID attribute),
unlike <media:audio> and <media:video> tags which get enriched with media
IDs. This made it harder for the LLM to confirm image receipt and
reference specific images.

Add enrichImageIDs() that embeds persisted media IDs into <media:image>
tags, matching the existing enrichAudioIDs()/enrichVideoIDs() pattern.
Iterates refs in reverse order to correctly map multiple image refs to
their positional tags when users attach several images at once.

Closes #178

https://claude.ai/code/session_01KkE9UxcNB8eXpqRiJHRqeB

* style(agent): add missing continue in enrichImageIDs for consistency with enrichVideoIDs

https://claude.ai/code/session_01KkE9UxcNB8eXpqRiJHRqeB

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Viet Tran <viettranx@gmail.com>
2026-03-13 23:01:59 +07:00
Viet TranandNam Nguyen Ngoc 1a42dc93a6 feat(teams): team system v2 with bug fixes, workspace scope, versioning, and prompt optimization (#183)
* feat(workspace): add team shared workspace for file collaboration

- Add workspace_write and workspace_read tools for agents to share files across team members
- Create team_workspaces DB table with migration 000017 (file metadata, pinning, tags)
- Implement PostgreSQL store layer for workspace CRUD operations
- Add RPC handlers for workspace list/read/delete from web UI
- Build React workspace tab with file listing, content preview, and delete
- Propagate workspace channel/chatID scope through delegation chain
- Auto-allow workspace tools in agent tool policy when agent belongs to a team
- Inject team workspace guidance into system prompt for team agents
- Add /reset command handler for clearing session history
- Harden MCP bridge context middleware to reject headers when no gateway token
- Add i18n strings for workspace UI in en/vi/zh locales

* feat(teams): add comprehensive task management with followup reminders and recovery

- Add task followup/reminder system with auto-set on lead agent reply and auto-clear when user responds on channel
- Add task recovery ticker to re-dispatch stale/pending tasks periodically
- Add task scopes, filtering by status/channel/chatID, and task events
- Add WS RPC handlers for task CRUD, assignments, comments, events, and bulk operations (teams_tasks.go)
- Add task detail dialog, settings UI for followup config, and scope filtering in web dashboard
- Add migrations 000018 (team_tasks_v2) and 000019 (task_followup)
- Extend team_tasks_tool with await_reply, clear_followup actions
- Auto-complete/fail team tasks when delegate agent finishes
- Add workspace file listing and team tool manager enhancements

* docs(teams): add team system architecture and playbook ideas documentation

- Add TEAM_SYSTEM.md with full architecture design covering task management, shared workspace, and delegation engine subsystems
- Add TEAM_PLAYBOOK_IDEAS.md outlining future team coordination layers (playbook, member capabilities, auto-learned patterns)
- Document data models, status flows, tool actions, followup reminder system, task ticker, execution locking, and workspace scope model

* fix(teams): resolve 6 critical bugs in team task system

- Fix unblock SQL: check array_length after array_remove (not before)
- Enforce single-team leadership in team creation
- Add requireLead() for approve/reject tool actions
- Validate cross-team dependency references in blocked_by
- Add team_id to handoff route for multi-team isolation
- Set blocked_by DEFAULT '{}' to prevent NULL array issues

* refactor(workspace): use stable userID as scope key instead of connection UUID

Workspace scope changed from (team_id, channel, chat_id) to (team_id, userID).
Fixes workspace fragmentation across WS tab refreshes and reconnections.

* feat(teams): add V1/V2 versioning with feature gating and optimized prompts

- IsTeamV2() helper gates advanced features (locking, followup, review, audit)
- V2 tool actions rejected for V1 teams with clear error message
- Ticker, gateway consumer, delegation hooks respect version flag
- TEAM.md renders v1/v2 sections conditionally
- Tool descriptions and params optimized (~38% token reduction)
- UI: version toggle in settings, V2 Beta badge, conditional rendering
- i18n: version modal keys for en/vi/zh

* fix(migration): use VARCHAR(255) for user ID columns and add metadata JSONB

- assignee_user_id, user_id, actor_id: TEXT → VARCHAR(255)
- Add metadata JSONB to team_task_comments and team_task_attachments

---------

Co-authored-by: Nam Nguyen Ngoc <namnn.0911@gmail.com>
2026-03-13 22:41:32 +07:00
viettranx 7bde3f2f7c fix(pairing): handle transient DB errors in IsPaired to prevent spurious pair requests
IsPaired() silently returned false on DB query failures (connection
timeout, pool exhaustion), causing the system to treat already-paired
users/groups as unpaired and create spurious pairing requests.

Changed IsPaired signature to return (bool, error). All 13 callers
across all channels (Telegram, Discord, Slack, Feishu, WhatsApp, Zalo)
and gateway (browser WS, pairing method) now fail-open on DB errors:
log a warning and assume paired, avoiding false rejections.
2026-03-13 17:29:28 +07:00
viettranx d2bd270968 feat(ui): add list view and creator filter to agents page
Add card/list view toggle and owner filter dropdown to the agents page.
New AgentListRow component for compact list display. i18n keys added
for en, vi, zh locales.
2026-03-13 17:21:38 +07:00
viettranx ddd4565380 fix(tools): add negative guidance for message tool and disable handoff by default
Message tool prompting now explicitly tells the LLM not to use it for
replying to the user — prevents false activations on phrases like
"gởi lại cho tôi" (send it back to me).

Handoff tool disabled by default since it's rarely used and causes
confusion with spawn. Admins can re-enable via DB/UI if needed.
2026-03-13 16:15:33 +07:00
viettranx 52c56978c5 fix(tools): improve workspace path guidance to reduce LLM path guessing
Agents were guessing absolute paths for file/exec tools, causing failed
tool calls and wasteful retries. Strengthen LLM guidance at three levels:

- System prompt: instruct to use relative paths, not guess absolute paths
- Tool param descriptions: mention workspace-relative resolution
- Subagent prompt: add missing workspace section with path guidance
2026-03-13 13:51:37 +07:00
viettranx 7f4f4a238e feat(memory): inject KG hint into memory_search results and improve KG tool prompting
- Add hasKG flag to MemorySearchTool, inject hint in results when KG is enabled
- Wire SetHasKG(true) in gateway when KG store is available
- Improve knowledge_graph_search tool description with concrete use cases
- Update system prompt KG guidance to be more actionable
2026-03-13 13:33:18 +07:00
viettranx 558bdd6d5c fix(memory): use per-user workspace for memory path detection and KG extraction
Two related fixes:

1. Memory interceptor now resolves workspace from request context
   (per-user workspace) instead of using the static global workspace.
   This fixes memory writes with absolute paths under per-user
   workspaces (e.g. workspace/channel/userID/memory/) being bypassed
   and written to disk instead of the database, which also prevented
   KG extraction, memory indexing, and cross-session recall.

2. KG extractor: increase max_tokens 4096→8192, add retry on
   truncation (finish_reason=length), and support chunking for
   long inputs with deduplication on merge.
2026-03-13 13:22:02 +07:00
viettranx 4c7db6e09b feat(agent): add mid-run message injection for DM and WebSocket
Inject user follow-up messages into the running agent loop at turn
boundaries instead of queueing them for a new run. This preserves
context so the LLM sees both tool results and user follow-ups together.

- Add InjectedMessage type and drainInjectChannel helper
- Add InjectCh to ActiveRun with buffered channel (cap=5)
- Drain injection channel at two points in agent loop (after tool
  results and before no-tool-calls exit)
- Route steer/new_task intents to InjectMessage with scheduler fallback
- WebSocket: inject into running loop when session is busy
- Remove IntentClassify config toggle (always on)
- Web UI: show send + stop buttons side by side during agent run
- i18n: add injection acknowledgment messages (en/vi/zh)
2026-03-13 11:55:55 +07:00
viettranx d7ce93d91d fix(channels): add DB fallback for pending messages on RAM cache miss
BuildContext() and GetEntries() only read from RAM, so after gateway
restart or LRU eviction the agent never saw pending group messages
despite them existing in the database. Add lazy loadFromDB() that
queries ListByKey on cache miss and populates RAM for subsequent calls.
2026-03-13 11:27:10 +07:00
viettranx 2308b2553c feat: Implement task approval, rejection, and cancellation with new statuses and task filtering capabilities. 2026-03-13 10:54:00 +07:00
Weir_Guoandweirguo 94e7aac3ee feat: i18n agent presets in setup wizard (#170)
Agent presets in the setup wizard and create dialog were hardcoded
in Vietnamese. This change moves them into the i18n catalog so they
follow the user's selected language.

- Replace static AGENT_PRESETS array with useAgentPresets() hook
  that reads from the i18n catalog via useTranslation
- Add presets.foxSpirit / artisan / astrologer entries to
  en/agents.json, vi/agents.json, and zh/agents.json
- Update step-agent.tsx and agent-create-dialog.tsx to use the hook

Co-authored-by: weirguo <weir_guo@foxmial.com>
2026-03-12 21:52:28 +07:00
viettranx 1a4c211539 feat(teams): add task approval workflow with approve/reject actions
Tasks can be created with require_approval flag, starting in
pending_approval status. Users approve/reject via tool actions or
WS methods. Approval respects blocked_by dependencies — tasks with
unresolved blockers transition to blocked instead of pending.
Delegate agents are restricted from approving/rejecting.
2026-03-12 21:45:28 +07:00
viettranx 853725a6d1 chore: add ui/simple-saas to .gitignore 2026-03-12 21:45:20 +07:00
Luan VuandLuvu182 b73f66d99b fix(tools): make MessageTool media path resolution workspace-aware (#169)
MessageTool.parseMediaPath() was hardcoded to only allow files in /tmp/,
while all other filesystem tools (read_file, write_file, edit, exec) use
workspace-aware resolvePath() with restrict_to_workspace enforcement.

This meant agents could create files in their workspace via write_file
but couldn't send them as attachments — only /tmp/ files from
create_image/create_audio worked.

Replace parseMediaPath() with resolveMediaPath() that:
- Reuses resolvePath() for consistent security (symlink, hardlink, traversal)
- Honors per-agent workspace + restrict_to_workspace from context
- Still allows /tmp/ as fallback (for create_image, create_audio, etc.)
- Supports relative paths resolved against workspace
- Updates tool description so LLM knows about MEDIA: prefix

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
2026-03-12 20:43:52 +07:00
viettranx b4133282a6 refactor(kg): improve extraction prompt with few-shot example and controlled vocabulary
Add domain context, coreference rules, controlled relation types (15 predefined),
few-shot example, and dynamic entity count (3-15). Increase max input from 6000
to 12000 chars, reduce max output tokens from 8192 to 4096.
2026-03-12 18:54:14 +07:00
Goon 93860714f1 fix(skills): update skill-creator paths and metadata for GoClaw (#168)
Align skill-creator with GoClaw conventions: update skill store paths
to ~/.goclaw/skills-store/, fix author metadata, remove external
Claude Code references, update publish_skill documentation.
2026-03-12 18:35:35 +07:00
viettranx 9115169c03 feat: expand audit logging via pub/sub event pattern
Replace direct ActivityStore injection with event-driven audit system.
Handlers emit audit events via msgBus.Broadcast(), a single subscriber
with buffered channel persists to activity_logs table.

Coverage expanded from 3 agent CRUD actions to ~65 audit points across
all HTTP handlers and WebSocket RPC methods including agents, providers,
skills, MCP servers, cron, sessions, teams, pairing, and more.
2026-03-12 18:34:56 +07:00
viettranx 6eb33f9cea feat: decouple memory/KG sharing from workspace folder sharing
Add independent `share_memory` config flag to control memory and
knowledge graph sharing separately from workspace folder isolation.

- Add ShareMemory field to WorkspaceSharingConfig
- Decouple WithSharedMemory(ctx) from shouldShareWorkspace() in loop.go
- Add shouldShareMemory() helper independent of workspace sharing
- Fix KG Traverse CTE to scope user_id in recursive step (pre-existing bug)
- Add memory toggle UI with violet styling in workspace sharing section
- Add i18n translations (en/vi/zh) for new memory sharing controls
- Add unit tests for shouldShareMemory() independence
2026-03-12 18:26:40 +07:00
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
Goon 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
Winter279 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
Goon 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
Luan VuandLuvu182 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
Luan VuandLuvu182 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
Viet TranandGoon 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
Luan VuandLuvu182 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
Luan VuandLuvu182 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
Luan VuandLuvu182 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