fix(media): persist generated files, prevent duplicate delivery, and improve group media history#206
Open
vanducng wants to merge 27 commits intonextlevelbuilder:mainfrom
Open
Conversation
61041b4 to
d8be726
Compare
Root cause: dispatch.go deleted ALL media files after channel send, including workspace-generated files (create_image, create_video, etc.). This caused "stat file: no such file" errors on subsequent send attempts and prevented files from persisting in workspace storage. Additionally, when the LLM used the message tool with MEDIA: prefix to send generated media, the same file was sent again via RunResult.Media, causing duplicate images/videos in channel chats. Changes: - dispatch.go: only delete temp files (/tmp/), not workspace files - loop.go: track media sent by message tool, deduplicate RunResult.Media - create_image/video/audio: add empty data guard, post-write verification with size logging for diagnostics - send_helpers.go: log directory contents on stat failure for debugging
…Zalo
- media_tool_routing: support chain format {"providers":[...]} in
hasReadImageProvider (was only flat {"provider":"X"})
- history: add Media field to HistoryEntry, CollectMedia() for pending
entries, temp file cleanup on eviction/clear
- discord/handler: record media in group history, collect on @mention
- zalo/personal/handlers: same pattern for Zalo group history
Zalo personal channel only downloaded images; non-image files (CSV, PDF, XLSX, etc.) were replaced with a text placeholder and never persisted. Now all attachments are downloaded, classified by MIME type, and tagged with <media:*> for the agent pipeline (matching Telegram/Discord/Feishu). Also remove the media bypass in InboundDebouncer so a file/image followed by a text caption within the debounce window are merged into one agent turn.
d8be726 to
0d1774a
Compare
…hlight - 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)
- Move task dispatch from mid-turn to post-turn to prevent dependent tasks from completing before the current agent's run finishes - Add team create lock to serialize list→create flows across concurrent group chat sessions, preventing duplicate task creation - Require list-before-create gate: agents must call team_tasks(list) before creating tasks - Make assignee required on task creation - Add pagination (50 per page) to task list with offset support - Slim task list/get/search responses with dedicated structs to reduce context token usage - Add task board snapshot in announce messages to leader - Workspace: allow subdirectory paths in read/delete, show directories in list output - UI: reduce kanban card title font size for better visual balance
- Change WS pairing check from fail-open to fail-closed on DB error (router.go: previously granted RoleOperator on any IsPaired() error) - Add "browser" to InternalChannels so it's properly excluded from outbound dispatch without ad-hoc helpers - Rate-limit browser.pairing.status endpoint to prevent sender_id enumeration (reuses server RateLimiter via PairingMethods injection) - Add expires_at column to paired_devices with 30-day TTL for defense-in-depth; IsPaired() now checks expiry, ListPaired() prunes - Add confidence_score column to team_tasks, team_messages, team_task_comments - Bump RequiredSchemaVersion to 21
…s for team workspace Remove dedicated workspace tools in favor of making existing file tools (read_file, write_file, list_files, edit) team-workspace-aware. - Delete workspace_tool_read.go and workspace_tool_write.go - Clean up workspace_dir.go: export WorkspaceDir, remove dead code (workspaceRelPath, sanitizeFilePath, inferMimeType, templates, etc.) - Remove workspace tool registration from gateway_managed.go - Remove workspace tool references from policy, subagent, MCP bridge - Add PathAllowable/PathDenyable to types.go for interface abstraction
… tools access - Add WithToolTeamWorkspace/ToolTeamWorkspaceFromCtx context key for team workspace path (accessible but not necessarily default) - Create WorkspaceInterceptor for team-specific write validation (RBAC, quota, blocked extensions, event broadcasting) - File tools (read_file, write_file, list_files, edit) allow access to team workspace via allowedWithTeamWorkspace() helper - read_file/list_files hint team workspace path when file not found - Registry detects empty tool call args and returns actionable hint (DashScope/Qwen large-output truncation workaround)
- Lead agents: auto-resolve team workspace as default (relative paths) - Dispatched members: team workspace as default via req.TeamWorkspace - Direct-chat members: own workspace default, team workspace accessible - Add dataDir field to Loop/LoopConfig for global workspace root - System prompt shows team workspace absolute path for model guidance - Remove orphan task detector (superseded by post-turn dispatch) - Log warning on OpenAI tool call argument parse failures
… WorkspaceDir callers - status="" now returns all tasks (was active-only); add explicit "active" filter - Reduce list/search page size from 50 to 30 - Update WorkspaceDir callers after signature change (remove unused channel param) - Update team_tasks schema descriptions for status and page params
Squash-merge PR nextlevelbuilder#225 with security fixes: - Fix browser pairing stuck on "Waiting for approval" (stale closure: useState → useRef for senderID in pairing-form) - Fix auto-kick after pairing (RequireAuth now accepts senderID, onAuthFailure skips logout for paired browser sessions) - Allow browser-paired users to access HTTP APIs via X-GoClaw-Sender-Id header with fail-closed IsPaired check - Remove ad-hoc IsInternalOrBrowser(), use channels.IsInternalChannel() - Log failed HTTP pairing auth attempts for security monitoring - Pass senderID to HttpClient for authenticated HTTP requests
- Kanban: reorder columns (blocked after pending), show blocked-by info on cards, clickable blocker links in task detail, framer-motion card animation between columns - Dialogs: standardize scroll pattern across all modals — header fixed, scrollbar flush with outer edge via negative margin trick - Remove delegation page, types, events, i18n, routes, and all references - Fix activity_logs NULL jsonb scan error (COALESCE) - Board header: show text labels on action buttons (desktop)
- Replace per-team loop with batch SQL (v2 filter in JOIN) - RecoverAllStaleTasks/ForceRecoverAllTasks/MarkAllStaleTasks return RecoveredTaskInfo for notification routing - Notify leaders per (teamID, channel, chatID) scope with actionable hints - Fix notifyLeaderCycleError routing (was silently DROPPED) - Stale threshold: 24h → 2h default - Remove per-session RecoverStaleTasks from loop.go (ticker handles it) - Add rows.Err() check to scanRecoveredTaskInfoRows
Remove delegate_search, evaluate_loop, handoff from: - Seed data, system prompt, i18n keys/catalogs, channel events - Consumer handler (handleHandoffAnnounce), handoff route lookup - HandoffRouteData struct + PG implementation - Protocol events, MCP bridge comment - Web UI locale files (en/vi/zh)
- IsSharedWorkspace() reads team.settings.workspace_scope
- Shared: workspace at teams/{teamID}/ (all chats share)
- Isolated (default): workspace at teams/{teamID}/{chatID}/
- Remove _default fallback; isolated mode requires chat_id
- Update loop.go, task creation, task listing, message dispatch,
workspace API (list/read/delete), task board snapshot
- Update UI descriptions to reflect per-conversation scoping
- Replace progress_notifications toggle with granular config: dispatched (on), progress (on), failed (on) + delivery mode - Direct mode: outbound to channel, no AI processing - Leader mode: inject into leader session with NO-ACTION instructions - Add consumer.team-notify subscriber for event forwarding - Enrich TeamTaskEventPayload with TaskNumber, ProgressPercent/Step - Add auto-status system prompt section - UI: card-select for delivery mode (Zap/Bot icons), 3 toggles
- Fix scope dropdown: cache scopes from initial "all" load so dropdown stays stable when filtering by chatID - Derive scopes from file chat_id when task scopes are empty - Remove dead files: team-workspace-tab.tsx, team-tasks-tab.tsx (replaced by board view and workspace dialog)
…uilder#231) * feat(ui): improve kanban UX, fix dialog scroll, remove delegation page - Kanban: reorder columns (blocked after pending), show blocked-by info on cards, clickable blocker links in task detail, framer-motion card animation between columns - Dialogs: standardize scroll pattern across all modals — header fixed, scrollbar flush with outer edge via negative margin trick - Remove delegation page, types, events, i18n, routes, and all references - Fix activity_logs NULL jsonb scan error (COALESCE) - Board header: show text labels on action buttons (desktop) * docs: comprehensive audit and update of all documentation - Update Go 1.25 → 1.26, PostgreSQL 15+ → 18 across all docs - Add 10 missing internal modules to CLAUDE.md project structure - Expand provider docs from 2 to 6 packages (Anthropic, OpenAI, DashScope, Claude CLI, ACP, Codex) - Add 8 missing store interfaces to data model docs (22 total) - Update bootstrap files from 7 to 13 templates - Expand tool inventory from ~35 to 60+ tools with media/KG/credential categories - Fix Team Task Board: add blocked status, 3 missing actions, V2 versioning, delegate restrictions - Remove all references to removed features: handoff, delegate_search, evaluate_loop, agent_links - Fix lane defaults (2/4/1 → 30/50/100/30), ghost file references, models.list → providers.models - Add SecureCLI, snapshot worker, cost calculation, pairing security docs - Comprehensive changelog catch-up - Trim docs/03-tools-system.md to 800-line limit
…r providers and breaking validation (nextlevelbuilder#230) * fix: prevent gemini thought_signature from leaking to other providers * test: refine gemini model detection for robust provider multiplexing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
dispatch.godeleted ALL media files after channel send, including workspace-generated files (create_image,create_video,create_audio). This causedstat file: no such fileerrors and prevented files from persisting in workspace storage.messagetool (MEDIA:prefix), the same file was also sent viaRunResult.Media, causing duplicate images/videos in channel chats. Previously masked by the file deletion bug.hasReadImageProvideronly supported flat{"provider":"X"}format, not the chain format{"providers":[...]}used by media provider chain config.Changes
Fix: Media file persistence & dedup
dispatch.go/tmp/), not workspace filesloop.gomessagetool, deduplicateRunResult.Mediacreate_image.gocreate_video.gocreate_audio.gosend_helpers.goFeat: Chain provider format + group media history
media_tool_routing.go{"providers":[...]}inhasReadImageProviderhistory.goMediafield toHistoryEntry,CollectMedia(), temp file cleanup on eviction/cleardiscord/handler.gozalo/personal/handlers.goTest plan
stat file: no such fileerrors in logs/tmp/still cleaned up after send