Skip to content

Commit 8dc6b44

Browse files
committed
fix(signal): review comments
1 parent 8eeac9b commit 8dc6b44

5 files changed

Lines changed: 68 additions & 47 deletions

File tree

src/config.rs

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -541,11 +541,9 @@ bind = "127.0.0.1"
541541
guild_id: None,
542542
workspace_id: workspace_id.map(String::from),
543543
chat_id: None,
544-
group_ids: vec![],
545544
channel_ids: vec![],
546545
require_mention: false,
547546
dm_allowed_users,
548-
group_allowed_users: vec![],
549547
}
550548
}
551549

@@ -1315,11 +1313,9 @@ association_max_per_pass = 55
13151313
guild_id: None,
13161314
workspace_id: None,
13171315
chat_id: None,
1318-
group_ids: vec![],
13191316
channel_ids: vec![],
13201317
require_mention: false,
13211318
dm_allowed_users: vec![],
1322-
group_allowed_users: vec![],
13231319
};
13241320
assert_eq!(binding.runtime_adapter_key(), "telegram:sales");
13251321
}
@@ -1333,11 +1329,9 @@ association_max_per_pass = 55
13331329
guild_id: None,
13341330
workspace_id: None,
13351331
chat_id: None,
1336-
group_ids: vec![],
13371332
channel_ids: vec![],
13381333
require_mention: false,
13391334
dm_allowed_users: vec![],
1340-
group_allowed_users: vec![],
13411335
};
13421336
assert!(binding.uses_default_adapter());
13431337
}
@@ -1366,11 +1360,9 @@ association_max_per_pass = 55
13661360
guild_id: None,
13671361
workspace_id: None,
13681362
chat_id: None,
1369-
group_ids: vec![],
13701363
channel_ids: vec![],
13711364
require_mention: false,
13721365
dm_allowed_users: vec![],
1373-
group_allowed_users: vec![],
13741366
};
13751367
let message = test_inbound_message("telegram", None);
13761368
assert!(binding_adapter_matches(&binding, &message));
@@ -1385,11 +1377,9 @@ association_max_per_pass = 55
13851377
guild_id: None,
13861378
workspace_id: None,
13871379
chat_id: None,
1388-
group_ids: vec![],
13891380
channel_ids: vec![],
13901381
require_mention: false,
13911382
dm_allowed_users: vec![],
1392-
group_allowed_users: vec![],
13931383
};
13941384
let message = test_inbound_message("telegram", Some("telegram:support"));
13951385
assert!(binding_adapter_matches(&binding, &message));
@@ -1404,11 +1394,9 @@ association_max_per_pass = 55
14041394
guild_id: None,
14051395
workspace_id: None,
14061396
chat_id: None,
1407-
group_ids: vec![],
14081397
channel_ids: vec![],
14091398
require_mention: false,
14101399
dm_allowed_users: vec![],
1411-
group_allowed_users: vec![],
14121400
};
14131401
let message = test_inbound_message("telegram", None);
14141402
assert!(!binding_adapter_matches(&binding, &message));
@@ -1423,11 +1411,9 @@ association_max_per_pass = 55
14231411
guild_id: None,
14241412
workspace_id: None,
14251413
chat_id: None,
1426-
group_ids: vec![],
14271414
channel_ids: vec![],
14281415
require_mention: false,
14291416
dm_allowed_users: vec![],
1430-
group_allowed_users: vec![],
14311417
};
14321418
let message = test_inbound_message("telegram", Some("telegram:support"));
14331419
assert!(!binding_adapter_matches(&binding, &message));
@@ -1442,11 +1428,9 @@ association_max_per_pass = 55
14421428
guild_id: None,
14431429
workspace_id: None,
14441430
chat_id: None,
1445-
group_ids: vec![],
14461431
channel_ids: vec![],
14471432
require_mention: false,
14481433
dm_allowed_users: vec![],
1449-
group_allowed_users: vec![],
14501434
};
14511435
let message = test_inbound_message("telegram", Some("telegram:sales"));
14521436
assert!(!binding_adapter_matches(&binding, &message));
@@ -1481,11 +1465,10 @@ association_max_per_pass = 55
14811465
guild_id: None,
14821466
workspace_id: None,
14831467
chat_id: None,
1484-
group_ids: vec![],
1468+
14851469
channel_ids: vec![],
14861470
require_mention: false,
14871471
dm_allowed_users: vec![],
1488-
group_allowed_users: vec![],
14891472
},
14901473
Binding {
14911474
agent_id: "support-agent".into(),
@@ -1494,11 +1477,10 @@ association_max_per_pass = 55
14941477
guild_id: None,
14951478
workspace_id: None,
14961479
chat_id: None,
1497-
group_ids: vec![],
1480+
14981481
channel_ids: vec![],
14991482
require_mention: false,
15001483
dm_allowed_users: vec![],
1501-
group_allowed_users: vec![],
15021484
},
15031485
];
15041486
assert!(validate_named_messaging_adapters(&messaging, &bindings).is_ok());
@@ -1527,11 +1509,9 @@ association_max_per_pass = 55
15271509
guild_id: None,
15281510
workspace_id: None,
15291511
chat_id: None,
1530-
group_ids: vec![],
15311512
channel_ids: vec![],
15321513
require_mention: false,
15331514
dm_allowed_users: vec![],
1534-
group_allowed_users: vec![],
15351515
}];
15361516
assert!(validate_named_messaging_adapters(&messaging, &bindings).is_err());
15371517
}
@@ -1592,11 +1572,9 @@ association_max_per_pass = 55
15921572
guild_id: None,
15931573
workspace_id: None,
15941574
chat_id: None,
1595-
group_ids: vec![],
15961575
channel_ids: vec![],
15971576
require_mention: false,
15981577
dm_allowed_users: vec![],
1599-
group_allowed_users: vec![],
16001578
}];
16011579
assert!(validate_named_messaging_adapters(&messaging, &bindings).is_err());
16021580
}
@@ -1630,11 +1608,9 @@ association_max_per_pass = 55
16301608
guild_id: None,
16311609
workspace_id: None,
16321610
chat_id: None,
1633-
group_ids: vec![],
16341611
channel_ids: vec![],
16351612
require_mention: false,
16361613
dm_allowed_users: vec![],
1637-
group_allowed_users: vec![],
16381614
}];
16391615
assert!(validate_named_messaging_adapters(&messaging, &bindings).is_err());
16401616
}

src/config/load.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2153,15 +2153,16 @@ impl Config {
21532153
let account = std::env::var("SIGNAL_ACCOUNT")
21542154
.ok()
21552155
.or_else(|| s.account.as_deref().and_then(resolve_env_value));
2156+
let has_default_credentials = http_url.is_some() && account.is_some();
21562157

2157-
if (http_url.is_none() || account.is_none())
2158-
&& !instances.iter().any(|inst| inst.enabled)
2158+
if !has_default_credentials
2159+
&& !instances.iter().any(|instance| instance.enabled)
21592160
{
21602161
return None;
21612162
}
21622163

21632164
Some(SignalConfig {
2164-
enabled: s.enabled,
2165+
enabled: s.enabled && has_default_credentials,
21652166
http_url: http_url.unwrap_or_default(),
21662167
account: account.unwrap_or_default(),
21672168
instances,

src/messaging/signal.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,7 +1079,13 @@ async fn sse_listener(
10791079
"signal SSE returned error, retrying in {:?}",
10801080
retry_delay
10811081
);
1082-
tokio::time::sleep(retry_delay).await;
1082+
tokio::select! {
1083+
_ = tokio::time::sleep(retry_delay) => {}
1084+
_ = shutdown_rx.recv() => {
1085+
tracing::info!("signal SSE listener shutting down during retry");
1086+
return;
1087+
}
1088+
}
10831089
retry_delay = (retry_delay * 2).min(SSE_MAX_BACKOFF);
10841090
continue;
10851091
}
@@ -1089,7 +1095,13 @@ async fn sse_listener(
10891095
"signal SSE connect error, retrying in {:?}",
10901096
retry_delay
10911097
);
1092-
tokio::time::sleep(retry_delay).await;
1098+
tokio::select! {
1099+
_ = tokio::time::sleep(retry_delay) => {}
1100+
_ = shutdown_rx.recv() => {
1101+
tracing::info!("signal SSE listener shutting down during retry");
1102+
return;
1103+
}
1104+
}
10931105
retry_delay = (retry_delay * 2).min(SSE_MAX_BACKOFF);
10941106
continue;
10951107
}
@@ -1229,7 +1241,13 @@ async fn sse_listener(
12291241
}
12301242

12311243
tracing::debug!("signal SSE stream ended, reconnecting with backoff...");
1232-
tokio::time::sleep(retry_delay).await;
1244+
tokio::select! {
1245+
_ = tokio::time::sleep(retry_delay) => {}
1246+
_ = shutdown_rx.recv() => {
1247+
tracing::info!("signal SSE listener shutting down during reconnect");
1248+
return;
1249+
}
1250+
}
12331251
retry_delay = (retry_delay * 2).min(SSE_MAX_BACKOFF);
12341252
}
12351253
}

src/messaging/target.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -341,13 +341,15 @@ fn json_value_to_string(value: &serde_json::Value) -> Option<String> {
341341
fn extract_signal_adapter_from_channel_id(channel_id: &str) -> String {
342342
let parts: Vec<&str> = channel_id.split(':').collect();
343343
match parts.as_slice() {
344-
// Named adapter: signal:{instance}:{target}
345-
// target must start with "uuid:", "group:", or "+" to confirm it's a real target
346-
["signal", instance, target_part, ..]
347-
if target_part.starts_with("uuid:")
348-
|| target_part.starts_with("group:")
349-
|| target_part.starts_with('+') =>
350-
{
344+
// Named adapter: signal:{instance}:uuid:{uuid}, signal:{instance}:group:{id}
345+
// or signal:{instance}:e164:+{phone}
346+
["signal", instance, "uuid", ..]
347+
| ["signal", instance, "group", ..]
348+
| ["signal", instance, "e164", ..] => {
349+
format!("signal:{instance}")
350+
}
351+
// Named adapter: signal:{instance}:+{phone}
352+
["signal", instance, phone, ..] if phone.starts_with('+') => {
351353
format!("signal:{instance}")
352354
}
353355
// Default adapter: signal:{target}
@@ -386,6 +388,11 @@ pub fn parse_signal_target_parts(parts: &[&str]) -> Option<BroadcastTarget> {
386388
target,
387389
})
388390
}
391+
// Single-part targets: delegate to normalize_signal_target for bare UUIDs/phones
392+
[single] => normalize_signal_target(single).map(|target| BroadcastTarget {
393+
adapter: "signal".to_string(),
394+
target,
395+
}),
389396
// Named adapter: signal:instance:uuid:xxx, signal:instance:group:xxx
390397
[instance, "uuid", uuid] => Some(BroadcastTarget {
391398
adapter: format!("signal:{instance}"),
@@ -409,6 +416,11 @@ pub fn parse_signal_target_parts(parts: &[&str]) -> Option<BroadcastTarget> {
409416
target,
410417
})
411418
}
419+
// Named adapter with single-part target: delegate to normalize_signal_target
420+
[instance, single] => normalize_signal_target(single).map(|target| BroadcastTarget {
421+
adapter: format!("signal:{instance}"),
422+
target,
423+
}),
412424
_ => None,
413425
}
414426
}

src/tools/send_message_to_another_channel.rs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -144,13 +144,27 @@ impl Tool for SendMessageTool {
144144
"send_message_to_another_channel tool called"
145145
);
146146

147-
// Check for explicit Signal target (named adapter only)
148-
// Only treat as explicit if it's a named adapter (e.g., "signal:work:..."),
149-
// not the default "signal:..." forms which should route via current_adapter.
150-
// Default "signal:" targets fall through to channel lookup or current_adapter below.
151-
if let Some(explicit_target) = parse_explicit_signal_target(&args.target) {
152-
// Only proceed if this is a named adapter (not the default "signal")
153-
if explicit_target.adapter != "signal" {
147+
// Check for explicit Signal target
148+
// Treat as explicit if it has a valid Signal target form (uuid:, group:, +)
149+
// regardless of whether it's the default "signal" adapter or a named one.
150+
if let Some(mut explicit_target) = parse_explicit_signal_target(&args.target) {
151+
if explicit_target.adapter == "signal"
152+
&& let Some(current_adapter) = self
153+
.current_adapter
154+
.as_ref()
155+
.filter(|adapter| adapter.starts_with("signal"))
156+
{
157+
explicit_target.adapter = current_adapter.clone();
158+
}
159+
160+
// Check if this is an explicit Signal target form
161+
let is_explicit_signal_target = explicit_target.target.starts_with("uuid:")
162+
|| explicit_target.target.starts_with("group:")
163+
|| explicit_target.target.starts_with("e164:")
164+
|| explicit_target.target.starts_with('+');
165+
166+
// Broadcast if it's a named adapter OR an explicit Signal target form
167+
if explicit_target.adapter != "signal" || is_explicit_signal_target {
154168
self.messaging_manager
155169
.broadcast(
156170
&explicit_target.adapter,
@@ -180,7 +194,7 @@ impl Tool for SendMessageTool {
180194
platform: explicit_target.adapter,
181195
});
182196
}
183-
// If adapter is "signal" (default), fall through to use current_adapter
197+
// If adapter is "signal" and not an explicit target form, fall through to use current_adapter
184198
}
185199

186200
// Check for explicit email target

0 commit comments

Comments
 (0)