mirror of
https://github.com/openai/codex.git
synced 2026-03-04 05:33:19 +00:00
Compare commits
1 Commits
codex-cli-
...
gt/additio
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
92e094f9b8 |
@@ -10957,6 +10957,12 @@
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"requiredDeveloperInstructions": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
|
||||
@@ -39,6 +39,12 @@
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"requiredDeveloperInstructions": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
|
||||
@@ -5,4 +5,4 @@ import type { AskForApproval } from "./AskForApproval";
|
||||
import type { ResidencyRequirement } from "./ResidencyRequirement";
|
||||
import type { SandboxMode } from "./SandboxMode";
|
||||
|
||||
export type ConfigRequirements = { allowedApprovalPolicies: Array<AskForApproval> | null, allowedSandboxModes: Array<SandboxMode> | null, enforceResidency: ResidencyRequirement | null, };
|
||||
export type ConfigRequirements = { allowedApprovalPolicies: Array<AskForApproval> | null, allowedSandboxModes: Array<SandboxMode> | null, enforceResidency: ResidencyRequirement | null, requiredDeveloperInstructions: string | null, };
|
||||
|
||||
@@ -501,6 +501,7 @@ pub struct ConfigRequirements {
|
||||
pub allowed_approval_policies: Option<Vec<AskForApproval>>,
|
||||
pub allowed_sandbox_modes: Option<Vec<SandboxMode>>,
|
||||
pub enforce_residency: Option<ResidencyRequirement>,
|
||||
pub required_developer_instructions: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
|
||||
|
||||
@@ -116,7 +116,7 @@ Example (from OpenAI's official VSCode extension):
|
||||
- `config/read` — fetch the effective config on disk after resolving config layering.
|
||||
- `config/value/write` — write a single config key/value to the user's config.toml on disk.
|
||||
- `config/batchWrite` — apply multiple config edits atomically to the user's config.toml on disk.
|
||||
- `configRequirements/read` — fetch the loaded requirements allow-lists and `enforceResidency` from `requirements.toml` and/or MDM (or `null` if none are configured).
|
||||
- `configRequirements/read` — fetch the loaded requirements allow-lists, `enforceResidency`, and `requiredDeveloperInstructions` from `requirements.toml` and/or MDM (or `null` if none are configured).
|
||||
|
||||
### Example: Start or resume a thread
|
||||
|
||||
|
||||
@@ -118,6 +118,7 @@ fn map_requirements_toml_to_api(requirements: ConfigRequirementsToml) -> ConfigR
|
||||
enforce_residency: requirements
|
||||
.enforce_residency
|
||||
.map(map_residency_requirement_to_api),
|
||||
required_developer_instructions: requirements.additional_developer_instructions,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,6 +181,7 @@ mod tests {
|
||||
mcp_servers: None,
|
||||
rules: None,
|
||||
enforce_residency: Some(CoreResidencyRequirement::Us),
|
||||
additional_developer_instructions: Some("Follow policy".to_string()),
|
||||
};
|
||||
|
||||
let mapped = map_requirements_toml_to_api(requirements);
|
||||
@@ -199,5 +201,9 @@ mod tests {
|
||||
mapped.enforce_residency,
|
||||
Some(codex_app_server_protocol::ResidencyRequirement::Us),
|
||||
);
|
||||
assert_eq!(
|
||||
mapped.required_developer_instructions,
|
||||
Some("Follow policy".to_string()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -570,6 +570,7 @@ fn append_rollout_turn_context(path: &Path, timestamp: &str, model: &str) -> std
|
||||
summary: ReasoningSummary::Auto,
|
||||
user_instructions: None,
|
||||
developer_instructions: None,
|
||||
required_developer_instructions: None,
|
||||
final_output_json_schema: None,
|
||||
truncation_policy: None,
|
||||
}),
|
||||
|
||||
@@ -384,6 +384,7 @@ mod tests {
|
||||
mcp_servers: None,
|
||||
rules: None,
|
||||
enforce_residency: None,
|
||||
additional_developer_instructions: None,
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -424,6 +425,7 @@ mod tests {
|
||||
mcp_servers: None,
|
||||
rules: None,
|
||||
enforce_residency: None,
|
||||
additional_developer_instructions: None,
|
||||
})
|
||||
);
|
||||
}
|
||||
@@ -467,6 +469,7 @@ mod tests {
|
||||
mcp_servers: None,
|
||||
rules: None,
|
||||
enforce_residency: None,
|
||||
additional_developer_instructions: None,
|
||||
})
|
||||
);
|
||||
assert_eq!(fetcher.request_count.load(Ordering::SeqCst), 2);
|
||||
|
||||
@@ -369,6 +369,7 @@ impl Codex {
|
||||
collaboration_mode,
|
||||
model_reasoning_summary: config.model_reasoning_summary,
|
||||
developer_instructions: config.developer_instructions.clone(),
|
||||
required_developer_instructions: config.required_developer_instructions.clone(),
|
||||
user_instructions,
|
||||
personality: config.personality,
|
||||
base_instructions,
|
||||
@@ -518,6 +519,7 @@ pub(crate) struct TurnContext {
|
||||
/// instead of `std::env::current_dir()`.
|
||||
pub(crate) cwd: PathBuf,
|
||||
pub(crate) developer_instructions: Option<String>,
|
||||
pub(crate) required_developer_instructions: Constrained<Option<String>>,
|
||||
pub(crate) compact_prompt: Option<String>,
|
||||
pub(crate) user_instructions: Option<String>,
|
||||
pub(crate) collaboration_mode: CollaborationMode,
|
||||
@@ -599,6 +601,7 @@ pub(crate) struct SessionConfiguration {
|
||||
|
||||
/// Developer instructions that supplement the base instructions.
|
||||
developer_instructions: Option<String>,
|
||||
required_developer_instructions: Constrained<Option<String>>,
|
||||
|
||||
/// Model instructions that are appended to the base instructions.
|
||||
user_instructions: Option<String>,
|
||||
@@ -809,6 +812,9 @@ impl Session {
|
||||
session_source,
|
||||
cwd,
|
||||
developer_instructions: session_configuration.developer_instructions.clone(),
|
||||
required_developer_instructions: session_configuration
|
||||
.required_developer_instructions
|
||||
.clone(),
|
||||
compact_prompt: session_configuration.compact_prompt.clone(),
|
||||
user_instructions: session_configuration.user_instructions.clone(),
|
||||
collaboration_mode: session_configuration.collaboration_mode.clone(),
|
||||
@@ -2117,8 +2123,14 @@ impl Session {
|
||||
)
|
||||
.into(),
|
||||
);
|
||||
if let Some(developer_instructions) = turn_context.developer_instructions.as_deref() {
|
||||
items.push(DeveloperInstructions::new(developer_instructions.to_string()).into());
|
||||
if let Some(developer_instructions) = Self::merge_developer_instructions(
|
||||
turn_context.developer_instructions.as_deref(),
|
||||
turn_context
|
||||
.required_developer_instructions
|
||||
.get()
|
||||
.as_deref(),
|
||||
) {
|
||||
items.push(DeveloperInstructions::new(developer_instructions).into());
|
||||
}
|
||||
// Add developer instructions from collaboration_mode if they exist and are non-empty
|
||||
let (collaboration_mode, base_instructions) = {
|
||||
@@ -2164,6 +2176,22 @@ impl Session {
|
||||
items
|
||||
}
|
||||
|
||||
fn merge_developer_instructions(
|
||||
developer_instructions: Option<&str>,
|
||||
required_developer_instructions: Option<&str>,
|
||||
) -> Option<String> {
|
||||
match (developer_instructions, required_developer_instructions) {
|
||||
(Some(developer_instructions), Some(required_developer_instructions)) => Some(format!(
|
||||
"{developer_instructions}\n\n{required_developer_instructions}"
|
||||
)),
|
||||
(Some(developer_instructions), None) => Some(developer_instructions.to_string()),
|
||||
(None, Some(required_developer_instructions)) => {
|
||||
Some(required_developer_instructions.to_string())
|
||||
}
|
||||
(None, None) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn persist_rollout_items(&self, items: &[RolloutItem]) {
|
||||
let recorder = {
|
||||
let guard = self.services.rollout.lock().await;
|
||||
@@ -3538,6 +3566,7 @@ async fn spawn_review_thread(
|
||||
features: parent_turn_context.features.clone(),
|
||||
ghost_snapshot: parent_turn_context.ghost_snapshot.clone(),
|
||||
developer_instructions: None,
|
||||
required_developer_instructions: Constrained::allow_any(None),
|
||||
user_instructions: None,
|
||||
compact_prompt: parent_turn_context.compact_prompt.clone(),
|
||||
collaboration_mode: parent_turn_context.collaboration_mode.clone(),
|
||||
@@ -4581,6 +4610,7 @@ async fn try_run_sampling_request(
|
||||
summary: turn_context.reasoning_summary,
|
||||
user_instructions: turn_context.user_instructions.clone(),
|
||||
developer_instructions: turn_context.developer_instructions.clone(),
|
||||
required_developer_instructions: turn_context.required_developer_instructions.get().clone(),
|
||||
final_output_json_schema: turn_context.final_output_json_schema.clone(),
|
||||
truncation_policy: Some(turn_context.truncation_policy.into()),
|
||||
});
|
||||
@@ -5401,6 +5431,7 @@ mod tests {
|
||||
collaboration_mode,
|
||||
model_reasoning_summary: config.model_reasoning_summary,
|
||||
developer_instructions: config.developer_instructions.clone(),
|
||||
required_developer_instructions: config.required_developer_instructions.clone(),
|
||||
user_instructions: config.user_instructions.clone(),
|
||||
personality: config.personality,
|
||||
base_instructions: config
|
||||
@@ -5484,6 +5515,7 @@ mod tests {
|
||||
collaboration_mode,
|
||||
model_reasoning_summary: config.model_reasoning_summary,
|
||||
developer_instructions: config.developer_instructions.clone(),
|
||||
required_developer_instructions: config.required_developer_instructions.clone(),
|
||||
user_instructions: config.user_instructions.clone(),
|
||||
personality: config.personality,
|
||||
base_instructions: config
|
||||
@@ -5757,6 +5789,7 @@ mod tests {
|
||||
collaboration_mode,
|
||||
model_reasoning_summary: config.model_reasoning_summary,
|
||||
developer_instructions: config.developer_instructions.clone(),
|
||||
required_developer_instructions: config.required_developer_instructions.clone(),
|
||||
user_instructions: config.user_instructions.clone(),
|
||||
personality: config.personality,
|
||||
base_instructions: config
|
||||
@@ -5887,6 +5920,7 @@ mod tests {
|
||||
collaboration_mode,
|
||||
model_reasoning_summary: config.model_reasoning_summary,
|
||||
developer_instructions: config.developer_instructions.clone(),
|
||||
required_developer_instructions: config.required_developer_instructions.clone(),
|
||||
user_instructions: config.user_instructions.clone(),
|
||||
personality: config.personality,
|
||||
base_instructions: config
|
||||
|
||||
@@ -105,6 +105,7 @@ async fn run_compact_task_inner(
|
||||
summary: turn_context.reasoning_summary,
|
||||
user_instructions: turn_context.user_instructions.clone(),
|
||||
developer_instructions: turn_context.developer_instructions.clone(),
|
||||
required_developer_instructions: turn_context.required_developer_instructions.get().clone(),
|
||||
final_output_json_schema: turn_context.final_output_json_schema.clone(),
|
||||
truncation_policy: Some(turn_context.truncation_policy.into()),
|
||||
});
|
||||
|
||||
@@ -178,6 +178,8 @@ pub struct Config {
|
||||
|
||||
/// Developer instructions override injected as a separate message.
|
||||
pub developer_instructions: Option<String>,
|
||||
/// Required developer instructions from requirements.
|
||||
pub required_developer_instructions: Constrained<Option<String>>,
|
||||
|
||||
/// Compact prompt override.
|
||||
pub compact_prompt: Option<String>,
|
||||
@@ -1624,6 +1626,7 @@ impl Config {
|
||||
mcp_servers,
|
||||
exec_policy: _,
|
||||
enforce_residency,
|
||||
required_developer_instructions,
|
||||
} = requirements;
|
||||
|
||||
apply_requirement_constrained_value(
|
||||
@@ -1662,6 +1665,7 @@ impl Config {
|
||||
base_instructions,
|
||||
personality,
|
||||
developer_instructions,
|
||||
required_developer_instructions: required_developer_instructions.value,
|
||||
compact_prompt,
|
||||
// The config.toml omits "_mode" because it's a config file. However, "_mode"
|
||||
// is important in code to differentiate the mode from the store implementation.
|
||||
@@ -3974,6 +3978,7 @@ model_verbosity = "high"
|
||||
chatgpt_base_url: "https://chatgpt.com/backend-api/".to_string(),
|
||||
base_instructions: None,
|
||||
developer_instructions: None,
|
||||
required_developer_instructions: Constrained::allow_any(None),
|
||||
compact_prompt: None,
|
||||
forced_chatgpt_workspace_id: None,
|
||||
forced_login_method: None,
|
||||
@@ -4062,6 +4067,7 @@ model_verbosity = "high"
|
||||
chatgpt_base_url: "https://chatgpt.com/backend-api/".to_string(),
|
||||
base_instructions: None,
|
||||
developer_instructions: None,
|
||||
required_developer_instructions: Constrained::allow_any(None),
|
||||
compact_prompt: None,
|
||||
forced_chatgpt_workspace_id: None,
|
||||
forced_login_method: None,
|
||||
@@ -4165,6 +4171,7 @@ model_verbosity = "high"
|
||||
chatgpt_base_url: "https://chatgpt.com/backend-api/".to_string(),
|
||||
base_instructions: None,
|
||||
developer_instructions: None,
|
||||
required_developer_instructions: Constrained::allow_any(None),
|
||||
compact_prompt: None,
|
||||
forced_chatgpt_workspace_id: None,
|
||||
forced_login_method: None,
|
||||
@@ -4254,6 +4261,7 @@ model_verbosity = "high"
|
||||
chatgpt_base_url: "https://chatgpt.com/backend-api/".to_string(),
|
||||
base_instructions: None,
|
||||
developer_instructions: None,
|
||||
required_developer_instructions: Constrained::allow_any(None),
|
||||
compact_prompt: None,
|
||||
forced_chatgpt_workspace_id: None,
|
||||
forced_login_method: None,
|
||||
@@ -4808,6 +4816,7 @@ mcp_oauth_callback_port = 5678
|
||||
mcp_servers: None,
|
||||
rules: None,
|
||||
enforce_residency: None,
|
||||
additional_developer_instructions: None,
|
||||
};
|
||||
|
||||
let config = ConfigBuilder::default()
|
||||
|
||||
@@ -79,6 +79,7 @@ pub struct ConfigRequirements {
|
||||
pub mcp_servers: Option<Sourced<BTreeMap<String, McpServerRequirement>>>,
|
||||
pub(crate) exec_policy: Option<Sourced<RequirementsExecPolicy>>,
|
||||
pub enforce_residency: ConstrainedWithSource<Option<ResidencyRequirement>>,
|
||||
pub required_developer_instructions: ConstrainedWithSource<Option<String>>,
|
||||
}
|
||||
|
||||
impl Default for ConfigRequirements {
|
||||
@@ -95,6 +96,10 @@ impl Default for ConfigRequirements {
|
||||
mcp_servers: None,
|
||||
exec_policy: None,
|
||||
enforce_residency: ConstrainedWithSource::new(Constrained::allow_any(None), None),
|
||||
required_developer_instructions: ConstrainedWithSource::new(
|
||||
Constrained::allow_any(None),
|
||||
None,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,6 +130,7 @@ pub struct ConfigRequirementsToml {
|
||||
pub mcp_servers: Option<BTreeMap<String, McpServerRequirement>>,
|
||||
pub rules: Option<RequirementsExecPolicyToml>,
|
||||
pub enforce_residency: Option<ResidencyRequirement>,
|
||||
pub additional_developer_instructions: Option<String>,
|
||||
}
|
||||
|
||||
/// Value paired with the requirement source it came from, for better error
|
||||
@@ -156,6 +162,7 @@ pub struct ConfigRequirementsWithSources {
|
||||
pub mcp_servers: Option<Sourced<BTreeMap<String, McpServerRequirement>>>,
|
||||
pub rules: Option<Sourced<RequirementsExecPolicyToml>>,
|
||||
pub enforce_residency: Option<Sourced<ResidencyRequirement>>,
|
||||
pub additional_developer_instructions: Option<Sourced<String>>,
|
||||
}
|
||||
|
||||
impl ConfigRequirementsWithSources {
|
||||
@@ -189,6 +196,7 @@ impl ConfigRequirementsWithSources {
|
||||
mcp_servers,
|
||||
rules,
|
||||
enforce_residency,
|
||||
additional_developer_instructions,
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -200,6 +208,7 @@ impl ConfigRequirementsWithSources {
|
||||
mcp_servers,
|
||||
rules,
|
||||
enforce_residency,
|
||||
additional_developer_instructions,
|
||||
} = self;
|
||||
ConfigRequirementsToml {
|
||||
allowed_approval_policies: allowed_approval_policies.map(|sourced| sourced.value),
|
||||
@@ -207,6 +216,8 @@ impl ConfigRequirementsWithSources {
|
||||
mcp_servers: mcp_servers.map(|sourced| sourced.value),
|
||||
rules: rules.map(|sourced| sourced.value),
|
||||
enforce_residency: enforce_residency.map(|sourced| sourced.value),
|
||||
additional_developer_instructions: additional_developer_instructions
|
||||
.map(|sourced| sourced.value),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -251,6 +262,7 @@ impl ConfigRequirementsToml {
|
||||
&& self.mcp_servers.is_none()
|
||||
&& self.rules.is_none()
|
||||
&& self.enforce_residency.is_none()
|
||||
&& self.additional_developer_instructions.is_none()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,6 +276,7 @@ impl TryFrom<ConfigRequirementsWithSources> for ConfigRequirements {
|
||||
mcp_servers,
|
||||
rules,
|
||||
enforce_residency,
|
||||
additional_developer_instructions,
|
||||
} = toml;
|
||||
|
||||
let approval_policy = match allowed_approval_policies {
|
||||
@@ -380,12 +393,36 @@ impl TryFrom<ConfigRequirementsWithSources> for ConfigRequirements {
|
||||
}
|
||||
None => ConstrainedWithSource::new(Constrained::allow_any(None), None),
|
||||
};
|
||||
let required_developer_instructions = match additional_developer_instructions {
|
||||
Some(Sourced {
|
||||
value: required_developer_instructions,
|
||||
source: requirement_source,
|
||||
}) => {
|
||||
let required = Some(required_developer_instructions);
|
||||
let requirement_source_for_error = requirement_source.clone();
|
||||
let constrained = Constrained::new(required.clone(), move |candidate| {
|
||||
if candidate == &required {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ConstraintError::InvalidValue {
|
||||
field_name: "required_developer_instructions",
|
||||
candidate: format!("{candidate:?}"),
|
||||
allowed: format!("{required:?}"),
|
||||
requirement_source: requirement_source_for_error.clone(),
|
||||
})
|
||||
}
|
||||
})?;
|
||||
ConstrainedWithSource::new(constrained, Some(requirement_source))
|
||||
}
|
||||
None => ConstrainedWithSource::new(Constrained::allow_any(None), None),
|
||||
};
|
||||
Ok(ConfigRequirements {
|
||||
approval_policy,
|
||||
sandbox_policy,
|
||||
mcp_servers,
|
||||
exec_policy,
|
||||
enforce_residency,
|
||||
required_developer_instructions,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -413,6 +450,7 @@ mod tests {
|
||||
mcp_servers,
|
||||
rules,
|
||||
enforce_residency,
|
||||
additional_developer_instructions,
|
||||
} = toml;
|
||||
ConfigRequirementsWithSources {
|
||||
allowed_approval_policies: allowed_approval_policies
|
||||
@@ -423,6 +461,8 @@ mod tests {
|
||||
rules: rules.map(|value| Sourced::new(value, RequirementSource::Unknown)),
|
||||
enforce_residency: enforce_residency
|
||||
.map(|value| Sourced::new(value, RequirementSource::Unknown)),
|
||||
additional_developer_instructions: additional_developer_instructions
|
||||
.map(|value| Sourced::new(value, RequirementSource::Unknown)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -437,7 +477,9 @@ mod tests {
|
||||
SandboxModeRequirement::DangerFullAccess,
|
||||
];
|
||||
let enforce_residency = ResidencyRequirement::Us;
|
||||
let required_developer_instructions = "use concise responses".to_string();
|
||||
let enforce_source = source.clone();
|
||||
let additional_source = source.clone();
|
||||
|
||||
// Intentionally constructed without `..Default::default()` so adding a new field to
|
||||
// `ConfigRequirementsToml` forces this test to be updated.
|
||||
@@ -447,6 +489,7 @@ mod tests {
|
||||
mcp_servers: None,
|
||||
rules: None,
|
||||
enforce_residency: Some(enforce_residency),
|
||||
additional_developer_instructions: Some(required_developer_instructions.clone()),
|
||||
};
|
||||
|
||||
target.merge_unset_fields(source.clone(), other);
|
||||
@@ -462,6 +505,10 @@ mod tests {
|
||||
mcp_servers: None,
|
||||
rules: None,
|
||||
enforce_residency: Some(Sourced::new(enforce_residency, enforce_source)),
|
||||
additional_developer_instructions: Some(Sourced::new(
|
||||
required_developer_instructions,
|
||||
additional_source,
|
||||
)),
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -492,6 +539,7 @@ mod tests {
|
||||
mcp_servers: None,
|
||||
rules: None,
|
||||
enforce_residency: None,
|
||||
additional_developer_instructions: None,
|
||||
}
|
||||
);
|
||||
Ok(())
|
||||
@@ -530,6 +578,7 @@ mod tests {
|
||||
mcp_servers: None,
|
||||
rules: None,
|
||||
enforce_residency: None,
|
||||
additional_developer_instructions: None,
|
||||
}
|
||||
);
|
||||
Ok(())
|
||||
@@ -616,6 +665,7 @@ mod tests {
|
||||
allowed_approval_policies = ["on-request"]
|
||||
allowed_sandbox_modes = ["read-only"]
|
||||
enforce_residency = "us"
|
||||
additional_developer_instructions = "follow policy"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
@@ -633,6 +683,13 @@ mod tests {
|
||||
Some(source_location.clone())
|
||||
);
|
||||
assert_eq!(requirements.enforce_residency.source, Some(source_location));
|
||||
assert_eq!(
|
||||
requirements
|
||||
.required_developer_instructions
|
||||
.get()
|
||||
.as_deref(),
|
||||
Some("follow policy")
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -539,6 +539,7 @@ allowed_approval_policies = ["on-request"]
|
||||
mcp_servers: None,
|
||||
rules: None,
|
||||
enforce_residency: None,
|
||||
additional_developer_instructions: None,
|
||||
})
|
||||
}),
|
||||
)
|
||||
@@ -585,6 +586,7 @@ allowed_approval_policies = ["on-request"]
|
||||
mcp_servers: None,
|
||||
rules: None,
|
||||
enforce_residency: None,
|
||||
additional_developer_instructions: None,
|
||||
},
|
||||
);
|
||||
load_requirements_toml(&mut config_requirements_toml, &requirements_file).await?;
|
||||
@@ -620,6 +622,7 @@ async fn load_config_layers_includes_cloud_requirements() -> anyhow::Result<()>
|
||||
mcp_servers: None,
|
||||
rules: None,
|
||||
enforce_residency: None,
|
||||
additional_developer_instructions: None,
|
||||
};
|
||||
let expected = requirements.clone();
|
||||
let cloud_requirements = CloudRequirementsLoader::new(async move { Some(requirements) });
|
||||
|
||||
@@ -32,6 +32,7 @@ fn resume_history(
|
||||
summary: config.model_reasoning_summary,
|
||||
user_instructions: None,
|
||||
developer_instructions: None,
|
||||
required_developer_instructions: None,
|
||||
final_output_json_schema: None,
|
||||
truncation_policy: None,
|
||||
};
|
||||
|
||||
@@ -1734,6 +1734,8 @@ pub struct TurnContextItem {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub developer_instructions: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub required_developer_instructions: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub final_output_json_schema: Option<Value>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub truncation_policy: Option<TruncationPolicy>,
|
||||
|
||||
@@ -99,6 +99,16 @@ fn render_debug_config_lines(stack: &ConfigLayerStack) -> Vec<Line<'static>> {
|
||||
));
|
||||
}
|
||||
|
||||
if let Some(required_developer_instructions) =
|
||||
requirements_toml.additional_developer_instructions.as_ref()
|
||||
{
|
||||
requirement_lines.push(requirement_line(
|
||||
"required_developer_instructions",
|
||||
required_developer_instructions.clone(),
|
||||
requirements.required_developer_instructions.source.as_ref(),
|
||||
));
|
||||
}
|
||||
|
||||
if requirement_lines.is_empty() {
|
||||
lines.push(" <none>".dim().into());
|
||||
} else {
|
||||
@@ -287,6 +297,10 @@ mod tests {
|
||||
Constrained::allow_any(Some(ResidencyRequirement::Us)),
|
||||
Some(RequirementSource::CloudRequirements),
|
||||
);
|
||||
requirements.required_developer_instructions = ConstrainedWithSource::new(
|
||||
Constrained::allow_any(Some("Always include source links.".to_string())),
|
||||
Some(RequirementSource::CloudRequirements),
|
||||
);
|
||||
|
||||
let requirements_toml = ConfigRequirementsToml {
|
||||
allowed_approval_policies: Some(vec![AskForApproval::OnRequest]),
|
||||
@@ -301,6 +315,7 @@ mod tests {
|
||||
)])),
|
||||
rules: None,
|
||||
enforce_residency: Some(ResidencyRequirement::Us),
|
||||
additional_developer_instructions: Some("Always include source links.".to_string()),
|
||||
};
|
||||
|
||||
let user_file = if cfg!(windows) {
|
||||
@@ -333,6 +348,9 @@ mod tests {
|
||||
);
|
||||
assert!(rendered.contains("mcp_servers: docs (source: MDM managed_config.toml (legacy))"));
|
||||
assert!(rendered.contains("enforce_residency: us (source: cloud requirements)"));
|
||||
assert!(rendered.contains(
|
||||
"required_developer_instructions: Always include source links. (source: cloud requirements)"
|
||||
));
|
||||
assert!(!rendered.contains(" - rules:"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1027,6 +1027,7 @@ mod tests {
|
||||
summary: config.model_reasoning_summary,
|
||||
user_instructions: None,
|
||||
developer_instructions: None,
|
||||
required_developer_instructions: None,
|
||||
final_output_json_schema: None,
|
||||
truncation_policy: None,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user