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,567 @@
1
+ """
2
+ Command-line argument parsing for Dolphin CLI
3
+
4
+ This module handles all CLI argument parsing with subcommand support.
5
+ """
6
+
7
+ import argparse
8
+ import sys
9
+ from dataclasses import dataclass, field
10
+ from typing import Any, Dict, List, Optional
11
+
12
+ from dolphin.cli.utils.version import getFullVersion
13
+ from dolphin.core.logging.logger import console
14
+
15
+
16
+ @dataclass
17
+ class Args:
18
+ """Command-line arguments dataclass"""
19
+
20
+ # Subcommand
21
+ subcommand: Optional[str] = None # run/debug/chat/explore
22
+
23
+ # Agent related
24
+ agent: Optional[str] = None
25
+ folder: Optional[str] = None
26
+ skillFolder: Optional[str] = None
27
+ query: Optional[str] = None
28
+
29
+ # Builtin agent mode
30
+ useBuiltinAgent: bool = False # True if using builtin explore agent
31
+
32
+ # Config related
33
+ config: Optional[str] = None
34
+ modelName: Optional[str] = None
35
+ apiKey: Optional[str] = None
36
+ api: Optional[str] = None
37
+ typeApi: Optional[str] = None
38
+ userId: Optional[str] = None
39
+ sessionId: Optional[str] = None
40
+ maxTokens: Optional[int] = None
41
+ temperature: Optional[float] = None
42
+
43
+ # Logging related
44
+ logLevel: Optional[str] = None
45
+ logSuffix: Optional[str] = None
46
+
47
+ # Mode related
48
+ interactive: bool = False
49
+ saveHistory: bool = True
50
+
51
+ # Output related
52
+ trajectoryPath: Optional[str] = None
53
+ tracePath: Optional[str] = None
54
+ outputVariables: List[str] = field(default_factory=list)
55
+ reportPath: Optional[str] = None
56
+
57
+ # Context Engineer
58
+ contextEngineerConfig: Optional[str] = None
59
+ contextEngineerData: Optional[str] = None
60
+
61
+ # Run subcommand options
62
+ timeout: Optional[int] = None
63
+ dryRun: bool = False
64
+
65
+ # Debug subcommand options
66
+ breakOnStart: bool = False
67
+ breakAt: Optional[List[int]] = None
68
+ snapshotOnPause: bool = False
69
+ commands: Optional[str] = None
70
+ autoContinue: bool = False # Renamed from nonInteractive - debug mode: auto-run until breakpoint
71
+
72
+ # Chat subcommand options
73
+ systemPrompt: Optional[str] = None
74
+ maxTurns: Optional[int] = None
75
+ initMessage: Optional[str] = None
76
+
77
+ # Custom arguments and flags
78
+ runArgs: Dict[str, Any] = field(default_factory=dict)
79
+ flagsOverrides: Dict[str, bool] = field(default_factory=dict)
80
+
81
+
82
+ def _addAgentArguments(parser: argparse.ArgumentParser, required: bool = True) -> None:
83
+ """Add agent-related arguments
84
+
85
+ Args:
86
+ parser: The argument parser
87
+ required: Whether --agent and --folder are required (False for explore subcommand)
88
+ """
89
+ parser.add_argument(
90
+ "--agent", "-a", type=str, required=required,
91
+ help="Agent name to execute"
92
+ )
93
+ parser.add_argument(
94
+ "--folder", type=str, required=required,
95
+ help="Directory containing agent definitions"
96
+ )
97
+ parser.add_argument(
98
+ "--skill-folder", "--skill_folder", type=str, dest="skill_folder",
99
+ help="Custom skillkit directory"
100
+ )
101
+ parser.add_argument(
102
+ "--query", "-q", type=str,
103
+ help="Query string passed to the agent as 'query' variable"
104
+ )
105
+
106
+
107
+ def _addConfigArguments(parser: argparse.ArgumentParser) -> None:
108
+ """Add configuration arguments"""
109
+ parser.add_argument(
110
+ "--config", "-c", type=str,
111
+ help="Config file path (default: ./config/global.yaml)"
112
+ )
113
+ parser.add_argument("--model-name", "--model_name", type=str, dest="model_name", help="Model name")
114
+ parser.add_argument("--api-key", "--api_key", type=str, dest="api_key", help="API Key")
115
+ parser.add_argument("--api", type=str, help="API endpoint URL")
116
+ parser.add_argument("--type-api", "--type_api", type=str, dest="type_api", help="API type")
117
+ parser.add_argument("--user-id", "--user_id", type=str, dest="user_id", help="User ID")
118
+ parser.add_argument("--session-id", "--session_id", type=str, dest="session_id", help="Session ID")
119
+ parser.add_argument("--max-tokens", "--max_tokens", type=int, dest="max_tokens", help="Maximum tokens")
120
+ parser.add_argument("--temperature", type=float, help="Temperature (0.0-2.0)")
121
+
122
+
123
+ def _addLoggingArguments(parser: argparse.ArgumentParser) -> None:
124
+ """Add logging arguments"""
125
+ verbosityGroup = parser.add_mutually_exclusive_group()
126
+ verbosityGroup.add_argument(
127
+ "-v", "--verbose", action="store_const", const="INFO", dest="verbosity",
128
+ help="Verbose output (INFO level)"
129
+ )
130
+ verbosityGroup.add_argument(
131
+ "-vv", "--very-verbose", action="store_const", const="DEBUG", dest="verbosity",
132
+ help="Very verbose output (DEBUG level)"
133
+ )
134
+ verbosityGroup.add_argument(
135
+ "--quiet", action="store_const", const="WARNING", dest="verbosity",
136
+ help="Quiet mode (WARNING and above only)"
137
+ )
138
+
139
+ parser.add_argument(
140
+ "--log-level", type=str,
141
+ choices=["DEBUG", "INFO", "WARNING", "ERROR"],
142
+ help="Set log level directly (overrides -v/-vv)"
143
+ )
144
+ parser.add_argument(
145
+ "--log-suffix", type=str,
146
+ help="Log file name suffix for concurrent experiments"
147
+ )
148
+
149
+
150
+ def _addOutputArguments(parser: argparse.ArgumentParser) -> None:
151
+ """Add output-related arguments"""
152
+ parser.add_argument(
153
+ "--output-variables", nargs="*", default=[],
154
+ help="List of variable names to output"
155
+ )
156
+ parser.add_argument(
157
+ "--trajectory-path", "--trajectorypath", type=str, dest="trajectorypath",
158
+ help="Dialog history save path (default: data/dialog/)"
159
+ )
160
+ parser.add_argument(
161
+ "--trace-path", "--tracepath", type=str, dest="tracepath",
162
+ help="Execution trace save path (default: data/execution_trace/)"
163
+ )
164
+ parser.add_argument(
165
+ "--report-path", "--reportpath", type=str, dest="reportpath",
166
+ help="Report output path"
167
+ )
168
+ parser.add_argument(
169
+ "--context-engineer-config", "--context_engineer_config",
170
+ type=str, dest="context_engineer_config",
171
+ help="Context-engineer config file path"
172
+ )
173
+ parser.add_argument(
174
+ "--context-engineer-data", "--context_engineer_data",
175
+ type=str, dest="context_engineer_data",
176
+ help="Context-engineer data file path"
177
+ )
178
+
179
+
180
+ def _addHistoryArguments(parser: argparse.ArgumentParser) -> None:
181
+ """Add history saving arguments"""
182
+ parser.add_argument(
183
+ '--save-history', action='store_true', default=True, dest='save_history',
184
+ help='Save dialog history to file (enabled by default)'
185
+ )
186
+ parser.add_argument(
187
+ '--no-save-history', action='store_false', dest='save_history',
188
+ help='Do not save dialog history'
189
+ )
190
+
191
+
192
+ def _addCommonArguments(parser: argparse.ArgumentParser, agent_required: bool = True) -> None:
193
+ """Add all common arguments shared by subcommands
194
+
195
+ Args:
196
+ parser: The argument parser
197
+ agent_required: Whether --agent and --folder are required
198
+ """
199
+ _addAgentArguments(parser, required=agent_required)
200
+ _addConfigArguments(parser)
201
+ _addLoggingArguments(parser)
202
+ _addOutputArguments(parser)
203
+
204
+
205
+ def _addRunSubcommandArguments(parser: argparse.ArgumentParser) -> None:
206
+ """Add run subcommand specific arguments"""
207
+ _addHistoryArguments(parser)
208
+ parser.add_argument(
209
+ '--timeout', type=int, metavar='SECONDS',
210
+ help='Execution timeout in seconds'
211
+ )
212
+ parser.add_argument(
213
+ '--dry-run', action='store_true',
214
+ help='Validate config and agent definition without execution'
215
+ )
216
+ parser.add_argument(
217
+ '--interactive', '-i', action='store_true',
218
+ help='Interactive mode: enter conversation loop after execution'
219
+ )
220
+
221
+
222
+ def _addDebugSubcommandArguments(parser: argparse.ArgumentParser) -> None:
223
+ """Add debug subcommand specific arguments"""
224
+ parser.add_argument(
225
+ '--break-on-start', action='store_true',
226
+ help='Pause at the first code block'
227
+ )
228
+ parser.add_argument(
229
+ '--break-at', type=int, metavar='N', action='append',
230
+ help='Set breakpoint at block N (can be used multiple times)'
231
+ )
232
+ parser.add_argument(
233
+ '--snapshot-on-pause', action='store_true',
234
+ help='Auto-display ContextSnapshot summary on each pause'
235
+ )
236
+ parser.add_argument(
237
+ '--commands', type=str, metavar='FILE',
238
+ help='Read debug commands from file (one per line)'
239
+ )
240
+ parser.add_argument(
241
+ '--auto-continue', action='store_true',
242
+ help='Auto-continue mode: only pause at breakpoints, auto-execute otherwise'
243
+ )
244
+ parser.add_argument(
245
+ '--interactive', '-i', action='store_true',
246
+ help='Interactive mode: enter conversation loop after execution'
247
+ )
248
+ parser.set_defaults(save_history=True)
249
+
250
+
251
+ def _addChatSubcommandArguments(parser: argparse.ArgumentParser) -> None:
252
+ """Add chat subcommand specific arguments"""
253
+ parser.add_argument(
254
+ '--system-prompt', type=str,
255
+ help='Custom system prompt (overrides default)'
256
+ )
257
+ parser.add_argument(
258
+ '--max-turns', type=int,
259
+ help='Maximum conversation turns (auto-exit when reached)'
260
+ )
261
+ parser.add_argument(
262
+ '--init-message', type=str,
263
+ help='Initial message (auto-sent as first message)'
264
+ )
265
+ parser.set_defaults(interactive=True, save_history=True)
266
+
267
+
268
+ def _addExploreSubcommandArguments(parser: argparse.ArgumentParser) -> None:
269
+ """Add explore subcommand specific arguments
270
+
271
+ The explore subcommand provides a default AI coding assistant experience
272
+ similar to Claude Code and OpenAI Codex, with access to local environment tools.
273
+ """
274
+ parser.add_argument(
275
+ '--system-prompt', type=str,
276
+ help='Custom system prompt (overrides default explore system prompt)'
277
+ )
278
+ parser.add_argument(
279
+ '--max-turns', type=int,
280
+ help='Maximum conversation turns (auto-exit when reached)'
281
+ )
282
+ # Note: interactive is always True for explore mode
283
+ parser.set_defaults(interactive=True, save_history=True, use_builtin_agent=True)
284
+
285
+
286
+ def _addFlagArguments(parser: argparse.ArgumentParser) -> List[str]:
287
+ """Add dynamic flag arguments
288
+
289
+ Supports two styles:
290
+ 1. Switch style: --flag_name (True) or --no-flag_name (False)
291
+ 2. Value style: --flag_name true/false (for experiment scripts)
292
+
293
+ Returns:
294
+ List of flag names
295
+ """
296
+ from dolphin.core.flags import definitions as flagDefs
297
+
298
+ flagShortOptions = {"debug": "-d"}
299
+ flagNames = []
300
+
301
+ for attrName in dir(flagDefs):
302
+ if attrName.isupper() and not attrName.startswith('_'):
303
+ flagValue = getattr(flagDefs, attrName)
304
+ if isinstance(flagValue, str):
305
+ flagNames.append(flagValue)
306
+ defaultValue = flagDefs.DEFAULT_VALUES.get(flagValue, False)
307
+
308
+ enableArgs = [f"--{flagValue}"]
309
+ if flagValue in flagShortOptions:
310
+ enableArgs.append(flagShortOptions[flagValue])
311
+
312
+ helpText = f"Set {flagValue} flag (optional: true/false)"
313
+
314
+ # Support both switch style (--flag) and value style (--flag true/false)
315
+ parser.add_argument(
316
+ *enableArgs, dest=flagValue, nargs='?', const=True,
317
+ help=helpText,
318
+ )
319
+ parser.add_argument(
320
+ f"--no-{flagValue}", dest=flagValue, action="store_const", const=False,
321
+ help=f"Disable {flagValue} flag",
322
+ )
323
+ parser.set_defaults(**{flagValue: defaultValue})
324
+
325
+ return flagNames
326
+
327
+
328
+ def _parseUnknownArgs(unknownArgs: List[str]) -> Dict[str, Any]:
329
+ """Parse unknown arguments as custom key-value pairs"""
330
+ runArgs = {}
331
+ i = 0
332
+ while i < len(unknownArgs):
333
+ if unknownArgs[i].startswith("--"):
334
+ key = unknownArgs[i][2:]
335
+ if i + 1 < len(unknownArgs) and not unknownArgs[i + 1].startswith("--"):
336
+ value = unknownArgs[i + 1]
337
+ i += 2
338
+ else:
339
+ value = True
340
+ i += 1
341
+ runArgs[key] = value
342
+ else:
343
+ i += 1
344
+ return runArgs
345
+
346
+
347
+ def _resolveLogLevel(argsDict: Dict[str, Any], subcommand: str, flagsOverrides: Dict[str, bool]) -> str:
348
+ """Resolve final log level from various sources
349
+
350
+ Priority: --log-level > -v/-vv > subcommand default > INFO
351
+ """
352
+ if argsDict.get("log_level"):
353
+ return argsDict["log_level"]
354
+
355
+ if argsDict.get("verbosity"):
356
+ return argsDict["verbosity"]
357
+
358
+ if subcommand == 'debug':
359
+ return "DEBUG"
360
+ elif subcommand == 'chat':
361
+ return "INFO"
362
+ elif flagsOverrides.get('debug'):
363
+ return "DEBUG"
364
+
365
+ return "INFO"
366
+
367
+
368
+ def _convertToArgs(argsDict: Dict[str, Any]) -> Args:
369
+ """Convert parsed args dict to Args dataclass with field name mapping"""
370
+ # Map CLI argument names to Args field names
371
+ fieldMapping = {
372
+ 'skill_folder': 'skillFolder',
373
+ 'model_name': 'modelName',
374
+ 'api_key': 'apiKey',
375
+ 'type_api': 'typeApi',
376
+ 'user_id': 'userId',
377
+ 'session_id': 'sessionId',
378
+ 'max_tokens': 'maxTokens',
379
+ 'log_level': 'logLevel',
380
+ 'log_suffix': 'logSuffix',
381
+ 'save_history': 'saveHistory',
382
+ 'trajectorypath': 'trajectoryPath',
383
+ 'tracepath': 'tracePath',
384
+ 'reportpath': 'reportPath',
385
+ 'output_variables': 'outputVariables',
386
+ 'context_engineer_config': 'contextEngineerConfig',
387
+ 'context_engineer_data': 'contextEngineerData',
388
+ 'dry_run': 'dryRun',
389
+ 'break_on_start': 'breakOnStart',
390
+ 'break_at': 'breakAt',
391
+ 'snapshot_on_pause': 'snapshotOnPause',
392
+ 'auto_continue': 'autoContinue',
393
+ 'system_prompt': 'systemPrompt',
394
+ 'max_turns': 'maxTurns',
395
+ 'init_message': 'initMessage',
396
+ 'run_args': 'runArgs',
397
+ 'flags_overrides': 'flagsOverrides',
398
+ 'use_builtin_agent': 'useBuiltinAgent',
399
+ }
400
+
401
+ convertedDict = {}
402
+ for key, value in argsDict.items():
403
+ newKey = fieldMapping.get(key, key)
404
+ convertedDict[newKey] = value
405
+
406
+ return Args(**convertedDict)
407
+
408
+
409
+ def parseArgs() -> Args:
410
+ """Parse command line arguments with subcommand support
411
+
412
+ Returns:
413
+ Parsed Args object
414
+ """
415
+ # Main parser
416
+ parser = argparse.ArgumentParser(
417
+ prog="dolphin",
418
+ description="Dolphin Language - AI Agent Development and Debugging Tool",
419
+ formatter_class=argparse.RawDescriptionHelpFormatter,
420
+ epilog="""Subcommands:
421
+ (default) Explore mode - Interactive AI coding assistant (like Claude Code)
422
+ explore Explore mode - Interactive AI coding assistant with local env tools
423
+ run Run Agent (execute and exit)
424
+ debug Debug mode (step-by-step execution, breakpoints, variable inspection)
425
+ chat Interactive chat mode (continuous conversation)
426
+
427
+ Examples:
428
+ # Default explore mode (similar to Claude Code / Codex)
429
+ dolphin
430
+ dolphin explore
431
+ dolphin explore -q "list all Python files in this directory"
432
+
433
+ # Run a specific agent
434
+ dolphin run --agent my_agent --folder ./agents --query "analyze data"
435
+
436
+ # Interactive mode (continue conversation after execution)
437
+ dolphin run --agent my_agent --folder ./agents -i
438
+
439
+ # Debug mode
440
+ dolphin debug --agent my_agent --folder ./agents --break-on-start
441
+
442
+ # Interactive chat
443
+ dolphin chat --agent my_agent --folder ./agents
444
+ """,
445
+ # Disable long argument abbreviations to avoid conflicts with custom args
446
+ allow_abbrev=False,
447
+ )
448
+
449
+ # Version
450
+ parser.add_argument(
451
+ '--version', action='version',
452
+ version=getFullVersion(),
453
+ help='Show version and exit'
454
+ )
455
+
456
+ # Subcommand setup
457
+ subparsers = parser.add_subparsers(dest='subcommand', help='Subcommand')
458
+
459
+ # explore subcommand (DEFAULT - similar to Claude Code / Codex)
460
+ parserExplore = subparsers.add_parser(
461
+ 'explore', help='Interactive AI coding assistant (default mode, like Claude Code)',
462
+ description='Start an interactive AI coding assistant with access to local environment tools'
463
+ )
464
+ _addCommonArguments(parserExplore, agent_required=False) # agent/folder are optional
465
+ _addExploreSubcommandArguments(parserExplore)
466
+ flagNamesExplore = _addFlagArguments(parserExplore)
467
+
468
+ # run subcommand
469
+ parserRun = subparsers.add_parser(
470
+ 'run', help='Run Agent (execute and exit)',
471
+ description='Run Agent, exit after execution'
472
+ )
473
+ _addCommonArguments(parserRun)
474
+ _addRunSubcommandArguments(parserRun)
475
+ flagNamesRun = _addFlagArguments(parserRun)
476
+
477
+ # debug subcommand
478
+ parserDebug = subparsers.add_parser(
479
+ 'debug', help='Debug mode (interactive step-by-step execution)',
480
+ description='Start interactive debugger with step-by-step execution, breakpoints, variable inspection'
481
+ )
482
+ _addCommonArguments(parserDebug)
483
+ _addDebugSubcommandArguments(parserDebug)
484
+ flagNamesDebug = _addFlagArguments(parserDebug)
485
+
486
+ # chat subcommand
487
+ parserChat = subparsers.add_parser(
488
+ 'chat', help='Interactive chat mode',
489
+ description='Start continuous conversation mode, multi-turn interaction until exit'
490
+ )
491
+ _addCommonArguments(parserChat)
492
+ _addChatSubcommandArguments(parserChat)
493
+ flagNamesChat = _addFlagArguments(parserChat)
494
+
495
+ # Get all flag names
496
+ flagNames = list(set(flagNamesExplore + flagNamesRun + flagNamesDebug + flagNamesChat))
497
+
498
+ # Check if subcommand is provided - default to 'explore' if no subcommand
499
+ validSubcommands = ['explore', 'run', 'debug', 'chat', '--version', '-h', '--help']
500
+
501
+ if len(sys.argv) < 2:
502
+ # No arguments - default to explore mode
503
+ sys.argv.insert(1, 'explore')
504
+ elif sys.argv[1] not in validSubcommands and not sys.argv[1].startswith('-'):
505
+ # User provided something that isn't a subcommand or flag
506
+ # It might be a query for explore mode
507
+ if not sys.argv[1].startswith('--'):
508
+ # Not a flag, treat as query and insert explore
509
+ sys.argv.insert(1, 'explore')
510
+ sys.argv.insert(2, '-q') # The original first arg becomes the query
511
+ elif sys.argv[1].startswith('-') and sys.argv[1] not in ['--version', '-h', '--help']:
512
+ # User started with a flag (like -q or --config) - default to explore
513
+ sys.argv.insert(1, 'explore')
514
+
515
+ # Parse arguments
516
+ knownArgs, unknownArgs = parser.parse_known_args()
517
+ argsDict = vars(knownArgs)
518
+
519
+ # Handle subcommand
520
+ subcommand = argsDict.get('subcommand') or 'explore'
521
+ argsDict['subcommand'] = subcommand
522
+
523
+ # Extract flags from argsDict into flagsOverrides
524
+ flagsOverrides = {}
525
+ for flagName in flagNames:
526
+ if flagName in argsDict:
527
+ flagsOverrides[flagName] = argsDict.pop(flagName)
528
+
529
+ # Apply subcommand-specific defaults
530
+ if subcommand == 'explore':
531
+ # Explore mode defaults
532
+ if argsDict.get('interactive') is None:
533
+ argsDict['interactive'] = True
534
+ if argsDict.get('save_history') is None:
535
+ argsDict['save_history'] = True
536
+ if argsDict.get('use_builtin_agent') is None:
537
+ argsDict['use_builtin_agent'] = True
538
+ elif subcommand == 'debug':
539
+ flagsOverrides['debug'] = True
540
+ if argsDict.get('save_history') is None:
541
+ argsDict['save_history'] = True
542
+ elif subcommand == 'chat':
543
+ if argsDict.get('interactive') is None:
544
+ argsDict['interactive'] = True
545
+ if argsDict.get('save_history') is None:
546
+ argsDict['save_history'] = True
547
+
548
+ argsDict["flags_overrides"] = flagsOverrides
549
+
550
+ # Validate arguments - allow missing agent/folder only for explore mode with builtin agent
551
+ if argsDict.get("agent") and not argsDict.get("folder"):
552
+ parser.error("--agent requires --folder")
553
+
554
+ if not argsDict.get("agent"):
555
+ if subcommand != 'explore':
556
+ parser.error("--agent is required")
557
+ # For explore, we'll use the builtin agent (set in runner)
558
+
559
+ # Parse custom arguments
560
+ argsDict["run_args"] = _parseUnknownArgs(unknownArgs)
561
+
562
+ # Resolve log level
563
+ argsDict["log_level"] = _resolveLogLevel(argsDict, subcommand, flagsOverrides)
564
+ argsDict.pop("verbosity", None)
565
+
566
+ return _convertToArgs(argsDict)
567
+
@@ -0,0 +1,22 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ 内置 Agent 定义
4
+
5
+ 提供 Dolphin CLI 默认使用的内置智能体,类似 OpenAI Codex 和 Claude Code 的默认交互模式。
6
+
7
+ 包含:
8
+ - explore: 带有本地环境工具的 explore 对话智能体
9
+ """
10
+
11
+ import os
12
+
13
+ # 获取内置 agents 目录路径
14
+ BUILTIN_AGENTS_DIR = os.path.dirname(os.path.abspath(__file__))
15
+
16
+ # 默认的 explore agent 名称
17
+ DEFAULT_EXPLORE_AGENT = "explore"
18
+
19
+ __all__ = [
20
+ "BUILTIN_AGENTS_DIR",
21
+ "DEFAULT_EXPLORE_AGENT",
22
+ ]
@@ -0,0 +1,4 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Commands 模块 - CLI 命令实现"""
3
+
4
+ __all__ = []
@@ -0,0 +1,8 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Interrupt 模块 - 中断处理"""
3
+
4
+ from dolphin.cli.interrupt.handler import InterruptToken
5
+
6
+ __all__ = [
7
+ "InterruptToken",
8
+ ]