codebuff-agent 2.1.74__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 (217) hide show
  1. codebuff_agent-2.1.74.data/data/etc/jupyter/jupyter_server_config.d/codebuff_agent.json +7 -0
  2. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/package.json +157 -0
  3. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/104.2b8f20f9d1ac2c9db01b.js +1 -0
  4. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/150.39fa98117cc8ca590465.js +1 -0
  5. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/166.386ff9b2c37ac865fdee.js +1 -0
  6. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/216.25cf81131bf7274dabf4.js +1 -0
  7. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/353.581bd1cb00746399b62e.js +1 -0
  8. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/367.575f9621b63c9a641aa9.js +1 -0
  9. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/421.11dac223a2c2da1b09f5.js +1 -0
  10. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/432.8513b4c6cc1d1232d165.js +2 -0
  11. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/432.8513b4c6cc1d1232d165.js.LICENSE.txt +19 -0
  12. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/439.ba5b5ef70ec6de214b8c.js +2 -0
  13. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/439.ba5b5ef70ec6de214b8c.js.LICENSE.txt +8 -0
  14. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/481.cc2dec9fa869d66f1407.js +1 -0
  15. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/487.0796e931d6e651482c14.js +1 -0
  16. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/49.d326f554b6f9ccde6580.js +1 -0
  17. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/541.26897ea32845659e36be.js +1 -0
  18. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/579.e569d3edd8391fd8fbb3.js +1 -0
  19. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/58.eb7cc679f7535cc8a2f1.js +2 -0
  20. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/58.eb7cc679f7535cc8a2f1.js.LICENSE.txt +8 -0
  21. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/666.d9bfdb23f98489d0a188.js +1 -0
  22. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/677.d266c39dbed33bc388b3.js +2 -0
  23. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/677.d266c39dbed33bc388b3.js.LICENSE.txt +8 -0
  24. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/68.26b6f59c8454adb17f20.js +204 -0
  25. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/694.4ac443814260057e68f7.js +1 -0
  26. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/791.61affb8d3480d3d60e0d.js +1 -0
  27. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/848.4d2db09cfbb09374b299.js +2 -0
  28. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/848.4d2db09cfbb09374b299.js.LICENSE.txt +9 -0
  29. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/868.5cfe7e1a348ec5af1b8c.js +1 -0
  30. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/97.ea559a5b8a9a09f17c6b.js +1 -0
  31. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/remoteEntry.5292fc9c6df7e7920cc8.js +1 -0
  32. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/style.js +4 -0
  33. codebuff_agent-2.1.74.data/data/share/jupyter/labextensions/codebuff/static/third-party-licenses.json +724 -0
  34. codebuff_agent-2.1.74.dist-info/METADATA +142 -0
  35. codebuff_agent-2.1.74.dist-info/RECORD +217 -0
  36. codebuff_agent-2.1.74.dist-info/WHEEL +4 -0
  37. codebuff_agent-2.1.74.dist-info/licenses/LICENSE +21 -0
  38. codebuff_core/__init__.py +153 -0
  39. codebuff_core/codebuff_config_defaults.json +64 -0
  40. codebuff_core/core/__init__.py +35 -0
  41. codebuff_core/core/code_validator.py +1238 -0
  42. codebuff_core/core/error_classifier.py +579 -0
  43. codebuff_core/core/exceptions.py +49 -0
  44. codebuff_core/data/tiktoken_cache/9b5ad71b2ce5302211f9c61530b329a4922fc6a4 +100256 -0
  45. codebuff_core/directory_policy.py +32 -0
  46. codebuff_core/factory.py +155 -0
  47. codebuff_core/interfaces.py +197 -0
  48. codebuff_core/knowledge/__init__.py +31 -0
  49. codebuff_core/knowledge/chunking.py +375 -0
  50. codebuff_core/knowledge/loader.py +339 -0
  51. codebuff_core/knowledge/watchdog_service.py +354 -0
  52. codebuff_core/legacy_paths.py +69 -0
  53. codebuff_core/llm/__init__.py +13 -0
  54. codebuff_core/llm/service.py +407 -0
  55. codebuff_core/managers/__init__.py +22 -0
  56. codebuff_core/managers/config_manager.py +690 -0
  57. codebuff_core/managers/remote_config.py +673 -0
  58. codebuff_core/managers/remote_skills.py +539 -0
  59. codebuff_core/managers/session_manager.py +255 -0
  60. codebuff_core/middleware/__init__.py +3 -0
  61. codebuff_core/middleware/error_recovery.py +394 -0
  62. codebuff_core/middleware/logging_utils.py +33 -0
  63. codebuff_core/models/__init__.py +111 -0
  64. codebuff_core/models/agent.py +306 -0
  65. codebuff_core/models/chat.py +57 -0
  66. codebuff_core/models/common.py +82 -0
  67. codebuff_core/models/rag.py +300 -0
  68. codebuff_core/platform_rules.py +127 -0
  69. codebuff_core/prompts/__init__.py +44 -0
  70. codebuff_core/prompts/auto_agent_prompts.py +1278 -0
  71. codebuff_core/services/__init__.py +30 -0
  72. codebuff_core/services/agent_service.py +345 -0
  73. codebuff_core/services/analytics_aggregate.py +837 -0
  74. codebuff_core/services/chat_service.py +898 -0
  75. codebuff_core/services/context_condenser.py +306 -0
  76. codebuff_core/services/pii_guardrail.py +393 -0
  77. codebuff_core/services/rag_chat_agent.py +2993 -0
  78. codebuff_core/services/rag_collections.py +2740 -0
  79. codebuff_core/services/rag_manager.py +890 -0
  80. codebuff_core/services/rag_service.py +145 -0
  81. codebuff_core/services/retriever.py +260 -0
  82. codebuff_core/services/vllm_embedding_service.py +290 -0
  83. codebuff_core/tests/__init__.py +1 -0
  84. codebuff_core/tests/conftest.py +81 -0
  85. codebuff_core/tests/test_error_recovery.py +647 -0
  86. codebuff_core/tests/test_factory.py +135 -0
  87. codebuff_core/tests/test_services.py +150 -0
  88. jupyter_ext/__init__.py +266 -0
  89. jupyter_ext/_version.py +4 -0
  90. jupyter_ext/agent/__init__.py +49 -0
  91. jupyter_ext/agent/agent_factory.py +2270 -0
  92. jupyter_ext/agent/ast_tools.py +451 -0
  93. jupyter_ext/agent/autofix_middleware.py +481 -0
  94. jupyter_ext/agent/background_procs.py +372 -0
  95. jupyter_ext/agent/code_history_middleware.py +211 -0
  96. jupyter_ext/agent/codex_autofix.py +160 -0
  97. jupyter_ext/agent/codex_bridge.py +3339 -0
  98. jupyter_ext/agent/codex_hooks.py +320 -0
  99. jupyter_ext/agent/codex_slash.py +685 -0
  100. jupyter_ext/agent/codex_threads.py +114 -0
  101. jupyter_ext/agent/content_injection.py +377 -0
  102. jupyter_ext/agent/continuation_middleware.py +548 -0
  103. jupyter_ext/agent/custom_skills.py +335 -0
  104. jupyter_ext/agent/file_diffs.py +99 -0
  105. jupyter_ext/agent/git_history.py +188 -0
  106. jupyter_ext/agent/guardrail_middleware.py +421 -0
  107. jupyter_ext/agent/json_repair_utils.py +54 -0
  108. jupyter_ext/agent/langchain_tools.py +2673 -0
  109. jupyter_ext/agent/mermaid_fixer.py +289 -0
  110. jupyter_ext/agent/mermaid_middleware.py +135 -0
  111. jupyter_ext/agent/middleware.py +359 -0
  112. jupyter_ext/agent/middleware_prompts.py +53 -0
  113. jupyter_ext/agent/observability.py +334 -0
  114. jupyter_ext/agent/patch_tool_calls.py +57 -0
  115. jupyter_ext/agent/prompts.py +112 -0
  116. jupyter_ext/agent/skill_middleware.py +257 -0
  117. jupyter_ext/agent/skills/airflow_dag_development.md +36 -0
  118. jupyter_ext/agent/skills/anomaly_detection.md +12 -0
  119. jupyter_ext/agent/skills/athena_sql.md +156 -0
  120. jupyter_ext/agent/skills/bdp_table_search.md +33 -0
  121. jupyter_ext/agent/skills/bigquery.md +65 -0
  122. jupyter_ext/agent/skills/bigquery_oracle.md +231 -0
  123. jupyter_ext/agent/skills/bigquery_tuning.md +307 -0
  124. jupyter_ext/agent/skills/classification_evaluation.md +11 -0
  125. jupyter_ext/agent/skills/clustering_analysis.md +12 -0
  126. jupyter_ext/agent/skills/comprehensive_eda.md +11 -0
  127. jupyter_ext/agent/skills/data_analysis.md +236 -0
  128. jupyter_ext/agent/skills/data_cleaning_pipeline.md +12 -0
  129. jupyter_ext/agent/skills/data_loading.md +158 -0
  130. jupyter_ext/agent/skills/data_quality_report.md +13 -0
  131. jupyter_ext/agent/skills/dimensionality_reduction.md +12 -0
  132. jupyter_ext/agent/skills/emr_script_development.md +17 -0
  133. jupyter_ext/agent/skills/experiment_tracking.md +13 -0
  134. jupyter_ext/agent/skills/feature_importance_analysis.md +10 -0
  135. jupyter_ext/agent/skills/hyperparameter_tuning.md +12 -0
  136. jupyter_ext/agent/skills/hypothesis_testing.md +12 -0
  137. jupyter_ext/agent/skills/imbalanced_data_handling.md +12 -0
  138. jupyter_ext/agent/skills/inference.md +392 -0
  139. jupyter_ext/agent/skills/lambda_function_development.md +19 -0
  140. jupyter_ext/agent/skills/model_comparison.md +11 -0
  141. jupyter_ext/agent/skills/model_explainability.md +12 -0
  142. jupyter_ext/agent/skills/model_training.md +318 -0
  143. jupyter_ext/agent/skills/pyspark.md +352 -0
  144. jupyter_ext/agent/skills/python_code_quality.md +35 -0
  145. jupyter_ext/agent/skills/regression_evaluation.md +12 -0
  146. jupyter_ext/agent/skills/spring_java_development.md +35 -0
  147. jupyter_ext/agent/skills/text_preprocessing.md +12 -0
  148. jupyter_ext/agent/skills/time_series_analysis.md +13 -0
  149. jupyter_ext/agent/skills/unit_testing.md +203 -0
  150. jupyter_ext/agent/todo_prompts.py +57 -0
  151. jupyter_ext/agent/tool_report.py +45 -0
  152. jupyter_ext/analytics_ingest.py +599 -0
  153. jupyter_ext/etc/jupyter/jupyter_server_config.d/codebuff_agent.json +7 -0
  154. jupyter_ext/handlers/__init__.py +8 -0
  155. jupyter_ext/handlers/analytics_handler.py +170 -0
  156. jupyter_ext/handlers/benchmark_handler.py +794 -0
  157. jupyter_ext/handlers/eda_benchmark_handler.py +1328 -0
  158. jupyter_ext/handlers/rag_admin_handler.py +689 -0
  159. jupyter_ext/handlers/websocket.py +497 -0
  160. jupyter_ext/http_handlers.py +8744 -0
  161. jupyter_ext/idle_monitor.py +346 -0
  162. jupyter_ext/labextension/package.json +157 -0
  163. jupyter_ext/labextension/static/104.2b8f20f9d1ac2c9db01b.js +1 -0
  164. jupyter_ext/labextension/static/150.39fa98117cc8ca590465.js +1 -0
  165. jupyter_ext/labextension/static/166.386ff9b2c37ac865fdee.js +1 -0
  166. jupyter_ext/labextension/static/216.25cf81131bf7274dabf4.js +1 -0
  167. jupyter_ext/labextension/static/353.581bd1cb00746399b62e.js +1 -0
  168. jupyter_ext/labextension/static/367.575f9621b63c9a641aa9.js +1 -0
  169. jupyter_ext/labextension/static/421.11dac223a2c2da1b09f5.js +1 -0
  170. jupyter_ext/labextension/static/432.8513b4c6cc1d1232d165.js +2 -0
  171. jupyter_ext/labextension/static/432.8513b4c6cc1d1232d165.js.LICENSE.txt +19 -0
  172. jupyter_ext/labextension/static/439.ba5b5ef70ec6de214b8c.js +2 -0
  173. jupyter_ext/labextension/static/439.ba5b5ef70ec6de214b8c.js.LICENSE.txt +8 -0
  174. jupyter_ext/labextension/static/481.cc2dec9fa869d66f1407.js +1 -0
  175. jupyter_ext/labextension/static/487.0796e931d6e651482c14.js +1 -0
  176. jupyter_ext/labextension/static/49.d326f554b6f9ccde6580.js +1 -0
  177. jupyter_ext/labextension/static/541.26897ea32845659e36be.js +1 -0
  178. jupyter_ext/labextension/static/579.e569d3edd8391fd8fbb3.js +1 -0
  179. jupyter_ext/labextension/static/58.eb7cc679f7535cc8a2f1.js +2 -0
  180. jupyter_ext/labextension/static/58.eb7cc679f7535cc8a2f1.js.LICENSE.txt +8 -0
  181. jupyter_ext/labextension/static/666.d9bfdb23f98489d0a188.js +1 -0
  182. jupyter_ext/labextension/static/677.d266c39dbed33bc388b3.js +2 -0
  183. jupyter_ext/labextension/static/677.d266c39dbed33bc388b3.js.LICENSE.txt +8 -0
  184. jupyter_ext/labextension/static/68.26b6f59c8454adb17f20.js +204 -0
  185. jupyter_ext/labextension/static/694.4ac443814260057e68f7.js +1 -0
  186. jupyter_ext/labextension/static/791.61affb8d3480d3d60e0d.js +1 -0
  187. jupyter_ext/labextension/static/848.4d2db09cfbb09374b299.js +2 -0
  188. jupyter_ext/labextension/static/848.4d2db09cfbb09374b299.js.LICENSE.txt +9 -0
  189. jupyter_ext/labextension/static/868.5cfe7e1a348ec5af1b8c.js +1 -0
  190. jupyter_ext/labextension/static/97.ea559a5b8a9a09f17c6b.js +1 -0
  191. jupyter_ext/labextension/static/remoteEntry.5292fc9c6df7e7920cc8.js +1 -0
  192. jupyter_ext/labextension/static/style.js +4 -0
  193. jupyter_ext/labextension/static/third-party-licenses.json +724 -0
  194. jupyter_ext/log_paths.py +113 -0
  195. jupyter_ext/resource_usage.py +519 -0
  196. jupyter_ext/secrets_bootstrap.py +116 -0
  197. jupyter_ext/team_access.py +105 -0
  198. jupyter_ext/tests/__init__.py +1 -0
  199. jupyter_ext/tests/test_context.py +234 -0
  200. jupyter_ext/tests/test_factory.py +563 -0
  201. jupyter_ext/tests/test_file_finder.py +139 -0
  202. jupyter_ext/tests/test_handlers.py +58 -0
  203. jupyter_ext/tests/test_mcp_selftest.py +204 -0
  204. jupyter_ext/tests/test_mermaid_fixer.py +272 -0
  205. jupyter_ext/tests/test_resource_tiers.py +298 -0
  206. jupyter_ext/tools/__init__.py +15 -0
  207. jupyter_ext/tools/base.py +90 -0
  208. jupyter_ext/tools/context.py +268 -0
  209. jupyter_ext/tools/dir_complete.py +86 -0
  210. jupyter_ext/tools/file_finder.py +303 -0
  211. jupyter_ext/tools/file_tools.py +244 -0
  212. jupyter_ext/tools/jupyter_tools.py +296 -0
  213. jupyter_ext/tools/registry.py +159 -0
  214. jupyter_ext/tools/search_tools.py +230 -0
  215. jupyter_ext/tools/security_tools.py +657 -0
  216. jupyter_ext/tools/shell_tools.py +109 -0
  217. jupyter_ext/tools/user_tools.py +132 -0
@@ -0,0 +1,300 @@
1
+ """
2
+ RAG 설정 및 API Pydantic 모델
3
+
4
+ 로컬 RAG 시스템을 위한 설정 스키마 정의:
5
+ - Qdrant 벡터 데이터베이스 설정
6
+ - 임베딩 모델 설정
7
+ - 문서 청킹 설정
8
+ - 파일 감시(watchdog) 설정
9
+ - 검색 API 요청/응답 모델
10
+ """
11
+
12
+ import os
13
+ from typing import Optional, List, Literal, Dict, Any
14
+ from pydantic import BaseModel, Field
15
+
16
+
17
+ class QdrantConfig(BaseModel):
18
+ """Qdrant 벡터 데이터베이스 설정"""
19
+
20
+ mode: Literal["local", "server", "cloud"] = Field(
21
+ default="local",
22
+ description="배포 모드: local (파일 기반), server (Docker), cloud",
23
+ )
24
+ # 로컬 모드 설정
25
+ local_path: Optional[str] = Field(
26
+ default=None,
27
+ description="로컬 Qdrant 저장소 경로. 기본값: $QDRANT_PATH, 없으면 $CODEBUFF_HOME/qdrant, 없으면 ~/.codebuff/qdrant",
28
+ )
29
+ # 서버 모드 설정
30
+ url: Optional[str] = Field(
31
+ default="http://localhost:6333",
32
+ description="server/cloud 모드용 Qdrant 서버 URL",
33
+ )
34
+ api_key: Optional[str] = Field(default=None, description="cloud 모드용 API 키")
35
+ # 컬렉션 설정
36
+ collection_name: str = Field(
37
+ default="hdsp_knowledge", description="벡터 컬렉션 이름"
38
+ )
39
+
40
+ def get_mode(self) -> str:
41
+ """Qdrant 배포 모드 반환"""
42
+ return self.mode
43
+
44
+ def get_url(self) -> str:
45
+ """Qdrant 서버 URL 반환"""
46
+ return self.url or "http://localhost:6333"
47
+
48
+ def get_local_path(self) -> str:
49
+ """해석된 로컬 경로 반환"""
50
+ if self.local_path:
51
+ return os.path.expanduser(self.local_path)
52
+ from codebuff_core.legacy_paths import resolve_home
53
+
54
+ return str(resolve_home("qdrant"))
55
+
56
+
57
+ class EmbeddingConfig(BaseModel):
58
+ """임베딩 모델 설정"""
59
+
60
+ model_name: str = Field(
61
+ default="intfloat/multilingual-e5-small",
62
+ description="임베딩용 HuggingFace 모델 이름",
63
+ )
64
+ device: Literal["cpu", "cuda", "mps"] = Field(
65
+ default="cpu", description="임베딩 계산용 디바이스"
66
+ )
67
+ batch_size: int = Field(default=32, description="임베딩 생성 배치 크기")
68
+ cache_folder: Optional[str] = Field(
69
+ default=None, description="모델 캐시 폴더. 기본값: ~/.cache/huggingface"
70
+ )
71
+ # 모델별 설정
72
+ normalize_embeddings: bool = Field(
73
+ default=True, description="코사인 유사도를 위한 임베딩 정규화"
74
+ )
75
+
76
+ def get_model_name(self) -> str:
77
+ """임베딩 모델 이름 반환"""
78
+ return self.model_name
79
+
80
+ def get_device(self) -> str:
81
+ """임베딩 계산 디바이스 반환"""
82
+ return self.device
83
+
84
+
85
+ class ChunkingConfig(BaseModel):
86
+ """문서 청킹 설정"""
87
+
88
+ chunk_size: int = Field(default=512, description="목표 청크 크기 (문자 단위)")
89
+ chunk_overlap: int = Field(default=50, description="청크 간 중첩 (문자 단위)")
90
+ split_by_header: bool = Field(
91
+ default=True, description="의미적 경계를 위해 마크다운을 헤더 기준으로 분할"
92
+ )
93
+ min_chunk_size: int = Field(default=100, description="포함할 최소 청크 크기")
94
+ max_chunk_size: int = Field(default=2000, description="최대 청크 크기 (하드 리밋)")
95
+
96
+
97
+ class WatchdogConfig(BaseModel):
98
+ """파일 모니터링 설정"""
99
+
100
+ enabled: bool = Field(default=True, description="파일 시스템 모니터링 활성화")
101
+ debounce_seconds: float = Field(
102
+ default=2.0, description="파일 변경 이벤트 디바운스 시간"
103
+ )
104
+ patterns: List[str] = Field(
105
+ default=["*.md", "*.py", "*.txt", "*.json"], description="모니터링할 파일 패턴"
106
+ )
107
+ ignore_patterns: List[str] = Field(
108
+ default=[".*", "__pycache__", "*.pyc", "*.egg-info"], description="무시할 패턴"
109
+ )
110
+
111
+
112
+ class RAGConfig(BaseModel):
113
+ """메인 RAG 시스템 설정"""
114
+
115
+ enabled: bool = Field(default=True, description="RAG 시스템 활성화")
116
+ knowledge_base_path: Optional[str] = Field(
117
+ default=None, description="지식 베이스 경로. 기본값: 내장 libraries/"
118
+ )
119
+ qdrant: QdrantConfig = Field(default_factory=QdrantConfig)
120
+ embedding: EmbeddingConfig = Field(default_factory=EmbeddingConfig)
121
+ chunking: ChunkingConfig = Field(default_factory=ChunkingConfig)
122
+ watchdog: WatchdogConfig = Field(default_factory=WatchdogConfig)
123
+
124
+ # 검색 설정
125
+ top_k: int = Field(default=5, description="검색할 청크 수")
126
+ score_threshold: float = Field(default=0.3, description="최소 유사도 점수 임계값")
127
+ max_context_tokens: int = Field(
128
+ default=1500, description="RAG 컨텍스트 주입 최대 토큰"
129
+ )
130
+
131
+ def is_enabled(self) -> bool:
132
+ """RAG 활성화 여부 확인"""
133
+ return self.enabled
134
+
135
+ def get_knowledge_base_path(self) -> Optional[str]:
136
+ """지식 베이스 경로 반환"""
137
+ if self.knowledge_base_path:
138
+ return os.path.expanduser(self.knowledge_base_path)
139
+ return None # 내장 기본값 사용
140
+
141
+
142
+ # ============ API 요청/응답 모델 ============
143
+
144
+
145
+ class SearchRequest(BaseModel):
146
+ """명시적 RAG 검색 요청 본문"""
147
+
148
+ query: str = Field(description="검색 쿼리")
149
+ top_k: Optional[int] = Field(default=None, description="기본 top_k 오버라이드")
150
+ filters: Optional[Dict[str, Any]] = Field(
151
+ default=None, description="메타데이터 필터 (예: {'source_type': 'library'})"
152
+ )
153
+ include_score: bool = Field(default=True, description="결과에 관련성 점수 포함")
154
+
155
+
156
+ class SearchResult(BaseModel):
157
+ """단일 검색 결과"""
158
+
159
+ content: str = Field(description="청크 내용")
160
+ score: float = Field(description="관련성 점수 (0-1)")
161
+ metadata: Dict[str, Any] = Field(description="청크 메타데이터 (소스, 유형 등)")
162
+
163
+
164
+ class SearchResponse(BaseModel):
165
+ """RAG 검색 응답 본문"""
166
+
167
+ results: List[SearchResult] = Field(description="관련성순으로 정렬된 검색 결과")
168
+ query: str = Field(description="원본 쿼리")
169
+ total_results: int = Field(description="총 일치 청크 수")
170
+
171
+
172
+ class IndexStatusResponse(BaseModel):
173
+ """인덱스 상태 응답 본문"""
174
+
175
+ ready: bool = Field(description="RAG 시스템 준비 여부")
176
+ total_documents: int = Field(default=0, description="총 인덱싱된 문서 수")
177
+ total_chunks: int = Field(default=0, description="총 인덱싱된 청크 수")
178
+ last_updated: Optional[str] = Field(
179
+ default=None, description="마지막 인덱스 업데이트 타임스탬프"
180
+ )
181
+ knowledge_base_path: Optional[str] = Field(
182
+ default=None, description="현재 지식 베이스 경로"
183
+ )
184
+
185
+
186
+ class ReindexRequest(BaseModel):
187
+ """수동 재인덱싱 요청 본문"""
188
+
189
+ force: bool = Field(
190
+ default=False, description="파일이 변경되지 않아도 전체 재인덱싱 강제"
191
+ )
192
+ path: Optional[str] = Field(
193
+ default=None, description="재인덱싱할 특정 파일 또는 디렉토리"
194
+ )
195
+
196
+
197
+ class ReindexResponse(BaseModel):
198
+ """재인덱싱 작업 응답 본문"""
199
+
200
+ success: bool = Field(description="재인덱싱 성공 여부")
201
+ indexed: int = Field(description="인덱싱된 파일 수")
202
+ skipped: int = Field(description="건너뛴 파일 수 (변경 없음)")
203
+ errors: List[Dict[str, str]] = Field(default=[], description="인덱싱 오류 목록")
204
+
205
+
206
+ # ============ 디버그 모델 ============
207
+
208
+
209
+ class ChunkDebugInfo(BaseModel):
210
+ """디버깅용 청크 상세 점수 정보"""
211
+
212
+ chunk_id: str
213
+ content_preview: str # 처음 200자
214
+ score: float # 벡터 유사도 점수 (0-1)
215
+ rank: int # 순위
216
+ metadata: Dict[str, Any] # source, section 등
217
+ passed_threshold: bool # 임계값 통과 여부
218
+
219
+
220
+ class LibraryDetectionDebug(BaseModel):
221
+ """라이브러리 감지 단계 디버그 정보"""
222
+
223
+ input_query: str
224
+ imported_libraries: List[str]
225
+ available_libraries: List[str]
226
+ detected_libraries: List[str]
227
+ detection_method: str
228
+
229
+
230
+ class SearchConfigDebug(BaseModel):
231
+ """검색 설정 정보"""
232
+
233
+ top_k: int
234
+ score_threshold: float
235
+ max_context_tokens: int
236
+
237
+
238
+ class DebugSearchRequest(BaseModel):
239
+ """디버그 검색 요청"""
240
+
241
+ query: str = Field(description="디버깅용 검색 쿼리")
242
+ imported_libraries: List[str] = Field(
243
+ default=[], description="검색 필터링을 위한 import된 라이브러리 목록"
244
+ )
245
+ top_k: Optional[int] = Field(default=None, description="기본 top_k 오버라이드")
246
+ include_full_content: bool = Field(
247
+ default=False, description="미리보기 대신 전체 내용 포함"
248
+ )
249
+ simulate_plan_context: bool = Field(
250
+ default=True, description="계획 생성 시와 같은 포맷된 컨텍스트 생성"
251
+ )
252
+
253
+
254
+ class DebugSearchResponse(BaseModel):
255
+ """디버그 검색 응답"""
256
+
257
+ library_detection: LibraryDetectionDebug
258
+ config: SearchConfigDebug
259
+ chunks: List[ChunkDebugInfo]
260
+ total_candidates: int
261
+ total_passed_threshold: int
262
+ search_ms: float # 벡터 검색 시간 (밀리초)
263
+ formatted_context: str
264
+ context_char_count: int
265
+ estimated_context_tokens: int
266
+
267
+
268
+ # ============ 팩토리 함수 ============
269
+
270
+
271
+ def get_default_rag_config() -> RAGConfig:
272
+ """ConfigManager JSON에서 RAG 설정 로드"""
273
+ from codebuff_core.managers.config_manager import get_config_manager
274
+
275
+ cfg = get_config_manager().get_config()
276
+ rag = cfg.get("rag", {})
277
+
278
+ # 환경변수 우선 → config 파일 폴백
279
+ qdrant_mode = os.environ.get("QDRANT_MODE", "") or rag.get("qdrantMode", "local")
280
+ qdrant_url = os.environ.get("QDRANT_URL", "") or rag.get("qdrantUrl", "http://localhost:6333")
281
+ qdrant_path = os.environ.get("QDRANT_PATH", "") or rag.get("qdrantPath")
282
+ qdrant_api_key = os.environ.get("QDRANT_API_KEY", "") or rag.get("qdrantApiKey")
283
+
284
+ return RAGConfig(
285
+ enabled=rag.get("enabled", True),
286
+ knowledge_base_path=rag.get("knowledgeBasePath"),
287
+ qdrant=QdrantConfig(
288
+ mode=qdrant_mode,
289
+ url=qdrant_url,
290
+ local_path=qdrant_path or None,
291
+ api_key=qdrant_api_key or None,
292
+ collection_name=rag.get("collectionName", "hdsp_knowledge"),
293
+ ),
294
+ embedding=EmbeddingConfig(
295
+ model_name=rag.get("embeddingModel", "intfloat/multilingual-e5-small"),
296
+ device=rag.get("embeddingDevice", "cpu"),
297
+ ),
298
+ chunking=ChunkingConfig(),
299
+ watchdog=WatchdogConfig(),
300
+ )
@@ -0,0 +1,127 @@
1
+ """사내 BDP 플랫폼(HDSP 노트북) 실행 환경 규칙 — 두 엔진이 같이 쓰는 정본 (이슈 #120).
2
+
3
+ HDSP 노트북 pod 에서는 boto3 를 직접 쓸 수 없다. 기본 자격증명·SSL 경로가 막혀 있어서
4
+ (`secrets_bootstrap.py` 주석 참고) 미리 설치된 bdpengine 의 클라이언트 팩토리를 거쳐야
5
+ Athena·S3·SageMaker·MinIO 에 닿는다. 모델이 이것을 모르면 boto3 로 코드를 쓴다.
6
+
7
+ 그래서 세 가지를 여기 한 곳에 둔다:
8
+ - 판정 `is_bdp_platform()` — `HDSP_ENV` 가 dev/prod 면 사내다. `CODEBUFF_BDP_RULES=1/0` 이 우선한다
9
+ (로컬에서 켜 보거나, 운영에서 문구가 틀렸을 때 재배포 없이 끄는 스위치).
10
+ - 규칙 텍스트 `platform_rules_block()` — 지시문에 붙인다. 사내가 아니면 빈 문자열이라
11
+ 로컬 동작은 한 글자도 안 바뀐다. centri 키 `prompts.bdp_platform_rules`(이슈 #178), 없으면
12
+ `~/.codebuff/bdp_rules.md` 가 내장 텍스트를 대체한다.
13
+ - 가드 `tool_call_violation()` — 도구 인자에서 boto3 직접 사용을 찾아 bdpengine 안내를 돌려준다.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import os
19
+ import re
20
+ from typing import Any, Dict, Optional
21
+
22
+ BDP_RULES_ENV = "CODEBUFF_BDP_RULES"
23
+ BDP_RULES_PATH = "~/.codebuff/bdp_rules.md"
24
+
25
+ _PLATFORM_ENVS = ("dev", "prod")
26
+
27
+ #: 내장 규칙 문구는 스냅샷 `prompts.bdp_platform_rules` 다 (이슈 #218 — 코드 상수 없음).
28
+ #: 저장소에서 확인된 bdpengine 함수는 `start_query`·`get_boto3_client` 둘뿐이다
29
+ #: (`secrets_bootstrap.py`, `http_handlers.py`, `mock_packages/bdpengine`). 나머지는 지어내지
30
+ #: 않고 모델이 직접 확인하게 한다. 사내 관리자는 `~/.codebuff/bdp_rules.md` 로 바꾼다.
31
+
32
+ BDP_GUARD_MESSAGE = (
33
+ "이 환경(HDSP 노트북)에서는 boto3 를 직접 쓸 수 없습니다 (감지: `{line}`). "
34
+ "`from bdpengine.functions import ...` 로 다시 작성하세요 — Athena 는 "
35
+ "`start_query(query=...)`, AWS 클라이언트가 필요하면 `get_boto3_client('<service>')`."
36
+ )
37
+
38
+ # 코드: 줄 머리의 import 와 클라이언트 직접 생성. `get_boto3_client` 는 `_` 가 단어 문자라
39
+ # `\bboto3` 경계가 서지 않아 걸리지 않는다.
40
+ _CODE_IMPORT = re.compile(r"^\s*(?:import|from)\s+boto3\b")
41
+ _CLIENT_CALL = re.compile(r"\bboto3\.(?:client|resource|Session|session)\s*\(")
42
+ # 셸: `python -c "import boto3"` 처럼 import 가 줄 가운데 온다.
43
+ _SHELL_IMPORT = re.compile(r"\b(?:import|from)\s+boto3\b")
44
+ # 검색은 실행이 아니다 — `grep "import boto3"` 는 boto3 를 옮기는 작업의 첫 수다.
45
+ _SHELL_SEARCH = re.compile(r"^\s*(?:grep|egrep|rg|ag|ack|git\s+grep)\b")
46
+ _SWITCH_ON = ("1", "true", "yes", "on")
47
+ _SWITCH_OFF = ("0", "false", "no", "off")
48
+ _MAX_REPORTED = 200
49
+
50
+ #: 도구 이름 → (코드가 실리는 인자, 셸 명령인가). 두 엔진의 쓰기·실행 도구를 다 적는다
51
+ #: — codex: write_file·edit_file·execute_command, client: jupyter_cell·file_write·write_file·edit_file.
52
+ _TOOL_CODE_FIELDS = {
53
+ "write_file": ("content", False),
54
+ "edit_file": ("new_string", False),
55
+ "execute_command": ("command", True),
56
+ "jupyter_cell": ("code", False),
57
+ "file_write": ("content", False),
58
+ }
59
+
60
+
61
+ def is_bdp_platform() -> bool:
62
+ switch = os.environ.get(BDP_RULES_ENV, "").strip().lower()
63
+ if switch in _SWITCH_ON or switch in _SWITCH_OFF:
64
+ return switch in _SWITCH_ON
65
+ return os.environ.get("HDSP_ENV", "").strip().lower() in _PLATFORM_ENVS
66
+
67
+
68
+ def platform_rules_block() -> str:
69
+ """사내면 지시문에 붙일 규칙, 아니면 빈 문자열.
70
+
71
+ 문구는 centri 키 `prompts.bdp_platform_rules` > `~/.codebuff/bdp_rules.md` > 스냅샷 기본값
72
+ 순이다 (이슈 #178, #218). 키는 문구만 바꾼다 — 사내가 아니면 키가 있어도 붙이지 않는다.
73
+ """
74
+ if not is_bdp_platform():
75
+ return ""
76
+ from codebuff_core.managers.config_manager import configured_prompt
77
+
78
+ configured = configured_prompt("bdp_platform_rules")
79
+ if configured:
80
+ return configured
81
+ try:
82
+ with open(os.path.expanduser(BDP_RULES_PATH), encoding="utf-8") as f:
83
+ custom = f.read().strip()
84
+ if custom:
85
+ return custom
86
+ except (OSError, UnicodeDecodeError):
87
+ # 관리자 파일 하나가 두 엔진의 시작을 막지 않게 내장 문구로 돌아간다
88
+ pass
89
+ from codebuff_core.managers.remote_config import snapshot_prompt
90
+
91
+ return snapshot_prompt("bdp_platform_rules")
92
+
93
+
94
+ def find_direct_boto3(text: str, shell: bool = False) -> Optional[str]:
95
+ """boto3 를 직접 쓰는 첫 줄(최대 200자)을 돌려준다. 없으면 None.
96
+
97
+ `#` 뒤 주석은 보지 않는다. 문자열·docstring 안의 `boto3.client(` 는 잡는다(오탐).
98
+ `import os, boto3` 처럼 줄 머리가 아닌 import 는 못 잡는다(미탐) — 앵커를 풀면
99
+ 주석·문자열 오탐이 늘어서 이쪽을 택했다. 한계는 테스트가 고정한다.
100
+ """
101
+ imports = _SHELL_IMPORT if shell else _CODE_IMPORT
102
+ for line in (text or "").splitlines():
103
+ code = line.split("#", 1)[0]
104
+ if not code.strip() or (shell and _SHELL_SEARCH.search(code)):
105
+ continue
106
+ if imports.search(code) or _CLIENT_CALL.search(code):
107
+ return line.strip()[:_MAX_REPORTED]
108
+ return None
109
+
110
+
111
+ def tool_call_violation(tool_name: str, args: Dict[str, Any]) -> Optional[str]:
112
+ """사내에서 도구 인자가 boto3 를 직접 쓰면 모델에 돌려줄 오류 문구, 아니면 None."""
113
+ field = _TOOL_CODE_FIELDS.get(tool_name)
114
+ if field is None or not is_bdp_platform():
115
+ return None
116
+ key, shell = field
117
+ value = (args or {}).get(key)
118
+ if not isinstance(value, str):
119
+ return None
120
+ line = find_direct_boto3(value, shell=shell)
121
+ return BDP_GUARD_MESSAGE.format(line=line) if line else None
122
+
123
+
124
+ def with_platform_rules(prompt: str) -> str:
125
+ """사내면 프롬프트 뒤에 규칙을 붙인다. 아니면 그대로 돌려준다."""
126
+ rules = platform_rules_block()
127
+ return prompt + "\n\n" + rules if rules else prompt
@@ -0,0 +1,44 @@
1
+ """
2
+ Codebuff Core - Prompts
3
+
4
+ Prompt templates for Auto-Agent.
5
+ """
6
+
7
+ from .auto_agent_prompts import (
8
+ ADAPTIVE_REPLAN_PROMPT,
9
+ CODE_GENERATION_PROMPT,
10
+ ERROR_ANALYSIS_PROMPT,
11
+ ERROR_REFINEMENT_PROMPT,
12
+ FINAL_ANSWER_PROMPT,
13
+ PIP_INDEX_OPTION,
14
+ PLAN_GENERATION_PROMPT,
15
+ REFLECTION_PROMPT,
16
+ STRUCTURED_PLAN_PROMPT,
17
+ format_error_analysis_prompt,
18
+ format_final_answer_prompt,
19
+ format_plan_prompt,
20
+ format_refine_prompt,
21
+ format_reflection_prompt,
22
+ format_replan_prompt,
23
+ format_structured_plan_prompt,
24
+ )
25
+
26
+ __all__ = [
27
+ # Auto-Agent Prompts
28
+ "PLAN_GENERATION_PROMPT",
29
+ "CODE_GENERATION_PROMPT",
30
+ "ERROR_REFINEMENT_PROMPT",
31
+ "ADAPTIVE_REPLAN_PROMPT",
32
+ "STRUCTURED_PLAN_PROMPT",
33
+ "REFLECTION_PROMPT",
34
+ "FINAL_ANSWER_PROMPT",
35
+ "ERROR_ANALYSIS_PROMPT",
36
+ "PIP_INDEX_OPTION",
37
+ "format_plan_prompt",
38
+ "format_refine_prompt",
39
+ "format_final_answer_prompt",
40
+ "format_replan_prompt",
41
+ "format_structured_plan_prompt",
42
+ "format_reflection_prompt",
43
+ "format_error_analysis_prompt",
44
+ ]