loopsmith_core/config/
constraints.rs1use serde::{Deserialize, Serialize};
4use std::collections::BTreeMap;
5
6#[derive(Debug, Clone, Serialize, Deserialize, Default)]
7#[serde(deny_unknown_fields)]
8pub struct Constraints {
9 #[serde(default)]
11 pub global: ConstraintSet,
12 #[serde(default)]
14 pub per_node: BTreeMap<String, ConstraintSet>,
15}
16
17#[derive(Debug, Clone, Serialize, Deserialize, Default)]
18#[serde(deny_unknown_fields)]
19pub struct ConstraintSet {
20 #[serde(default)]
22 pub rules: Vec<String>,
23 #[serde(default)]
24 pub forbidden_paths: Vec<String>,
25 #[serde(default)]
26 pub forbidden_commands: Vec<String>,
27 #[serde(default)]
28 pub max_tokens: Option<u64>,
29 #[serde(default)]
30 pub max_seconds: Option<u64>,
31 #[serde(default)]
34 pub human_checkpoint: Vec<String>,
35}
36
37impl ConstraintSet {
38 pub fn frozen_git_rules() -> Vec<String> {
41 vec![
42 "Never git stash. Never git reset.".into(),
43 "No git command except committing a specific file.".into(),
44 "No slow commands before the test phase.".into(),
45 ]
46 }
47
48 pub fn merged(global: &ConstraintSet, node: Option<&ConstraintSet>) -> ConstraintSet {
51 let mut out = global.clone();
52 if let Some(n) = node {
53 out.rules.extend(n.rules.iter().cloned());
54 out.forbidden_paths.extend(n.forbidden_paths.iter().cloned());
55 out.forbidden_commands
56 .extend(n.forbidden_commands.iter().cloned());
57 out.human_checkpoint
58 .extend(n.human_checkpoint.iter().cloned());
59 if n.max_tokens.is_some() {
60 out.max_tokens = n.max_tokens;
61 }
62 if n.max_seconds.is_some() {
63 out.max_seconds = n.max_seconds;
64 }
65 }
66 out
67 }
68}