deepstrike_sdk/runtime/
os_profile.rs1use deepstrike_core::runtime::kernel::{
2 ConstraintSpec, KernelInputEvent, PolicyAction, PolicyRule, RateLimitSpec,
3};
4
5use crate::{Error, Result};
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub struct AttentionPolicy {
9 pub max_queue_size: Option<u32>,
10}
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub struct SchedulerBudget {
14 pub max_wall_ms: Option<u64>,
15}
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
18pub struct MemoryWriteRateLimit {
19 pub max_writes: u32,
20 pub window_ms: u64,
21}
22
23impl From<MemoryWriteRateLimit> for (u32, u64) {
24 fn from(limit: MemoryWriteRateLimit) -> Self {
25 (limit.max_writes, limit.window_ms)
26 }
27}
28
29#[derive(Debug, Clone)]
30pub struct GovernancePolicy {
31 pub default_action: Option<PolicyAction>,
32 pub rules: Vec<PolicyRule>,
33 pub vetoed_tools: Vec<String>,
34 pub rate_limits: Vec<RateLimitSpec>,
35 pub constraints: Vec<ConstraintSpec>,
36 pub surface_denied_in_system: bool,
38}
39
40impl GovernancePolicy {
41 pub fn allow_all() -> Self {
42 Self {
43 default_action: None,
44 rules: vec![PolicyRule {
45 tool_pattern: "*".to_string(),
46 action: PolicyAction::Allow,
47 }],
48 vetoed_tools: vec![],
49 rate_limits: vec![],
50 constraints: vec![],
51 surface_denied_in_system: true,
52 }
53 }
54
55 pub fn into_kernel_event(self) -> KernelInputEvent {
56 KernelInputEvent::LoadGovernancePolicy {
57 default_action: self.default_action,
58 rules: self.rules,
59 vetoed_tools: self.vetoed_tools,
60 rate_limits: self.rate_limits,
61 constraints: self.constraints,
62 }
63 }
64}
65
66#[derive(Debug, Clone)]
67pub struct NativeOsProfile {
68 pub id: &'static str,
69 pub attention_policy: AttentionPolicy,
70 pub governance_policy: GovernancePolicy,
71}
72
73#[derive(Debug, Clone)]
74pub enum OsProfile {
75 Native,
76 Concrete(NativeOsProfile),
77}
78
79pub const DEFAULT_NATIVE_ATTENTION_POLICY: AttentionPolicy = AttentionPolicy {
80 max_queue_size: Some(64),
81};
82
83pub fn default_native_governance_policy() -> GovernancePolicy {
84 GovernancePolicy::allow_all()
85}
86
87pub fn governance_filter_schema(
89 tools: &[deepstrike_core::types::message::ToolSchema],
90 policy: &GovernancePolicy,
91) -> (Vec<deepstrike_core::types::message::ToolSchema>, Vec<String>) {
92 let mut allowed = Vec::with_capacity(tools.len());
93 let mut denied = Vec::new();
94 let matches = |pat: &str, name: &str| -> bool {
95 if pat == name {
96 return true;
97 }
98 if let Some(prefix) = pat.strip_suffix('*') {
99 return name.starts_with(prefix);
100 }
101 false
102 };
103 for tool in tools {
104 let name = tool.name.as_str();
105 if policy.vetoed_tools.iter().any(|v| v == name) {
106 denied.push(name.to_string());
107 continue;
108 }
109 let mut action = policy
110 .default_action
111 .clone()
112 .unwrap_or(PolicyAction::Allow);
113 for r in &policy.rules {
114 if matches(&r.tool_pattern, name) {
115 action = r.action.clone();
116 }
117 }
118 if matches!(action, PolicyAction::Deny) {
119 denied.push(name.to_string());
120 } else {
121 allowed.push(tool.clone());
122 }
123 }
124 (allowed, denied)
125}
126
127pub fn os_profile(profile: Option<OsProfile>) -> NativeOsProfile {
128 match profile.unwrap_or(OsProfile::Native) {
129 OsProfile::Native => NativeOsProfile {
130 id: "native",
131 attention_policy: DEFAULT_NATIVE_ATTENTION_POLICY,
132 governance_policy: default_native_governance_policy(),
133 },
134 OsProfile::Concrete(profile) => profile,
135 }
136}
137
138pub fn assert_native_profile(profile: Option<OsProfile>) -> Result<NativeOsProfile> {
139 let resolved = os_profile(profile);
140 if resolved.id != "native" {
141 return Err(Error::Other(format!("Unsupported OS profile: {}", resolved.id)));
142 }
143 if let Some(max_queue_size) = resolved.attention_policy.max_queue_size {
144 if max_queue_size == 0 {
145 return Err(Error::Other(
146 "Invalid native OS profile: AttentionPolicy max_queue_size must be positive"
147 .to_string(),
148 ));
149 }
150 }
151 Ok(resolved)
152}