Document process monitoring handoff
Add ACP discovery and configuration support
This commit is contained in:
@@ -7,6 +7,22 @@ pub(crate) fn acp_model_id(agent_id: &str) -> String {
|
||||
format!("acp:{}", agent_id.trim().to_ascii_lowercase())
|
||||
}
|
||||
|
||||
pub(crate) fn acp_selection_model_id(
|
||||
agent_id: &str,
|
||||
values: &std::collections::BTreeMap<String, serde_json::Value>,
|
||||
) -> String {
|
||||
let suffix = values
|
||||
.iter()
|
||||
.map(|(key, value)| format!("{key}={value}"))
|
||||
.collect::<Vec<_>>()
|
||||
.join(";");
|
||||
if suffix.is_empty() {
|
||||
acp_model_id(agent_id)
|
||||
} else {
|
||||
format!("{}:{suffix}", acp_model_id(agent_id))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn acp_launch_fingerprint(
|
||||
agent_id: &str,
|
||||
custom_command: &str,
|
||||
|
||||
@@ -12,8 +12,8 @@ mod runtime_model;
|
||||
mod transport;
|
||||
|
||||
pub(crate) use launch::{
|
||||
acp_launch_fingerprint, acp_model_id, resolve_acp_launch, validate_acp_dispatch,
|
||||
validate_acp_launch_identity,
|
||||
acp_launch_fingerprint, acp_model_id, acp_selection_model_id, resolve_acp_launch,
|
||||
validate_acp_dispatch, validate_acp_launch_identity,
|
||||
};
|
||||
pub(crate) use permissions::resolve_acp_permissions;
|
||||
pub(crate) use runtime_model::AcpRuntimeModel;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
use crate::settings::{
|
||||
AISettings, AcpAgentSettings, AcpConfigOptionSettings, AcpConfigValueSettings,
|
||||
};
|
||||
use galaxy_acp::{AcpLaunchConfig, AcpManagerConfig, AcpSessionManager};
|
||||
use galaxyui::{Entity, ModelContext, SingletonEntity};
|
||||
|
||||
@@ -33,6 +36,70 @@ impl AcpRuntimeModel {
|
||||
});
|
||||
Ok(manager)
|
||||
}
|
||||
|
||||
pub(crate) fn normalize_config_options(
|
||||
options: Vec<galaxy_acp::SessionConfigOption>,
|
||||
) -> Vec<AcpConfigOptionSettings> {
|
||||
options
|
||||
.into_iter()
|
||||
.map(|option| {
|
||||
let kind = match &option.kind {
|
||||
galaxy_acp::SessionConfigOptionType::Select => "select",
|
||||
galaxy_acp::SessionConfigOptionType::Boolean => "boolean",
|
||||
}
|
||||
.to_owned();
|
||||
let current_value = serde_json::to_value(&option.current_value).unwrap_or_default();
|
||||
let values = option
|
||||
.options
|
||||
.into_iter()
|
||||
.map(|value| AcpConfigValueSettings {
|
||||
value: serde_json::to_value(value.value).unwrap_or_default(),
|
||||
name: value.name,
|
||||
description: value.description,
|
||||
})
|
||||
.collect();
|
||||
AcpConfigOptionSettings {
|
||||
id: option.id,
|
||||
name: option.name,
|
||||
description: option.description,
|
||||
category: option
|
||||
.category
|
||||
.map(|category| format!("{category:?}").to_lowercase()),
|
||||
kind,
|
||||
current_value,
|
||||
options: values,
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub(crate) fn upsert_agent_settings(
|
||||
settings: &mut AISettings,
|
||||
agent_id: &str,
|
||||
options: Vec<galaxy_acp::SessionConfigOption>,
|
||||
) -> Result<(), String> {
|
||||
let config_options = Self::normalize_config_options(options);
|
||||
let mut agents = settings.acp_agents.value().clone();
|
||||
if let Some(agent) = agents
|
||||
.iter_mut()
|
||||
.find(|agent| agent.id.eq_ignore_ascii_case(agent_id))
|
||||
{
|
||||
agent.config_options = config_options;
|
||||
} else {
|
||||
agents.push(AcpAgentSettings {
|
||||
id: agent_id.to_owned(),
|
||||
name: agent_id.to_owned(),
|
||||
version: None,
|
||||
description: None,
|
||||
icon_url: None,
|
||||
capabilities: Vec::new(),
|
||||
config_options,
|
||||
});
|
||||
}
|
||||
settings
|
||||
.acp_agents
|
||||
.set_value(agents, &mut settings.context())
|
||||
}
|
||||
}
|
||||
|
||||
impl Entity for AcpRuntimeModel {
|
||||
|
||||
@@ -8,11 +8,11 @@ use futures::stream::FusedStream as _;
|
||||
use futures::{FutureExt as _, StreamExt as _};
|
||||
use galaxy_acp::{
|
||||
AcpEvent, AcpPermissionPolicy, AcpRuntimeError, AcpSessionHandle, AcpSessionManager,
|
||||
AcpSteeringOutcome, AcpTurnRequest, ContentBlock, McpServer, McpServerStdio, SessionId,
|
||||
TextContent,
|
||||
AcpSteeringOutcome, AcpTurnRequest, ContentBlock, McpServer, McpServerStdio,
|
||||
SessionConfigOptionValue, SessionId, TextContent,
|
||||
};
|
||||
|
||||
use super::launch::acp_model_id;
|
||||
use super::launch::acp_selection_model_id;
|
||||
use super::prompt::{prompt_content, GalaxyTerminalTools};
|
||||
use super::response_translator::AcpResponseTranslator;
|
||||
use crate::ai::agent::api::{self, RequestParams};
|
||||
@@ -25,6 +25,7 @@ pub(crate) struct AcpSessionMetadata {
|
||||
pub(crate) session_id: Option<String>,
|
||||
pub(crate) can_load: bool,
|
||||
pub(crate) can_steer: bool,
|
||||
pub(crate) config_options: Vec<galaxy_acp::SessionConfigOption>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@@ -121,6 +122,15 @@ pub(crate) async fn acp_output_stream(
|
||||
mcp_servers.push(server);
|
||||
}
|
||||
let request = AcpTurnRequest {
|
||||
config_values: backend
|
||||
.config_values
|
||||
.into_iter()
|
||||
.filter_map(|(key, value)| {
|
||||
serde_json::from_value::<SessionConfigOptionValue>(value)
|
||||
.ok()
|
||||
.map(|value| (key, value))
|
||||
})
|
||||
.collect(),
|
||||
conversation_key: conversation_id,
|
||||
session_id: backend.session_id.map(SessionId::from),
|
||||
cwd,
|
||||
@@ -222,6 +232,7 @@ pub(crate) async fn acp_output_stream(
|
||||
session_id,
|
||||
can_load,
|
||||
can_steer,
|
||||
..
|
||||
} = &event
|
||||
{
|
||||
if let Ok(mut metadata) = session_metadata.lock() {
|
||||
@@ -230,6 +241,11 @@ pub(crate) async fn acp_output_stream(
|
||||
metadata.can_steer = *can_steer;
|
||||
}
|
||||
}
|
||||
if let AcpEvent::ConfigOptions { options } = &event {
|
||||
if let Ok(mut metadata) = session_metadata.lock() {
|
||||
metadata.config_options = options.clone();
|
||||
}
|
||||
}
|
||||
match translator.translate(event) {
|
||||
Ok(response_events) => {
|
||||
for response_event in response_events {
|
||||
@@ -272,7 +288,7 @@ fn response_translator(
|
||||
task_id,
|
||||
params.tasks.is_empty(),
|
||||
user_query,
|
||||
acp_model_id(&backend.agent_id),
|
||||
acp_selection_model_id(&backend.agent_id, &backend.config_values),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user