diff --git a/.trajectories/completed/2026-03/traj_hn0583gzi86w.json b/.trajectories/completed/2026-03/traj_hn0583gzi86w.json new file mode 100644 index 00000000..04644647 --- /dev/null +++ b/.trajectories/completed/2026-03/traj_hn0583gzi86w.json @@ -0,0 +1,65 @@ +{ + "id": "traj_hn0583gzi86w", + "version": 1, + "task": { + "title": "Fix DM routing filter in wrap.rs — allow thread replies, presence events, and conversation_id targets" + }, + "status": "completed", + "startedAt": "2026-03-25T16:25:02.609Z", + "agents": [ + { + "name": "default", + "role": "lead", + "joinedAt": "2026-03-25T16:25:26.589Z" + } + ], + "chapters": [ + { + "id": "chap_7w31qsrd314j", + "title": "Work", + "agentName": "default", + "startedAt": "2026-03-25T16:25:26.589Z", + "events": [ + { + "ts": 1774455926589, + "type": "decision", + "content": "Widen DM filter rather than restructure — add pass-through for empty targets (presence), 'thread' synthetic targets, dm_/conv_ prefixed conversation IDs. Also removed dead code: format_injection_with_workspace import and function.: Widen DM filter rather than restructure — add pass-through for empty targets (presence), 'thread' synthetic targets, dm_/conv_ prefixed conversation IDs. Also removed dead code: format_injection_with_workspace import and function.", + "raw": { + "question": "Widen DM filter rather than restructure — add pass-through for empty targets (presence), 'thread' synthetic targets, dm_/conv_ prefixed conversation IDs. Also removed dead code: format_injection_with_workspace import and function.", + "chosen": "Widen DM filter rather than restructure — add pass-through for empty targets (presence), 'thread' synthetic targets, dm_/conv_ prefixed conversation IDs. Also removed dead code: format_injection_with_workspace import and function.", + "alternatives": [], + "reasoning": "" + }, + "significance": "high" + }, + { + "ts": 1774456153059, + "type": "decision", + "content": "Expanded DM filter to allow empty targets (presence), thread synthetic target, and dm_/conv_ prefixed conversation_id fallbacks. Removed unused format_injection_with_workspace function and import.: Expanded DM filter to allow empty targets (presence), thread synthetic target, and dm_/conv_ prefixed conversation_id fallbacks. Removed unused format_injection_with_workspace function and import.", + "raw": { + "question": "Expanded DM filter to allow empty targets (presence), thread synthetic target, and dm_/conv_ prefixed conversation_id fallbacks. Removed unused format_injection_with_workspace function and import.", + "chosen": "Expanded DM filter to allow empty targets (presence), thread synthetic target, and dm_/conv_ prefixed conversation_id fallbacks. Removed unused format_injection_with_workspace function and import.", + "alternatives": [], + "reasoning": "" + }, + "significance": "high" + } + ], + "endedAt": "2026-03-25T16:29:26.110Z" + } + ], + "commits": [], + "filesChanged": [], + "projectId": "/Users/khaliqgant/Projects/Agent Workforce/relay", + "tags": [], + "_trace": { + "startRef": "184f502cf5542b2ba0f918681eff6be194699c71", + "endRef": "184f502cf5542b2ba0f918681eff6be194699c71" + }, + "completedAt": "2026-03-25T16:29:26.110Z", + "retrospective": { + "summary": "Fixed DM routing filter and cleaned up dead code per Devin review on PR #641", + "approach": "Added explicit exceptions for empty targets, thread, dm_/conv_ prefixes. Removed unused format_injection_with_workspace.", + "confidence": 0.95 + } +} \ No newline at end of file diff --git a/.trajectories/completed/2026-03/traj_hn0583gzi86w.md b/.trajectories/completed/2026-03/traj_hn0583gzi86w.md new file mode 100644 index 00000000..c66f6cdd --- /dev/null +++ b/.trajectories/completed/2026-03/traj_hn0583gzi86w.md @@ -0,0 +1,24 @@ +# Trajectory: Fix DM routing filter in wrap.rs — allow thread replies, presence events, and conversation_id targets + +> **Status:** ✅ Completed +> **Confidence:** 95% +> **Started:** March 25, 2026 at 05:25 PM +> **Completed:** March 25, 2026 at 05:29 PM + +--- + +## Summary + +Fixed DM routing filter and cleaned up dead code per Devin review on PR #641 + +**Approach:** Added explicit exceptions for empty targets, thread, dm_/conv_ prefixes. Removed unused format_injection_with_workspace. + +--- + +## Chapters + +### 1. Work +*Agent: default* + +- Widen DM filter rather than restructure — add pass-through for empty targets (presence), 'thread' synthetic targets, dm_/conv_ prefixed conversation IDs. Also removed dead code: format_injection_with_workspace import and function.: Widen DM filter rather than restructure — add pass-through for empty targets (presence), 'thread' synthetic targets, dm_/conv_ prefixed conversation IDs. Also removed dead code: format_injection_with_workspace import and function. +- Expanded DM filter to allow empty targets (presence), thread synthetic target, and dm_/conv_ prefixed conversation_id fallbacks. Removed unused format_injection_with_workspace function and import.: Expanded DM filter to allow empty targets (presence), thread synthetic target, and dm_/conv_ prefixed conversation_id fallbacks. Removed unused format_injection_with_workspace function and import. diff --git a/.trajectories/index.json b/.trajectories/index.json index 519d85fb..7de0a909 100644 --- a/.trajectories/index.json +++ b/.trajectories/index.json @@ -1,6 +1,6 @@ { "version": 1, - "lastUpdated": "2026-03-25T09:28:53.988Z", + "lastUpdated": "2026-03-25T16:29:26.213Z", "trajectories": { "traj_1b1dj40sl6jl": { "title": "Revert aggressive retry logic in relay-pty-orchestrator", @@ -856,6 +856,13 @@ "startedAt": "2026-03-25T09:28:08.884Z", "completedAt": "2026-03-25T09:28:53.882Z", "path": "/Users/khaliqgant/Projects/AgentWorkforce/relay/.trajectories/completed/2026-03/traj_1qnnaojcl0w6.json" + }, + "traj_hn0583gzi86w": { + "title": "Fix DM routing filter in wrap.rs — allow thread replies, presence events, and conversation_id targets", + "status": "completed", + "startedAt": "2026-03-25T16:25:02.609Z", + "completedAt": "2026-03-25T16:29:26.110Z", + "path": "/Users/khaliqgant/Projects/Agent Workforce/relay/.trajectories/completed/2026-03/traj_hn0583gzi86w.json" } } } \ No newline at end of file diff --git a/src/helpers.rs b/src/helpers.rs index 806227ce..d2f7570f 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -532,27 +532,6 @@ pub(crate) fn format_injection(from: &str, event_id: &str, body: &str, target: & format_injection_with_reminder(from, event_id, body, target, true) } -pub(crate) fn format_injection_with_workspace( - from: &str, - event_id: &str, - body: &str, - target: &str, - workspace_id: Option<&str>, - workspace_alias: Option<&str>, -) -> String { - format_injection_for_worker_with_workspace( - from, - event_id, - body, - target, - true, - true, - None, - workspace_id, - workspace_alias, - ) -} - #[cfg_attr(not(test), allow(dead_code))] pub(crate) fn format_injection_with_reminder( from: &str, diff --git a/src/wrap.rs b/src/wrap.rs index f549a187..50d4d681 100644 --- a/src/wrap.rs +++ b/src/wrap.rs @@ -3,8 +3,8 @@ use std::time::{Duration, Instant}; use super::*; use crate::helpers::{ - check_echo_in_output, floor_char_boundary, format_injection_with_workspace, ActivityDetector, - DeliveryOutcome, PendingActivity, PendingVerification, ThrottleState, + check_echo_in_output, floor_char_boundary, format_injection_for_worker_with_workspace, + ActivityDetector, DeliveryOutcome, PendingActivity, PendingVerification, ThrottleState, ACTIVITY_BUFFER_KEEP_BYTES, ACTIVITY_BUFFER_MAX_BYTES, ACTIVITY_WINDOW, MAX_VERIFICATION_ATTEMPTS, VERIFICATION_WINDOW, }; @@ -546,6 +546,7 @@ pub(crate) async fn run_wrap( let requested_name = std::env::var("RELAY_AGENT_NAME").unwrap_or_else(|_| resolved_cli.clone()); let channels = std::env::var("RELAY_CHANNELS").unwrap_or_else(|_| "general".to_string()); let channel_list = channels_from_csv(&channels); + let skip_prompt = env_flag_enabled("RELAY_SKIP_PROMPT"); eprintln!( "[agent-relay] wrapping {} (agent: {}, channels: {:?})", @@ -578,6 +579,16 @@ pub(crate) async fn run_wrap( workspaces, mut ws_inbound_rx, } = relay; + // Ensure the requested agent name (from RELAY_AGENT_NAME) is in self_names + // so that messages sent by the MCP server child (which registers with the + // same name) are recognized as self-echo and filtered out. + let workspaces: Vec = workspaces + .into_iter() + .map(|mut ws| { + ws.self_names.insert(requested_name.clone()); + ws + }) + .collect(); let workspace_lookup: std::collections::HashMap = workspaces .iter() .cloned() @@ -1024,6 +1035,25 @@ pub(crate) async fn run_wrap( continue; } + // DM routing: only deliver DMs addressed to this agent. + // Channel messages (target starts with '#') are broadcast + // to all subscribers. Allow through: empty targets (presence), + // thread replies, conversation_id fallbacks. + if !mapped.target.is_empty() + && !mapped.target.starts_with('#') + && mapped.target != "thread" + && !mapped.target.starts_with("dm_") + && !mapped.target.starts_with("conv_") + && !workspace_self_names.contains(&mapped.target) + { + tracing::debug!( + target = %mapped.target, + self_names = ?workspace_self_names, + "skipping DM not addressed to this agent" + ); + continue; + } + let delivery_id = format!("wrap_{}", mapped.event_id); tracing::debug!( delivery_id = %delivery_id, @@ -1072,11 +1102,14 @@ pub(crate) async fn run_wrap( pty_auto.auto_suggestion_visible = false; } tracing::debug!("relay from {} → {}", pending.from, pending.target); - let injection = format_injection_with_workspace( + let injection = format_injection_for_worker_with_workspace( &pending.from, &pending.event_id, &pending.body, &pending.target, + !skip_prompt, // include_reminder + true, // pre_registered + None, // assigned_name pending.workspace_id.as_deref(), pending.workspace_alias.as_deref(), ); @@ -1171,11 +1204,14 @@ pub(crate) async fn run_wrap( // Re-inject retries for mut pv in retry_queue { tokio::time::sleep(throttle.delay()).await; - let injection = format_injection_with_workspace( + let injection = format_injection_for_worker_with_workspace( &pv.from, &pv.event_id, &pv.body, &pv.target, + !skip_prompt, + true, + None, pv.workspace_id.as_deref(), pv.workspace_alias.as_deref(), );