mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-12 18:16:09 +00:00
dev
23
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
3f90057c24 |
fix(pipeline): stop aborting runs on heuristic context budget estimates (#1587)
Runs on models without a registered tokenizer (e.g. 9router brand models)
ended with the generic "Agent couldn't generate a response" fallback even
though the real request used about 55% of the context window.
PruneStage counted history with TokenCounter, which falls back to a
chars/2 heuristic for unregistered models and overcounted about 1.8x.
Once over budget it ran memory flush (~35s, invisible in traces), then
mid-loop compaction, which cannot summarize a history made only of tool
call/result pairs. The callback reported the untouched history as
compacted, PruneStage still saw it over budget and returned AbortRun
before any LLM call, and FinalizeStage replaced the empty reply with the
fallback.
- PruneStage and ContextStage overhead count with the request guard's
BudgetCounter. PruneStage no longer controls loop flow; the final
request guard in ThinkStage decides.
- CompactMessages returns ErrNotCompacted when history is unchanged.
Callers stop counting it as a compaction and do not retry it in the
same run, while post-run summarization still sees the pressure.
- When the guard exhausts every reduction step, ThinkStage stops the run
with a localized chat.context_budget_exceeded notice instead of an
error, so the run's tool results are still persisted. The stop reason
marks the trace and agent span as error; team tasks, cron and
heartbeat treat it as a failure via RunOutcome.Failure().
- Memory flush and mid-loop compaction emit event spans.
- Web and desktop UIs treat an unset context_pruning as enabled (the
backend default since
|
||
|
|
bb7712a9ff |
fix(collaboration): harden delegated task isolation (#1486)
* feat(collaboration): isolate delegated artifacts and child runs Isolate delegated inputs and outputs behind secure artifact exchange lifecycles. Scope Agent Link tasks by tenant and root agent, and enforce delegation spawn-tree boundaries. Add process-wide child-run admission and preserve logical media paths across native, MCP, and sandbox execution. * fix(collaboration): harden delegated task isolation Enforce tenant and root-agent task scope across migrations and stores. Add exactly-once async completion delivery, delegated sandbox boundaries, and confined artifact and media recovery across runtime surfaces. * fix(collaboration): recover interrupted async tasks * fix(collaboration): normalize persisted child-run status --------- Co-authored-by: ntduc <ntduc@cpp.ai.vn> |
||
|
|
db69ccf882 |
tracing: nest tool calls under LLM spans, emit hook spans, fix usage_events FK (#1415)
- Reparent tool_call spans under their producing llm_call span via RunState.CurrentLLMSpanID so a model turn's trace visibly contains the tool calls it triggered. - Wire internal/hooks EmitHookSpan into the dispatcher writeExec so every hook execution (pre/post tool use, etc.) produces a trace span with input, console output, decision, error, and duration for agent troubleshooting. - Fix usage_events_span_id_fkey violations: usage events were inserted synchronously referencing a span flushed ~5s later, silently dropping token/cost data. Route them through the collector so they flush after spans in the same cycle. No schema migration; FK preserved. Co-authored-by: Bruno Clermont <bruno.clermont@gmail.com> Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
75d89da5e7 |
fix(tracing): dedupe tool_call span rows in hourly snapshot aggregation to prevent ON CONFLICT DO UPDATE double-affect error (#1366)
Co-authored-by: Bruno Clermont <bruno.clermont@gmail.com> |
||
|
|
747b58d24c |
fix(usage): repair cost analytics and display precision (#1330)
fix(usage): repair cost analytics and display precision - Automatic OpenRouter pricing sync with cost backfill for traces/snapshots/events - Live usage data merging for current-hour dashboard accuracy - 2-decimal API cost formatting across usage/overview pages - Comprehensive test coverage (PG, SQLite, HTTP, UI) Merged by github-maintain automation. |
||
|
|
4002bb4c13 | feat(usage): add event analytics dashboard | ||
|
|
3b4004946e |
chore: apply go fix syntax upgrades (min/max, switch patterns)
Apply Go 1.21+ min/max builtins and improved switch pattern matching across test files and utilities. No functional changes. |
||
|
|
b68b3b12d7 |
fix(trace): disable stale recovery loop until last_span_at lands
Stale recovery sweeps traces by `start_time < NOW() - threshold`, which measures trace age rather than inactivity. Any threshold low enough to be useful (2-10 min) kills legitimate long-running agent runs: research chains, large code generation, extended shell commands routinely exceed 10 minutes. Disabled in Start() — function kept in place for easy re-enable once a `last_span_at` column is added so recovery can gate on "no activity for N minutes" instead of "started > N min ago". Trade-off: zombie traces from gateway crashes may remain `running` in DB. Accepted: primary abort path (router 2-phase + trace.status WS event) handles the common case; safety-net gap preferred over false kills of healthy runs. Integration test RecoverStaleNow() still works (manual trigger, not loop-dependent) so coverage of the recovery function itself is preserved for when it's re-enabled. |
||
|
|
1ac08155b0 |
feat(trace): reliable stop/abort with ctx-aware streams and 2-phase router
Makes the Stop button on the traces page actually stop running traces. Seven-phase implementation across provider HTTP, agent router, trace persistence, WS events, tool exec, i18n, and integration tests. - Provider HTTP+SSE ctx-aware: close socket on cancel via CtxBody wrapper - Router 2-phase abort: CAS state machine, 3s grace, force-mark fallback - Trace retry: 3 inline retries + 10-max retry queue, stale recovery 10min - trace.status WS event: real-time UI updates (invalidates query on receive) - Tool exec: process-group kill (SIGTERM→3s→SIGKILL), Rod page ctx watch - i18n: 6 abort toast variants in en/vi/zh - Integration: 9 scenarios, -race clean Fixes tenant-ctx loss in forceMarkTraceAborted and retry worker broadcast (caught by code-reviewer: C1/C2). Stale threshold intentionally 10min because start_time-based; last_span_at migration is a follow-up. |
||
|
|
77a80680ff |
fix(tracing): include thinking tokens in cost calculation
CalculateCost previously ignored usage.ThinkingTokens entirely, causing cost underestimation for every reasoning-capable model (OpenAI o3/o4-mini, Codex/GPT-5, Anthropic extended thinking). Thinking tokens are reported by providers as a sub-count of completion tokens — OpenAI completion_tokens already includes reasoning_tokens, Codex output_tokens likewise, and Anthropic output_tokens counts thinking at the output rate. Default behaviour (ReasoningPerMillion=0) now matches provider billing semantics: full CompletionTokens priced at OutputPerMillion, no double-counting. When ReasoningPerMillion is explicitly configured, the completion bucket is split into visible output + thinking and each priced independently. Defensive clamp to zero when Anthropic's thinkingChars/4 estimate exceeds reported OutputTokens. Adds ReasoningPerMillion field to ModelPricing and 7 regression tests covering the double-count gate, distinct-rate split, Anthropic estimate overrun, and backward compatibility for non-reasoning models. |
||
|
|
41e6c8f5cc |
feat(infra): tracing recovery, browser cleanup, CLI fixes, UI workspace split (#709)
- Tracing: recover stale running traces/spans on startup (PG + SQLite) - Browser: Chrome orphan cleanup via launcher PID, timeouts, Leakless - Claude CLI: WaitDelay 5s + context-cancel early exit - Agent loop: safety-net defer to finalize orphan root traces - UI: split workspace sharing into separate Memory and KG toggles - Minor: for-range idiom, min() builtin |
||
|
|
21b6c454ca |
feat: merge pipeline, per-user credentials, unified picker, group contacts
- Enable merge UI for linking channel contacts to tenant_users - Contact → tenant_user resolution with cached lookup (60s TTL) - MCP per-user credentials via user-keyed connection pool - Secure CLI per-user credentials with AES-256-GCM encryption - Unified UserPickerCombobox searching contacts + tenant_users - Group contact collection with chat title in all channels - Group permission inheritance via wildcard user_id="*" - Fix heartbeat using wrong userID in group chats - Filter internal senders from contact collection - Add contact_type column (user/group) to channel_contacts - SQLite schema v2 migration for desktop edition |
||
|
|
e183b459c9 |
feat: SQLite desktop edition — full desktop app with team tasks (#505)
* feat(store): add SQLite backend foundation with build-tag injection
Add sqlitestore package (//go:build sqlite) as alternative to PostgreSQL:
- pool.go: WAL mode, busy_timeout, 4 concurrent read connections
- helpers.go: ? param helpers, JSON array storage, nullable/update utils
- scope.go: tenant scope with ? placeholders (vs PG's $N)
- schema.sql: 1296-line flattened DDL from 29 PG migrations (51 tables)
- schema.go: embedded schema with transactional apply + version tracking
- factory.go: NewSQLiteStores() stub (stores wired in Phase 2)
Build-tag split for store initialization:
- cmd/gateway_stores_pg.go (//go:build !sqlite) — default PG-only
- cmd/gateway_stores_sqlite.go (//go:build sqlite) — runtime PG/SQLite switch
- cmd/gateway_setup.go: extracted wireTracingAndCron() shared helper
Config: GOCLAW_STORAGE_BACKEND + GOCLAW_SQLITE_PATH env vars.
Security: goclaw.db added to DenyPaths (exec, read_file, filesystem tools).
* feat(edition): add centralized edition package for feature tier limits
New internal/edition/ package — single source of truth for all edition limits:
- Edition struct with MaxAgents, MaxTeams, MaxChannels, KGEnabled, TeamFullMode, etc.
- Standard (default, all features) and Lite (desktop, 5 agents, 1 team) presets
- atomic.Pointer for thread-safe Current()/SetCurrent()
Wiring:
- cmd/gateway.go: GOCLAW_EDITION env override (lite/standard) at startup
- cmd/gateway_stores_sqlite.go: auto-set Lite when backend=sqlite
- /v1/edition HTTP endpoint for UI comparison modal (public, no auth)
* feat(sqlitestore): implement Phase 2A core stores + sqliteonly build tag
Implement 12 SQLite store backends (4200+ LOC) mirroring existing PG stores:
- SessionStore, AgentStore, ProviderStore, TracingStore, SnapshotStore
- ConfigSecretsStore, SystemConfigStore, TenantStore, HeartbeatStore
- BuiltinToolStore, BuiltinToolTenantConfigStore, SkillTenantConfigStore
All stores wired in factory.go. Remaining stores (Memory, Cron, Skills,
Teams, etc.) left nil — gateway handles gracefully.
Add sqliteonly build tag for PG-free desktop builds:
- go build . → PG only
- go build -tags sqlite . → PG + SQLite (runtime switch)
- go build -tags sqliteonly . → SQLite only (no pgx dependency)
Key SQLite adaptations:
- ? placeholders (not $N), json_extract/json_each/json_array_length
- DISTINCT ON → GROUP BY + Go dedup, ANY($1) → IN (?,?...)
- rows.Err() checks on all scan loops, execMapUpdateWhereTenant in helpers
- GetOrCreateUserProfile uses RowsAffected() instead of PG's xmax trick
* feat(sqlitestore): implement Phase 2B feature stores
Port 8 additional store backends to SQLite (19 new files, ~6000 LOC):
Cron: cron.go, cron_crud.go, cron_exec.go, cron_scheduler.go
- Job scheduling with cache, ListDue, MarkRunning, MarkComplete
Skills: skills.go, skills_crud.go, skills_content.go, skills_grants.go
- CRUD, grants, content management. LIKE search (no FTS/vector in Lite)
MCP: mcp_servers.go, mcp_servers_access.go, mcp_user_credentials.go
- Server CRUD, agent/user grants, encrypted credentials
Channels: channel_instances.go, pairing.go, pending_messages.go, contacts.go
- Channel management, device pairing, message queue, contact store
Teams: teams.go, teams_tasks.go, teams_tasks_lifecycle.go, teams_tasks_activity.go
- Team/task CRUD, lifecycle transitions, activity log, progress tracking
- JSON array for members/blocked_by (replaces PG text[])
Remaining nil stores: Memory, AgentLinks, KnowledgeGraph, Activity,
SecureCLI, APIKeys, ConfigPermissions — gateway handles gracefully.
* fix(sqlitestore): fix critical arg ordering + data races in Phase 2B stores
C1: ListTasks arg mismatch — limit+1 in userID slot, wrong results
C2: SearchTasks missing duplicate userID arg for (? = '' OR t.user_id = ?)
H3: cron_crud.go cacheLoaded written without mutex → use InvalidateCache()
H4: cron_exec.go discarded ExecContext error → log warning
H1: Add rows.Err() checks in cron_crud, cron_scheduler, cron_exec, pairing
* feat(sqlitestore): implement Phase 2C — Memory, Activity, APIKeys, ConfigPermissions
Complete remaining essential stores (6 new files, ~900 LOC):
Memory: memory.go, memory_docs.go, memory_search.go
- Document/chunk CRUD, LIKE-based search (no vector in Lite edition)
- Embedding methods return empty results gracefully
Activity: activity.go — simple activity logging
APIKeys: api_keys.go — API key CRUD with SHA-256 hash lookup
ConfigPermissions: config_permissions.go — permission rules with TTL cache
24/27 stores now wired. Only AgentLinks, KnowledgeGraph, SecureCLI
remain nil (disabled in Lite edition by design).
Total: 49 files, 11,435 LOC in internal/store/sqlitestore/
* fix(sqlitestore): fix variable shadow in GetDocument + handle chunk delete error
C1: GetDocument scopeClause used := inside if/else blocks, shadowing
outer err variable — query errors silently swallowed. Fixed by renaming
to tcErr matching PG pattern.
H1: IndexDocument chunk deletion ExecContext error was discarded, could
cause duplicate chunks. Now returns error on failure.
* feat(desktop): Phase 3 — Wails v2 desktop app shell with chat UI
Desktop app (ui/desktop/) using Wails v2 + React 19 + Tailwind CSS 4:
Go backend:
- main.go: Wails entry point with embedded frontend assets
- app.go: gateway embedding via goroutine, health check, Wails bindings
- keyring.go: OS keyring secrets with file fallback
- cmd/gateway_export.go: exports RunGateway() for desktop embedding
React frontend:
- WS v3 client: protocol handshake, exponential backoff, call queue
- Chat system: Zustand stores, RAF-batched streaming, 10 event handlers
- Components: MessageBubble, MarkdownRenderer (rehype-sanitize),
CodeBlock, ToolCallBlock, ThinkingBlock, ActivityIndicator, InputBar
- Layout: AppShell (2-column), Sidebar with agent/session list, TopBar
- Onboarding wizard (5 steps): welcome, gateway, provider, agent, ready
- Magic Blue theme (dark/light), Inter + JetBrains Mono typography
Build: all 3 variants pass (PG, sqlite, sqliteonly)
* chore: ignore Wails build artifacts (wailsjs, build, package.json.md5)
* fix(desktop): correct onboarding provider list and agent creation API contract
- ProviderStep: expand from 3 to 16 providers in 4 groups (Popular, Cloud, Local, Regional)
with correct provider_type values and api_base defaults
- AgentStep: fix API payload — use agent_key (slug), provider (name string),
agent_type=predefined with description in other_config
- use-agents: fix field mapping — agent_key, display_name from backend response
- Clean up failed provider on verify error
* fix(desktop): add missing providers — Bailian Coding, Z.ai Coding, Ollama Cloud
* fix(desktop): match web dashboard brand colors + persist onboarding in store
- Replace Magic Blue theme with web dashboard's warm blue OKLCH palette
- Move onboarding state from localStorage to Zustand persist store
- Add "Run Setup Wizard" option in TopBar settings menu to re-trigger onboarding
- Fix light mode theme activation (explicit :root:not(.dark) overrides)
* fix(desktop): apply dark theme before first paint + better error messages
- Add class="dark" default on <html> + inline script to read persisted theme
before React hydrate (prevents light flash on dark mode)
- Improve provider test error message for network failures
* feat(desktop): add GoClaw logo from web UI to onboarding + topbar
* fix(desktop): add Vite proxy for dev mode to avoid CORS gateway errors
- Proxy /v1, /ws, /health to localhost:18790 in Vite dev server
- Use relative URLs in dev mode (import.meta.env.DEV) so proxy handles CORS
- Production build uses direct gateway URL from Wails binding
* fix(desktop): GoClaw dock icon + fix duplicate provider slug on re-test
- Convert goclaw-icon.svg to 1024x1024 PNG for macOS dock icon
- Fix provider creation: handle existing slug by finding and updating
- Track build/appicon.png in git (exclude only build/bin/)
* fix(sqlitestore): UUID text/blob mismatch in scopeClause breaks all queries
scopeClause passed uuid.UUID (16-byte array) to SQLite ? placeholder,
but tenant_id column stores TEXT strings. SQLite compared BLOB vs TEXT
→ no match → all scoped queries returned empty results.
Fix: pass scope.TenantID.String() to ensure TEXT comparison.
Also includes:
- macOS dock icon (.icns from GoClaw logo)
- Onboarding auto-detect existing providers/agents
- Debug logging for token + API URL
* fix(desktop): CORS for dev mode + direct gateway URL
- Wails dev server (port 34115) doesn't proxy API calls, causing 405
- Frontend now connects directly to gateway URL from Wails binding
- Added GOCLAW_DESKTOP=1 env → enables CORS middleware on gateway
- desktopCORS wraps mux with Access-Control-Allow-* headers + OPTIONS
- Simplified provider test flow: list-then-create/update
* fix(desktop): split onboarding into 6 steps matching web UI flow
Web UI flow: create provider → select model + verify → create agent.
Desktop was incorrectly trying to verify before creating provider.
Changes:
- ProviderStep: now only creates/saves provider (no verify)
- NEW ModelVerifyStep: loads models from provider, test connection
- AgentStep: receives pre-selected model, shows read-only model field
- OnboardingWizard: 6 steps with auto-detect skip logic
- Auto-detect: has agents→Ready, has providers→ModelVerify, nothing→Provider
* feat(desktop): add Combobox component, use searchable model selector
- New Combobox: searchable dropdown with custom value support
- ModelVerifyStep: replace plain input/select with Combobox
- Models loaded from GET /v1/providers/{id}/models API
- Allows typing custom model name if API returns empty list
* fix(desktop): rename icon to iconfile.icns matching Wails convention
* refactor(desktop): overhaul UI/UX, fix onboarding, fix event handling
Desktop app major refactor:
UI/UX:
- Chat-focused layout with floating panels on dotted canvas
- Sidebar: agent list + sessions grouped by date (no resource counts)
- Modern input bar: rounded pill with attach/send buttons
- User bubble: card style matching web UI (not solid color)
- Thinking block: collapsible, max-height, proper label
- ErrorBoundary wrapping app
- Dock icon: regenerated with transparent bg + dark rounded frame
Onboarding:
- 3-step flow matching web UI (Provider → Model → Agent)
- Proper create vs update (check DB before POST)
- SetupStepper with step circles + connectors
- Agent presets from web UI (Fox Spirit, Artisan, Astrologer)
- Auto-detect existing setup via use-bootstrap-status hook
Event handling (verified from Go source):
- chunk: payload.content (not payload.chunk)
- thinking: payload.content (not payload.thinking)
- tool.call: payload.id/name (not toolId/toolName)
- tool.result: payload.is_error/content (not error field)
- run.completed: usage.prompt_tokens/completion_tokens
- New: block.reply, run.retrying handlers
Backend fixes:
- SQLite scanTime helper for modernc.org/sqlite text timestamps
- X-GoClaw-User-Id header in desktop API client (not X-User-ID)
- user_id: system (owner role in desktop single-user mode)
- CORS: allow X-GoClaw-User-Id header
- SQLite busy timeout: 5s → 10s
- Snapshot SQL: cross-DB compatible (FILTER→CASE, ::BIGINT→CAST)
- Promise.allSettled for bootstrap status (one fail doesn't block other)
* feat(desktop): chat polish, SQLite fixes, summoning modal, bootstrap guard
Chat Polish (Phase 1):
- ToolCallBlock: Wrench/Zap icons, phase badges, arg summary, grouped rendering
- ThinkingBlock: auto-expand on stream, Brain icon, cursor pulse
- MessageBubble: isStreaming prop, streaming cursor, grouped tool calls
- ImageLightbox: fullscreen overlay, gallery nav, keyboard shortcuts, download
- MediaBlock: grid layout, click-to-open lightbox, hover overlay
- ActivityIndicator: phase-specific icons (Brain/Wrench/RefreshCw)
- ChatCanvas: track lastAssistantId for streaming, EmptyState with prompts
- Filter [System] nudge messages and tool-role messages from chat history
SQLite Fixes:
- sessions_list: fix time.Time scan failure (3 sites) using sqliteTime scanner
- snapshots: fix ON CONFLICT expression mismatch with unique index
- snapshots: fix GetLatestBucket using nullSqliteTime
- pool: explicit PRAGMAs (busy_timeout=15s, WAL, synchronous=NORMAL)
- schema: seed master tenant (was missing, causing FK violations)
- schema: incremental migration framework (version-gated patches)
Onboarding:
- SummoningModal: port from web UI with framer-motion animations
- AgentStep: show summoning modal after create, continue button
- App: auto-detect empty DB and reset onboarded flag
- ChatCanvas: loading spinner while agent loads after onboarding
Bootstrap Guard:
- After auto-cleanup of BOOTSTRAP.md, check if USER.md is still empty
- Inject reminder if agent cleared BOOTSTRAP but didn't fill USER.md
Session Management:
- Load chat history on session click (was missing useEffect)
- Fix race condition: don't clear messages on session switch (atomic replace)
- SidebarFooter: center New Chat button text
* fix(desktop): session management, delete confirm, event listener race fix
- New Chat: only clears state, no empty session creation (sendMessage auto-creates)
- Delete session: hover X button with ConfirmDialog confirmation
- Event listener: use sessionKeyRef instead of closure to prevent stale events
- Remove "skip to dashboard" link from onboarding
- Add reusable ConfirmDialog + ConfirmDeleteDialog common components
* feat(desktop): settings view with tabbed layout (Phase 4)
- SettingsView: tab container with header, close button, canvas-dots bg
- SettingsTabBar: 9 tabs (Appearance, Providers, Agents, MCP, Skills, Tools, Cron, Traces, About)
- AppearanceTab: dark/light theme toggle, language + timezone placeholders
- AboutTab: version, edition limits, runtime info
- ui-store: activeView, settingsTab, openSettings(), closeSettings()
- AppShell: switch between chat and settings views
- SidebarFooter: gear icon opens settings (was "Run Setup Wizard")
- Keyboard: Cmd+, opens settings, Escape closes
- Branding: "GoClaw Lite" in sidebar header
- Agent status: online (green) instead of idle for desktop
- Tab content wrapped in solid bg card with border
* feat(desktop): provider management CRUD in settings (Phase 5)
- use-providers hook: list, create, update, delete, verify via HTTP API
- ProviderList: list view with Add button, empty state
- ProviderRow: status dot, type badge, edit/delete actions
- ProviderFormDialog: create/edit with type selector, masked API key, test connection
- Wire ProviderList into Settings Providers tab
* fix(desktop): remove Test Connection from provider form (requires model + provider ID)
* feat(desktop): agent management CRUD in settings (Phase 6)
- AgentData/AgentInput types matching web UI contracts
- use-agent-crud hook: list, create, update, delete, resummon (5 agent limit)
- AgentCard: emoji, status dot, provider/model/type badges, edit/delete/resummon
- AgentFormDialog: provider Combobox + model Combobox (from /v1/providers/{id}/models)
- Create: agent_type selector, "Check & Create" verifies model before create
- Edit: no type change, no re-verify needed
- Personality textarea for predefined agents
- AgentList: grid, edition limit warning, create triggers SummoningModal
- Delete uses ConfirmDeleteDialog (type name to confirm)
- Sidebar agent list refreshes after CRUD
* feat(desktop): agent detail panel with full config (Phase 6 polish)
Agent detail panel (fullscreen overlay covering sidebar):
- PersonalitySection: emoji editor, display name, description, status select, default toggle, agent key display
- ModelBudgetSection: provider/model Combobox with verify-before-save, context window, max tool iterations
- EvolutionSection: self_evolve toggle with info callout (predefined agents only)
- Sticky save bar: backdrop blur, cancel/save buttons, spinner on save
- Save blocked if provider/model changed but not verified
AgentList: card click opens detail panel, create dialog separate
AgentFormDialog: create-only, Check & Create with verify
* fix(desktop): resummon confirm, summoning z-index, save bar UX
- Resummon requires confirm dialog before triggering
- SummoningModal z-index z-50 → z-[70] (above detail panel z-[60])
- Save bar: show error inline, "Verify model first" when blocked
* feat(desktop): agent detail quality polish — files tab, memory config, rich cards
Types (synced with web UI):
- AgentData: added owner_id, workspace, restrict_to_workspace, frontmatter, context_window, max_tool_iterations as required fields
- MemoryConfig, CompactionConfig interfaces
- BootstrapFile type for WS file operations
AgentCard (matching web UI agent-card.tsx):
- Star icon for default agent
- Animated pulse badge for summoning status
- Self-evolve sparkle indicator (orange when active)
- Frontmatter/expertise with line-clamp-3
- Context window display (e.g. "200K ctx")
- Safe emoji extraction, UUID name detection
AgentDetailPanel:
- Tab navigation: Overview + Files tabs
- Overview: Personality + ModelBudget + Memory + Evolution sections
- Files tab: WS-based file editor (agents.files.list/get/set)
- File sidebar with selection
- Textarea editor with dirty tracking
- Save button with spinner
- Sticky save bar with backdrop blur (overview only)
- Resummon with confirm dialog
MemorySection (matching web UI memory-section.tsx):
- Enable/disable toggle
- 6 config fields: max_results, min_score, max_chunk_len, chunk_overlap, vector_weight, text_weight
- "Using global defaults" when disabled
* feat(desktop): agent files — hide USER/HEARTBEAT, add Edit with AI
- Hide USER.md, USER_PREDEFINED.md, HEARTBEAT.md from files tab (managed by bootstrap/cron)
- Add "Edit with AI" button → RegenerateDialog → POST /v1/agents/{id}/regenerate
- Auto-select first file on load
- Show file size in sidebar
- Pass agentId to files tab for regenerate API call
* fix(desktop): remove memory config section (no embedding in SQLite)
* fix(desktop): remove misleading bytes display from file sidebar
* fix(desktop): replace native checkboxes/selects with custom Switch + Combobox
- New Switch component matching Radix UI toggle style
- Replace all native <input type="checkbox"> with Switch in agent/provider forms
- Replace native <select> for status with Combobox
- All interactive elements have cursor-pointer
* fix(desktop): evolution callout colors — use opacity-based for both themes
* fix(desktop): global cursor-pointer for all interactive elements
* fix(desktop): improve dark mode contrast for text and status colors
- text-secondary: 0.62 → 0.68 lightness (better readability on dark bg)
- text-muted: 0.52 → 0.58 lightness (was below WCAG AA 4.5:1 minimum)
- success: 0.45 → 0.55 (green was too dim on dark bg)
- warning: 0.65 → 0.70 (slightly brighter)
- idle: 0.52 → 0.58 (match text-muted)
* fix(desktop): revert color values to exact web UI match (0.62/0.52/0.45)
* fix(desktop): agent card badge colors — match web UI badge variants exactly
* feat(desktop): add MCP servers + Builtin Tools settings tabs
Phase 7 implementation:
MCP Tab:
- Full CRUD with 5-server edition limit
- Form dialog with transport-conditional fields (stdio/SSE/streamable-http)
- Test Connection with inline success/error feedback
- Agent grants dialog (grant/revoke per agent)
- Tools discovery dialog (view server tools)
- KeyValueEditor with sensitive field masking (auth/token/secret)
Tools Tab:
- Category-grouped list of 41 seeded builtin tools
- Toggle enable/disable with optimistic update
- Specialized settings forms: web_fetch extractor chain, media provider chain
- Generic JSON editor fallback for other tools
- Provider/model Combobox selection for media tools
Common:
- RefreshButton component with 500ms min spin animation
- KeyValueEditor with password masking for sensitive keys
Fixes:
- SQLite builtin_tools scan: use scanTimePair() for timestamps
- Session click while in settings: now closes settings view
- Dark mode text contrast: bumped text-secondary/text-muted lightness
- Light mode text contrast: darkened text-secondary/text-muted
- Focus ring thickness: ring-2 → ring-1 globally
- Misleading "memory layering (Postgres)" log label
* feat(desktop): add Skills tab, agent skill grants, emoji avatar, agent form redesign
Skills:
- Skills settings tab with upload ZIP, toggle, delete, runtime check
- Agent skill grants section in agent detail panel (toggle per agent)
- SQLite SkillManageStore interface compliance fixes
Agent form:
- 2-column layout, wider modal (max-w-3xl)
- 6 personality presets (Fox Spirit, Artisan, Astrologer, Researcher, Writer, Coder)
- Separate Verify Model + Summon buttons
- Always predefined type (removed open option)
Fixes:
- SQLite time.Time scan: mcp_servers, mcp_grants, activity_logs
- Combobox portal with scroll/resize tracking
- AgentAvatar shows emoji from other_config
- uploadFile sends X-GoClaw-User-Id header + generic type
- isApiClientReady guard prevents ErrorBoundary crash
- Verify model field: valid (not success)
* fix(sqlitestore): comprehensive timestamp scan sweep + UI fixes
SQLite timestamp sweep (13 files, 25+ sites):
All time.Time direct scans replaced with sqliteTime/scanTimePair/nullSqliteTime.
Files: activity, teams, teams_tasks, teams_tasks_activity, config_permissions,
agents_access, tracing_spans, tracing_scan, channel_instances, tenants,
pending_messages, api_keys, heartbeat.
UI fixes:
- Agent switching: clear active session + chat when agent changes
- MCP table: vertical align middle on row cells
* fix(sqlitestore): fix json.RawMessage scan + sqliteVal for dynamic updates
- mcp_servers_access: scan json columns via string intermediates (SQLite
TEXT → json.RawMessage incompatible, use string then convert)
- helpers: add sqliteVal() to auto-marshal map/slice/struct to JSON
string in execMapUpdate/execMapUpdateWhereTenant — fixes agent save
500 error when updating other_config, tools_config, etc.
- Add AgentMcpSection: toggle MCP server grants per agent in detail panel
- Clean up debug logging from McpGrantsDialog
* feat(desktop): add i18n (react-i18next) + toast system + language/timezone pickers
i18n:
- Install react-i18next + i18next
- Copy 12 web locale namespaces (en/vi/zh) + desktop.json namespace
- Create i18n/index.ts with browser language detection + localStorage persist
- Replace ~300 hardcoded strings across 40+ components with t() calls
- Language picker in ChatTopBar (top-right) + Settings > Appearance
- Timezone picker in ChatTopBar with search + Intl.supportedValuesOf fallback
- All 6 agent presets fully translated (vi/zh) with prompts from locale files
- Agent Key never translated (uses stable English slugs)
Toast:
- Zustand toast store (success/error/warning/default, 4s auto-dismiss)
- Toaster component (bottom-right, z-100, slide-in animation)
- Toast calls in all CRUD hooks (agents, providers, MCP, skills, tools)
* feat(desktop): add Cron Jobs + Traces settings tabs with syntax highlighting
Cron Jobs (Phase 8):
- WS RPC hook (cron.list/create/delete/toggle/run/runs)
- CronList table with schedule formatting, status badges, run/toggle/delete
- CronFormDialog with slug name, agent selector, 3-way schedule (every/cron/once)
- CronRunsDialog for execution history
Traces (Phase 9):
- HTTP REST hook (GET /v1/traces with pagination + agent filter)
- TraceList table with duration, tokens, spans, relative time
- TraceDetailDialog with metadata, collapsible input/output, flat span list
- Syntax-highlighted JSON/code previews via react-syntax-highlighter
* fix(sqlitestore): fix tracing scan — endTime *time.Time → nullSqliteTime
Both trace and span scan functions used *time.Time for nullable end_time
column, which fails on SQLite TEXT timestamps. Changed to nullSqliteTime
with Valid check before assigning pointer.
* fix(desktop): fix cron schedule type label — map 'at' kind to 'once' i18n key
* fix(desktop): prevent flash on cron/traces refresh — keep data while refetching
* feat(desktop): add file attachment rendering — FileButton + FilePreviewDialog
- FileButton: compact attachment button with emoji icon, filename, size, download
- FilePreviewDialog: modal with type-detected preview (image/video/audio/markdown/code/text)
- MarkdownRenderer: override a/img for /v1/files/ links → FileButton + resolved URLs
- MediaBlock: non-image files render as FileButton instead of plain links
- api.ts: add getBaseUrl() for file URL resolution
* fix(desktop): resolve file URLs in chat — toFileUrl for media_refs + relative paths
- use-chat: add toFileUrl() to convert raw paths to /v1/files/{basename} URLs
for both run.completed media and history media_refs
- MarkdownRenderer: detect relative file paths (./path/file.ext) via isFileLink
in addition to /v1/files/ links, resolve all to gateway URL
* fix(desktop): authenticated file serving — media cache + blob URLs
Security fix: all /v1/files/ requests now use Bearer auth via fetchFile().
No more raw <a href> or <img src> with unauthenticated file URLs.
- Add media-cache.ts (blob cache with 5-min TTL, dedup inflight fetches)
- Add use-media-url.ts hook (returns cached blob URL for authenticated media)
- Add AuthImage component (loads images via auth blob) + downloadFile helper
- Update MarkdownRenderer: file images use AuthImage, downloads use downloadFile
- Update FileButton: authenticated download via blob
- Update FilePreviewDialog: authenticated fetch for text/preview content
- Clean filename display (strip timestamps + query params)
* fix(desktop): fix file attachments — use media_refs.id for URL, auth all media
Root cause: media_refs from backend has {id, mime_type, kind} but no path/url.
The id IS the filename basename. Fixed toFileUrl to use ref.id as fallback.
Also: AuthImage for lightbox, authenticated audio/video in MediaBlock,
clean filename display (strip timestamps).
* fix(desktop): file serving, traces, and media rendering improvements
Backend:
- Store MediaRef.Path in loop_finalize for direct file serving
- Use full path (not basename) in gateway_managed event signing
- Add fuzzyMatchInDir for LLM-hallucinated filenames
- Add findInWorkspace support for agent dirs and ws/ directory
- Add POST /v1/files/sign endpoint for client-side URL signing
- Always save LLM span input_preview (not just verbose mode)
- Truncate previews from tail (keep recent context), limit 2000 chars
- Add exact filename hint to create_image/video/audio tool results
Desktop frontend:
- File attachments: FileButton, FilePreviewDialog, AuthImage with blob cache
- Media cache: sign URLs via API for non-ft URLs, Bearer auth fallback
- Download via Wails SaveFile binding (native Save As dialog)
- OpenFile + DownloadURL Wails Go bindings
- Traces: rewrite with span tree hierarchy, formatTokens (90.8K),
formatDuration with start/end fallback, expandable spans
- Traces: export via DownloadURL, copy with checkmark state
- Code preview: JSON = oneDark syntax highlight, text = light pre block
- MarkdownRenderer: baseUrl prop for relative image resolution
- ImageLightbox: preventDefault on keyboard nav (no macOS beep)
- ErrorBoundary: reload instead of re-render on retry
- Combobox: compact sizing (py-1.5, text-sm)
- FileButton: fix nested button HTML violation
* feat(desktop): team tasks kanban board + edition policy + file preview fixes
Phase 11 implementation:
Backend:
- TeamActionPolicy interface — lite/full edition gating for team_tasks tool
- Filter blocked actions from schema enum + early guard in Execute()
- System prompt: edition-specific team member guidance
- Skip skill_manage/publish_skill registration + seeding in lite
- teams.create: require at least 1 member
- files.go: 2-layer path isolation (workspace boundary + tenant scope)
Desktop UI:
- Kanban board with 6 status columns + framer-motion layout animation
- Task detail modal with collapsible description/result sections
- Team create dialog with styled member checkboxes
- Sidebar: teams section with create button + Lite edition badge
- Chat TaskPanel: compact active tasks with real-time WS updates
- Real-time: debounced get-light fetch (300ms) + progress patch (1s)
- Edition comparison modal (Lite vs Standard feature table)
- Custom dropdown filter replacing native select
- i18n: teams namespace (en/vi/zh)
Fixes:
- WS params: camelCase (teamId, taskId, sessionKey) matching backend
- FileButton: span wrapper (HTML nesting) + createPortal for dialog
- FilePreviewDialog: defensive filename normalization for extension check
- use-chat: prevSessionRef init null — fix blank chat on view switch
- Scrollbar: 3px auto-hide
- Agent click in sidebar returns to chat view
* feat: Update frontend build assets, change the default agent thinking level to 'low', and update Go module dependencies.
|
||
|
|
0d9906d40e |
feat(traces): improve trace/span UI with timestamps, copy, syntax highlight
- Add created_at display to trace summary and span detail - Add PreviewBlock component with copy button (top-right) and JSON syntax highlighting via highlight.js - Show span start/end time inline with timezone support - Use Badge for span duration and created_at on summary row - StatusBadge: icon-only on mobile, text on desktop - Double verbose trace preview limit from 100K to 200K chars - Double preview content height on desktop (20vh → 40vh) - formatDate() now accepts timezone param from useUiStore - Show seconds in all timestamp displays - Add i18n keys for all 3 locales (en, vi, zh) |
||
|
|
9a9744077e |
refactor(teams): v2 system cleanup — remove legacy tools, fix followup, add events API (#210)
Major refactoring of the team system with multiple improvements:
## Removed legacy delegation tools
- Delete `delegate.go`, `delegate_async.go`, `delegate_sync.go`, `delegate_events.go`,
`delegate_policy.go`, `delegate_prep.go`, `delegate_state.go`, `delegate_search_tool.go`
- Delete `evaluate_loop_tool.go`, `handoff_tool.go`
- Remove all references and registrations from tool manager and policy
- Clean up TEAM_PLAYBOOK_IDEAS.md and TEAM_SYSTEM.md (moved to docs)
## Rename await_reply → ask_user
- Rename action `await_reply` → `ask_user`, `clear_followup` → `clear_ask_user`
- Rename functions `executeAwaitReply` → `executeAskUser`, `executeClearFollowup` → `executeClearAskUser`
- Update system prompt with stronger wording to prevent model misuse
- Model was confusing "await_reply" with general waiting; "ask_user" is unambiguous
## Fix auto-followup false positives
- Add `HasActiveMemberTasks(ctx, teamID, excludeAgentID)` store method
- Guard `autoSetFollowup()` in consumer: skip when lead has active member tasks
- Prevents auto-followup when lead is orchestrating teammates (not waiting for user)
## Task identifier zero-padding
- Change format from `T-1-xxxx` → `T-001-xxxx` (3-digit minimum)
## Refactor workspace WS handlers to filesystem-only
- Rewrite `teams.workspace.list/read/delete` to use pure filesystem (os.ReadDir/ReadFile/Remove)
- Remove DB dependency from workspace WS handlers
- Consistent with storage handler and workspace tools
- Simplify TeamWorkspaceFile type and frontend hook
## Add team events listing API
- New WS method `teams.events.list` with team_id, limit, offset params
- New HTTP endpoint `GET /v1/teams/{id}/events` with bearer auth
- New `ListTeamEvents(ctx, teamID, limit, offset)` store method
- JOIN with team_tasks for team-wide event filtering
## Extract team access policy
- New `team_access_policy.go` — centralized team tool access control
## Migration 000019: team_id columns
- Add team_id foreign key columns to relevant tables
## Other improvements
- Add team_id propagation through agent loop, tracing, sessions
- Update i18n locale files (en/vi/zh) for new tool labels
- Update frontend builtin-tools page and require-setup component
- Bump RequiredSchemaVersion for migration 000019
|
||
|
|
73389d2715 |
fix(ui): align usage data contracts, add timezone setting, and fix empty usage page (#146)
- Fix 6 data contract mismatches between Go backend JSON tags and React frontend TypeScript interfaces (field renames, response envelope changes) - Add timezone selector to topbar with 12 common timezone options - Replace date-fns formatting with native Intl.DateTimeFormat for timezone-aware chart labels (reduces bundle ~20KB) - Add missing SnapshotTimeSeries fields (memory_docs, memory_chunks, kg_entities, kg_relations) that caused empty usage page - Add error banner to usage page for API error visibility - Sanitize backend error messages in usage HTTP handlers - Add batch chunking (max 3000 rows) for snapshot upserts - Remove userId display from topbar - Add usage analytics i18n strings for en/vi/zh |
||
|
|
0926d053b0 |
feat: add token usage tracking, cost analytics, budget enforcement, wake API, and activity audit trail (#142)
- A1+C2: Include token usage in run.completed event payload for WS clients
- A2: Cost tracking with model pricing config, cost calculation, and cost summary API
- A3: Budget enforcement per agent with monthly budget limits (migration 000015)
- C1: External wake/trigger API (POST /v1/agents/{id}/wake) for orchestrators
- C3: Activity audit trail with structured logging and queryable API
- UI: Activity page, cost stat card on overview, budget section in agent detail
- i18n: Complete en/vi/zh translations for all new features
|
||
|
|
004f6055ff |
fix(tracing): set trace back to running while announce span is active
When an announce (child trace) run starts, toggle the parent trace status to "running" so the UI doesn't show "completed" with a running child span. Restore to "completed" when the announce finishes. |
||
|
|
ef720ee13a |
feat(tracing): two-phase spans — show running state before completion
Spans are now emitted BEFORE execution starts with status "running" and input visible, then updated when the step completes. This lets users see what the system is doing during long-running LLM calls and tool executions. - Add EmitSpanUpdate() to collector with separate update buffer - Flush ordering: batch INSERT new spans first, then process updates - Split LLM/tool/agent spans into start/end pairs (agent loop + subagent) - Emit tool span end inside goroutines for parallel calls (no orphans) - EmitSpanUpdate is a channel send — works after ctx cancellation |
||
|
|
bdb60de7ae |
chore: upgrade Go 1.25 → 1.26 and apply go fix modernizations
- Update go.mod and Dockerfile to Go 1.26 - Apply `go fix ./...` stdlib modernizations across 170+ files - Add `go fix` to post-implementation checklist in CLAUDE.md - Fix go fix misapplied rewrite in loop_history.go |
||
|
|
0f2737ce53 |
feat(media): persistent media storage, read_document tool, and pipeline refactor
- Add persistent media storage (internal/media/) replacing temp file deletion
- Add MediaRef type for lightweight media references in session messages
- Refactor media pipeline to use bus.MediaFile{Path, MimeType} across all channels
- Add read_document builtin tool for PDF/DOCX/XLSX analysis via Gemini native API
- Move image sanitization from Telegram to shared agent/media layer
- Add media reload for multi-turn conversations (images from last 5 messages)
- Add reply-to-message media resolution for Telegram (re-download on reply)
- Add media inventory to compaction summary to preserve awareness after truncation
- Fix coreToolSummaries for read_image, read_document, create_image tools
- Add real-time trace update events via WebSocket broadcast
- Improve trace detail UI with media refs and tool result display
|
||
|
|
dfd91556f8 | feat: Introduce agent teams, agent linking, and advanced agent orchestration features. | ||
|
|
f3f4c67b36 |
Initial commit: GoClaw AI agent gateway
Multi-agent AI gateway with WebSocket RPC, HTTP API, and messaging channel integrations. Go port of OpenClaw with multi-tenant PostgreSQL, per-user isolation, security hardening, and production observability. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |