open_agent_profile/
lib.rs1#![warn(missing_docs)]
8
9mod canonical;
10mod composition;
11mod delta;
12mod parse;
13mod policy;
14mod render;
15mod validate;
16
17pub use canonical::{CanonicalError, canonical_json, profile_digest, profile_digests, spec_digest};
18pub use composition::{
19 CompositionError, ProfileReference, merge_profile_values, resolve_composition,
20};
21pub use delta::{
22 ApplyError, ApplyOptions, ConflictError, apply_delta, serialize, write_atomically,
23};
24pub use parse::{OapFormat, ParseError, load, parse};
25pub use policy::{
26 EffectiveTools, PermissionDecision, intersect_tools, narrow_decision, narrow_permission_map,
27};
28pub use render::{RenderError, RenderOptions, render_system_prompt, substitute_variables};
29pub use validate::{escapes_workspace, validate, validate_path};
30
31use serde::{Deserialize, Serialize};
32use serde_json::{Map, Value};
33
34pub const OAP_VERSION: &str = "1.0";
36pub const SUPPORT_VERSION: &str = "1.0.5";
38pub type Document = Map<String, Value>;
40pub type AgentProfile = Document;
42pub type AgentStateDelta = Document;
44
45#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
47pub struct Issue {
48 pub pointer: String,
50 pub message: String,
52}
53
54#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
56pub struct Digests {
57 pub profile: String,
59 pub spec: String,
61}
62
63#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct ValidationReport {
66 pub kind: String,
68 #[serde(skip_serializing_if = "Option::is_none")]
69 pub document: Option<Document>,
71 pub errors: Vec<Issue>,
73 pub warnings: Vec<Issue>,
75 #[serde(skip_serializing_if = "Option::is_none")]
76 pub digests: Option<Digests>,
78 pub ok: bool,
80}
81
82#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
84pub struct Adjustment {
85 pub field: String,
87 pub requested: Value,
89 pub effective: Value,
91 pub reason: String,
93}
94
95#[derive(Debug, Clone, Serialize, Deserialize)]
97pub struct DeltaApplication {
98 pub profile: AgentProfile,
100 pub warnings: Vec<String>,
102 pub pending_proposals: Vec<Document>,
104}
105
106pub(crate) fn object(value: Option<&Value>) -> &Map<String, Value> {
107 value.and_then(Value::as_object).unwrap_or_else(|| {
108 static EMPTY: std::sync::LazyLock<Map<String, Value>> = std::sync::LazyLock::new(Map::new);
109 &EMPTY
110 })
111}
112
113pub(crate) fn strings(value: Option<&Value>) -> Vec<String> {
114 value
115 .and_then(Value::as_array)
116 .into_iter()
117 .flatten()
118 .filter_map(Value::as_str)
119 .map(str::to_owned)
120 .collect()
121}