mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
3de8790714
- This PR is to make it on path for truncating by tokens. This path will be initially used by unified exec and context manager (responsible for MCP calls mainly). - We are exposing new config `calls_output_max_tokens` - Use `tokens` as the main budget unit but truncate based on the model family by Introducing `TruncationPolicy`. - Introduce `truncate_text` as a router for truncation based on the mode. In next PRs: - remove truncate_with_line_bytes_budget - Add the ability to the model to override the token budget.
101 lines
3.0 KiB
Rust
101 lines
3.0 KiB
Rust
use std::sync::Arc;
|
|
|
|
use crate::Prompt;
|
|
use crate::codex::Session;
|
|
use crate::codex::TurnContext;
|
|
use crate::error::Result as CodexResult;
|
|
use crate::protocol::AgentMessageEvent;
|
|
use crate::protocol::CompactedItem;
|
|
use crate::protocol::ErrorEvent;
|
|
use crate::protocol::EventMsg;
|
|
use crate::protocol::RolloutItem;
|
|
use crate::protocol::TaskStartedEvent;
|
|
use codex_protocol::models::ResponseInputItem;
|
|
use codex_protocol::models::ResponseItem;
|
|
use codex_protocol::user_input::UserInput;
|
|
|
|
pub(crate) async fn run_remote_compact_task(
|
|
sess: Arc<Session>,
|
|
turn_context: Arc<TurnContext>,
|
|
input: Vec<UserInput>,
|
|
) -> Option<String> {
|
|
let start_event = EventMsg::TaskStarted(TaskStartedEvent {
|
|
model_context_window: turn_context.client.get_model_context_window(),
|
|
});
|
|
sess.send_event(&turn_context, start_event).await;
|
|
|
|
match run_remote_compact_task_inner(&sess, &turn_context, input).await {
|
|
Ok(()) => {
|
|
let event = EventMsg::AgentMessage(AgentMessageEvent {
|
|
message: "Compact task completed".to_string(),
|
|
});
|
|
sess.send_event(&turn_context, event).await;
|
|
}
|
|
Err(err) => {
|
|
let event = EventMsg::Error(ErrorEvent {
|
|
message: err.to_string(),
|
|
});
|
|
sess.send_event(&turn_context, event).await;
|
|
}
|
|
}
|
|
|
|
None
|
|
}
|
|
|
|
async fn run_remote_compact_task_inner(
|
|
sess: &Arc<Session>,
|
|
turn_context: &Arc<TurnContext>,
|
|
input: Vec<UserInput>,
|
|
) -> CodexResult<()> {
|
|
let mut history = sess.clone_history().await;
|
|
if !input.is_empty() {
|
|
let initial_input_for_turn: ResponseInputItem = ResponseInputItem::from(input);
|
|
history.record_items(
|
|
&[initial_input_for_turn.into()],
|
|
turn_context.truncation_policy,
|
|
);
|
|
}
|
|
|
|
let prompt = Prompt {
|
|
input: history.get_history_for_prompt(),
|
|
tools: vec![],
|
|
parallel_tool_calls: false,
|
|
base_instructions_override: turn_context.base_instructions.clone(),
|
|
output_schema: None,
|
|
};
|
|
|
|
let mut new_history = turn_context
|
|
.client
|
|
.compact_conversation_history(&prompt)
|
|
.await?;
|
|
// Required to keep `/undo` available after compaction
|
|
let ghost_snapshots: Vec<ResponseItem> = history
|
|
.get_history()
|
|
.iter()
|
|
.filter(|item| matches!(item, ResponseItem::GhostSnapshot { .. }))
|
|
.cloned()
|
|
.collect();
|
|
|
|
if !ghost_snapshots.is_empty() {
|
|
new_history.extend(ghost_snapshots);
|
|
}
|
|
sess.replace_history(new_history.clone()).await;
|
|
|
|
if let Some(estimated_tokens) = sess
|
|
.clone_history()
|
|
.await
|
|
.estimate_token_count(turn_context.as_ref())
|
|
{
|
|
sess.override_last_token_usage_estimate(turn_context.as_ref(), estimated_tokens)
|
|
.await;
|
|
}
|
|
|
|
let compacted_item = CompactedItem {
|
|
message: String::new(),
|
|
replacement_history: Some(new_history),
|
|
};
|
|
sess.persist_rollout_items(&[RolloutItem::Compacted(compacted_item)])
|
|
.await;
|
|
Ok(())
|
|
}
|