kweaver-dolphin 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. DolphinLanguageSDK/__init__.py +58 -0
  2. dolphin/__init__.py +62 -0
  3. dolphin/cli/__init__.py +20 -0
  4. dolphin/cli/args/__init__.py +9 -0
  5. dolphin/cli/args/parser.py +567 -0
  6. dolphin/cli/builtin_agents/__init__.py +22 -0
  7. dolphin/cli/commands/__init__.py +4 -0
  8. dolphin/cli/interrupt/__init__.py +8 -0
  9. dolphin/cli/interrupt/handler.py +205 -0
  10. dolphin/cli/interrupt/keyboard.py +82 -0
  11. dolphin/cli/main.py +49 -0
  12. dolphin/cli/multimodal/__init__.py +34 -0
  13. dolphin/cli/multimodal/clipboard.py +327 -0
  14. dolphin/cli/multimodal/handler.py +249 -0
  15. dolphin/cli/multimodal/image_processor.py +214 -0
  16. dolphin/cli/multimodal/input_parser.py +149 -0
  17. dolphin/cli/runner/__init__.py +8 -0
  18. dolphin/cli/runner/runner.py +989 -0
  19. dolphin/cli/ui/__init__.py +10 -0
  20. dolphin/cli/ui/console.py +2795 -0
  21. dolphin/cli/ui/input.py +340 -0
  22. dolphin/cli/ui/layout.py +425 -0
  23. dolphin/cli/ui/stream_renderer.py +302 -0
  24. dolphin/cli/utils/__init__.py +8 -0
  25. dolphin/cli/utils/helpers.py +135 -0
  26. dolphin/cli/utils/version.py +49 -0
  27. dolphin/core/__init__.py +107 -0
  28. dolphin/core/agent/__init__.py +10 -0
  29. dolphin/core/agent/agent_state.py +69 -0
  30. dolphin/core/agent/base_agent.py +970 -0
  31. dolphin/core/code_block/__init__.py +0 -0
  32. dolphin/core/code_block/agent_init_block.py +0 -0
  33. dolphin/core/code_block/assign_block.py +98 -0
  34. dolphin/core/code_block/basic_code_block.py +1865 -0
  35. dolphin/core/code_block/explore_block.py +1327 -0
  36. dolphin/core/code_block/explore_block_v2.py +712 -0
  37. dolphin/core/code_block/explore_strategy.py +672 -0
  38. dolphin/core/code_block/judge_block.py +220 -0
  39. dolphin/core/code_block/prompt_block.py +32 -0
  40. dolphin/core/code_block/skill_call_deduplicator.py +291 -0
  41. dolphin/core/code_block/tool_block.py +129 -0
  42. dolphin/core/common/__init__.py +17 -0
  43. dolphin/core/common/constants.py +176 -0
  44. dolphin/core/common/enums.py +1173 -0
  45. dolphin/core/common/exceptions.py +133 -0
  46. dolphin/core/common/multimodal.py +539 -0
  47. dolphin/core/common/object_type.py +165 -0
  48. dolphin/core/common/output_format.py +432 -0
  49. dolphin/core/common/types.py +36 -0
  50. dolphin/core/config/__init__.py +16 -0
  51. dolphin/core/config/global_config.py +1289 -0
  52. dolphin/core/config/ontology_config.py +133 -0
  53. dolphin/core/context/__init__.py +12 -0
  54. dolphin/core/context/context.py +1580 -0
  55. dolphin/core/context/context_manager.py +161 -0
  56. dolphin/core/context/var_output.py +82 -0
  57. dolphin/core/context/variable_pool.py +356 -0
  58. dolphin/core/context_engineer/__init__.py +41 -0
  59. dolphin/core/context_engineer/config/__init__.py +5 -0
  60. dolphin/core/context_engineer/config/settings.py +402 -0
  61. dolphin/core/context_engineer/core/__init__.py +7 -0
  62. dolphin/core/context_engineer/core/budget_manager.py +327 -0
  63. dolphin/core/context_engineer/core/context_assembler.py +583 -0
  64. dolphin/core/context_engineer/core/context_manager.py +637 -0
  65. dolphin/core/context_engineer/core/tokenizer_service.py +260 -0
  66. dolphin/core/context_engineer/example/incremental_example.py +267 -0
  67. dolphin/core/context_engineer/example/traditional_example.py +334 -0
  68. dolphin/core/context_engineer/services/__init__.py +5 -0
  69. dolphin/core/context_engineer/services/compressor.py +399 -0
  70. dolphin/core/context_engineer/utils/__init__.py +6 -0
  71. dolphin/core/context_engineer/utils/context_utils.py +441 -0
  72. dolphin/core/context_engineer/utils/message_formatter.py +270 -0
  73. dolphin/core/context_engineer/utils/token_utils.py +139 -0
  74. dolphin/core/coroutine/__init__.py +15 -0
  75. dolphin/core/coroutine/context_snapshot.py +154 -0
  76. dolphin/core/coroutine/context_snapshot_profile.py +922 -0
  77. dolphin/core/coroutine/context_snapshot_store.py +268 -0
  78. dolphin/core/coroutine/execution_frame.py +145 -0
  79. dolphin/core/coroutine/execution_state_registry.py +161 -0
  80. dolphin/core/coroutine/resume_handle.py +101 -0
  81. dolphin/core/coroutine/step_result.py +101 -0
  82. dolphin/core/executor/__init__.py +18 -0
  83. dolphin/core/executor/debug_controller.py +630 -0
  84. dolphin/core/executor/dolphin_executor.py +1063 -0
  85. dolphin/core/executor/executor.py +624 -0
  86. dolphin/core/flags/__init__.py +27 -0
  87. dolphin/core/flags/definitions.py +49 -0
  88. dolphin/core/flags/manager.py +113 -0
  89. dolphin/core/hook/__init__.py +95 -0
  90. dolphin/core/hook/expression_evaluator.py +499 -0
  91. dolphin/core/hook/hook_dispatcher.py +380 -0
  92. dolphin/core/hook/hook_types.py +248 -0
  93. dolphin/core/hook/isolated_variable_pool.py +284 -0
  94. dolphin/core/interfaces.py +53 -0
  95. dolphin/core/llm/__init__.py +0 -0
  96. dolphin/core/llm/llm.py +495 -0
  97. dolphin/core/llm/llm_call.py +100 -0
  98. dolphin/core/llm/llm_client.py +1285 -0
  99. dolphin/core/llm/message_sanitizer.py +120 -0
  100. dolphin/core/logging/__init__.py +20 -0
  101. dolphin/core/logging/logger.py +526 -0
  102. dolphin/core/message/__init__.py +8 -0
  103. dolphin/core/message/compressor.py +749 -0
  104. dolphin/core/parser/__init__.py +8 -0
  105. dolphin/core/parser/parser.py +405 -0
  106. dolphin/core/runtime/__init__.py +10 -0
  107. dolphin/core/runtime/runtime_graph.py +926 -0
  108. dolphin/core/runtime/runtime_instance.py +446 -0
  109. dolphin/core/skill/__init__.py +14 -0
  110. dolphin/core/skill/context_retention.py +157 -0
  111. dolphin/core/skill/skill_function.py +686 -0
  112. dolphin/core/skill/skill_matcher.py +282 -0
  113. dolphin/core/skill/skillkit.py +700 -0
  114. dolphin/core/skill/skillset.py +72 -0
  115. dolphin/core/trajectory/__init__.py +10 -0
  116. dolphin/core/trajectory/recorder.py +189 -0
  117. dolphin/core/trajectory/trajectory.py +522 -0
  118. dolphin/core/utils/__init__.py +9 -0
  119. dolphin/core/utils/cache_kv.py +212 -0
  120. dolphin/core/utils/tools.py +340 -0
  121. dolphin/lib/__init__.py +93 -0
  122. dolphin/lib/debug/__init__.py +8 -0
  123. dolphin/lib/debug/visualizer.py +409 -0
  124. dolphin/lib/memory/__init__.py +28 -0
  125. dolphin/lib/memory/async_processor.py +220 -0
  126. dolphin/lib/memory/llm_calls.py +195 -0
  127. dolphin/lib/memory/manager.py +78 -0
  128. dolphin/lib/memory/sandbox.py +46 -0
  129. dolphin/lib/memory/storage.py +245 -0
  130. dolphin/lib/memory/utils.py +51 -0
  131. dolphin/lib/ontology/__init__.py +12 -0
  132. dolphin/lib/ontology/basic/__init__.py +0 -0
  133. dolphin/lib/ontology/basic/base.py +102 -0
  134. dolphin/lib/ontology/basic/concept.py +130 -0
  135. dolphin/lib/ontology/basic/object.py +11 -0
  136. dolphin/lib/ontology/basic/relation.py +63 -0
  137. dolphin/lib/ontology/datasource/__init__.py +27 -0
  138. dolphin/lib/ontology/datasource/datasource.py +66 -0
  139. dolphin/lib/ontology/datasource/oracle_datasource.py +338 -0
  140. dolphin/lib/ontology/datasource/sql.py +845 -0
  141. dolphin/lib/ontology/mapping.py +177 -0
  142. dolphin/lib/ontology/ontology.py +733 -0
  143. dolphin/lib/ontology/ontology_context.py +16 -0
  144. dolphin/lib/ontology/ontology_manager.py +107 -0
  145. dolphin/lib/skill_results/__init__.py +31 -0
  146. dolphin/lib/skill_results/cache_backend.py +559 -0
  147. dolphin/lib/skill_results/result_processor.py +181 -0
  148. dolphin/lib/skill_results/result_reference.py +179 -0
  149. dolphin/lib/skill_results/skillkit_hook.py +324 -0
  150. dolphin/lib/skill_results/strategies.py +328 -0
  151. dolphin/lib/skill_results/strategy_registry.py +150 -0
  152. dolphin/lib/skillkits/__init__.py +44 -0
  153. dolphin/lib/skillkits/agent_skillkit.py +155 -0
  154. dolphin/lib/skillkits/cognitive_skillkit.py +82 -0
  155. dolphin/lib/skillkits/env_skillkit.py +250 -0
  156. dolphin/lib/skillkits/mcp_adapter.py +616 -0
  157. dolphin/lib/skillkits/mcp_skillkit.py +771 -0
  158. dolphin/lib/skillkits/memory_skillkit.py +650 -0
  159. dolphin/lib/skillkits/noop_skillkit.py +31 -0
  160. dolphin/lib/skillkits/ontology_skillkit.py +89 -0
  161. dolphin/lib/skillkits/plan_act_skillkit.py +452 -0
  162. dolphin/lib/skillkits/resource/__init__.py +52 -0
  163. dolphin/lib/skillkits/resource/models/__init__.py +6 -0
  164. dolphin/lib/skillkits/resource/models/skill_config.py +109 -0
  165. dolphin/lib/skillkits/resource/models/skill_meta.py +127 -0
  166. dolphin/lib/skillkits/resource/resource_skillkit.py +393 -0
  167. dolphin/lib/skillkits/resource/skill_cache.py +215 -0
  168. dolphin/lib/skillkits/resource/skill_loader.py +395 -0
  169. dolphin/lib/skillkits/resource/skill_validator.py +406 -0
  170. dolphin/lib/skillkits/resource_skillkit.py +11 -0
  171. dolphin/lib/skillkits/search_skillkit.py +163 -0
  172. dolphin/lib/skillkits/sql_skillkit.py +274 -0
  173. dolphin/lib/skillkits/system_skillkit.py +509 -0
  174. dolphin/lib/skillkits/vm_skillkit.py +65 -0
  175. dolphin/lib/utils/__init__.py +9 -0
  176. dolphin/lib/utils/data_process.py +207 -0
  177. dolphin/lib/utils/handle_progress.py +178 -0
  178. dolphin/lib/utils/security.py +139 -0
  179. dolphin/lib/utils/text_retrieval.py +462 -0
  180. dolphin/lib/vm/__init__.py +11 -0
  181. dolphin/lib/vm/env_executor.py +895 -0
  182. dolphin/lib/vm/python_session_manager.py +453 -0
  183. dolphin/lib/vm/vm.py +610 -0
  184. dolphin/sdk/__init__.py +60 -0
  185. dolphin/sdk/agent/__init__.py +12 -0
  186. dolphin/sdk/agent/agent_factory.py +236 -0
  187. dolphin/sdk/agent/dolphin_agent.py +1106 -0
  188. dolphin/sdk/api/__init__.py +4 -0
  189. dolphin/sdk/runtime/__init__.py +8 -0
  190. dolphin/sdk/runtime/env.py +363 -0
  191. dolphin/sdk/skill/__init__.py +10 -0
  192. dolphin/sdk/skill/global_skills.py +706 -0
  193. dolphin/sdk/skill/traditional_toolkit.py +260 -0
  194. kweaver_dolphin-0.1.0.dist-info/METADATA +521 -0
  195. kweaver_dolphin-0.1.0.dist-info/RECORD +199 -0
  196. kweaver_dolphin-0.1.0.dist-info/WHEEL +5 -0
  197. kweaver_dolphin-0.1.0.dist-info/entry_points.txt +27 -0
  198. kweaver_dolphin-0.1.0.dist-info/licenses/LICENSE.txt +201 -0
  199. kweaver_dolphin-0.1.0.dist-info/top_level.txt +2 -0
@@ -0,0 +1,161 @@
1
+ """
2
+ Context Manager module for backward compatibility.
3
+
4
+ This module provides the ContextEngineer class which is an alias/wrapper
5
+ around MessageCompressor for SDK compatibility.
6
+
7
+ Note: The compression strategies (TruncationStrategy, SlidingWindowStrategy,
8
+ LevelStrategy) are now defined in dolphin.core.message.compressor.
9
+ """
10
+
11
+ from typing import List, Dict, Optional, TYPE_CHECKING
12
+
13
+ from dolphin.core.common.enums import Messages
14
+ from dolphin.core.config.global_config import ContextEngineerConfig
15
+
16
+ # Import compression classes from the canonical location
17
+ from dolphin.core.message.compressor import (
18
+ CompressionResult,
19
+ CompressionStrategy,
20
+ TruncationStrategy,
21
+ SlidingWindowStrategy,
22
+ LevelStrategy,
23
+ )
24
+
25
+ if TYPE_CHECKING:
26
+ from dolphin.core.config.global_config import (
27
+ ContextConstraints,
28
+ LLMInstanceConfig,
29
+ )
30
+ from dolphin.core.context.context import Context
31
+
32
+ from dolphin.core.logging.logger import get_logger
33
+
34
+ logger = get_logger("context_engineer")
35
+
36
+
37
+ # Re-export for backward compatibility
38
+ __all__ = [
39
+ "CompressionResult",
40
+ "CompressionStrategy",
41
+ "TruncationStrategy",
42
+ "SlidingWindowStrategy",
43
+ "LevelStrategy",
44
+ "ContextEngineer",
45
+ ]
46
+
47
+
48
+ class ContextEngineer:
49
+ """Context Engineer: Responsible for optimizing message context to meet model constraints.
50
+
51
+ This class is maintained for backward compatibility with the SDK.
52
+ New code should use MessageCompressor from dolphin.core.message.compressor instead.
53
+ """
54
+
55
+ def __init__(self, config: "ContextEngineerConfig" = None, context: "Context" = None):
56
+ self.config = config or ContextEngineerConfig()
57
+ self.context = context
58
+ self.strategies = self._register_default_strategies()
59
+ logger.debug(
60
+ f"ContextEngineer initialized with strategy: {self.config.default_strategy}"
61
+ )
62
+
63
+ def _register_default_strategies(self) -> Dict[str, CompressionStrategy]:
64
+ """Register default compression strategy"""
65
+ strategies = {
66
+ "level": LevelStrategy(),
67
+ "truncation": TruncationStrategy(),
68
+ "sliding_window_5": SlidingWindowStrategy(5),
69
+ "sliding_window_10": SlidingWindowStrategy(10),
70
+ "sliding_window_20": SlidingWindowStrategy(20),
71
+ }
72
+ # Merge user-defined policy configurations
73
+ for name, strategy_config in self.config.strategy_configs.items():
74
+ # Here, corresponding strategy instances can be created based on strategy_config
75
+ # Skip temporarily, keep extension interface
76
+ pass
77
+ return strategies
78
+
79
+ def engineer_context(
80
+ self,
81
+ messages: Messages,
82
+ strategy_name: Optional[str] = None,
83
+ constraints: Optional["ContextConstraints"] = None,
84
+ model_config: Optional["LLMInstanceConfig"] = None,
85
+ **kwargs,
86
+ ) -> CompressionResult:
87
+ """Engineering processing of context
88
+
89
+ Args:
90
+ messages: List of original messages
91
+ strategy_name: Name of the compression strategy to use, default uses the default strategy from configuration
92
+ constraints: Compression constraints, default uses constraints from configuration
93
+ model_config: Model configuration, used to automatically adjust constraints
94
+
95
+ Returns:
96
+ CompressionResult: Compression result
97
+ """
98
+ # Select Strategy
99
+ strategy_name = strategy_name or self.config.default_strategy
100
+ if strategy_name not in self.strategies:
101
+ logger.warning(f"Strategy '{strategy_name}' not found, using 'truncation'")
102
+ strategy_name = "truncation"
103
+ if strategy_name not in self.strategies:
104
+ # If there is no truncation at all, create a default one.
105
+ self.strategies["truncation"] = TruncationStrategy()
106
+
107
+ strategy = self.strategies[strategy_name]
108
+
109
+ # Select constraint conditions; if model_config is provided, adjust constraints according to model capabilities.
110
+ if constraints is None:
111
+ constraints = self.config.constraints
112
+
113
+ # Automatically adjust constraints according to model_config
114
+ if model_config is not None:
115
+ from dolphin.core.config.global_config import ContextConstraints
116
+
117
+ # Dynamically create constraints suitable for the current model
118
+ adjusted_constraints = ContextConstraints(
119
+ max_input_tokens=constraints.max_input_tokens,
120
+ reserve_output_tokens=model_config.max_tokens, # Use the model's max_tokens as reserved output
121
+ preserve_system=constraints.preserve_system,
122
+ )
123
+ constraints = adjusted_constraints
124
+
125
+ logger.debug(
126
+ f"Adjusted constraints for model {model_config.model_name}: "
127
+ f"max_input={constraints.max_input_tokens}, "
128
+ f"reserve_output={constraints.reserve_output_tokens}"
129
+ )
130
+
131
+ # Perform compression
132
+ result = strategy.compress(
133
+ context=self.context, messages=messages, constraints=constraints, **kwargs
134
+ )
135
+
136
+ # Log records
137
+ if result.compression_ratio < 1.0:
138
+ self.context.info(
139
+ f"Context compressed using {strategy_name}: "
140
+ f"{result.original_token_count} -> {result.compressed_token_count} tokens "
141
+ f"(ratio: {result.compression_ratio:.2f})"
142
+ )
143
+
144
+ return result
145
+
146
+ def register_strategy(self, name: str, strategy: CompressionStrategy):
147
+ """Register a new compression strategy"""
148
+ self.strategies[name] = strategy
149
+ logger.debug(f"Registered new compression strategy: {name}")
150
+
151
+ def get_available_strategies(self) -> List[str]:
152
+ """Get the list of available compression strategies"""
153
+ return list(self.strategies.keys())
154
+
155
+ def estimate_tokens(self, messages: Messages) -> int:
156
+ """Estimate the number of tokens in a message"""
157
+ # Token estimation method using default strategy
158
+ default_strategy = self.strategies.get(
159
+ self.config.default_strategy, TruncationStrategy()
160
+ )
161
+ return default_strategy.estimate_tokens(messages)
@@ -0,0 +1,82 @@
1
+ from dolphin.core.common.types import SourceType, Var
2
+ from dolphin.core.common.enums import SkillInfo
3
+
4
+
5
+ class VarOutput(Var):
6
+ def __init__(self, name, value, source_type=SourceType.OTHER, skill_info=None):
7
+ super().__init__(value)
8
+
9
+ self.name = name
10
+ self.source_type = source_type
11
+ self.skill_info = skill_info
12
+
13
+ def add(self, var: Var):
14
+ if self.source_type == SourceType.LIST:
15
+ self.val.append(var)
16
+ return self
17
+
18
+ return VarOutput(name=self.name, value=[self, var], source_type=SourceType.LIST)
19
+
20
+ def set_last(self, var: Var):
21
+ if self.source_type == SourceType.LIST:
22
+ self.val[-1] = var
23
+ return self
24
+
25
+ def to_dict(self):
26
+ # Processing the serialization of value
27
+ if self.source_type == SourceType.LIST:
28
+ # LIST type: recursively serialize each VarOutput item
29
+ value = [item.to_dict() for item in self.val]
30
+ elif self.source_type == SourceType.EXPLORE:
31
+ # EXPLORE type: value is already a list of dictionaries, use directly
32
+ value = self.val
33
+ else:
34
+ value = self.val
35
+
36
+ return {
37
+ "__type__": "VarOutput", # Type identifier for deserialization
38
+ "name": self.name,
39
+ "value": value,
40
+ "source_type": self.source_type.value,
41
+ "skill_info": self.skill_info.to_dict() if self.skill_info else {},
42
+ }
43
+
44
+ @staticmethod
45
+ def is_serialized_dict(data) -> bool:
46
+ """Check if data is a serialized VarOutput dictionary"""
47
+ return isinstance(data, dict) and data.get("__type__") == "VarOutput"
48
+
49
+ @staticmethod
50
+ def from_dict(dict_data: dict) -> "VarOutput":
51
+ source_type = SourceType(dict_data.get("source_type"))
52
+ if source_type == SourceType.LIST:
53
+ # LIST type: recursively deserialize each VarOutput item
54
+ value = [VarOutput.from_dict(item) for item in dict_data["value"]]
55
+ elif source_type == SourceType.EXPLORE:
56
+ # EXPLORE type: value is a regular dictionary list (exploration results), no recursive deserialization needed
57
+ value = dict_data["value"]
58
+ else:
59
+ value = dict_data["value"]
60
+
61
+ return VarOutput(
62
+ name=dict_data["name"],
63
+ value=value,
64
+ source_type=source_type,
65
+ skill_info=(
66
+ SkillInfo.from_dict(dict_data["skill_info"])
67
+ if dict_data["skill_info"]
68
+ else None
69
+ ),
70
+ )
71
+
72
+ @property
73
+ def value(self):
74
+ if self.source_type == SourceType.LIST:
75
+ return [item.value for item in self.val]
76
+ return self.val
77
+
78
+ def __str__(self):
79
+ return f"{self.name}: {self.val}"
80
+
81
+ def __repr__(self):
82
+ return self.__str__()
@@ -0,0 +1,356 @@
1
+ """Dolphin Language SDK - Variable Pool Module
2
+
3
+ Variable Classification Description:
4
+ ==============
5
+
6
+ 1. User Variables
7
+ - Variables defined by user scripts
8
+ - Returned when retrieved via the get_user_variables() method
9
+ - Example: result, user_input, calculation, etc.
10
+
11
+ 2. Internal Variables
12
+ - Automatically recognized: All variables starting with an underscore (_) are automatically treated as internal variables
13
+ - Special internal variables: props, usage
14
+ - Automatically excluded when retrieved via the get_user_variables() method
15
+
16
+ List of internal variables:
17
+ - _progress: Execution progress details
18
+ - _user_id: User ID (optionally included)
19
+ - _session_id: Session ID (optionally included)
20
+ - _max_answer_len: Maximum answer length (optionally included)
21
+ - _status: Current execution status
22
+ - _previous_status: Previous execution status
23
+ - props: Execution properties
24
+ - usage: Usage statistics
25
+
26
+ Methods to retrieve variables:
27
+ - get_user_variables(): Get user variables, excluding all internal variables
28
+ - get_user_variables(include_system_context_vars=True): Get user variables, including system context variables
29
+ - get_all_variables(): Get all variables (including internal variables)
30
+ """
31
+
32
+ import re
33
+
34
+ from dolphin.core.common.constants import KEY_STATUS, KEY_PREVIOUS_STATUS
35
+ from dolphin.core.common.types import SourceType, Var
36
+ from dolphin.core.context.var_output import VarOutput
37
+
38
+
39
+ class VariablePool:
40
+ def __init__(self):
41
+ self.variable_pool = {}
42
+
43
+ def copy(self):
44
+ new_variable_pool = VariablePool()
45
+ new_variable_pool.variable_pool = self.variable_pool.copy()
46
+ return new_variable_pool
47
+
48
+ def init_variables(self, variables):
49
+ self.variable_pool = {name: Var(value) for name, value in variables.items()}
50
+
51
+ def contain_var(self, name):
52
+ return name in self.variable_pool
53
+
54
+ def get_var(self, name):
55
+ return self.variable_pool.get(name)
56
+
57
+ def get_var_value(self, name, default_value=None):
58
+ var = self.variable_pool.get(name)
59
+ if not var:
60
+ return default_value
61
+
62
+ val = var.value
63
+ # Compatibility with dictionary structure after restoration from snapshot (VarOutput.to_dict format)
64
+ if isinstance(val, dict) and "value" in val and "source_type" in val:
65
+ inner = val.get("value")
66
+ # List scenario: extract the value of each element
67
+ if isinstance(inner, list):
68
+ return [
69
+ (
70
+ item.get("value")
71
+ if isinstance(item, dict) and "value" in item
72
+ else item
73
+ )
74
+ for item in inner
75
+ ]
76
+ # Normal scenario: return the value field directly
77
+ return inner
78
+
79
+ return val
80
+
81
+ def get_var_path_value(self, varpath, default_value=None):
82
+ """
83
+ Get value from variable pool using dot notation path
84
+ Example: get_var_path_value('user.profile.name')
85
+ :param varpath: Variable path with dot notation
86
+ :return: Value at the specified path
87
+ :raises: AttributeError if variable or path not found
88
+ """
89
+ if not varpath:
90
+ return default_value
91
+
92
+ parts = varpath.split(".")
93
+ base_var = parts[0]
94
+
95
+ # Get base variable
96
+ var = self.get_var(base_var)
97
+ if var is None:
98
+ return default_value
99
+
100
+ value = var.value
101
+
102
+ # Navigate through the path
103
+ for part in parts[1:]:
104
+ if isinstance(value, dict):
105
+ if part not in value:
106
+ return default_value
107
+ value = value[part]
108
+ else:
109
+ return default_value
110
+
111
+ return value
112
+
113
+ def get_all_variables(self):
114
+ return {name: var.to_dict() for name, var in self.variable_pool.items()}
115
+
116
+ def get_user_variables(self, include_system_context_vars=False):
117
+ """Get user-defined variables, excluding internal variables.
118
+
119
+ Args:
120
+ include_system_context_vars: Whether to include system context variables (e.g., _user_id, _session_id, etc.)
121
+ Default is False for backward compatibility
122
+
123
+ Internal variable rules:
124
+ - All variables starting with an underscore (_) are automatically considered internal variables (unless explicitly included)
125
+ - Special internal variables: props, usage
126
+
127
+ If include_system_context_vars=True, the following system context variables will be included:
128
+ - _user_id: User ID
129
+ - _session_id: Session ID
130
+ - _max_answer_len: Maximum answer length
131
+ """
132
+ # Automatically recognize all variables starting with an underscore as built-in variables
133
+ underscore_vars = {
134
+ name for name in self.variable_pool.keys() if name.startswith("_")
135
+ }
136
+
137
+ # Extra internal variables (not starting with underscore)
138
+ additional_internal_vars = {"props", KEY_PREVIOUS_STATUS, KEY_STATUS, "usage"}
139
+
140
+ # System context variables (if requested by the user, these variables are not excluded)
141
+ system_context_vars = {"_user_id", "_session_id", "_max_answer_len"}
142
+
143
+ # Set of variables that need to be excluded in the end
144
+ if include_system_context_vars:
145
+ # Include system context variables: exclude all variables starting with underscores and additional internal variables, except for system context variables
146
+ internal_vars = (
147
+ underscore_vars - system_context_vars
148
+ ) | additional_internal_vars
149
+ else:
150
+ # Default behavior: exclude all underscore variables and additional internal variables
151
+ internal_vars = underscore_vars | additional_internal_vars
152
+
153
+ return {
154
+ name: var.to_dict()
155
+ for name, var in self.variable_pool.items()
156
+ if name not in internal_vars
157
+ }
158
+
159
+ def get_all_variables_values(self):
160
+ result = {}
161
+ for name, var in self.variable_pool.items():
162
+ val = var.value
163
+ if isinstance(val, dict) and "value" in val and "source_type" in val:
164
+ inner = val.get("value")
165
+ if isinstance(inner, list):
166
+ result[name] = [
167
+ (
168
+ item.get("value")
169
+ if isinstance(item, dict) and "value" in item
170
+ else item
171
+ )
172
+ for item in inner
173
+ ]
174
+ else:
175
+ result[name] = inner
176
+ else:
177
+ result[name] = val
178
+ return result
179
+
180
+ def keys(self):
181
+ return self.variable_pool.keys()
182
+
183
+ def set_var(self, name, value):
184
+ if isinstance(value, Var):
185
+ self.variable_pool[name] = value
186
+ else:
187
+ self.variable_pool[name] = Var(value)
188
+
189
+ def set_var_output(
190
+ self, name, value, source_type=SourceType.OTHER, skill_info=None
191
+ ):
192
+ # Create VarOutput with all parameters
193
+ self.variable_pool[name] = VarOutput(name, value, source_type, skill_info)
194
+
195
+ def delete_var(self, name):
196
+ if name in self.variable_pool:
197
+ del self.variable_pool[name]
198
+
199
+ def sync_variables(self, variable_pool: "VariablePool"):
200
+ for name, var in variable_pool.variable_pool.items():
201
+ self.variable_pool[name] = var
202
+
203
+ def clear(self):
204
+ self.variable_pool.clear()
205
+
206
+ def get_variable_type(self, variable_str):
207
+ """Get variable value from string, including simple variables, array indices, and nested attributes
208
+ :param variable_str: Variable string, for example '$var', '$arr[0]', '$obj.attr'
209
+ :return: Variable value
210
+ """
211
+ variable_name = variable_str[1:]
212
+ variable_name = convert_object_to_dict_access(variable_name)
213
+ if "." not in variable_str and "[" not in variable_str:
214
+ var = self.get_var(variable_name)
215
+ if var is None:
216
+ raise AttributeError(
217
+ f"Variable '{variable_name}' not found in variable pool"
218
+ )
219
+ value = var.value
220
+ else:
221
+ while "[0" in variable_name and "[0]" not in variable_name:
222
+ variable_name = variable_name.replace("[0", "[")
223
+
224
+ variable_first_name = (
225
+ variable_name.split(".")[0].strip().split("[")[0].strip()
226
+ )
227
+ var = self.get_var(variable_first_name)
228
+ if var is None:
229
+ raise AttributeError(
230
+ f"Variable '{variable_first_name}' not found in variable pool"
231
+ )
232
+ variable_value = var.value
233
+ variable_full_index = variable_name.replace(
234
+ variable_first_name, str(variable_value), 1
235
+ )
236
+ try:
237
+ value = eval(variable_full_index)
238
+ except Exception:
239
+ raise AttributeError(f"failed to eval '{variable_full_index}'")
240
+
241
+ if (
242
+ isinstance(value, list)
243
+ and len(value) > 0
244
+ and isinstance(value[0], dict)
245
+ and "agent_name" in value[0]
246
+ ):
247
+ result = ""
248
+ for item in value:
249
+ if (
250
+ isinstance(item, dict)
251
+ and item.get("agent_name") == "main"
252
+ and "answer" in item
253
+ ):
254
+ result += item["answer"]
255
+ value = result
256
+ return value
257
+
258
+ @staticmethod
259
+ def find_substring_positions(main_string, substring):
260
+ positions = []
261
+ start = 0
262
+
263
+ while True:
264
+ # Find the position of a substring
265
+ pos = main_string.find(substring, start)
266
+ if pos == -1:
267
+ break
268
+ positions.append(pos)
269
+ # Update the starting position to avoid infinite loops
270
+ start = pos + 1
271
+ return positions
272
+
273
+ def recognize_variable(self, dolphin_str):
274
+ # Identify the positions of all variables in the string - Simple variables: `$variableName` - Array indices: `$variableName[index]` - Nested properties: `$variableName.key1.key2`
275
+ """Identify the positions of all variables in a string
276
+ :param dolphin_str: The string to be identified
277
+ :return: A list of tuples containing variable names and their positions [('variable name', (start position, end position)), ...]
278
+ """
279
+ prompt_variable_pattern = re.compile(
280
+ r"\$[a-zA-Z_][a-zA-Z0-9_]*(?:(?:\.[a-zA-Z_][a-zA-Z0-9_]*)|(?:\[\d+\]))*"
281
+ )
282
+ matches = prompt_variable_pattern.findall(dolphin_str)
283
+
284
+ result = []
285
+
286
+ # Sort by length, with the longest variable names first
287
+ matches.sort(key=len, reverse=True)
288
+
289
+ # Record processed positions to avoid overlap
290
+ processed_positions = set()
291
+
292
+ for match in matches:
293
+ index_list = VariablePool.find_substring_positions(dolphin_str, match)
294
+
295
+ for start_pos in index_list:
296
+ end_pos = start_pos + len(match)
297
+
298
+ # Check whether this position has already been processed
299
+ if any(
300
+ start_pos >= existing_start and end_pos <= existing_end
301
+ for existing_start, existing_end in processed_positions
302
+ ):
303
+ continue
304
+
305
+ # Check whether a variable exists in the variable pool
306
+ variable_base_name = match[1:].split(".")[0].split("[")[0].strip()
307
+ if variable_base_name in self.variable_pool.keys():
308
+ result.append((match, (start_pos, end_pos)))
309
+ processed_positions.add((start_pos, end_pos))
310
+
311
+ return result
312
+
313
+
314
+ def convert_object_to_dict_access(access_str):
315
+ """
316
+ Convert object attribute access to dictionary access format
317
+ Example: "result.text[0].content[0].answer" -> "result['text'][0]['content'][0]['answer']"
318
+ """
319
+ parts = []
320
+ current = ""
321
+ i = 0
322
+ while i < len(access_str):
323
+ if access_str[i] == ".":
324
+ if current:
325
+ parts.append(current)
326
+ current = ""
327
+ i += 1
328
+ elif access_str[i] == "[":
329
+ if current:
330
+ parts.append(current)
331
+ current = ""
332
+ # Find matching closing bracket
333
+ bracket_count = 1
334
+ j = i + 1
335
+ while j < len(access_str) and bracket_count > 0:
336
+ if access_str[j] == "[":
337
+ bracket_count += 1
338
+ elif access_str[j] == "]":
339
+ bracket_count -= 1
340
+ j += 1
341
+ parts.append(access_str[i:j])
342
+ i = j
343
+ else:
344
+ current += access_str[i]
345
+ i += 1
346
+ if current:
347
+ parts.append(current)
348
+
349
+ result = parts[0]
350
+ for i, part in enumerate(parts[1:], 1):
351
+ if part.startswith("["):
352
+ result += part
353
+ else:
354
+ result += f"['{part}']"
355
+
356
+ return result
@@ -0,0 +1,41 @@
1
+ """
2
+ ContextEngineer: A system for optimizing context management in large language models.
3
+
4
+ This package provides tools for token budgeting, context optimization, and dynamic
5
+ information retrieval to maximize signal density while minimizing noise in LLM contexts.
6
+ """
7
+
8
+ __version__ = "0.1.0"
9
+ __author__ = "ContextEngineer Team"
10
+
11
+ from .core.budget_manager import BudgetManager
12
+ from .core.tokenizer_service import TokenizerService
13
+ from .core.context_assembler import ContextAssembler
14
+ from .services.compressor import Compressor
15
+ from .config.settings import ContextConfig, BucketConfig
16
+
17
+ __all__ = [
18
+ "BudgetManager",
19
+ "TokenizerService",
20
+ "ContextAssembler",
21
+ "Compressor",
22
+ "ContextConfig",
23
+ "BucketConfig",
24
+ "ContextEngineer",
25
+ ]
26
+
27
+
28
+ def __getattr__(name: str):
29
+ """Lazy import for ContextEngineer to avoid naming conflict with package."""
30
+ if name == "ContextEngineer":
31
+ import importlib.util
32
+ from pathlib import Path
33
+
34
+ module_file = Path(__file__).resolve().parent.parent / "context_engineer.py"
35
+ if module_file.exists():
36
+ spec = importlib.util.spec_from_file_location("_context_engineer_module", module_file)
37
+ if spec and spec.loader:
38
+ module = importlib.util.module_from_spec(spec)
39
+ spec.loader.exec_module(module)
40
+ return module.ContextEngineer
41
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
@@ -0,0 +1,5 @@
1
+ """Configuration management for context engineering."""
2
+
3
+ from .settings import ContextConfig
4
+
5
+ __all__ = ["ContextConfig"]