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,340 @@
1
+ """
2
+ Input utilities with auto-completion and interrupt support.
3
+
4
+ Provides enhanced input prompts with:
5
+ - Tab/arrow-key completion for debug commands
6
+ - ESC key interrupt handling for agent execution
7
+ - Slash command shortcuts for conversation mode
8
+ - Multimodal input processing (@paste, @image:, @url: markers)
9
+
10
+ Type Annotations:
11
+ All public functions use proper type hints with forward references
12
+ for InterruptToken (via TYPE_CHECKING) to avoid circular imports.
13
+ """
14
+
15
+ from typing import List, Optional, TYPE_CHECKING, Union, Dict, Any
16
+ from prompt_toolkit.shortcuts import PromptSession
17
+ from prompt_toolkit.completion import Completer, Completion
18
+ from prompt_toolkit.history import InMemoryHistory
19
+ from prompt_toolkit.key_binding import KeyBindings
20
+ from prompt_toolkit.keys import Keys
21
+
22
+ if TYPE_CHECKING:
23
+ from dolphin.cli.interrupt.handler import InterruptToken
24
+
25
+ # Type aliases for better clarity
26
+ MultimodalContentBlock = Dict[str, Any]
27
+ MultimodalInput = Union[str, List[MultimodalContentBlock]]
28
+
29
+
30
+ # Debug command definitions for auto-completion
31
+ DEBUG_COMMANDS = [
32
+ # Execution control
33
+ ("step", "单步执行下一个 block"),
34
+ ("next", "单步执行下一个 block (同 step)"),
35
+ ("continue", "继续执行到下一个断点"),
36
+ ("run", "运行到结束(忽略所有断点)"),
37
+ ("until", "运行到指定 block: until <n>"),
38
+ ("quit", "退出调试模式"),
39
+ # Breakpoint management
40
+ ("break", "设置断点: break <n>"),
41
+ ("delete", "删除断点: delete <n>"),
42
+ ("list", "显示所有断点"),
43
+ # Variable inspection
44
+ ("vars", "显示所有变量"),
45
+ ("var", "显示特定变量: var <name>"),
46
+ ("progress", "显示执行进度信息"),
47
+ ("trace", "显示执行轨迹 - trace [brief/full] 默认简略"),
48
+ ("trace full", "显示执行轨迹 (完整模式 - 不折叠只读消息)"),
49
+ # Snapshot
50
+ ("snapshot", "显示快照分析"),
51
+ # Help
52
+ ("help", "显示帮助信息"),
53
+ ]
54
+
55
+ # Slash command shortcuts (for conversation mode)
56
+ # These are quick inspection commands - user types / and gets completions
57
+ # /debug enters interactive debug REPL, others execute once and return to conversation
58
+ SLASH_COMMANDS = [
59
+ ("/debug", "进入实时调试交互模式 (REPL)"),
60
+ ("/trace", "查看执行轨迹 默认简略"),
61
+ ("/trace full", "查看执行轨迹 (完整模式 - 不折叠只读消息)"),
62
+ ("/snapshot", "查看快照分析"),
63
+ ("/vars", "查看所有变量"),
64
+ ("/var", "查看特定变量: /var <name>"),
65
+ ("/progress", "查看执行进度"),
66
+ ("/help", "查看调试命令帮助"),
67
+ ]
68
+
69
+
70
+ class DebugCommandCompleter(Completer):
71
+ """Completer for debug commands.
72
+
73
+ Supports both direct input (e.g., 'vars') and slash-prefixed input (e.g., '/vars').
74
+ When user types '/', completions are shown but the actual command is without slash.
75
+ """
76
+
77
+ def __init__(self, commands: List[tuple]):
78
+ """
79
+ Args:
80
+ commands: List of (command, description) tuples
81
+ """
82
+ self.commands = commands
83
+
84
+ def get_completions(self, document, complete_event):
85
+ text = document.text_before_cursor.lower()
86
+
87
+ # Handle slash prefix: "/va" -> complete to "vars" (strip the slash)
88
+ has_slash = text.startswith("/")
89
+ search_text = text[1:] if has_slash else text
90
+
91
+ for cmd, desc in self.commands:
92
+ cmd_lower = cmd.lower()
93
+
94
+ if cmd_lower.startswith(search_text):
95
+ # Always complete to command without slash (debug mode uses bare commands)
96
+ yield Completion(
97
+ cmd_lower,
98
+ start_position=-len(document.text_before_cursor),
99
+ display_meta=desc,
100
+ )
101
+
102
+
103
+ class ConversationCompleter(Completer):
104
+ """Completer that only activates for slash commands in conversation mode."""
105
+
106
+ def __init__(self):
107
+ self.slash_commands = SLASH_COMMANDS
108
+
109
+ def get_completions(self, document, complete_event):
110
+ text = document.text_before_cursor
111
+
112
+ # Only show completions when text starts with "/"
113
+ if not text.startswith("/"):
114
+ return
115
+
116
+ text_lower = text.lower()
117
+ for cmd, desc in self.slash_commands:
118
+ if cmd.startswith(text_lower):
119
+ yield Completion(
120
+ cmd,
121
+ start_position=-len(text),
122
+ display_meta=desc,
123
+ )
124
+
125
+
126
+ # Shared PromptSession instances
127
+ _debug_session = PromptSession(history=InMemoryHistory())
128
+ _conversation_session = PromptSession(history=InMemoryHistory())
129
+
130
+
131
+ async def prompt_debug_command(prompt_text: str = "Debug > ", allow_execution_control: bool = True) -> str:
132
+ """
133
+ Prompt for debug command with auto-completion (async version).
134
+
135
+ Args:
136
+ prompt_text: The prompt string to display
137
+ allow_execution_control: If False, exclude execution control commands from completion
138
+
139
+ Returns:
140
+ User input string
141
+ """
142
+ commands = DEBUG_COMMANDS
143
+ if not allow_execution_control:
144
+ # Filter out execution control commands for live debug / post-mortem
145
+ execution_cmds = {"step", "next", "continue", "run", "until"}
146
+ commands = [(cmd, desc) for cmd, desc in commands if cmd not in execution_cmds]
147
+
148
+ completer = DebugCommandCompleter(commands)
149
+
150
+ try:
151
+ return (await _debug_session.prompt_async(
152
+ prompt_text,
153
+ completer=completer,
154
+ complete_while_typing=True,
155
+ )).strip()
156
+ except (EOFError, KeyboardInterrupt):
157
+ raise
158
+
159
+
160
+ async def prompt_conversation(prompt_text: str = "\n> ") -> str:
161
+ """
162
+ Prompt for user input in conversation mode with slash-command completion (async version).
163
+
164
+ Args:
165
+ prompt_text: The prompt string to display
166
+
167
+ Returns:
168
+ User input string
169
+ """
170
+ completer = ConversationCompleter()
171
+
172
+ try:
173
+ return (await _conversation_session.prompt_async(
174
+ prompt_text,
175
+ completer=completer,
176
+ complete_while_typing=True,
177
+ )).strip()
178
+ except (EOFError, KeyboardInterrupt):
179
+ raise
180
+
181
+
182
+ class EscapeInterrupt(Exception):
183
+ """Exception raised when ESC key is pressed during prompt."""
184
+ pass
185
+
186
+
187
+ def create_interrupt_key_bindings(
188
+ interrupt_token: Optional["InterruptToken"] = None
189
+ ) -> KeyBindings:
190
+ """Create key bindings that handle ESC for interrupt.
191
+
192
+ Args:
193
+ interrupt_token: Optional InterruptToken to trigger on ESC
194
+
195
+ Returns:
196
+ KeyBindings with ESC handler
197
+ """
198
+ kb = KeyBindings()
199
+
200
+ @kb.add(Keys.Escape)
201
+ def handle_escape(event):
202
+ """Handle ESC key press to trigger interrupt."""
203
+ if interrupt_token:
204
+ interrupt_token.trigger_interrupt()
205
+ # Use app.exit with exception - the proper way to exit prompt_toolkit
206
+ event.app.exit(exception=EscapeInterrupt())
207
+
208
+ return kb
209
+
210
+
211
+ # Session for interrupt-aware prompts
212
+ _interrupt_session: Optional[PromptSession] = None
213
+
214
+
215
+ def _get_interrupt_session() -> PromptSession:
216
+ """Get or create the interrupt-aware prompt session."""
217
+ global _interrupt_session
218
+ if _interrupt_session is None:
219
+ _interrupt_session = PromptSession(history=InMemoryHistory())
220
+ return _interrupt_session
221
+
222
+
223
+ async def prompt_with_interrupt(
224
+ prompt_text: str = "> ",
225
+ interrupt_token: Optional["InterruptToken"] = None,
226
+ completer: Optional[Completer] = None,
227
+ default_text: str = ""
228
+ ) -> str:
229
+ """
230
+ Prompt for user input with ESC key interrupt support.
231
+
232
+ When ESC is pressed, the interrupt_token is triggered and EscapeInterrupt
233
+ is raised. The caller should catch this and handle the interrupt appropriately.
234
+
235
+ Args:
236
+ prompt_text: The prompt string to display
237
+ interrupt_token: InterruptToken to trigger on ESC press
238
+ completer: Optional completer for auto-completion
239
+ default_text: Initial text to pre-fill the input buffer
240
+
241
+ Returns:
242
+ User input string
243
+
244
+ Raises:
245
+ EscapeInterrupt: When ESC key is pressed
246
+ EOFError: When Ctrl+D is pressed
247
+ KeyboardInterrupt: When Ctrl+C is pressed
248
+ """
249
+ session = _get_interrupt_session()
250
+ key_bindings = create_interrupt_key_bindings(interrupt_token)
251
+
252
+ # Use ConversationCompleter if no completer provided
253
+ if completer is None:
254
+ completer = ConversationCompleter()
255
+
256
+ try:
257
+ return (await session.prompt_async(
258
+ prompt_text,
259
+ key_bindings=key_bindings,
260
+ completer=completer,
261
+ complete_while_typing=True,
262
+ default=default_text,
263
+ )).strip()
264
+ except EscapeInterrupt:
265
+ raise
266
+ except (EOFError, KeyboardInterrupt):
267
+ raise
268
+
269
+
270
+ async def prompt_interrupt_input(prompt_text: str = "💬 New instructions (Enter to continue): ") -> str:
271
+ """
272
+ Prompt for user input after an interrupt.
273
+
274
+ This is a simplified prompt without ESC handling, used after execution
275
+ has been interrupted to get the user's new instructions.
276
+
277
+ Args:
278
+ prompt_text: The prompt string to display
279
+
280
+ Returns:
281
+ User input string (may be empty if user just pressed Enter)
282
+ """
283
+ session = PromptSession()
284
+
285
+ try:
286
+ return (await session.prompt_async(prompt_text)).strip()
287
+ except (EOFError, KeyboardInterrupt):
288
+ return ""
289
+
290
+
291
+ async def prompt_conversation_with_multimodal(
292
+ prompt_text: str = "> ",
293
+ interrupt_token: Optional["InterruptToken"] = None,
294
+ verbose: bool = False
295
+ ) -> MultimodalInput:
296
+ """
297
+ Prompt for user input with ESC interrupt support and multimodal marker processing.
298
+
299
+ Supports the following multimodal markers:
300
+ - @paste: Read image from clipboard
301
+ - @image:<path>: Read image from file path
302
+ - @url:<url>: Reference image by URL
303
+
304
+ Args:
305
+ prompt_text: The prompt string to display
306
+ interrupt_token: InterruptToken to trigger on ESC press
307
+ verbose: If True, print image processing status messages
308
+
309
+ Returns:
310
+ str: Plain text input if no multimodal markers
311
+ List[MultimodalContentBlock]: Multimodal content blocks if markers are present
312
+
313
+ Raises:
314
+ EscapeInterrupt: When ESC key is pressed
315
+ EOFError: When Ctrl+D is pressed
316
+ KeyboardInterrupt: When Ctrl+C is pressed
317
+ """
318
+ from dolphin.cli.multimodal import process_multimodal_input
319
+
320
+ # Get raw input using interrupt-aware prompt
321
+ raw_input = await prompt_with_interrupt(
322
+ prompt_text=prompt_text,
323
+ interrupt_token=interrupt_token,
324
+ completer=ConversationCompleter()
325
+ )
326
+
327
+ # Process multimodal markers
328
+ try:
329
+ return process_multimodal_input(raw_input, verbose=verbose)
330
+ except (ValueError, IOError, FileNotFoundError) as e:
331
+ # Expected errors during multimodal processing (invalid path, clipboard error, etc.)
332
+ # Always notify user of multimodal processing failure
333
+ print(f"⚠️ Multimodal processing failed: {e}")
334
+ if verbose:
335
+ import traceback
336
+ traceback.print_exc()
337
+ # Fallback to raw text input
338
+ return raw_input
339
+
340
+