mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
a8c9530911
## Stack 1. [#26547](https://github.com/openai/codex/pull/26547) - [1 of 2] Align goal extension with core behavior 2. [#26548](https://github.com/openai/codex/pull/26548) - [2 of 2] Move goal runtime to extension ## Why The goal runtime is moving out of `codex-core` and into `codex-goal-extension`. This first PR brings the extension back in line with the current core behavior before the follow-up PR switches app-server sessions over to the extension, so that review can focus on ownership and wiring rather than hidden behavior drift. ## What Changed - Updates the extension `create_goal` and `update_goal` tool schemas/descriptions to match the current core wording for explicit token budgets, blocked-goal audits, resumed blocked goals, and system-owned budget/usage-limit transitions. - Marks `codex-goal-extension` as the live `/goal` extension crate rather than an unwired sketch. - Looks up the live thread before reading goal state for idle continuation, so continuation setup exits early when no live thread can accept the automatic turn.
95 lines
4.5 KiB
Rust
95 lines
4.5 KiB
Rust
//! Responses API tool definitions for persisted thread goals.
|
|
|
|
use codex_tools::JsonSchema;
|
|
use codex_tools::ResponsesApiTool;
|
|
use codex_tools::ToolSpec;
|
|
use serde_json::json;
|
|
use std::collections::BTreeMap;
|
|
|
|
pub const GET_GOAL_TOOL_NAME: &str = "get_goal";
|
|
pub const CREATE_GOAL_TOOL_NAME: &str = "create_goal";
|
|
pub const UPDATE_GOAL_TOOL_NAME: &str = "update_goal";
|
|
|
|
pub fn create_get_goal_tool() -> ToolSpec {
|
|
ToolSpec::Function(ResponsesApiTool {
|
|
name: GET_GOAL_TOOL_NAME.to_string(),
|
|
description: "Get the current goal for this thread, including status, budgets, token and elapsed-time usage, and remaining token budget."
|
|
.to_string(),
|
|
strict: false,
|
|
defer_loading: None,
|
|
parameters: JsonSchema::object(BTreeMap::new(), Some(Vec::new()), Some(false.into())),
|
|
output_schema: None,
|
|
})
|
|
}
|
|
|
|
pub fn create_create_goal_tool() -> ToolSpec {
|
|
let properties = BTreeMap::from([
|
|
(
|
|
"objective".to_string(),
|
|
JsonSchema::string(Some(
|
|
"Required. The concrete objective to start pursuing. This starts a new active goal only when no goal is currently defined; if a goal already exists, this tool fails."
|
|
.to_string(),
|
|
)),
|
|
),
|
|
(
|
|
"token_budget".to_string(),
|
|
JsonSchema::integer(Some(
|
|
"Positive token budget for the new goal. Omit unless explicitly requested."
|
|
.to_string(),
|
|
)),
|
|
),
|
|
]);
|
|
|
|
ToolSpec::Function(ResponsesApiTool {
|
|
name: CREATE_GOAL_TOOL_NAME.to_string(),
|
|
description: format!(
|
|
r#"Create a goal only when explicitly requested by the user or system/developer instructions; do not infer goals from ordinary tasks.
|
|
Set token_budget only when an explicit token budget is requested. Fails if a goal exists; use {UPDATE_GOAL_TOOL_NAME} only for status."#
|
|
),
|
|
strict: false,
|
|
defer_loading: None,
|
|
parameters: JsonSchema::object(
|
|
properties,
|
|
/*required*/ Some(vec!["objective".to_string()]),
|
|
Some(false.into()),
|
|
),
|
|
output_schema: None,
|
|
})
|
|
}
|
|
|
|
pub fn create_update_goal_tool() -> ToolSpec {
|
|
let properties = BTreeMap::from([(
|
|
"status".to_string(),
|
|
JsonSchema::string_enum(
|
|
vec![json!("complete"), json!("blocked")],
|
|
Some(
|
|
"Required. Set to `complete` only when the objective is achieved and no required work remains. Set to `blocked` only after the same blocking condition has recurred for at least three consecutive goal turns and the agent is at an impasse. After a previously blocked goal is resumed, the resumed run starts a fresh blocked audit."
|
|
.to_string(),
|
|
),
|
|
),
|
|
)]);
|
|
|
|
ToolSpec::Function(ResponsesApiTool {
|
|
name: UPDATE_GOAL_TOOL_NAME.to_string(),
|
|
description: r#"Update the existing goal.
|
|
Use this tool only to mark the goal achieved or genuinely blocked.
|
|
Set status to `complete` only when the objective has actually been achieved and no required work remains.
|
|
Set status to `blocked` only when the same blocking condition has repeated for at least three consecutive goal turns, counting the original/user-triggered turn and any automatic continuations, and the agent cannot make meaningful progress without user input or an external-state change.
|
|
If the user resumes a goal that was previously marked `blocked`, treat the resumed run as a fresh blocked audit. If the same blocking condition then repeats for at least three consecutive resumed goal turns, set status to `blocked` again.
|
|
Once the blocked threshold is satisfied, do not keep reporting that you are still blocked while leaving the goal active; set status to `blocked`.
|
|
Do not use `blocked` merely because the work is hard, slow, uncertain, incomplete, or would benefit from clarification.
|
|
Do not mark a goal complete merely because its budget is nearly exhausted or because you are stopping work.
|
|
You cannot use this tool to pause, resume, budget-limit, or usage-limit a goal; those status changes are controlled by the user or system.
|
|
When marking a budgeted goal achieved with status `complete`, report the final token usage from the tool result to the user."#
|
|
.to_string(),
|
|
strict: false,
|
|
defer_loading: None,
|
|
parameters: JsonSchema::object(
|
|
properties,
|
|
/*required*/ Some(vec!["status".to_string()]),
|
|
Some(false.into()),
|
|
),
|
|
output_schema: None,
|
|
})
|
|
}
|