feat(teams): task hints for weak models + force v2

- Add lead hint in search/list results with member+model info and task
  creation guidelines (description quality, complexity, model matching)
- Add member instructions in dispatch message (progress, comment, complete)
- Include member comments and attachments in announce content to leader
- Cap announce content at 50k runes to prevent context blowup
- Remove duplicate comment block in announce path
- Force all teams to v2: remove IsTeamV2 gate, v2Actions map,
  isConsumerTeamV2, and v1 TEAM.md branch
- Replace version comparison modal with features showcase modal
- Remove version selector from team settings UI
This commit is contained in:
viettranx committed 2026-03-23 12:14:29 +07:00
1 parent 57f249a89d
commit 8d3eb5bb6f
17 files changed
+259 -362

No files matched your search

-8
View File
@@ -136,11 +136,6 @@ func autoSetFollowup(ctx context.Context, teamStore store.TeamStore, agentStore
if err != nil || team == nil || team.LeadAgentID != ag.ID {
return // only lead agent triggers auto-set
}
// Followup is a v2 feature.
if !isConsumerTeamV2(team) {
return
}
// Skip auto-followup when lead is waiting for teammates (not user).
if hasMember, _ := teamStore.HasActiveMemberTasks(ctx, team.ID, ag.ID); hasMember {
slog.Debug("auto-followup: skipping, active member tasks exist", "team_id", team.ID)
@@ -159,9 +154,6 @@ func autoSetFollowup(ctx context.Context, teamStore store.TeamStore, agentStore
}
}
// isConsumerTeamV2 delegates to tools.IsTeamV2 for version checking.
var isConsumerTeamV2 = tools.IsTeamV2
// parseFollowupSettings extracts followup interval and max reminders from team settings.
func parseFollowupSettings(team *store.TeamData) (time.Duration, int) {
const (
+32 -25
View File
@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"log/slog"
"path/filepath"
"strings"
"sync"
"time"
@@ -330,7 +331,7 @@ func handleTeammateMessage(
teamID, _ := uuid.Parse(inMeta["team_id"])
if teamTaskID != uuid.Nil && teamStore != nil {
cachedTeam, _ = teamStore.GetTeam(ctx, teamID)
if cachedTeam != nil && isConsumerTeamV2(cachedTeam) {
if cachedTeam != nil {
// Check current task status — agent may have already updated it via tool.
currentTask, taskErr := teamStore.GetTask(ctx, teamTaskID)
alreadyTerminal := taskErr == nil && currentTask != nil &&
@@ -432,6 +433,33 @@ func handleTeammateMessage(
announceMedia = outcome.Result.Media
}
// Append member comments & attachments so leader sees them in the announce.
if taskIDStr := inMeta["team_task_id"]; taskIDStr != "" && teamStore != nil {
if taskUUID, err := uuid.Parse(taskIDStr); err == nil {
if comments, err := teamStore.ListRecentTaskComments(ctx, taskUUID, 5); err == nil && len(comments) > 0 {
var parts []string
for _, c := range comments {
author := c.AgentKey
if author == "" {
author = "system"
}
text := c.Content
if len([]rune(text)) > 500 {
text = string([]rune(text)[:500]) + "..."
}
parts = append(parts, fmt.Sprintf("- [%s]: %s", author, text))
}
announceContent += "\n\n[Member notes]\n" + strings.Join(parts, "\n")
}
if attachments, err := teamStore.ListTaskAttachments(ctx, taskUUID); err == nil && len(attachments) > 0 {
announceContent += "\n\n[Attached files in team workspace]"
for _, a := range attachments {
announceContent += "\n- " + filepath.Base(a.Path)
}
}
}
}
// Announce result (or failure) to lead agent via announce queue.
// Queue merges concurrent completions into a single batched announce.
if origChatID == "" {
@@ -483,30 +511,9 @@ func handleTeammateMessage(
parentRootSpanID, _ = uuid.Parse(sid)
}
// Enrich announce content with member comments on the task (if any).
if taskIDStr := inMeta["team_task_id"]; taskIDStr != "" && teamStore != nil {
if tid, err := uuid.Parse(taskIDStr); err == nil {
if comments, err := teamStore.ListTaskComments(ctx, tid); err == nil && len(comments) > 0 {
// Include last 5 comments, each truncated to 200 chars.
start := 0
if len(comments) > 5 {
start = len(comments) - 5
}
var commentLines []string
for _, c := range comments[start:] {
author := c.AgentKey
if author == "" && c.UserID != "" {
author = "user:" + c.UserID
}
body := c.Content
if len(body) > 200 {
body = body[:200] + "..."
}
commentLines = append(commentLines, fmt.Sprintf("- [%s]: %s", author, body))
}
announceContent += "\n\n--- Member comments ---\n" + strings.Join(commentLines, "\n")
}
}
// Cap announce content to prevent context blowup for the leader agent.
if len([]rune(announceContent)) > 50_000 {
announceContent = string([]rune(announceContent)[:50_000]) + "\n[truncated]"
}
// Enqueue result. If we become the processor, run the announce loop.