mirror of
https://github.com/RightNow-AI/openfang.git
synced 2026-07-30 23:05:08 +00:00
Merge pull request #1020 from rozsival/upstream
feat(channels): use plain text as default output formatter for Signal
This commit is contained in:
@@ -484,9 +484,7 @@ pub async fn get_agent_session(
|
||||
let filtered_messages: Vec<&openfang_types::message::Message> = session
|
||||
.messages
|
||||
.iter()
|
||||
.filter(|m| {
|
||||
include_system || m.role != openfang_types::message::Role::System
|
||||
})
|
||||
.filter(|m| include_system || m.role != openfang_types::message::Role::System)
|
||||
.collect();
|
||||
|
||||
// Two-pass approach: ToolUse blocks live in Assistant messages while
|
||||
|
||||
@@ -418,7 +418,10 @@ async fn test_agent_session_filters_system_messages() {
|
||||
let messages = body["messages"].as_array().unwrap();
|
||||
assert_eq!(messages.len(), 3, "include_system=true should return all 3");
|
||||
assert_eq!(messages[0]["role"], "System");
|
||||
assert_eq!(messages[0]["content"], "INTERNAL SYSTEM PROMPT — must not leak to UI");
|
||||
assert_eq!(
|
||||
messages[0]["content"],
|
||||
"INTERNAL SYSTEM PROMPT — must not leak to UI"
|
||||
);
|
||||
assert_eq!(body["message_count"], 3);
|
||||
assert_eq!(body["raw_message_count"], 3);
|
||||
}
|
||||
|
||||
@@ -517,6 +517,7 @@ fn default_output_format_for_channel(channel_type: &str) -> OutputFormat {
|
||||
"telegram" => OutputFormat::TelegramHtml,
|
||||
"slack" => OutputFormat::SlackMrkdwn,
|
||||
"wecom" => OutputFormat::PlainText,
|
||||
"signal" => OutputFormat::PlainText,
|
||||
_ => OutputFormat::Markdown,
|
||||
}
|
||||
}
|
||||
@@ -1932,6 +1933,10 @@ mod tests {
|
||||
default_output_format_for_channel("discord"),
|
||||
OutputFormat::Markdown
|
||||
);
|
||||
assert_eq!(
|
||||
default_output_format_for_channel("signal"),
|
||||
OutputFormat::PlainText
|
||||
)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
@@ -1011,7 +1011,10 @@ mod tests {
|
||||
assert!(payload["d"].is_null());
|
||||
let s = serde_json::to_string(&payload).unwrap();
|
||||
let parsed: serde_json::Value = serde_json::from_str(&s).unwrap();
|
||||
assert_eq!(parsed, serde_json::json!({"op": 1, "d": serde_json::Value::Null}));
|
||||
assert_eq!(
|
||||
parsed,
|
||||
serde_json::json!({"op": 1, "d": serde_json::Value::Null})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -127,10 +127,7 @@ impl HandsState {
|
||||
if let Some(sel) = self.marketplace_list.selected() {
|
||||
if sel < self.definitions.len() {
|
||||
// TODO: add text-input modal for custom instance names (#878 follow-up)
|
||||
return HandsAction::ActivateHand(
|
||||
self.definitions[sel].id.clone(),
|
||||
None,
|
||||
);
|
||||
return HandsAction::ActivateHand(self.definitions[sel].id.clone(), None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1141,9 +1141,7 @@ metrics = []
|
||||
fn test_activate_same_hand_unnamed_twice_still_rejects() {
|
||||
let reg = test_registry_with_dummy_hand("test-hand");
|
||||
reg.activate("test-hand", HashMap::new(), None).unwrap();
|
||||
let err = reg
|
||||
.activate("test-hand", HashMap::new(), None)
|
||||
.unwrap_err();
|
||||
let err = reg.activate("test-hand", HashMap::new(), None).unwrap_err();
|
||||
assert!(matches!(err, HandError::AlreadyActive(_)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -898,12 +898,12 @@ impl OpenFangKernel {
|
||||
// Auto-detect embedding provider by checking API key env vars in
|
||||
// priority order. First match wins.
|
||||
const API_KEY_PROVIDERS: &[(&str, &str)] = &[
|
||||
("OPENAI_API_KEY", "openai"),
|
||||
("GROQ_API_KEY", "groq"),
|
||||
("MISTRAL_API_KEY", "mistral"),
|
||||
("TOGETHER_API_KEY", "together"),
|
||||
("OPENAI_API_KEY", "openai"),
|
||||
("GROQ_API_KEY", "groq"),
|
||||
("MISTRAL_API_KEY", "mistral"),
|
||||
("TOGETHER_API_KEY", "together"),
|
||||
("FIREWORKS_API_KEY", "fireworks"),
|
||||
("COHERE_API_KEY", "cohere"),
|
||||
("COHERE_API_KEY", "cohere"),
|
||||
];
|
||||
|
||||
let detected_from_key = API_KEY_PROVIDERS
|
||||
@@ -1144,8 +1144,7 @@ impl OpenFangKernel {
|
||||
!= entry.manifest.tool_allowlist
|
||||
|| disk_manifest.tool_blocklist
|
||||
!= entry.manifest.tool_blocklist
|
||||
|| disk_manifest.skills
|
||||
!= entry.manifest.skills
|
||||
|| disk_manifest.skills != entry.manifest.skills
|
||||
|| disk_manifest.mcp_servers
|
||||
!= entry.manifest.mcp_servers;
|
||||
if changed {
|
||||
|
||||
@@ -308,8 +308,8 @@ impl McpConnection {
|
||||
|
||||
// rmcp 1.3+ marks StreamableHttpClientTransportConfig as #[non_exhaustive].
|
||||
// Use the official builder API (credit: @jefflower, PR #986).
|
||||
let config = StreamableHttpClientTransportConfig::with_uri(url)
|
||||
.custom_headers(custom_headers);
|
||||
let config =
|
||||
StreamableHttpClientTransportConfig::with_uri(url).custom_headers(custom_headers);
|
||||
|
||||
let transport = StreamableHttpClientTransport::from_config(config);
|
||||
|
||||
|
||||
@@ -1090,7 +1090,11 @@ mod tests {
|
||||
is_error,
|
||||
content,
|
||||
..
|
||||
} => tool_use_id == "memory_store:0" && *is_error && content.contains("interrupted"),
|
||||
} => {
|
||||
tool_use_id == "memory_store:0"
|
||||
&& *is_error
|
||||
&& content.contains("interrupted")
|
||||
}
|
||||
_ => false,
|
||||
})
|
||||
} else {
|
||||
|
||||
@@ -3141,8 +3141,7 @@ async fn tool_process_start(
|
||||
// shared validate_command_allowlist handles Deny / Full / Allowlist and
|
||||
// falls through to allow commands listed in safe_bins or allowed_commands.
|
||||
if let Some(policy) = exec_policy {
|
||||
if let Err(reason) =
|
||||
crate::subprocess_sandbox::validate_command_allowlist(command, policy)
|
||||
if let Err(reason) = crate::subprocess_sandbox::validate_command_allowlist(command, policy)
|
||||
{
|
||||
return Err(format!(
|
||||
"process_start blocked: {reason}. Current exec_policy.mode = '{:?}'. \
|
||||
|
||||
@@ -506,7 +506,11 @@ mod tests {
|
||||
assert!(check_ssrf("http://169.254.169.254/latest/meta-data/", &allow).is_err());
|
||||
// Also verify hostname-based metadata blocks
|
||||
let allow2 = vec!["metadata.google.internal".to_string()];
|
||||
assert!(check_ssrf("http://metadata.google.internal/computeMetadata/v1/", &allow2).is_err());
|
||||
assert!(check_ssrf(
|
||||
"http://metadata.google.internal/computeMetadata/v1/",
|
||||
&allow2
|
||||
)
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -358,7 +358,10 @@ impl WebSearchEngine {
|
||||
|
||||
let resp = self
|
||||
.client
|
||||
.get(format!("{}/search", self.config.searxng.url.trim_end_matches('/')))
|
||||
.get(format!(
|
||||
"{}/search",
|
||||
self.config.searxng.url.trim_end_matches('/')
|
||||
))
|
||||
.query(&[
|
||||
("q", query),
|
||||
("format", "json"),
|
||||
@@ -451,7 +454,10 @@ impl WebSearchEngine {
|
||||
|
||||
let resp = self
|
||||
.client
|
||||
.get(format!("{}/config", self.config.searxng.url.trim_end_matches('/')))
|
||||
.get(format!(
|
||||
"{}/config",
|
||||
self.config.searxng.url.trim_end_matches('/')
|
||||
))
|
||||
.header("User-Agent", "Mozilla/5.0 (compatible; OpenFangAgent/0.1)")
|
||||
.send()
|
||||
.await
|
||||
|
||||
Reference in New Issue
Block a user