Commit Graph
498 Commits
Author SHA1 Message Date
viettranx 5b349db7eb feat(heartbeat): provider/model override + fix cache invalidation
- Add ProviderModelSelect to heartbeat config dialog (allowEmpty, verify button)
- Backend: accept providerName in HEARTBEAT.SET, resolve to UUID via GetProviderByName
- Add ModelOverride to RunRequest, used by Loop when set (cheaper model for heartbeat)
- Ticker passes heartbeat model override to agent RunRequest
- Fix: InvalidateCache after UpdateState so ListDue picks up new next_run_at immediately
- i18n: add sectionModel/modelHint keys (en/vi/zh)
2026-03-18 23:02:48 +07:00
Keith 74c9fdd66b fix: add database name to postgres healthcheck (#203)
When POSTGRES_USER differs from POSTGRES_DB, pg_isready defaults to
connecting to a database named after the user, causing healthcheck
to fail with "database does not exist".
2026-03-18 22:45:24 +07:00
Duc Nguyenandviettranx dc51018563 fix: subagent provider routing + api_base fallback (#262)
* fix(subagent): inherit parent agent's provider instead of alphabetical fallback

Subagents previously used a fixed provider (alphabetically first from the
registry, often "anthropic") regardless of which provider the parent agent
used. This caused invalid combos like anthropic/glm-5 when a zai-coding
agent spawned subagents.

- Pass provider registry to SubagentManager for runtime resolution
- Inject parent provider name into context (WithParentProvider)
- Resolve activeProvider from parent context before LLM call
- Fix trace spans to show actual resolved provider, not default

* fix(providers): api_base fallback from config/env for DB providers

DB providers with empty api_base now inherit from config/env vars
(e.g., GOCLAW_ANTHROPIC_BASE_URL). Prevents proxy API keys from being
sent to the real provider API endpoint.

- Add APIBaseForType() method on ProvidersConfig
- registerProvidersFromDB falls back to config when api_base is empty
- ProvidersHandler uses resolveAPIBase() for model listing
- Add api_base, display_name, settings to provider validation whitelist

* fix(tracing): pass resolved provider name to subagent span emitters

- emitSubagentSpanStart now accepts providerName param instead of
  reading sm.provider.Name() — ensures root subagent span reflects
  the inherited parent provider, not the fallback default
- registerInMemory now uses resolveAPIBase() so DB providers with
  empty api_base inherit the config/env fallback (same as startup path)

---------

Co-authored-by: viettranx <viettranx@gmail.com>
2026-03-18 22:40:49 +07:00
Luan VuandLuvu182 b379c3ba30 fix(feishu): align WebSocket protocol with Lark SDK + fix incorrect UI labels (#263)
Backend — WSClient protocol fixes (larkws.go):
- Parse service_id from WS URL query params instead of hardcoding 0
- Update all 4 server config values from pong payload (PingInterval,
  ReconnectCount, ReconnectInterval, ReconnectNonce)
- Use server-configured reconnect params instead of hardcoded 120s wait
- Return HTTP 500 in ACK when event handler fails (enables Lark retry)
- Filter data frames by type header — only process "event" frames
- Report actual processing time in biz_rt header (was hardcoded "0")

Backend — event adapter (feishu.go):
- Return parse error from HandleEvent so ACK reflects failure status

UI — fix incorrect Feishu channel form labels:
- Remove "webhook only" from Lark Global domain label (WebSocket works
  on both Lark Global and Feishu China)
- Remove "Feishu only" from WebSocket option label
- Change default connection_mode from "webhook" to "websocket" (matches
  backend default)
- Add showWhen conditional field support to ChannelFields component
- Hide webhook_port, webhook_path, encrypt_key, verification_token when
  WebSocket mode is selected
- Update i18n labels in all 3 locales (en, vi, zh)

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
2026-03-18 17:51:09 +07:00
viettranx 2504095dfe fix(agents): complete shell deny groups propagation chain
ShellDenyGroups was defined in SystemPromptConfig but lacked full propagation
through parser, Loop fields, context injection, and system prompt population.
Per-agent overrides from other_config JSONB had zero runtime effect.

Changes:
- agent_store.go: Add ParseShellDenyGroups() to extract overrides from JSONB
- loop_types.go: Add shellDenyGroups field to Loop and LoopConfig, wire in NewLoop
- resolver.go: Wire agent-parsed shell deny groups into LoopConfig
- loop.go: Inject shellDenyGroups into context via store.WithShellDenyGroups
- loop_history.go: Populate ShellDenyGroups in system prompt config
- message_test.go: Fix macOS symlink path normalization in test expectations

Fixes test failures on macOS where /var/folders symlinks to /private/var/folders.
2026-03-18 17:04:26 +07:00
viettranx b818de6d63 fix(heartbeat): delayed refresh after toggle/update, taller checklist textarea
- Wait 2s after toggle/update before refreshing config for accurate countdown
- Checklist textarea: min-h-[200px] mobile, min-h-[400px] desktop, resizable
2026-03-18 16:48:01 +07:00
viettranx 551184c5b2 fix(heartbeat): delayed refresh after toggle/update for accurate countdown
Wait 2s after toggle/update before refreshing config from backend to
ensure nextRunAt is computed and persisted. Prevents stale countdown
in header heartbeat button.
2026-03-18 16:43:41 +07:00
Nguyễn Hoàng Thức b7d8d52f5e fix(ui): dark mode white dropdown on language and timezone selects (#255)
* fix(ui): use color-scheme dark for select dropdowns in dark mode

Language and timezone selects rendered with white native dropdown in
dark mode because browser ignores CSS bg-transparent on <option>.
Adding dark:scheme-dark tells the browser to render the native select
dropdown using dark color scheme in dark mode.

* fix(ui): replace native select with Radix UI Select for dark mode fix

Native <select> dropdown ignores CSS styling — browser always renders
the popup with its default (light) color scheme, causing white box in
dark mode. Replace language and timezone selectors with Radix UI Select
which renders custom HTML/CSS dropdowns that fully respect dark mode.

- Use bg-popover/text-popover-foreground from ui/select.tsx (dark-aware)
- Remove unused handleLanguageChange handler
- Use Tailwind v4 canonical **:data-radix-select-icon:hidden to hide chevron
2026-03-18 16:38:33 +07:00
viettranx 2141852945 fix(ui): hide [System] nudge messages from web chat and session viewer
Bootstrap nudge messages (role=user, [System] prefix) are internal
prompts for the model, not meant for end users. Filter them from
chat-thread render and recognize both [System] and [System Message]
prefixes in session detail page.
2026-03-18 16:38:15 +07:00
viettranx 1b27fa7a9b feat(agents): inject team members into system prompt
Team agents now see a ## Team Members section listing all teammates with
agent_key, display_name, role, and frontmatter excerpt. This allows the
agent to correctly assign tasks via team_tasks instead of guessing keys.
2026-03-18 16:38:03 +07:00
viettranx 1ae5c7641a feat(ui): refactor agent detail page — 3 tabs, heartbeat UI, compact header
- Reduce 5 tabs to 3 (Agent, Files, Instances) + Advanced Settings dialog
- Team-style compact header with heartbeat countdown, advanced, delete buttons
- New heartbeat UI: config dialog with channel/chatId picker, logs viewer
- Personality section with large emoji + frontmatter textarea
- Model & Budget merged section, inline skills toggles
- Capabilities section with collapsible Memory/Tools/Subagents
- Auto-refresh heartbeat when countdown reaches 0 (poll every 5s)
- Shared useCountdown hook for mm:ss / hh:mm:ss display
2026-03-18 16:37:53 +07:00
viettranx 96cfd1bf08 feat(heartbeat): improve prompting, suppression, delivery targets and session cleanup
- Rewrite heartbeat prompt to instruct agent to EXECUTE checklist tasks, not echo them
- Simplify suppression: HEARTBEAT_OK present = always suppress, absent = always deliver
- Add delivery targets RPC (heartbeat.targets) for channel/chatId picker
- Sanitize backend errors — never expose raw SQL to client
- Add session cleanup for isolated heartbeat sessions after run
- Cap StaggerOffset at 10% of interval to avoid user-visible delay
- Fix Upsert to persist next_run_at correctly
2026-03-18 16:37:36 +07:00
viettranx b6f6af01d2 docs: add SQL safety rules to post-implementation checklist 2026-03-18 13:13:03 +07:00
viettranx 29816db0ab feat(heartbeat): cron wakeMode, queue-aware scheduling, lightContext
- CronPayload.WakeHeartbeat triggers heartbeat immediately after cron job completes
- Cron tool supports wake_heartbeat param on add/update actions
- Scheduler.HasActiveSessionsForAgent() detects busy agents for heartbeat skip
- RunRequest.LightContext skips loading context files during heartbeat runs
2026-03-18 13:11:58 +07:00
viettranx 08a2d95c0c feat: agent heartbeat system — periodic proactive check-ins (#245)
Phase 1 (Core):
- Migration 000022: agent_heartbeats, heartbeat_run_logs, agent_config_permissions tables
- HeartbeatStore + ConfigPermissionStore interfaces with PG implementations
- HeartbeatTicker: background poll → active hours filter → queue-aware skip → run → smart suppression → deliver/log
- Heartbeat tool: status/get/set/toggle/set_checklist/get_checklist/test/logs actions
- Permission check with wildcard scope matching + TTL cache (60s)
- RPC methods: heartbeat.get/set/toggle/test/logs/checklist.get/checklist.set
- HEARTBEAT.md routed via context file interceptor (read/write for both open + predefined agents)
- Session keys: agent:{id}:heartbeat or agent:{id}💓{ts} (isolated)
- PromptMinimal for heartbeat sessions (like cron/subagent)
- Event broadcasting + cache invalidation via bus (heartbeat + config_perms)
- Gateway wiring: ticker init, event wiring, graceful shutdown

Phase 2 (Integration):
- wakeMode: CronPayload.WakeHeartbeat triggers heartbeat after cron job completes
- Queue-aware: Scheduler.HasActiveSessionsForAgent() skips busy agents
- Stagger: deterministic FNV offset spreads heartbeats across interval
- lightContext: RunRequest.LightContext skips context files, only injects checklist
- System prompt distinguishes cron (user-scheduled tasks) vs heartbeat (autonomous monitoring)
2026-03-18 13:11:44 +07:00
viettranx da59377387 fix(teams): use OR logic for task search instead of AND
plainto_tsquery ANDs all terms, so queries like "teenager coffee
instagram" return 0 results when any single term is missing from the
tsvector. Switch to to_tsquery with OR-joined terms so tasks matching
any keyword are returned, ranked by relevance. Sanitize input with
a whitelist (letters, digits, hyphens, underscores) to prevent
tsquery syntax injection.
2026-03-18 13:02:07 +07:00
viettranx c7d0bc19f8 fix(teams): auto-copy media files to team workspace on task creation, scope task_number per chat
- Add RunMediaPaths context key to track media files from current run
- Collect persisted media paths in agent loop after enrichment
- Auto-copy media files to {workspace}/attachments/ when leader creates task
- Append attached files hint in dispatch content so members know what to read
- Scope task_number per (team_id, chat_id) instead of global per team
- Fix NULL chat_id comparison with COALESCE
- Use hard link first, copy fallback to save disk space
- Validate filenames and use restrictive file permissions (0640)
2026-03-18 12:58:09 +07:00
viettranx 4fc072697f fix(streaming): prevent mid-run stream content loss on Telegram
- Skip FinalizeStream on tool.call — keep streamed message visible
- Gate tool_status placeholder_update to non-streaming runs only
- Prevents streamed text from being overwritten by tool status emoji
2026-03-18 11:05:43 +07:00
viettranx 7b3ac84152 docs: update references for delegate→team/teammate rename
- Update lane name, env var, channel references across all docs
- Mark delegate tool as removed in tools system docs
- Update routing tables and architecture diagrams
2026-03-18 11:05:23 +07:00
viettranx 48ebcf999b fix(tools): add append mode to write_file, warn about content size limits
- Add append=true parameter for chunked file writing
- Add ~12000 char warning in tool description and system prompt
- Helps models avoid API truncation on large file writes
2026-03-18 11:05:09 +07:00
viettranx 5a4c72018a fix(teams): include agent display name in task create, list, and announce
- Add display_name to task create response (assignee name)
- Add owner_display_name and created_by_display_name to list/get items
- Pass to_agent_display via dispatch metadata (zero extra DB queries)
- Use display name in announce messages to leader for correct attribution
2026-03-18 11:04:56 +07:00
viettranx 49441f7305 refactor: remove dead delegate code, rename lane/channel to team/teammate
- Remove handleDelegateAnnounce() dead code (no sender emits delegate:* messages)
- Remove delegate tool reference from intent_classify.go
- Rename LaneDelegate → LaneTeam with backward-compat env var fallback
- Rename ChannelDelegate → ChannelTeammate across all team tool files
- Comment out lifecycle guards in team_tasks_lifecycle.go (TODO: reviewer workflow)
- Update string literals in cron.go, task_ticker.go
- Gate tool_status placeholder_update to non-streaming runs only
- Skip FinalizeStream on tool.call to prevent mid-run content loss
2026-03-18 11:04:45 +07:00
viettranx 120fc2d09c fix(media): chain provider format, post-write verification, group media history (#206)
Cherry-picked valuable changes from PR #206:
- hasReadImageProvider supports chain format {"providers":[...]} config
- create_image/video/audio verify file persistence after write with diagnostic logging
- HistoryEntry gains Media field + CollectMedia() for group media context on @mention
- Zalo extractContentAndMedia refactored: all media types via DetectMIMEType/BuildMediaTags, 20MB limit
- Discord/Zalo pass media paths to Record() and collect historical media on @mention
- Zalo send_helpers logs directory contents when checkFileSize stat fails
2026-03-18 08:12:10 +07:00
Keith 796a7ecd22 fix(ui): support comma separator in allowed users field (#205)
Allow users to be entered with commas or newlines in the channel
config textarea field. Previously only newlines were supported,
but the Enter key was not working in some browsers.

💘 Generated with Crush

Assisted-by: MiniMax-M2.5 via Crush <crush@charm.land>
2026-03-18 07:51:00 +07:00
SpencerSwagger 827c784b62 fix(feishu): response websocket event as success (#110) 2026-03-18 07:50:08 +07:00
Viet Tran ce333c70f3 fix(security): followup hardening — ILIKE ESCAPE, allowlist logging, shell deny, tests (#251)
- Add explicit ESCAPE '\' clause to all ILIKE queries (knowledge_graph,
  custom_tools, channel_instances, channel_contacts) for correct wildcard
  escaping regardless of PostgreSQL standard_conforming_strings setting
- Log warning when filterAllowedKeys drops unknown fields for debuggability
- Widen base64 decode shell deny pattern to catch -di, -dw0 variants
- Add unit tests for filterAllowedKeys, pqStringArray, scanStringArray,
  pqStringArray↔scanStringArray roundtrip, limitedBuffer, base64 deny
2026-03-18 07:48:48 +07:00
Luan VuandLuvu182 a7f5acc1e3 fix(security): harden SQL injection, MCP prompt injection, sandbox fallback, and file serving (#246)
- execMapUpdate: validate column names with strict regex to prevent SQL injection
- HTTP update handlers: add field allowlists (agents, providers, custom_tools, mcp, channel_instances)
- pqStringArray: properly escape array elements to prevent PostgreSQL array literal injection
- scanStringArray: handle quoted elements in PostgreSQL array format
- MCP bridge: wrap tool results as external/untrusted content to prevent prompt injection
- File serving: block access to sensitive system directories (/etc, /proc, /sys, etc.)
- Sandbox: fail closed when Docker unavailable instead of silent fallback to host
- Shell deny: fix base64 --decode bypass, add host exec 1MB output limit
- ILIKE queries: escape % and _ wildcards in knowledge_graph, custom_tools, channel_instances

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
2026-03-18 07:42:38 +07:00
Luan VuandLuvu182 8cbd30f1ab fix(channels): harden error handling and type safety across Telegram, Zalo, Feishu (#247)
Telegram:
- Fix context cancellation in reaction timer callbacks — use context.Background()
  so emoji reactions still work after request context is cancelled
- Add comma-ok safety on sync.Map type assertions in OnReactionEvent/ClearReaction

Zalo:
- Add comma-ok safety on sync.Map type assertions for typing controllers
- Validate non-empty senderID before processing text/image messages

Feishu/Lark:
- Handle json.Unmarshal errors in all 7 LarkClient messaging methods instead of
  silently returning empty values
- Add 30s HTTP timeout for WebSocket endpoint request (was using DefaultClient)
- Eliminate double decryption in webhook handler — cache first result
- Replace goroutine+sleep with time.AfterFunc for dedup cleanup
- Add comma-ok safety on pairing debounce type assertion
- Use json.Marshal instead of fmt.Sprintf for image/file key JSON construction

Co-authored-by: Luvu182 <208665161+Luvu182@users.noreply.github.com>
2026-03-18 07:39:03 +07:00
viettranx 06e995ce03 feat: Add legacy and Claude Code tool aliases to the system prompt. 2026-03-18 07:38:41 +07:00
Thieu Nguyen 7f19db14f5 fix(install): bundle migrations in release tarball and install script (#249)
The install script only copied the binary, so `goclaw migrate up` and
`goclaw onboard` failed when run from the installed location because the
migrations directory was missing.

- Include migrations/ in the release tarball
- Install migrations to /usr/local/share/goclaw/migrations
- Guide users to export GOCLAW_MIGRATIONS_DIR before onboard
- Align next-steps output with onboard's own instructions
2026-03-18 07:32:53 +07:00
viettranx 57754a569b refactor(ui): simplify agent detail page — remove Links, Shares tabs and Other Config section
Remove unused UI sections from agent detail:
- Links tab + link-sections components + use-agent-links hook
- Shares tab + use-agent-shares hook
- "Quality & Advanced" config group + OtherConfigSection

Also fix skills tab sort (ungranted non-system first) and
harden use-contact-search with Array.isArray guard.
2026-03-17 22:28:00 +07:00
viettranx 843b550651 feat: runtime packages UI, pkg-helper, configurable shell deny groups (#244)
Runtime package management with security hardening:

- pkg-helper: root-privileged daemon for apk install/uninstall via Unix socket
- HTTP API: /v1/packages (list/install/uninstall/runtimes), admin role required for writes
- Shell deny groups: 15 configurable groups (per-agent overrides via context)
- Packages UI: Web page for managing system/pip/npm packages with confirmation dialogs
- Docker: privilege separation (root entrypoint → su-exec drop), init for zombie reaping
- Security: umask socket creation, persist file validation, deny pattern hardening
  (Node.js fetch/http, Python from/import, curl localhost, sensitive env vars)
- Auth: empty gateway token → admin role (dev/single-user mode)
2026-03-17 19:50:26 +07:00
badgerbeesandviettranx d46061405f fix(telegram): enforce transport policy and SSRF guard for media downloads
* fix(telegram): thread transport policy into media downloads with SSRF guard

* fix(telegram): trust configured APIServer during media downloads

* fix(telegram): use proper download timeout and clone DefaultTransport

- Clone http.DefaultTransport when proxy is configured to preserve
  connection pool, TLS handshake timeout, and keep-alive defaults
- Use dedicated 5-minute context timeout for media downloads instead
  of the shared 30s client timeout, preventing large file timeouts
  (local Bot API supports up to 200 MB)

---------

Co-authored-by: viettranx <viettranx@gmail.com>
2026-03-17 18:21:45 +07:00
viettranx 31ff5eefca fix(tools): prevent duplicate media delivery from write_file
Tell LLM that auto-delivered files should not be sent again via
message tool, preventing double sends (document + photo) on Telegram.
2026-03-17 18:18:20 +07:00
viettranx 517e6c89ab fix(agents): preserve emoji when updating agent config + validate emoji input
- Read existing IDENTITY.md before overwriting to preserve emoji field
- Config tab: merge existing other_config to prevent wiping emoji on save
- Emoji input: validate single emoji only with extractSingleEmoji()
- Select-all on focus for easy emoji replacement
2026-03-17 18:03:54 +07:00
viettranx 53fc15597e feat(teams): delta realtime updates for task list
- Replace full-list-reload on WS events with delta patching
- Progress events: local patch with 1s debounce (no network call)
- Delete events: local remove (no network call)
- Created/status changes: debounced fetch-one per task_id (300ms)
- Add channel field to TeamTaskData type for scope-aware filtering
- Clear stale progress patches when fetch-one fires (race prevention)
2026-03-17 18:03:22 +07:00
viettranx b231878a85 feat(teams): add limit param to ListTasks + lightweight get-light endpoint
- Add limit parameter to ListTasks interface (dashboard=200, agent=30)
- Add teams.tasks.get-light WS method returning task only (no comments/events)
- Truncate dashboard response to exact limit (fix off-by-one from limit+1)
- Update all 7 ListTasks callers with explicit limit values
2026-03-17 18:03:10 +07:00
viettranx b735c16d93 feat(teams): split dispatched/assigned events + add completed notifications
- Change agent-side broadcasts from EventTeamTaskAssigned to
  EventTeamTaskDispatched (post-turn, fallback, unblock, retry)
- Add completed notification with leader-completion skip logic
- Add Completed field to TeamNotifyConfig with *bool backwards compat
- Differentiate dispatched messages: unblocked vs regular dispatch
- Add EventTeamTaskDispatched to audit event mapper
2026-03-17 18:02:54 +07:00
viettranx 4678065887 refactor: remove dead quality gates / hook engine code
The delegation system this depended on was previously removed,
leaving internal/hooks/ as dead code with zero imports. Remove
the entire hook engine, UI config section, protocol types, i18n
keys, and all documentation references.
2026-03-17 18:00:09 +07:00
viettranx 6106d3d04f fix(teams): show task_number in create result and allow search to satisfy gate 2026-03-17 17:11:22 +07:00
viettranx de2eca9acb fix(i18n): keep "workspace" untranslated in Vietnamese locale 2026-03-17 16:10:22 +07:00
viettranx 946cbb9eb1 fix(teams): allow search action to satisfy list-before-create gate
Search now acquires the team create lock and marks listed, so leaders
can use search instead of list before creating tasks — reduces token
consumption by returning only matching tasks instead of the full board.
2026-03-17 16:00:59 +07:00
viettranx 70f3e1f5d5 feat(tools): auto-deliver write_file results as channel attachments
Flip write_file deliver param default from false to true so result files
(reports, articles, generated content) are automatically sent as document
attachments to chat channels without requiring explicit LLM opt-in.
Add .md MIME type to mimeFromExt for proper markdown file delivery.
2026-03-17 15:43:24 +07:00
viettranx 66de3504d4 feat(teams): add client-side pagination to task list view
Use existing usePagination hook (default 20/page) with Pagination
component. Select-all checkbox applies to current page only; selections
persist across pages.
2026-03-17 15:25:59 +07:00
viettranx ae3e5cebcf feat(teams): add multi-select checkboxes and bulk delete to task list
Add checkbox column to task list view for selecting terminal-status
tasks (completed/failed/cancelled). Header checkbox supports select-all
with indeterminate state. Bulk action bar appears on selection with
delete button that opens ConfirmDeleteDialog requiring user to type
"delete" to confirm.

Backend: new teams.tasks.delete-bulk RPC method with DeleteTasks batch
SQL (DELETE ... WHERE id = ANY($1) RETURNING id). Broadcasts delete
event per task for real-time UI sync.

i18n: added bulk action keys for en/vi/zh.
2026-03-17 15:10:43 +07:00
viettranx aeadb20ba7 fix(teams): deduplicate task notifications and batch with debounce
Remove premature EventTeamTaskAssigned broadcast in executeCreate() that
caused duplicate "assigned to" Telegram notifications. Assignment
notification now only fires at actual dispatch (post-turn, fallback, or
unblocked).

Add TeamNotifyQueue (2s debounce, cap 20) to batch rapid-fire task
notifications per chat — reduces N messages to 1 when leader dispatches
multiple tasks at once. In leader mode this also reduces agent turns
from N to 1.

Also fix: ResetTaskStatus now clears progress_percent/progress_step on
retry, and retry broadcast includes TaskNumber/Subject for correct
notification formatting.
2026-03-17 14:29:52 +07:00
viettranx 8c662e7af4 fix(teams): hide progress bar on completed tasks
Clear progress_percent in DB on all terminal transitions (complete,
cancel, fail, approve, reject). Also hide progress bar in UI for
terminal statuses as a safety net (kanban, list, detail dialog).
2026-03-17 14:19:29 +07:00
teexiiiandviettranx 99dd363b13 feat(mcp): lazy-activate deferred tools on direct call in search mode (#235)
* feat: Implement MCP manager for server connections, tool registration, and deferred tool loading for agents.

* feat: Add tests for deferred tool activation logic within the tool registry and agent loop.

* fix(mcp): prevent deny list bypass via lazy activation + fix idempotency race

- Add PolicyEngine.IsDenied() to check deny patterns (incl. group: expansion)
  before allowing lazily-activated deferred tools to execute
- Check IsDenied() in both single-tool and parallel execution paths in loop.go
- Make ActivateToolIfDeferred idempotent by checking activatedTools before
  returning false, preventing concurrent goroutines from being blocked
- Add tests for deny-on-first-call, group deny patterns, and idempotent
  concurrent activation

---------

Co-authored-by: viettranx <viettranx@gmail.com>
2026-03-17 13:18:27 +07:00
badgerbeesandviettranx 1c4dce0ccf feat(telegram): implement robust message splitting and dynamic HTML retry logic (#236)
* feat(telegram): implement robust message splitting and dynamic HTML retry logic

* fix(telegram): fix sendHTML error chain regression and add split depth limit

- Re-check err.Error() in thread-not-found handler instead of stale errStr,
  restoring the original chained fallback behavior
- Add maxSplitDepth (5) to prevent unbounded recursion when Telegram
  repeatedly rejects split chunks
- Rename misleading test case to reflect actual monolithic fallback behavior

---------

Co-authored-by: viettranx <viettranx@gmail.com>
2026-03-17 13:01:20 +07:00
Goon 9429a7c844 ci: publish Docker images to GHCR and Docker Hub (#237)
* feat(ci): add node/python/full runtime variants to Docker publish

Add runtime image variants alongside existing build-tag variants:
- :node (pre-installed Node.js)
- :python (pre-installed Python)
- :full (Node.js + Python + all skill deps)

* feat(ci): add install scripts, release binaries, and Discord notifications

- scripts/install.sh: one-liner binary installer from GitHub Releases
- scripts/setup-docker.sh: interactive Docker setup with variant selection
  (alpine/node/python/full), auto-generates .env + docker-compose.yaml
  with persistent volumes for data, skills, workspace, storage
- release.yaml: build cross-platform binaries (linux/darwin × amd64/arm64)
  and attach to GitHub Release, notify Discord on new releases
- .gitignore: ignore Apple Double (._*) files from external volumes

* docs(docker): add pre-built image references and update docker-compose workflows

- Add `image:` directives to docker-compose.yml, docker-compose.selfservice.yml, and docker-compose.upgrade.yml pointing to ghcr.io/nextlevelbuilder/goclaw pre-built images
- Add Docker Hub mirror references (digitop/goclaw) for public access
- Document available image tags (latest, node, python, full, otel, tsnet, redis) with descriptions
- Update README with pre-built image pull instructions and semver tag examples
- Clarify deployment workflows: use pre-built images by default (no --build), add --build only when building from source
- Update upgrade workflow to pull pre-built images instead of rebuild
- Add note about build args requirement for otel/tsnet/redis overlays
- Update .dockerignore to exclude macOS temp files (._*)

* fix(ci): use claude_code_oauth_token instead of anthropic_api_key
2026-03-17 12:44:18 +07:00