mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-09-03 16:16:44 +00:00
feat: Deny team_message tool for team leads and update string truncation to handle Unicode characters.
This commit is contained in:
@@ -160,6 +160,7 @@ func NewManagedResolver(deps ResolverDeps) ResolverFunc {
|
||||
// Inject TEAM.md for all team members (lead + members) so every agent
|
||||
// knows the team workflow: create/claim/complete tasks via team_tasks tool.
|
||||
hasTeam := false
|
||||
isTeamLead := false
|
||||
if deps.TeamStore != nil {
|
||||
hasTeamMD := false
|
||||
for _, cf := range contextFiles {
|
||||
@@ -176,6 +177,13 @@ func NewManagedResolver(deps ResolverDeps) ResolverFunc {
|
||||
Path: bootstrap.TeamFile,
|
||||
Content: buildTeamMD(team, members, ag.ID),
|
||||
})
|
||||
// Detect lead role for tool policy
|
||||
for _, m := range members {
|
||||
if m.AgentID == ag.ID && m.Role == store.TeamRoleLead {
|
||||
isTeamLead = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -325,7 +333,7 @@ func NewManagedResolver(deps ResolverDeps) ResolverFunc {
|
||||
Sessions: deps.Sessions,
|
||||
Tools: toolsReg,
|
||||
ToolPolicy: deps.ToolPolicy,
|
||||
AgentToolPolicy: agentToolPolicyWithMCP(ag.ParseToolsConfig(), hasMCPTools),
|
||||
AgentToolPolicy: agentToolPolicyForTeam(agentToolPolicyWithMCP(ag.ParseToolsConfig(), hasMCPTools), isTeamLead),
|
||||
SkillsLoader: deps.Skills,
|
||||
SkillAllowList: skillAllowList,
|
||||
HasMemory: hasMemory,
|
||||
|
||||
@@ -145,7 +145,6 @@ func buildTeamMD(team *store.TeamData, members []store.TeamMemberData, selfID uu
|
||||
sb.WriteString("- action=search, query=<text> → search tasks by subject/description\n")
|
||||
sb.WriteString("- action=complete, task_id=<id>, result=<summary> → manually complete a task\n")
|
||||
sb.WriteString("- action=cancel, task_id=<id>, reason=<why> → cancel a pending task that is no longer needed\n\n")
|
||||
sb.WriteString("Use `team_message` to send updates to team members.\n\n")
|
||||
sb.WriteString("For simple questions about team composition, answer directly from the member list above.\n")
|
||||
} else {
|
||||
sb.WriteString("As a member, when you receive a delegated task, just do the work.\n")
|
||||
@@ -156,13 +155,32 @@ func buildTeamMD(team *store.TeamData, members []store.TeamMemberData, selfID uu
|
||||
sb.WriteString("- action=list → check team task board (active tasks)\n")
|
||||
sb.WriteString("- action=get, task_id=<id> → read a completed task's full result\n")
|
||||
sb.WriteString("- action=search, query=<text> → search tasks\n\n")
|
||||
sb.WriteString("Use `team_message` to send updates to your team lead.\n\n")
|
||||
sb.WriteString("Use `team_message` to send progress updates to your team lead (one-way, no response expected).\n\n")
|
||||
sb.WriteString("For simple questions about team composition, answer directly from the member list above.\n")
|
||||
}
|
||||
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
// agentToolPolicyForTeam denies team_message for team leads.
|
||||
// Leads should use spawn (which auto-announces results back) instead of team_message
|
||||
// (one-way notification that leaks raw responses to the output channel).
|
||||
func agentToolPolicyForTeam(policy *config.ToolPolicySpec, isLead bool) *config.ToolPolicySpec {
|
||||
if !isLead {
|
||||
return policy
|
||||
}
|
||||
if policy == nil {
|
||||
policy = &config.ToolPolicySpec{}
|
||||
}
|
||||
for _, d := range policy.Deny {
|
||||
if d == "team_message" {
|
||||
return policy
|
||||
}
|
||||
}
|
||||
policy.Deny = append(policy.Deny, "team_message")
|
||||
return policy
|
||||
}
|
||||
|
||||
// agentToolPolicyWithMCP injects "group:mcp" into the agent's alsoAllow list
|
||||
// when MCP tools are loaded, ensuring the PolicyEngine doesn't block them.
|
||||
func agentToolPolicyWithMCP(policy *config.ToolPolicySpec, hasMCP bool) *config.ToolPolicySpec {
|
||||
|
||||
@@ -166,8 +166,8 @@ func (dm *DelegateManager) DelegateAsync(ctx context.Context, opts DelegateOpts)
|
||||
var announceSummaries []protocol.DelegationAnnounceResultSummary
|
||||
for _, r := range artifacts.Results {
|
||||
preview := r.Content
|
||||
if len(preview) > 200 {
|
||||
preview = preview[:200] + "..."
|
||||
if runes := []rune(preview); len(runes) > 200 {
|
||||
preview = string(runes[:200]) + "..."
|
||||
}
|
||||
announceSummaries = append(announceSummaries, protocol.DelegationAnnounceResultSummary{
|
||||
AgentKey: r.AgentKey,
|
||||
|
||||
@@ -100,8 +100,8 @@ func formatDelegateAnnounce(task *DelegationTask, artifacts *DelegateArtifacts,
|
||||
if len(r.Deliverables) > 0 {
|
||||
for _, d := range r.Deliverables {
|
||||
preview := d
|
||||
if len(preview) > 4000 {
|
||||
preview = preview[:4000] + "\n[...truncated, full content in team_tasks]"
|
||||
if runes := []rune(preview); len(runes) > 4000 {
|
||||
preview = string(runes[:4000]) + "\n[...truncated, full content in team_tasks]"
|
||||
}
|
||||
msg += fmt.Sprintf("\n[Deliverable]\n%s\n", preview)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user