Preserve completed command assessments
This commit is contained in:
@@ -37,6 +37,21 @@ use crate::settings::AISettings;
|
||||
use crate::terminal::safe_mode_settings::get_secret_obfuscation_mode;
|
||||
use crate::workspaces::user_workspaces::UserWorkspaces;
|
||||
|
||||
const INTERNAL_COMMAND_COMPLETION_ASSESSMENT_MESSAGE_DATA: &str =
|
||||
"galaxy:internal-command-completion-assessment:v1";
|
||||
|
||||
pub(crate) fn mark_internal_command_completion_assessment(
|
||||
message: &mut warp_multi_agent_api::Message,
|
||||
) {
|
||||
message.server_message_data = INTERNAL_COMMAND_COMPLETION_ASSESSMENT_MESSAGE_DATA.to_string();
|
||||
}
|
||||
|
||||
pub(crate) fn is_internal_command_completion_assessment(
|
||||
message: &warp_multi_agent_api::Message,
|
||||
) -> bool {
|
||||
message.server_message_data == INTERNAL_COMMAND_COMPLETION_ASSESSMENT_MESSAGE_DATA
|
||||
}
|
||||
|
||||
/// Unique, server-generated conversation-scoped token to be roundtripped to the API when sending
|
||||
/// requests that follow-up within a given conversation.
|
||||
#[derive(Serialize, Debug, Clone, PartialEq, Eq, Hash)]
|
||||
|
||||
@@ -23,6 +23,7 @@ use crate::ai::agent::api::convert_from::{
|
||||
convert_user_query_mode, ConversionParams, ConvertAPIMessageToClientOutputMessage,
|
||||
MaybeAIAgentOutputMessage,
|
||||
};
|
||||
use crate::ai::agent::api::is_internal_command_completion_assessment;
|
||||
use crate::ai::agent::conversation::{
|
||||
update_todo_list_from_todo_op, AIConversation, AIConversationId, ServerAIConversationMetadata,
|
||||
};
|
||||
@@ -389,17 +390,21 @@ impl ConvertToExchanges for &api::Task {
|
||||
|
||||
let added_message_as_exchange_input = match message {
|
||||
api::message::Message::UserQuery(user_query) => {
|
||||
// Add user query as input
|
||||
current_inputs.push(AIAgentInput::UserQuery {
|
||||
if is_internal_command_completion_assessment(api_message) {
|
||||
false
|
||||
} else {
|
||||
// Add user query as input
|
||||
current_inputs.push(AIAgentInput::UserQuery {
|
||||
query: user_query.query.clone(),
|
||||
context: convert_input_context(user_query.context.as_ref()),
|
||||
static_query_type: None,
|
||||
referenced_attachments: HashMap::new(),
|
||||
user_query_mode: convert_user_query_mode(user_query.mode.as_ref()),
|
||||
running_command: None,
|
||||
intended_agent: Some(user_query.intended_agent()),
|
||||
});
|
||||
true
|
||||
intended_agent: Some(user_query.intended_agent()),
|
||||
});
|
||||
true
|
||||
}
|
||||
}
|
||||
api::message::Message::SystemQuery(query) => {
|
||||
let Some(query_type) = &query.r#type else {
|
||||
|
||||
@@ -4,7 +4,7 @@ use chrono::Utc;
|
||||
use warp_multi_agent_api as api;
|
||||
|
||||
use crate::ai::agent::api::convert_conversation::*;
|
||||
use crate::ai::agent::api::ServerConversationToken;
|
||||
use crate::ai::agent::api::{mark_internal_command_completion_assessment, ServerConversationToken};
|
||||
use crate::ai::agent::conversation::{
|
||||
AIAgentHarness, AIConversationId, ServerAIConversationMetadata,
|
||||
};
|
||||
@@ -2129,6 +2129,61 @@ fn test_create_then_edit_then_create_version_tracking() {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_internal_command_completion_assessment_restores_output_without_visible_input() {
|
||||
let assessment_text =
|
||||
"[Completed command: cargo test]\n[Final terminal output:\ntest result: ok\n]";
|
||||
let mut hidden_assessment = api::Message {
|
||||
id: "msg_assessment".to_string(),
|
||||
task_id: "task1".to_string(),
|
||||
request_id: "req1".to_string(),
|
||||
message: Some(api::message::Message::UserQuery(api::message::UserQuery {
|
||||
query: assessment_text.to_string(),
|
||||
..Default::default()
|
||||
})),
|
||||
..Default::default()
|
||||
};
|
||||
mark_internal_command_completion_assessment(&mut hidden_assessment);
|
||||
let provider_history =
|
||||
crate::ai::bedrock::request_translator::convert_proto_message(&hidden_assessment)
|
||||
.expect("hidden assessment should remain in provider history");
|
||||
assert_eq!(
|
||||
provider_history.role,
|
||||
crate::ai::provider::types::MessageRole::User
|
||||
);
|
||||
assert!(matches!(
|
||||
provider_history.content,
|
||||
crate::ai::provider::types::MessageContent::Text(text) if text == assessment_text
|
||||
));
|
||||
|
||||
let task = api::Task {
|
||||
id: "task1".to_string(),
|
||||
messages: vec![
|
||||
hidden_assessment,
|
||||
api::Message {
|
||||
id: "msg_output".to_string(),
|
||||
task_id: "task1".to_string(),
|
||||
request_id: "req1".to_string(),
|
||||
message: Some(api::message::Message::AgentOutput(
|
||||
api::message::AgentOutput {
|
||||
text: "The command completed successfully.".to_string(),
|
||||
},
|
||||
)),
|
||||
..Default::default()
|
||||
},
|
||||
],
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let exchanges = task.into_exchanges();
|
||||
assert_eq!(exchanges.len(), 1);
|
||||
assert!(exchanges[0].input.is_empty());
|
||||
assert_eq!(
|
||||
exchanges[0].format_output_for_copy(None),
|
||||
"The command completed successfully."
|
||||
);
|
||||
}
|
||||
|
||||
/// Verify that a `SystemQuery::HandoffRehydration` message does not produce
|
||||
/// a displayed input when restoring a conversation. It must be treated as
|
||||
/// hidden, so the exchange should have zero user-visible inputs.
|
||||
|
||||
@@ -16,6 +16,7 @@ use warp_multi_agent_api as api;
|
||||
use crate::ai::agent::api::convert_conversation::{
|
||||
convert_input_context, convert_tool_call_result_to_input,
|
||||
};
|
||||
use crate::ai::agent::api::is_internal_command_completion_assessment;
|
||||
use crate::ai::agent::comment::CodeReview;
|
||||
use crate::ai::agent::task::TaskId;
|
||||
use crate::ai::agent::todos::AIAgentTodoList;
|
||||
@@ -957,6 +958,9 @@ pub fn user_inputs_from_messages(messages: &[api::Message]) -> Vec<AIAgentInput>
|
||||
let Some(inner) = &m.message else { continue };
|
||||
match inner {
|
||||
api::message::Message::UserQuery(uq) => {
|
||||
if is_internal_command_completion_assessment(m) {
|
||||
continue;
|
||||
}
|
||||
let context = convert_input_context(uq.context.as_ref());
|
||||
let referenced_attachments = uq
|
||||
.referenced_attachments
|
||||
|
||||
@@ -7,13 +7,14 @@ use warp_multi_agent_api as api;
|
||||
use warp_util::local_or_remote_path::LocalOrRemotePath;
|
||||
|
||||
use super::{
|
||||
convert_api_question, ConversionParams, ConvertAPIMessageToClientOutputMessage,
|
||||
MaybeAIAgentOutputMessage,
|
||||
convert_api_question, user_inputs_from_messages, ConversionParams,
|
||||
ConvertAPIMessageToClientOutputMessage, MaybeAIAgentOutputMessage,
|
||||
};
|
||||
use crate::ai::agent::api::mark_internal_command_completion_assessment;
|
||||
use crate::ai::agent::task::TaskId;
|
||||
use crate::ai::agent::{
|
||||
runtime_activity, AIAgentActionType, AIAgentOutputMessageType, LifecycleEventType,
|
||||
StartAgentExecutionMode,
|
||||
runtime_activity, AIAgentActionType, AIAgentInput, AIAgentOutputMessageType,
|
||||
LifecycleEventType, StartAgentExecutionMode,
|
||||
};
|
||||
|
||||
fn start_agent_tool_call_message(
|
||||
@@ -617,6 +618,36 @@ fn converts_local_start_agent_v2_with_harness_type() {
|
||||
assert_eq!(lifecycle_subscription, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn internal_command_completion_assessment_is_not_restored_as_shared_user_input() {
|
||||
let mut hidden_assessment = api::Message {
|
||||
id: "hidden-assessment".to_string(),
|
||||
task_id: "task".to_string(),
|
||||
message: Some(api::message::Message::UserQuery(api::message::UserQuery {
|
||||
query: "[Completed command: cargo test]".to_string(),
|
||||
..Default::default()
|
||||
})),
|
||||
..Default::default()
|
||||
};
|
||||
mark_internal_command_completion_assessment(&mut hidden_assessment);
|
||||
let visible_query = api::Message {
|
||||
id: "visible-query".to_string(),
|
||||
task_id: "task".to_string(),
|
||||
message: Some(api::message::Message::UserQuery(api::message::UserQuery {
|
||||
query: "What changed?".to_string(),
|
||||
..Default::default()
|
||||
})),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let inputs = user_inputs_from_messages(&[hidden_assessment, visible_query]);
|
||||
assert_eq!(inputs.len(), 1);
|
||||
assert!(matches!(
|
||||
&inputs[0],
|
||||
AIAgentInput::UserQuery { query, .. } if query == "What changed?"
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transfer_control_tool_call_converts_to_action_message() {
|
||||
let task_id = TaskId::new("task".to_string());
|
||||
|
||||
@@ -348,6 +348,43 @@ fn convert_input_to_user_input(
|
||||
}
|
||||
))
|
||||
}
|
||||
AIAgentInput::CommandCompletionAssessment {
|
||||
prompt,
|
||||
completed_command:
|
||||
RunningCommand {
|
||||
command,
|
||||
block_id,
|
||||
grid_contents: output,
|
||||
cursor,
|
||||
requested_command_id,
|
||||
is_alt_screen_active,
|
||||
},
|
||||
..
|
||||
} => Ok(
|
||||
api::request::input::user_inputs::user_input::Input::CliAgentUserQuery(
|
||||
api::request::input::CliAgentUserQuery {
|
||||
user_query: Some(api::request::input::UserQuery {
|
||||
query: prompt,
|
||||
referenced_attachments: Default::default(),
|
||||
mode: Some(UserQueryMode::Normal.into()),
|
||||
intended_agent: api::AgentType::Primary.into(),
|
||||
}),
|
||||
running_command: Some(api::RunningShellCommand {
|
||||
command,
|
||||
snapshot: Some(api::LongRunningShellCommandSnapshot {
|
||||
output,
|
||||
cursor,
|
||||
command_id: block_id.as_str().to_owned(),
|
||||
is_alt_screen_active,
|
||||
is_preempted: false,
|
||||
}),
|
||||
}),
|
||||
run_shell_command_tool_call_id: requested_command_id
|
||||
.map(|id| id.to_string())
|
||||
.unwrap_or_default(),
|
||||
},
|
||||
),
|
||||
),
|
||||
AIAgentInput::ActionResult { result, .. } => result.try_into(),
|
||||
AIAgentInput::MessagesReceivedFromAgents { messages } => Ok(
|
||||
api::request::input::user_inputs::user_input::Input::MessagesReceivedFromAgents(
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use chrono::{DateTime, Utc};
|
||||
use galaxy_core::command::ExitCode;
|
||||
use warp_multi_agent_api as api;
|
||||
|
||||
use crate::ai::agent::task::TaskId;
|
||||
use crate::ai::agent::{
|
||||
AIAgentActionResult, AIAgentActionResultType, AIAgentContext, ImageContext,
|
||||
TransferShellCommandControlToUserResult,
|
||||
AIAgentActionResult, AIAgentActionResultType, AIAgentContext, AIAgentInput, ImageContext,
|
||||
RunningCommand, TransferShellCommandControlToUserResult, UserQueryMode,
|
||||
};
|
||||
use crate::terminal::model::block::BlockId;
|
||||
|
||||
@@ -132,6 +134,84 @@ fn git_context_deserializes_legacy_string_pull_request_number() {
|
||||
assert_eq!(pull_request.number, 42);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn command_completion_assessment_converts_to_primary_cli_query() {
|
||||
let block_id = BlockId::from("completed-block".to_string());
|
||||
let converted = super::convert_input(vec![AIAgentInput::CommandCompletionAssessment {
|
||||
prompt: "Summarize whether the command succeeded.".to_string(),
|
||||
context: Arc::from([AIAgentContext::SelectedText("root context".to_string())]),
|
||||
completed_command: RunningCommand {
|
||||
command: "cargo test -p galaxy".to_string(),
|
||||
block_id: block_id.clone(),
|
||||
grid_contents: "test result: ok".to_string(),
|
||||
cursor: "cursor".to_string(),
|
||||
requested_command_id: Some("run-call".to_string().into()),
|
||||
is_alt_screen_active: true,
|
||||
},
|
||||
}])
|
||||
.unwrap();
|
||||
|
||||
let Some(api::request::input::Type::UserInputs(inputs)) = converted.r#type else {
|
||||
panic!("expected user inputs");
|
||||
};
|
||||
let Some(api::request::input::user_inputs::user_input::Input::CliAgentUserQuery(query)) =
|
||||
inputs.inputs[0].input.as_ref()
|
||||
else {
|
||||
panic!("expected CLI agent query");
|
||||
};
|
||||
let user_query = query
|
||||
.user_query
|
||||
.as_ref()
|
||||
.expect("expected assessment prompt");
|
||||
assert_eq!(user_query.query, "Summarize whether the command succeeded.");
|
||||
assert_eq!(user_query.intended_agent(), api::AgentType::Primary);
|
||||
let command = query
|
||||
.running_command
|
||||
.as_ref()
|
||||
.expect("expected completed command");
|
||||
assert_eq!(command.command, "cargo test -p galaxy");
|
||||
let snapshot = command.snapshot.as_ref().expect("expected final snapshot");
|
||||
assert_eq!(snapshot.command_id, block_id.as_str());
|
||||
assert_eq!(snapshot.output, "test result: ok");
|
||||
assert_eq!(snapshot.cursor, "cursor");
|
||||
assert!(snapshot.is_alt_screen_active);
|
||||
assert_eq!(query.run_shell_command_tool_call_id, "run-call");
|
||||
|
||||
let active = super::convert_input(vec![AIAgentInput::UserQuery {
|
||||
query: "Keep monitoring.".to_string(),
|
||||
context: Arc::from([]),
|
||||
static_query_type: None,
|
||||
referenced_attachments: Default::default(),
|
||||
user_query_mode: UserQueryMode::Normal,
|
||||
running_command: Some(RunningCommand {
|
||||
command: "cargo test -p galaxy".to_string(),
|
||||
block_id,
|
||||
grid_contents: "still running".to_string(),
|
||||
cursor: String::new(),
|
||||
requested_command_id: None,
|
||||
is_alt_screen_active: false,
|
||||
}),
|
||||
intended_agent: None,
|
||||
}])
|
||||
.unwrap();
|
||||
let Some(api::request::input::Type::UserInputs(inputs)) = active.r#type else {
|
||||
panic!("expected active user inputs");
|
||||
};
|
||||
let Some(api::request::input::user_inputs::user_input::Input::CliAgentUserQuery(query)) =
|
||||
inputs.inputs[0].input.as_ref()
|
||||
else {
|
||||
panic!("expected active CLI agent query");
|
||||
};
|
||||
assert_eq!(
|
||||
query
|
||||
.user_query
|
||||
.as_ref()
|
||||
.expect("expected active monitor prompt")
|
||||
.intended_agent(),
|
||||
api::AgentType::Cli
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn transfer_control_snapshot_result_converts_to_tool_call_result_input() {
|
||||
let block_id = BlockId::default();
|
||||
|
||||
@@ -7,7 +7,7 @@ use warp_multi_agent_api as api;
|
||||
|
||||
use super::convert_to::convert_input;
|
||||
use super::{ConvertToAPITypeError, RequestParams, ResponseStream, StreamEvent};
|
||||
use crate::ai::agent::redaction;
|
||||
use crate::ai::agent::{redaction, AIAgentInput};
|
||||
use crate::ai::openai::translator as openai_translator;
|
||||
use crate::ai::provider::ProviderConfig;
|
||||
use crate::server::server_api::AIApiError;
|
||||
@@ -97,6 +97,10 @@ pub async fn generate_multi_agent_output(
|
||||
);
|
||||
}
|
||||
|
||||
let emit_user_query_message = !params
|
||||
.input
|
||||
.iter()
|
||||
.any(|input| matches!(input, AIAgentInput::CommandCompletionAssessment { .. }));
|
||||
let mut request = api::Request {
|
||||
task_context: Some(api::request::TaskContext {
|
||||
tasks: params.tasks,
|
||||
@@ -189,6 +193,7 @@ pub async fn generate_multi_agent_output(
|
||||
progressive_summary: params.progressive_summary.clone(),
|
||||
messages_sent: params.messages_sent.clone(),
|
||||
global_rules: params.global_rules.clone(),
|
||||
emit_user_query_message,
|
||||
};
|
||||
|
||||
match openai_translator::execute(translator_request, &mut request).await {
|
||||
@@ -223,6 +228,7 @@ pub async fn generate_multi_agent_output(
|
||||
bedrock_progressive_summary: params.progressive_summary.clone(),
|
||||
bedrock_messages_sent: params.messages_sent.clone(),
|
||||
global_rules: params.global_rules.clone(),
|
||||
emit_user_query_message,
|
||||
};
|
||||
|
||||
match crate::ai::bedrock::translator::execute(translator_request, &mut request).await {
|
||||
|
||||
+15
-2
@@ -2705,6 +2705,13 @@ pub enum AIAgentInput {
|
||||
intended_agent: Option<AgentType>,
|
||||
},
|
||||
|
||||
/// A hidden system turn that asks for the final assessment of a completed command.
|
||||
CommandCompletionAssessment {
|
||||
prompt: String,
|
||||
context: Arc<[AIAgentContext]>,
|
||||
completed_command: RunningCommand,
|
||||
},
|
||||
|
||||
AutoCodeDiffQuery {
|
||||
query: String,
|
||||
context: Arc<[AIAgentContext]>,
|
||||
@@ -2869,6 +2876,9 @@ impl Display for AIAgentInput {
|
||||
Self::UserQuery { .. } => {
|
||||
write!(f, "UserQuery: {}", self.display_query().unwrap_or_default())
|
||||
}
|
||||
Self::CommandCompletionAssessment { .. } => {
|
||||
write!(f, "CommandCompletionAssessment")
|
||||
}
|
||||
Self::AutoCodeDiffQuery { query, .. } => {
|
||||
write!(f, "AutoCodeDiffQuery: {query}")
|
||||
}
|
||||
@@ -2957,7 +2967,8 @@ impl AIAgentInput {
|
||||
suggestion: PassiveSuggestionResultType::Prompt { prompt },
|
||||
..
|
||||
} => Some(prompt.clone()),
|
||||
Self::AutoCodeDiffQuery { .. }
|
||||
Self::CommandCompletionAssessment { .. }
|
||||
| Self::AutoCodeDiffQuery { .. }
|
||||
| Self::ActionResult { .. }
|
||||
| Self::TriggerPassiveSuggestion { .. }
|
||||
| Self::ResumeConversation { .. }
|
||||
@@ -3048,6 +3059,7 @@ impl AIAgentInput {
|
||||
pub fn context(&self) -> Option<&[AIAgentContext]> {
|
||||
match self {
|
||||
Self::UserQuery { context, .. }
|
||||
| Self::CommandCompletionAssessment { context, .. }
|
||||
| Self::ActionResult { context, .. }
|
||||
| Self::AutoCodeDiffQuery { context, .. }
|
||||
| Self::ResumeConversation { context, .. }
|
||||
@@ -3081,7 +3093,8 @@ impl AIAgentInput {
|
||||
Some(res)
|
||||
}
|
||||
Self::TriggerPassiveSuggestion { attachments, .. } => Some(attachments.clone()),
|
||||
Self::ActionResult { .. }
|
||||
Self::CommandCompletionAssessment { .. }
|
||||
| Self::ActionResult { .. }
|
||||
| Self::AutoCodeDiffQuery { .. }
|
||||
| Self::ResumeConversation { .. }
|
||||
| Self::InitProjectRules { .. }
|
||||
|
||||
@@ -1,17 +1,22 @@
|
||||
use std::collections::HashSet;
|
||||
use std::ops::Range;
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use chrono::Local;
|
||||
use markdown_parser::{FormattedText, FormattedTextFragment, FormattedTextLine};
|
||||
use warp_multi_agent_api::{FileContent, FileContentLineRange};
|
||||
|
||||
use crate::ai::agent::{
|
||||
AIAgentContext, AIAgentOutput, AIAgentOutputMessage, AIAgentOutputMessageType, AIAgentText,
|
||||
AIAgentContext, AIAgentExchange, AIAgentExchangeId, AIAgentInput, AIAgentOutput,
|
||||
AIAgentOutputMessage, AIAgentOutputMessageType, AIAgentOutputStatus, AIAgentText,
|
||||
AIAgentTextSection, AgentOutputImage, AgentOutputImageLayout, AgentOutputMermaidDiagram,
|
||||
AnyFileContent, FileContext, FormattedTextWrapper, MessageId, ProgrammingLanguage,
|
||||
RenderableAIError, TransientNetworkErrorKind,
|
||||
RenderableAIError, RunningCommand, TransientNetworkErrorKind,
|
||||
};
|
||||
use crate::ai::llms::LLMId;
|
||||
use crate::server::server_api::AIApiError;
|
||||
use crate::terminal::model::block::BlockId;
|
||||
use crate::terminal::shell::ShellType;
|
||||
|
||||
fn to_range(range: Range<u32>) -> Option<FileContentLineRange> {
|
||||
@@ -21,6 +26,51 @@ fn to_range(range: Range<u32>) -> Option<FileContentLineRange> {
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn command_completion_assessment_stays_hidden_from_user_transcript() {
|
||||
let context: Arc<[AIAgentContext]> =
|
||||
Arc::from([AIAgentContext::SelectedText("relevant context".to_string())]);
|
||||
let input = AIAgentInput::CommandCompletionAssessment {
|
||||
prompt: "Report the final result.".to_string(),
|
||||
context: context.clone(),
|
||||
completed_command: RunningCommand {
|
||||
command: "cargo test -p galaxy".to_string(),
|
||||
block_id: BlockId::from("completed-command".to_string()),
|
||||
grid_contents: "test result: ok".to_string(),
|
||||
cursor: String::new(),
|
||||
requested_command_id: None,
|
||||
is_alt_screen_active: false,
|
||||
},
|
||||
};
|
||||
|
||||
assert_eq!(input.display_query(), None);
|
||||
assert!(!input.is_user_query());
|
||||
assert!(!input.is_passive_request());
|
||||
assert_eq!(input.context(), Some(context.as_ref()));
|
||||
assert_eq!(input.attachments(), None);
|
||||
|
||||
let now = Local::now();
|
||||
let exchange = AIAgentExchange {
|
||||
id: AIAgentExchangeId::new(),
|
||||
input: vec![input],
|
||||
output_status: AIAgentOutputStatus::Streaming { output: None },
|
||||
added_message_ids: HashSet::new(),
|
||||
start_time: now,
|
||||
finish_time: None,
|
||||
time_to_first_token_ms: None,
|
||||
working_directory: None,
|
||||
model_id: LLMId::from("test-model"),
|
||||
request_cost: None,
|
||||
coding_model_id: LLMId::from("test-model"),
|
||||
cli_agent_model_id: LLMId::from("test-model"),
|
||||
computer_use_model_id: LLMId::from("test-model"),
|
||||
response_initiator: None,
|
||||
};
|
||||
assert_eq!(exchange.format_input_for_copy(), "");
|
||||
assert_eq!(exchange.format_for_copy(None), "");
|
||||
assert!(!exchange.has_user_query());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn formatted_text_wrapper_shares_arc_across_calls() {
|
||||
let text = FormattedText::new([FormattedTextLine::Line(vec![
|
||||
|
||||
@@ -47,6 +47,17 @@ pub(crate) fn redact_inputs(inputs: &mut [AIAgentInput]) {
|
||||
redact_secrets(&mut running_command.cursor);
|
||||
}
|
||||
}
|
||||
AIAgentInput::CommandCompletionAssessment {
|
||||
prompt,
|
||||
context,
|
||||
completed_command,
|
||||
} => {
|
||||
redact_secrets(prompt);
|
||||
redact_context(Arc::make_mut(context));
|
||||
redact_secrets(&mut completed_command.command);
|
||||
redact_secrets(&mut completed_command.grid_contents);
|
||||
redact_secrets(&mut completed_command.cursor);
|
||||
}
|
||||
AIAgentInput::AutoCodeDiffQuery { query, context, .. } => {
|
||||
redact_secrets(query);
|
||||
redact_context(Arc::make_mut(context));
|
||||
|
||||
Reference in New Issue
Block a user