mirror of
https://github.com/openai/codex.git
synced 2026-10-31 19:28:49 +00:00
fix(core): refine next-prompt suggestion requests
This commit is contained in:
@@ -798,7 +798,6 @@ impl ModelClient {
|
||||
store: provider.is_azure_responses_endpoint(),
|
||||
stream: true,
|
||||
include,
|
||||
max_output_tokens: prompt.max_output_tokens,
|
||||
service_tier,
|
||||
prompt_cache_key,
|
||||
text,
|
||||
@@ -1317,7 +1316,9 @@ impl ModelClientSession {
|
||||
client_setup.api_auth,
|
||||
)
|
||||
.with_telemetry(Some(request_telemetry), Some(sse_telemetry));
|
||||
let stream_result = client.stream_request(request, options).await;
|
||||
let stream_result = client
|
||||
.stream_request_with_max_output_tokens(request, options, prompt.max_output_tokens)
|
||||
.await;
|
||||
|
||||
match stream_result {
|
||||
Ok(stream) => {
|
||||
@@ -1491,7 +1492,11 @@ impl ModelClientSession {
|
||||
))
|
||||
})?;
|
||||
let stream_result = websocket_connection
|
||||
.stream_request(ws_request, self.websocket_session.connection_reused())
|
||||
.stream_request_with_max_output_tokens(
|
||||
ws_request,
|
||||
self.websocket_session.connection_reused(),
|
||||
prompt.max_output_tokens,
|
||||
)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
let response_debug_context =
|
||||
|
||||
@@ -22,7 +22,6 @@ fn serializes_text_verbosity_when_set() {
|
||||
store: false,
|
||||
stream: true,
|
||||
include: vec![],
|
||||
max_output_tokens: None,
|
||||
prompt_cache_key: None,
|
||||
service_tier: None,
|
||||
text: Some(TextControls {
|
||||
@@ -70,7 +69,6 @@ fn serializes_text_schema_with_strict_format() {
|
||||
store: false,
|
||||
stream: true,
|
||||
include: vec![],
|
||||
max_output_tokens: None,
|
||||
prompt_cache_key: None,
|
||||
service_tier: None,
|
||||
text: Some(text_controls),
|
||||
@@ -132,7 +130,6 @@ fn omits_text_when_not_set() {
|
||||
store: false,
|
||||
stream: true,
|
||||
include: vec![],
|
||||
max_output_tokens: None,
|
||||
prompt_cache_key: None,
|
||||
service_tier: None,
|
||||
text: None,
|
||||
@@ -156,7 +153,6 @@ fn serializes_flex_service_tier_when_set() {
|
||||
store: false,
|
||||
stream: true,
|
||||
include: vec![],
|
||||
max_output_tokens: None,
|
||||
prompt_cache_key: None,
|
||||
service_tier: Some(ServiceTier::Flex.to_string()),
|
||||
text: None,
|
||||
|
||||
@@ -73,9 +73,6 @@ pub(crate) async fn suggest_next_prompt(
|
||||
let started_at = Instant::now();
|
||||
let mut turn_context = sess.new_lightweight_turn().await;
|
||||
prefer_fast_suggestion_profile(&mut turn_context);
|
||||
if !suggestion_prompt_fits_context_window(sess, &turn_context).await {
|
||||
return None;
|
||||
}
|
||||
|
||||
let history = sess.clone_history().await;
|
||||
let history_snapshot = HistorySnapshot::from_history(&history);
|
||||
@@ -111,6 +108,9 @@ pub(crate) async fn suggest_next_prompt(
|
||||
output_schema_strict: true,
|
||||
max_output_tokens: Some(NEXT_PROMPT_SUGGESTION_MAX_OUTPUT_TOKENS),
|
||||
};
|
||||
if !suggestion_prompt_fits_context_window(&prompt, &turn_context) {
|
||||
return None;
|
||||
}
|
||||
if !session_is_idle_for_suggestion(sess).await {
|
||||
return None;
|
||||
}
|
||||
@@ -276,14 +276,19 @@ fn history_matches_snapshot(history: &ContextManager, snapshot: HistorySnapshot)
|
||||
history.history_version() == snapshot.version && history.raw_items().len() == snapshot.len
|
||||
}
|
||||
|
||||
async fn suggestion_prompt_fits_context_window(sess: &Session, turn_context: &TurnContext) -> bool {
|
||||
fn suggestion_prompt_fits_context_window(prompt: &Prompt, turn_context: &TurnContext) -> bool {
|
||||
let Some(model_context_window) = turn_context.model_context_window() else {
|
||||
tracing::debug!("next prompt suggestion skipped without model context window");
|
||||
return false;
|
||||
};
|
||||
if let Some(estimated_token_count) = sess.get_estimated_token_count(turn_context).await
|
||||
&& !suggestion_prompt_has_headroom(estimated_token_count, model_context_window)
|
||||
{
|
||||
let Ok(input) = serde_json::to_string(&prompt.input) else {
|
||||
tracing::debug!("next prompt suggestion skipped without serializable prompt input");
|
||||
return false;
|
||||
};
|
||||
let estimated_token_count = approx_token_count(&prompt.base_instructions.text)
|
||||
.saturating_add(approx_token_count(&input));
|
||||
let estimated_token_count = i64::try_from(estimated_token_count).unwrap_or(i64::MAX);
|
||||
if !suggestion_prompt_has_headroom(estimated_token_count, model_context_window) {
|
||||
let suggestion_prompt_limit =
|
||||
model_context_window.saturating_sub(NEXT_PROMPT_SUGGESTION_TOKEN_HEADROOM);
|
||||
tracing::debug!(
|
||||
@@ -503,6 +508,7 @@ fn filter_next_prompt_suggestion(raw: &str) -> Option<String> {
|
||||
) || lower.starts_with("suggestion:")
|
||||
|| lower.starts_with("next prompt:")
|
||||
|| is_wrapped_meta(&suggestion)
|
||||
|| is_wrapped_quote(&suggestion)
|
||||
|| starts_with_any(&lower, &["looks good", "thanks", "thank you"])
|
||||
|| starts_with_any(&lower, &["let me", "i'll", "i will", "here's"])
|
||||
{
|
||||
@@ -524,6 +530,11 @@ fn is_wrapped_meta(suggestion: &str) -> bool {
|
||||
|| (suggestion.starts_with('[') && suggestion.ends_with(']'))
|
||||
}
|
||||
|
||||
fn is_wrapped_quote(suggestion: &str) -> bool {
|
||||
(suggestion.starts_with('"') && suggestion.ends_with('"'))
|
||||
|| (suggestion.starts_with('\'') && suggestion.ends_with('\''))
|
||||
}
|
||||
|
||||
fn starts_with_any(value: &str, prefixes: &[&str]) -> bool {
|
||||
prefixes.iter().any(|prefix| value.starts_with(prefix))
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ fn filter_keeps_valid_prompts() {
|
||||
("set CODEX_HOME", "set CODEX_HOME"),
|
||||
("update Cargo.toml", "update Cargo.toml"),
|
||||
("open app-server/README.md", "open app-server/README.md"),
|
||||
("don't run tests yet", "don't run tests yet"),
|
||||
] {
|
||||
assert_eq!(
|
||||
filter_next_prompt_suggestion(suggestion),
|
||||
@@ -235,6 +236,8 @@ fn filter_rejects_invalid_prompts() {
|
||||
"let me run tests",
|
||||
"what about tests?",
|
||||
"run tests.",
|
||||
"\"run the tests\"",
|
||||
"'run the tests'",
|
||||
"run\ntests",
|
||||
"continue with every possible next step in this project and explain every detail now",
|
||||
] {
|
||||
|
||||
Reference in New Issue
Block a user