| 23 | |
| 24 | @dataclass(frozen=True, slots=True) |
| 25 | class CompositionPolicy: |
| 26 | tool_offload_threshold_tokens: int = 2400 |
| 27 | semantic_tool_summary_threshold_tokens: int = 1400 |
| 28 | inline_compact_threshold_chars: int = 800 |
| 29 | preview_chars: int = 320 |
| 30 | tail_chars: int = 160 |
| 31 | checkpoint_threshold_tokens: int = 16_000 |
| 32 | checkpoint_agentic_threshold_tokens: int = 32_000 |
| 33 | checkpoint_keep_last_messages: int = 8 |
| 34 | checkpoint_agentic_keep_last_messages: int = 14 |
| 35 | checkpoint_min_messages: int = 14 |
| 36 | checkpoint_skip_recent_tool_window: int = 8 |
| 37 | checkpoint_skip_tool_selection: bool = True |
| 38 | rehydrate_max_artifacts: int = 2 |
| 39 | rehydrate_append_chars: int = 900 |
| 40 | sidechannel: SideChannelConfig = field(default_factory=lambda: DEFAULT_SIDECHANNEL_CONFIG) |
| 41 | |
| 42 | def to_dict(self) -> dict[str, Any]: |
| 43 | return { |
| 44 | "tool_offload_threshold_tokens": self.tool_offload_threshold_tokens, |
| 45 | "semantic_tool_summary_threshold_tokens": self.semantic_tool_summary_threshold_tokens, |
| 46 | "inline_compact_threshold_chars": self.inline_compact_threshold_chars, |
| 47 | "preview_chars": self.preview_chars, |
| 48 | "tail_chars": self.tail_chars, |
| 49 | "checkpoint_threshold_tokens": self.checkpoint_threshold_tokens, |
| 50 | "checkpoint_agentic_threshold_tokens": self.checkpoint_agentic_threshold_tokens, |
| 51 | "checkpoint_keep_last_messages": self.checkpoint_keep_last_messages, |
| 52 | "checkpoint_agentic_keep_last_messages": self.checkpoint_agentic_keep_last_messages, |
| 53 | "checkpoint_min_messages": self.checkpoint_min_messages, |
| 54 | "checkpoint_skip_recent_tool_window": self.checkpoint_skip_recent_tool_window, |
| 55 | "checkpoint_skip_tool_selection": self.checkpoint_skip_tool_selection, |
| 56 | "rehydrate_max_artifacts": self.rehydrate_max_artifacts, |
| 57 | "rehydrate_append_chars": self.rehydrate_append_chars, |
| 58 | "sidechannel": self.sidechannel.to_dict(), |
| 59 | } |
| 60 | |
| 61 | @classmethod |
| 62 | def from_dict( |
| 63 | cls, |
| 64 | data: dict[str, Any] | None, |
| 65 | *, |
| 66 | base: CompositionPolicy | None = None, |
| 67 | ) -> CompositionPolicy: |
| 68 | base = base or cls() |
| 69 | if not data: |
| 70 | return base |
| 71 | policy = cls( |
| 72 | tool_offload_threshold_tokens=int( |
| 73 | data.get("tool_offload_threshold_tokens", base.tool_offload_threshold_tokens), |
| 74 | ), |
| 75 | semantic_tool_summary_threshold_tokens=int( |
| 76 | data.get( |
| 77 | "semantic_tool_summary_threshold_tokens", |
| 78 | base.semantic_tool_summary_threshold_tokens, |
| 79 | ), |
| 80 | ), |
| 81 | inline_compact_threshold_chars=int( |
| 82 | data.get("inline_compact_threshold_chars", base.inline_compact_threshold_chars), |
no outgoing calls