Skip to content

Commit ac6881b

Browse files
committed
feat: added owned extensions and did some refactoring.
Signed-off-by: Teryl Taylor <terylt@ibm.com>
1 parent 9d08049 commit ac6881b

10 files changed

Lines changed: 615 additions & 569 deletions

File tree

crates/cpex-core/examples/cmf_capabilities_demo.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use cpex_core::cmf::{ContentPart, CmfHook, Message, MessagePayload, Role, ToolCa
1717
use cpex_core::context::PluginContext;
1818
use cpex_core::error::{PluginError, PluginViolation};
1919
use cpex_core::extensions::{
20-
Guarded, HttpExtension, RequestExtension, SecurityExtension,
20+
HttpExtension, RequestExtension, SecurityExtension,
2121
};
2222
use cpex_core::factory::{PluginFactory, PluginInstance};
2323
use cpex_core::hooks::adapter::TypedHandlerAdapter;
@@ -126,7 +126,7 @@ impl HookHandler<CmfHook> for HeaderInjector {
126126
) -> PluginResult<MessagePayload> {
127127
// Can see HTTP (has read_headers)
128128
if let Some(ref http) = extensions.http {
129-
println!(" [header-injector] HTTP headers visible: {:?}", http.read().request_headers);
129+
println!(" [header-injector] HTTP headers visible: {:?}", http.request_headers);
130130
}
131131

132132
// Can NOT see security subject (no read_subject)
@@ -202,7 +202,7 @@ impl HookHandler<CmfHook> for AuditLogger {
202202
}
203203

204204
if let Some(ref http) = extensions.http {
205-
if let Some(req_id) = http.read().get_header("X-Request-ID") {
205+
if let Some(req_id) = http.get_header("X-Request-ID") {
206206
print!("request_id='{}' ", req_id);
207207
}
208208
}
@@ -330,8 +330,8 @@ async fn main() {
330330
request_id: Some("req-abc-123".into()),
331331
..Default::default()
332332
})),
333-
security: Some(security),
334-
http: Some(Guarded::new(http)),
333+
security: Some(Arc::new(security)),
334+
http: Some(Arc::new(http)),
335335
meta: Some(Arc::new(MetaExtension {
336336
entity_type: Some("tool".into()),
337337
entity_name: Some("get_compensation".into()),
@@ -362,7 +362,7 @@ async fn main() {
362362
println!(" Labels after pre-invoke: {:?}", labels);
363363
}
364364
if let Some(ref http) = modified_ext.http {
365-
println!(" Headers after pre-invoke: {:?}", http.read().request_headers);
365+
println!(" Headers after pre-invoke: {:?}", http.request_headers);
366366
}
367367
}
368368
} else {
@@ -405,7 +405,7 @@ async fn main() {
405405
let mut security = SecurityExtension::default();
406406
security.add_label("PII");
407407
Extensions {
408-
security: Some(security),
408+
security: Some(Arc::new(security)),
409409
meta: Some(Arc::new(MetaExtension {
410410
entity_type: Some("tool".into()),
411411
entity_name: Some("get_compensation".into()),

crates/cpex-core/src/cmf/view.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ impl<'a> MessageView<'a> {
328328
pub fn get_header(&self, name: &str) -> Option<&str> {
329329
self.extensions
330330
.and_then(|e| e.http.as_ref())
331-
.and_then(|h| h.read().get_header(name))
331+
.and_then(|h| h.get_header(name))
332332
}
333333

334334
// -- Serialization --
@@ -438,8 +438,7 @@ impl<'a> MessageView<'a> {
438438

439439
// Request headers (strip sensitive)
440440
if let Some(ref http) = ext.http {
441-
let http_ref = http.read();
442-
let safe: std::collections::HashMap<&String, &String> = http_ref
441+
let safe: std::collections::HashMap<&String, &String> = http
443442
.request_headers
444443
.iter()
445444
.filter(|(k, _)| {
@@ -701,7 +700,8 @@ mod tests {
701700

702701
#[test]
703702
fn test_view_with_extensions() {
704-
use crate::extensions::{SecurityExtension, Guarded, HttpExtension};
703+
use std::sync::Arc;
704+
use crate::extensions::{SecurityExtension, HttpExtension};
705705

706706
let mut security = SecurityExtension::default();
707707
security.add_label("PII");
@@ -710,8 +710,8 @@ mod tests {
710710
http.set_header("Authorization", "Bearer tok");
711711

712712
let ext = Extensions {
713-
security: Some(security),
714-
http: Some(Guarded::new(http)),
713+
security: Some(Arc::new(security)),
714+
http: Some(Arc::new(http)),
715715
..Default::default()
716716
};
717717

@@ -768,7 +768,7 @@ mod tests {
768768
fn test_to_dict_with_extensions() {
769769
use std::sync::Arc;
770770
use crate::extensions::{
771-
SecurityExtension, Guarded, HttpExtension, RequestExtension, AgentExtension,
771+
SecurityExtension, HttpExtension, RequestExtension, AgentExtension,
772772
};
773773

774774
let mut security = SecurityExtension::default();
@@ -785,8 +785,8 @@ mod tests {
785785
http.set_header("X-Request-ID", "req-123");
786786

787787
let ext = Extensions {
788-
security: Some(security),
789-
http: Some(Guarded::new(http)),
788+
security: Some(Arc::new(security)),
789+
http: Some(Arc::new(http)),
790790
request: Some(Arc::new(RequestExtension {
791791
environment: Some("production".into()),
792792
..Default::default()

crates/cpex-core/src/executor.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -427,17 +427,17 @@ impl Executor {
427427
if let Some(mp) = erased.modified_payload {
428428
*payload = mp;
429429
}
430-
if let Some(me) = erased.modified_extensions {
430+
if let Some(owned) = erased.modified_extensions {
431431
// Validate tier constraints before accepting
432-
if !extensions.validate_immutable(&me) {
432+
if !extensions.validate_immutable(&owned) {
433433
warn!(
434434
"{} plugin '{}' violated immutable tier — \
435435
modified an immutable extension slot. \
436436
Extension changes rejected.",
437437
phase_label, plugin_name
438438
);
439439
} else if let Some(ref orig_sec) = extensions.security {
440-
if let Some(ref new_sec) = me.security {
440+
if let Some(ref new_sec) = owned.security {
441441
if !new_sec.labels.is_superset(&orig_sec.labels) {
442442
warn!(
443443
"{} plugin '{}' violated monotonic tier — \
@@ -446,13 +446,13 @@ impl Executor {
446446
phase_label, plugin_name
447447
);
448448
} else {
449-
*extensions = me;
449+
extensions.merge_owned(owned);
450450
}
451451
} else {
452-
*extensions = me;
452+
extensions.merge_owned(owned);
453453
}
454454
} else {
455-
*extensions = me;
455+
extensions.merge_owned(owned);
456456
}
457457
}
458458
}
@@ -809,7 +809,7 @@ impl Default for Executor {
809809
pub struct ErasedResultFields {
810810
pub continue_processing: bool,
811811
pub modified_payload: Option<Box<dyn PluginPayload>>,
812-
pub modified_extensions: Option<Extensions>,
812+
pub modified_extensions: Option<crate::hooks::payload::OwnedExtensions>,
813813
pub violation: Option<crate::error::PluginViolation>,
814814
}
815815

@@ -894,10 +894,11 @@ mod tests {
894894
let mut security = crate::extensions::SecurityExtension::default();
895895
security.add_label("PII");
896896
let ext = Extensions {
897-
security: Some(security),
897+
security: Some(Arc::new(security)),
898898
..Default::default()
899899
};
900-
let result: PluginResult<TestPayload> = PluginResult::modify_extensions(ext);
900+
let owned = ext.cow_copy();
901+
let result: PluginResult<TestPayload> = PluginResult::modify_extensions(owned);
901902
let erased = erase_result(result);
902903
let fields = extract_erased(erased).unwrap();
903904
assert!(fields.continue_processing);

0 commit comments

Comments
 (0)