siada-cli 0.0.1__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 (215) hide show
  1. agent_config.yaml +34 -0
  2. siada/__init__.py +13 -0
  3. siada/agent_hub/__init__.py +10 -0
  4. siada/agent_hub/coder/bug_fix_agent.py +398 -0
  5. siada/agent_hub/coder/code_gen_agent.py +235 -0
  6. siada/agent_hub/coder/fe_gen_agent.py +37 -0
  7. siada/agent_hub/coder/issue_review_agent.py +68 -0
  8. siada/agent_hub/coder/prompt/__init__.py +0 -0
  9. siada/agent_hub/coder/prompt/base/__init__.py +0 -0
  10. siada/agent_hub/coder/prompt/base/capabilities.py +18 -0
  11. siada/agent_hub/coder/prompt/base/non_interactive.py +14 -0
  12. siada/agent_hub/coder/prompt/base/prompt_builder.py +33 -0
  13. siada/agent_hub/coder/prompt/base/rules.py +40 -0
  14. siada/agent_hub/coder/prompt/base/tool_use.py +14 -0
  15. siada/agent_hub/coder/prompt/bug_prompt/bug_fix_prompt.py +51 -0
  16. siada/agent_hub/coder/prompt/bug_prompt/rules.py +53 -0
  17. siada/agent_hub/coder/prompt/code_gen_prompt.py +45 -0
  18. siada/agent_hub/coder/prompt/fe_gen_prompt.py +45 -0
  19. siada/agent_hub/coder/prompt/issue_review_prompt.py +121 -0
  20. siada/agent_hub/coder/tracing/__init__.py +22 -0
  21. siada/agent_hub/coder/tracing/logger_tracing_processor.py +458 -0
  22. siada/agent_hub/hooks/__init__.py +0 -0
  23. siada/agent_hub/hooks/io_hooks.py +30 -0
  24. siada/agent_hub/siada_agent.py +214 -0
  25. siada/config/__init__.py +0 -0
  26. siada/config/config_loader.py +67 -0
  27. siada/entrypoint/__init__.py +3 -0
  28. siada/entrypoint/args_parser/__init__.py +0 -0
  29. siada/entrypoint/args_parser/args.py +195 -0
  30. siada/entrypoint/interaction/__init__.py +0 -0
  31. siada/entrypoint/interaction/base_turn.py +107 -0
  32. siada/entrypoint/interaction/config.py +30 -0
  33. siada/entrypoint/interaction/controller.py +122 -0
  34. siada/entrypoint/interaction/nointeractive_controller.py +27 -0
  35. siada/entrypoint/interaction/turn/interface.py +116 -0
  36. siada/entrypoint/interaction/turn/models.py +34 -0
  37. siada/entrypoint/interaction/turn/run_turn.py +641 -0
  38. siada/entrypoint/interaction/turn_factory.py +35 -0
  39. siada/entrypoint/interaction/turn_models.py +28 -0
  40. siada/entrypoint/siadahub.py +413 -0
  41. siada/foundation/__init__.py +0 -0
  42. siada/foundation/code_agent_context.py +48 -0
  43. siada/foundation/config.py +59 -0
  44. siada/foundation/constants.py +2 -0
  45. siada/foundation/context.py +76 -0
  46. siada/foundation/logging.py +341 -0
  47. siada/foundation/tools/__init__.py +0 -0
  48. siada/foundation/tools/get_git_diff.py +105 -0
  49. siada/io/__init__.py +0 -0
  50. siada/io/banner.py +148 -0
  51. siada/io/color_settings.py +207 -0
  52. siada/io/color_utils.py +16 -0
  53. siada/io/components/__init__.py +0 -0
  54. siada/io/components/mdstream.py +204 -0
  55. siada/io/console_printer.py +68 -0
  56. siada/io/io.py +661 -0
  57. siada/io/key_bindings.py +129 -0
  58. siada/io/notification_command.py +40 -0
  59. siada/io/test_banner.py +64 -0
  60. siada/models/__init__.py +0 -0
  61. siada/models/agent.py +47 -0
  62. siada/models/coder/__init__.py +0 -0
  63. siada/models/converter.py +27 -0
  64. siada/models/model_base_config.py +121 -0
  65. siada/models/model_run_config.py +153 -0
  66. siada/provider/__init__.py +0 -0
  67. siada/provider/client_factory.py +112 -0
  68. siada/provider/llm_client.py +11 -0
  69. siada/provider/openrouter/__init__.py +0 -0
  70. siada/provider/openrouter/coverter.py +17 -0
  71. siada/provider/openrouter/openroute_provider.py +33 -0
  72. siada/provider/provider_factory.py +53 -0
  73. siada/queries/tree-sitter-language-pack/README.md +7 -0
  74. siada/queries/tree-sitter-language-pack/arduino-tags.scm +5 -0
  75. siada/queries/tree-sitter-language-pack/c-tags.scm +9 -0
  76. siada/queries/tree-sitter-language-pack/chatito-tags.scm +16 -0
  77. siada/queries/tree-sitter-language-pack/commonlisp-tags.scm +122 -0
  78. siada/queries/tree-sitter-language-pack/cpp-tags.scm +15 -0
  79. siada/queries/tree-sitter-language-pack/csharp-tags.scm +26 -0
  80. siada/queries/tree-sitter-language-pack/d-tags.scm +26 -0
  81. siada/queries/tree-sitter-language-pack/dart-tags.scm +92 -0
  82. siada/queries/tree-sitter-language-pack/elisp-tags.scm +5 -0
  83. siada/queries/tree-sitter-language-pack/elixir-tags.scm +54 -0
  84. siada/queries/tree-sitter-language-pack/elm-tags.scm +19 -0
  85. siada/queries/tree-sitter-language-pack/gleam-tags.scm +41 -0
  86. siada/queries/tree-sitter-language-pack/go-tags.scm +42 -0
  87. siada/queries/tree-sitter-language-pack/java-tags.scm +20 -0
  88. siada/queries/tree-sitter-language-pack/javascript-tags.scm +88 -0
  89. siada/queries/tree-sitter-language-pack/lua-tags.scm +34 -0
  90. siada/queries/tree-sitter-language-pack/ocaml-tags.scm +115 -0
  91. siada/queries/tree-sitter-language-pack/ocaml_interface-tags.scm +98 -0
  92. siada/queries/tree-sitter-language-pack/pony-tags.scm +39 -0
  93. siada/queries/tree-sitter-language-pack/properties-tags.scm +5 -0
  94. siada/queries/tree-sitter-language-pack/python-tags.scm +14 -0
  95. siada/queries/tree-sitter-language-pack/r-tags.scm +21 -0
  96. siada/queries/tree-sitter-language-pack/racket-tags.scm +12 -0
  97. siada/queries/tree-sitter-language-pack/ruby-tags.scm +64 -0
  98. siada/queries/tree-sitter-language-pack/rust-tags.scm +60 -0
  99. siada/queries/tree-sitter-language-pack/solidity-tags.scm +43 -0
  100. siada/queries/tree-sitter-language-pack/swift-tags.scm +51 -0
  101. siada/queries/tree-sitter-language-pack/udev-tags.scm +20 -0
  102. siada/queries/tree-sitter-languages/README.md +23 -0
  103. siada/queries/tree-sitter-languages/c-tags.scm +9 -0
  104. siada/queries/tree-sitter-languages/c_sharp-tags.scm +46 -0
  105. siada/queries/tree-sitter-languages/cpp-tags.scm +15 -0
  106. siada/queries/tree-sitter-languages/dart-tags.scm +91 -0
  107. siada/queries/tree-sitter-languages/elisp-tags.scm +8 -0
  108. siada/queries/tree-sitter-languages/elixir-tags.scm +54 -0
  109. siada/queries/tree-sitter-languages/elm-tags.scm +19 -0
  110. siada/queries/tree-sitter-languages/go-tags.scm +30 -0
  111. siada/queries/tree-sitter-languages/hcl-tags.scm +77 -0
  112. siada/queries/tree-sitter-languages/java-tags.scm +20 -0
  113. siada/queries/tree-sitter-languages/javascript-tags.scm +88 -0
  114. siada/queries/tree-sitter-languages/kotlin-tags.scm +27 -0
  115. siada/queries/tree-sitter-languages/ocaml-tags.scm +115 -0
  116. siada/queries/tree-sitter-languages/ocaml_interface-tags.scm +98 -0
  117. siada/queries/tree-sitter-languages/php-tags.scm +26 -0
  118. siada/queries/tree-sitter-languages/python-tags.scm +12 -0
  119. siada/queries/tree-sitter-languages/ql-tags.scm +26 -0
  120. siada/queries/tree-sitter-languages/ruby-tags.scm +64 -0
  121. siada/queries/tree-sitter-languages/rust-tags.scm +60 -0
  122. siada/queries/tree-sitter-languages/scala-tags.scm +65 -0
  123. siada/queries/tree-sitter-languages/typescript-tags.scm +41 -0
  124. siada/services/__init__.py +30 -0
  125. siada/services/at_file_recommendation_design_document.md +1213 -0
  126. siada/services/code_context_manager.py +136 -0
  127. siada/services/enhanced_fix_result_check.py +546 -0
  128. siada/services/execution_trace_collector.py +207 -0
  129. siada/services/file_recommendation/__init__.py +136 -0
  130. siada/services/file_recommendation/core/__init__.py +17 -0
  131. siada/services/file_recommendation/core/completion_engine.py +351 -0
  132. siada/services/file_recommendation/core/config.py +62 -0
  133. siada/services/file_recommendation/core/file_discovery.py +353 -0
  134. siada/services/file_recommendation/core/suggestion.py +110 -0
  135. siada/services/file_recommendation/utils/__init__.py +22 -0
  136. siada/services/file_recommendation/utils/path_utils.py +138 -0
  137. siada/services/file_recommendation/utils/text_utils.py +253 -0
  138. siada/services/fix_result_check.py +377 -0
  139. siada/services/handle_at_command/README.md +247 -0
  140. siada/services/handle_at_command/__init__.py +115 -0
  141. siada/services/handle_at_command/exceptions.py +46 -0
  142. siada/services/handle_at_command/models.py +92 -0
  143. siada/services/handle_at_command/parser.py +189 -0
  144. siada/services/handle_at_command/processor.py +321 -0
  145. siada/services/handle_at_command/resolver.py +318 -0
  146. siada/services/handle_at_command/utils.py +345 -0
  147. siada/services/model_info_service.py +103 -0
  148. siada/services/siada_runner.py +170 -0
  149. siada/session/__init__.py +29 -0
  150. siada/session/session_manager.py +66 -0
  151. siada/session/session_models.py +43 -0
  152. siada/support/__init__.py +0 -0
  153. siada/support/completer.py +204 -0
  154. siada/support/editor.py +146 -0
  155. siada/support/envprocessor.py +54 -0
  156. siada/support/repo.py +51 -0
  157. siada/support/slash_commands.py +410 -0
  158. siada/support/spinner.py +320 -0
  159. siada/tools/__init__.py +0 -0
  160. siada/tools/ast/README.md +345 -0
  161. siada/tools/ast/ast_tool.py +341 -0
  162. siada/tools/ast/models.py +11 -0
  163. siada/tools/coder/__init__.py +0 -0
  164. siada/tools/coder/ask_followup_question.py +70 -0
  165. siada/tools/coder/cmd_runner.py +132 -0
  166. siada/tools/coder/file_operator.py +284 -0
  167. siada/tools/coder/file_search/README.md +223 -0
  168. siada/tools/coder/file_search/__init__.py +10 -0
  169. siada/tools/coder/file_search/bin/rg-linux-arm64 +0 -0
  170. siada/tools/coder/file_search/bin/rg-linux-x64 +0 -0
  171. siada/tools/coder/file_search/bin/rg-macos-arm64 +0 -0
  172. siada/tools/coder/file_search/bin/rg-macos-x64 +0 -0
  173. siada/tools/coder/file_search/bin/rg.exe +0 -0
  174. siada/tools/coder/file_search/search.py +437 -0
  175. siada/tools/coder/file_search/setup_package.py +150 -0
  176. siada/tools/coder/file_search/test_search.py +142 -0
  177. siada/tools/coder/files.py +147 -0
  178. siada/tools/coder/fix_attempt_completion.py +58 -0
  179. siada/tools/coder/issue_review_completion.py +29 -0
  180. siada/tools/coder/observation/__init__.py +0 -0
  181. siada/tools/coder/observation/error.py +22 -0
  182. siada/tools/coder/observation/file_observation.py +216 -0
  183. siada/tools/coder/observation/observation.py +71 -0
  184. siada/tools/coder/repo_map/__init__.py +157 -0
  185. siada/tools/coder/repo_map/dump.py +29 -0
  186. siada/tools/coder/repo_map/io.py +226 -0
  187. siada/tools/coder/repo_map/repo_map.py +881 -0
  188. siada/tools/coder/repo_map/special.py +203 -0
  189. siada/tools/coder/repo_map/token_counter.py +154 -0
  190. siada/tools/coder/repo_map/waiting.py +221 -0
  191. siada/tools/coder/reproduce_completion.py +39 -0
  192. siada/tools/coder/run_cmd.py +60 -0
  193. siada/tools/coder/test_completion.py +25 -0
  194. siada/tools/coder/tool_docs.py +44 -0
  195. siada/tools/compression_tool.py +200 -0
  196. siada/tools/read_many_files/README.md +220 -0
  197. siada/tools/read_many_files/__init__.py +25 -0
  198. siada/tools/read_many_files/file_processor.py +486 -0
  199. siada/tools/read_many_files/filters.py +326 -0
  200. siada/tools/read_many_files/formatters.py +204 -0
  201. siada/tools/read_many_files/models.py +189 -0
  202. siada/tools/read_many_files_tool.py +233 -0
  203. siada/tools/tool_call_format/__init__.py +55 -0
  204. siada/tools/tool_call_format/file_to_language.py +231 -0
  205. siada/tools/tool_call_format/formatter_factory.py +80 -0
  206. siada/tools/tool_call_format/formatters.py +282 -0
  207. siada/tools/tool_call_format/tool_call_formatter.py +54 -0
  208. siada/tools/web/__init__.py +0 -0
  209. siada/tools/web/web_crawl.py +208 -0
  210. siada/utils.py +194 -0
  211. siada_cli-0.0.1.dist-info/LICENSE +201 -0
  212. siada_cli-0.0.1.dist-info/METADATA +457 -0
  213. siada_cli-0.0.1.dist-info/RECORD +215 -0
  214. siada_cli-0.0.1.dist-info/WHEEL +4 -0
  215. siada_cli-0.0.1.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,207 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from dataclasses import dataclass, field
5
+ from datetime import datetime
6
+ from typing import Any, Dict, List, Optional
7
+
8
+ from agents.tracing import TracingProcessor, Trace, Span
9
+ from openai.types.responses import ResponseFunctionToolCall
10
+
11
+ @dataclass
12
+ class ModelCall:
13
+ """模型调用记录"""
14
+ call_id: int
15
+ model: str
16
+ input_messages: List[Dict[str, Any]]
17
+ output_messages: List[Dict[str, Any]]
18
+ usage: Optional[Dict[str, Any]] = None
19
+ timestamp: datetime = field(default_factory=datetime.now)
20
+ duration_ms: Optional[float] = None
21
+
22
+
23
+ @dataclass
24
+ class ToolCall:
25
+ """工具调用记录"""
26
+ call_id: int
27
+ tool_name: str
28
+ input_args: Any
29
+ output_result: Any
30
+ timestamp: datetime = field(default_factory=datetime.now)
31
+ duration_ms: Optional[float] = None
32
+ success: bool = True
33
+ error_message: Optional[str] = None
34
+
35
+
36
+ @dataclass
37
+ class ExecutionTrace:
38
+ trace_id: str
39
+ workflow_name: str
40
+ start_time: datetime
41
+ end_time: Optional[datetime] = None
42
+ model_calls: List[ModelCall] = field(default_factory=list)
43
+ tool_calls: List[ToolCall] = field(default_factory=list)
44
+ total_tokens: int = 0
45
+ total_input_tokens: int = 0
46
+ total_output_tokens: int = 0
47
+
48
+ @property
49
+ def duration_seconds(self) -> float:
50
+ if self.end_time:
51
+ return (self.end_time - self.start_time).total_seconds()
52
+ return 0.0
53
+
54
+ def to_dict(self) -> Dict[str, Any]:
55
+ return {
56
+ "trace_id": self.trace_id,
57
+ "workflow_name": self.workflow_name,
58
+ "start_time": self.start_time.isoformat(),
59
+ "end_time": self.end_time.isoformat() if self.end_time else None,
60
+ "duration_seconds": self.duration_seconds,
61
+ "model_calls": [
62
+ {
63
+ "call_id": call.call_id,
64
+ "model": call.model,
65
+ "input_messages": call.input_messages,
66
+ "output_messages": call.output_messages,
67
+ "usage": call.usage,
68
+ "timestamp": call.timestamp.isoformat(),
69
+ "duration_ms": call.duration_ms
70
+ }
71
+ for call in self.model_calls
72
+ ],
73
+ "tool_calls": [
74
+ {
75
+ "call_id": call.call_id,
76
+ "tool_name": call.tool_name,
77
+ "input_args": call.input_args,
78
+ "output_result": call.output_result,
79
+ "timestamp": call.timestamp.isoformat(),
80
+ "duration_ms": call.duration_ms,
81
+ "success": call.success,
82
+ "error_message": call.error_message
83
+ }
84
+ for call in self.tool_calls
85
+ ],
86
+ "statistics": {
87
+ "total_model_calls": len(self.model_calls),
88
+ "total_tool_calls": len(self.tool_calls),
89
+ "total_tokens": self.total_tokens,
90
+ "total_input_tokens": self.total_input_tokens,
91
+ "total_output_tokens": self.total_output_tokens
92
+ }
93
+ }
94
+
95
+
96
+ class ExecutionTraceCollector(TracingProcessor):
97
+ """
98
+ Collect the execution traces of Agents (MODEL CALL and TOOL CALL).
99
+ """
100
+
101
+ def __init__(self):
102
+ self.traces: Dict[str, ExecutionTrace] = {}
103
+ self.active_spans: Dict[str, Dict[str, Any]] = {} # span_id -> span_info
104
+
105
+ def get_trace(self, trace_id: str) -> Optional[ExecutionTrace]:
106
+ return self.traces.get(trace_id)
107
+
108
+ def get_latest_trace(self) -> Optional[ExecutionTrace]:
109
+ if not self.traces:
110
+ return None
111
+ return max(self.traces.values(), key=lambda t: t.start_time)
112
+
113
+ def clear_traces(self) -> None:
114
+ self.traces.clear()
115
+ self.active_spans.clear()
116
+
117
+ def on_trace_start(self, trace: Trace) -> None:
118
+ execution_trace = ExecutionTrace(
119
+ trace_id=trace.trace_id,
120
+ workflow_name=trace.name or "unknown",
121
+ start_time=datetime.now()
122
+ )
123
+ self.traces[trace.trace_id] = execution_trace
124
+
125
+ def on_trace_end(self, trace: Trace) -> None:
126
+ if trace.trace_id in self.traces:
127
+ self.traces[trace.trace_id].end_time = datetime.now()
128
+
129
+ def on_span_start(self, span: Span) -> None:
130
+ span_info = {
131
+ "span_id": span.span_id,
132
+ "trace_id": span.trace_id,
133
+ "type": span.span_data.type,
134
+ "start_time": datetime.now()
135
+ }
136
+ self.active_spans[span.span_id] = span_info
137
+
138
+ def on_span_end(self, span: Span) -> None:
139
+ span_info = self.active_spans.get(span.span_id)
140
+ if not span_info:
141
+ return
142
+
143
+ trace = self.traces.get(span.trace_id)
144
+ if not trace:
145
+ return
146
+
147
+ duration_ms = None
148
+ if span_info.get("start_time"):
149
+ duration = datetime.now() - span_info["start_time"]
150
+ duration_ms = duration.total_seconds() * 1000
151
+
152
+ span_type = span.span_data.type
153
+
154
+ if span_type == "generation":
155
+ self._handle_model_call(span, trace, duration_ms)
156
+ elif span_type == "function":
157
+ self._handle_tool_call(span, trace, duration_ms)
158
+
159
+ self.active_spans.pop(span.span_id, None)
160
+
161
+ def _handle_model_call(self, span: Span, trace: ExecutionTrace, duration_ms: Optional[float]) -> None:
162
+ data = span.span_data
163
+
164
+ model_call = ModelCall(
165
+ call_id=len(trace.model_calls) + 1,
166
+ model=data.model or "unknown",
167
+ input_messages=data.input or [],
168
+ output_messages=data.output or [],
169
+ usage=data.usage,
170
+ duration_ms=duration_ms
171
+ )
172
+
173
+ trace.model_calls.append(model_call)
174
+
175
+ if data.usage:
176
+ trace.total_input_tokens += data.usage.get('input_tokens', 0)
177
+ trace.total_output_tokens += data.usage.get('output_tokens', 0)
178
+ trace.total_tokens += data.usage.get('total_tokens', 0)
179
+
180
+ def _handle_tool_call(self, span: Span, trace: ExecutionTrace, duration_ms: Optional[float]) -> None:
181
+ data = span.span_data
182
+
183
+ success = True
184
+ error_message = None
185
+
186
+ if data.output and isinstance(data.output, str):
187
+ if "error" in data.output.lower() or "exception" in data.output.lower():
188
+ success = False
189
+ error_message = data.output
190
+
191
+ tool_call = ToolCall(
192
+ call_id=len(trace.tool_calls) + 1,
193
+ tool_name=data.name or "unknown",
194
+ input_args=data.input,
195
+ output_result=data.output,
196
+ duration_ms=duration_ms,
197
+ success=success,
198
+ error_message=error_message
199
+ )
200
+
201
+ trace.tool_calls.append(tool_call)
202
+
203
+ def shutdown(self) -> None:
204
+ pass
205
+
206
+ def force_flush(self) -> None:
207
+ pass
@@ -0,0 +1,136 @@
1
+ """
2
+ File Recommendation Service - @ 文件推荐功能
3
+
4
+ This package provides intelligent file path auto-completion for @ commands.
5
+ When users type @ followed by text, the system provides real-time file and directory suggestions.
6
+
7
+ Main Components:
8
+ - FileRecommendationEngine: Main engine that coordinates all components
9
+ - CompletionEngine: Core completion logic
10
+ - FileDiscoveryService: File discovery and filtering
11
+ - Suggestion data structures and utilities
12
+
13
+ Usage:
14
+ from siada.services.file_recommendation import FileRecommendationEngine
15
+
16
+ engine = FileRecommendationEngine(
17
+ current_directory=os.getcwd(),
18
+ config=CompletionConfig()
19
+ )
20
+
21
+ if engine.should_show_suggestions("@src/main"):
22
+ suggestions = engine.get_suggestions("@src/main")
23
+ """
24
+
25
+ from .core.completion_engine import CompletionEngine
26
+ from .core.file_discovery import FileDiscoveryService
27
+ from .core.suggestion import Suggestion
28
+ from .core.config import CompletionConfig, FilterOptions, DEFAULT_COMPLETION_CONFIG
29
+ from .utils.path_utils import escape_path, unescape_path
30
+ from .utils.text_utils import (
31
+ is_completion_active,
32
+ parse_at_command_path,
33
+ to_code_points,
34
+ cp_len,
35
+ cp_slice
36
+ )
37
+
38
+ __all__ = [
39
+ # Main classes
40
+ 'CompletionEngine',
41
+ 'FileDiscoveryService',
42
+ 'FileRecommendationEngine',
43
+
44
+ # Data structures
45
+ 'Suggestion',
46
+ 'CompletionConfig',
47
+ 'FilterOptions',
48
+ 'DEFAULT_COMPLETION_CONFIG',
49
+
50
+ # Utilities
51
+ 'escape_path',
52
+ 'unescape_path',
53
+ 'is_completion_active',
54
+ 'parse_at_command_path',
55
+ 'to_code_points',
56
+ 'cp_len',
57
+ 'cp_slice'
58
+ ]
59
+
60
+ # Version information
61
+ __version__ = '1.0.0'
62
+ __author__ = 'Siada Team'
63
+ __description__ = 'Intelligent file path auto-completion for @ commands'
64
+
65
+
66
+ class FileRecommendationEngine:
67
+ """
68
+ Main file recommendation engine
69
+
70
+ This is the primary interface for the file recommendation functionality.
71
+ """
72
+
73
+ def __init__(self, current_directory: str = None, config: CompletionConfig = None):
74
+ """
75
+ Initialize the file recommendation engine
76
+
77
+ Args:
78
+ current_directory: Current working directory (default: current working directory)
79
+ config: Completion configuration (default: DEFAULT_COMPLETION_CONFIG)
80
+ """
81
+ import os
82
+
83
+ self.current_directory = current_directory or os.getcwd()
84
+ self.config = config or DEFAULT_COMPLETION_CONFIG
85
+
86
+ # Initialize components
87
+ self.file_discovery = FileDiscoveryService(self.current_directory)
88
+ self.completion_engine = CompletionEngine(
89
+ search_directories=[self.current_directory],
90
+ config=self.config
91
+ )
92
+
93
+ def should_show_suggestions(self, text: str, cursor_row: int = 0, cursor_col: int = None) -> bool:
94
+ """
95
+ Check if file suggestions should be shown
96
+
97
+ Args:
98
+ text: Input text
99
+ cursor_row: Cursor row position (default: 0)
100
+ cursor_col: Cursor column position (default: end of text)
101
+
102
+ Returns:
103
+ bool: True if suggestions should be shown
104
+ """
105
+ # Use the completion engine's logic for determining when to show suggestions
106
+ return self.completion_engine.should_show_suggestions(text)
107
+
108
+ async def get_suggestions(self, text: str) -> list[Suggestion]:
109
+ """
110
+ Get file suggestions for the given text
111
+
112
+ Args:
113
+ text: Input text containing @ command
114
+
115
+ Returns:
116
+ List of file suggestions
117
+ """
118
+ return await self.completion_engine.get_suggestions(text)
119
+
120
+ def get_suggestions_sync(self, text: str) -> list[Suggestion]:
121
+ """
122
+ Synchronous version of get_suggestions
123
+
124
+ Args:
125
+ text: Input text containing @ command
126
+
127
+ Returns:
128
+ List of file suggestions
129
+ """
130
+ import asyncio
131
+ try:
132
+ loop = asyncio.get_event_loop()
133
+ return loop.run_until_complete(self.get_suggestions(text))
134
+ except RuntimeError:
135
+ # No event loop running, create a new one
136
+ return asyncio.run(self.get_suggestions(text))
@@ -0,0 +1,17 @@
1
+ """
2
+ Core components for file recommendation functionality.
3
+ """
4
+
5
+ from .completion_engine import CompletionEngine
6
+ from .file_discovery import FileDiscoveryService
7
+ from .suggestion import Suggestion
8
+ from .config import CompletionConfig, FilterOptions, DEFAULT_COMPLETION_CONFIG
9
+
10
+ __all__ = [
11
+ 'CompletionEngine',
12
+ 'FileDiscoveryService',
13
+ 'Suggestion',
14
+ 'CompletionConfig',
15
+ 'FilterOptions',
16
+ 'DEFAULT_COMPLETION_CONFIG'
17
+ ]