DeL-TaiseiOzaki commited on
Commit
6ee54ae
·
verified ·
1 Parent(s): c1b3404

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +78 -76
app.py CHANGED
@@ -8,6 +8,23 @@ from config.settings import Settings
8
  from core.file_scanner import FileScanner, FileInfo
9
  from services.llm_service import LLMService
10
  from typing import List, Set
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
  st.set_page_config(
13
  page_title="Repository Code Analysis",
@@ -15,7 +32,6 @@ st.set_page_config(
15
  layout="wide"
16
  )
17
 
18
- # ダークテーマの設定
19
  st.markdown("""
20
  <style>
21
  .stApp {
@@ -31,29 +47,34 @@ st.markdown("""
31
  background-color: #1e2329;
32
  color: #ffffff;
33
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  </style>
35
  """, unsafe_allow_html=True)
36
 
37
- def create_download_content(files: List[FileInfo]) -> str:
38
- content = "# スキャン結果\n\n"
39
- for file in files:
40
- content += f"## {file.path}\n"
41
- content += f"サイズ: {file.formatted_size}\n"
42
- content += f"エンコーディング: {file.encoding or '不明'}\n\n"
43
- if file.content:
44
- content += f"```{file.extension[1:] if file.extension else ''}\n"
45
- content += file.content
46
- content += "\n```\n\n"
47
- return content
48
-
49
- def clone_repository(repo_url: str) -> Path:
50
- temp_dir = Path(tempfile.mkdtemp())
51
- git.Repo.clone_from(repo_url, temp_dir)
52
- return temp_dir
53
-
54
  # セッション状態の初期化
55
  if 'repo_content' not in st.session_state:
56
  st.session_state.repo_content = None
 
 
 
 
 
 
57
  if 'temp_dir' not in st.session_state:
58
  st.session_state.temp_dir = None
59
  if 'llm_service' not in st.session_state:
@@ -67,83 +88,72 @@ if 'llm_service' not in st.session_state:
67
  st.error(str(e))
68
  st.stop()
69
 
70
- # メインのUIレイアウト
71
  st.title("🔍 リポジトリ解析・質問システム")
72
 
73
- # サイドバーの設定
74
  with st.sidebar:
75
  st.subheader("📌 使い方")
76
  st.markdown("""
77
- 1. スキャン対象の拡張子を選択
78
- 2. GitHubリポジトリのURLを入力
79
- 3. スキャンを実行
80
- 4. コードについて質問(最大5ターンの会話が可能)
 
81
  """)
82
-
83
- # スキャン対象の拡張子選択
84
- st.subheader("🔍 スキャン対象の選択")
85
-
86
- # 拡張子をカテゴリごとに表示
87
- st.write("プログラミング言語:")
88
- prog_exts = {'.py', '.js', '.ts', '.java', '.cpp', '.hpp', '.c', '.h', '.go', '.rs'}
89
- selected_prog = {ext: st.checkbox(ext, value=True, key=f"prog_{ext}")
90
- for ext in prog_exts}
91
-
92
- st.write("設定ファイル:")
93
- config_exts = {'.json', '.yml', '.yaml', '.toml'}
94
- selected_config = {ext: st.checkbox(ext, value=True, key=f"config_{ext}")
95
- for ext in config_exts}
96
-
97
- st.write("ドキュメント:")
98
- doc_exts = {'.md', '.txt'}
99
- selected_doc = {ext: st.checkbox(ext, value=True, key=f"doc_{ext}")
100
- for ext in doc_exts}
101
-
102
- # 選択された拡張子の集合を作成
103
- selected_extensions = {ext for exts in [selected_prog, selected_config, selected_doc]
104
- for ext, selected in exts.items() if selected}
105
 
106
- # URLの入力
107
  repo_url = st.text_input(
108
  "GitHubリポジトリのURLを入力",
109
  placeholder="https://github.com/username/repository.git"
110
  )
111
 
112
- # スキャン実行ボタン
113
  if st.button("スキャン開始", disabled=not repo_url):
114
  try:
115
- with st.spinner('リポジトリをクローン中...'):
116
- temp_dir = clone_repository(repo_url)
117
- st.session_state.temp_dir = temp_dir
118
-
119
- with st.spinner('ファイルをスキャン中...'):
120
- scanner = FileScanner(temp_dir, selected_extensions)
121
- files = scanner.scan_files()
 
 
122
  st.session_state.repo_content = LLMService.format_code_content(files)
123
 
124
  st.success(f"スキャン完了: {len(files)}個のファイルを検出")
125
 
126
- # スキャン結果のダウンロードボタン
127
- scan_result = create_download_content(files)
128
- st.download_button(
129
- label="スキャン結果をダウンロード",
130
- data=scan_result,
131
- file_name=f"scan_result_{datetime.now().strftime('%Y%m%d_%H%M%S')}.md",
132
- mime="text/markdown"
133
- )
134
-
135
- # 新しいスキャン時に会話履歴をクリア
136
  st.session_state.llm_service.clear_history()
137
 
138
  except Exception as e:
139
  st.error(f"エラーが発生しました: {str(e)}")
140
 
141
- # スキャン完了後の質問セクション
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  if st.session_state.repo_content:
143
  st.divider()
144
  st.subheader("💭 コードについて質問する")
145
 
146
- # 会話履歴の表示
147
  for message in st.session_state.llm_service.conversation_history:
148
  if message.role == "assistant":
149
  st.markdown(f'<div class="chat-message assistant-message">{message.content}</div>',
@@ -172,11 +182,3 @@ if st.session_state.repo_content:
172
  st.error(error)
173
  else:
174
  st.rerun()
175
-
176
- # セッション終了時のクリーンアップ
177
- if st.session_state.temp_dir and Path(st.session_state.temp_dir).exists():
178
- try:
179
- import shutil
180
- shutil.rmtree(st.session_state.temp_dir)
181
- except:
182
- pass
 
8
  from core.file_scanner import FileScanner, FileInfo
9
  from services.llm_service import LLMService
10
  from typing import List, Set
11
+ from main import DirectoryStructureScanner, MarkdownGenerator
12
+
13
+ class StreamlitFileWriter:
14
+ def __init__(self, output_file: Path):
15
+ self.output_file = output_file
16
+
17
+ def create_markdown(self, files: List[FileInfo]) -> str:
18
+ content = []
19
+ for file_info in files:
20
+ content.append(f"## {file_info.path}")
21
+ content.append("------------")
22
+ if file_info.content is not None:
23
+ content.append(file_info.content)
24
+ else:
25
+ content.append("# Failed to read content")
26
+ content.append("\n")
27
+ return "\n".join(content)
28
 
29
  st.set_page_config(
30
  page_title="Repository Code Analysis",
 
32
  layout="wide"
33
  )
34
 
 
35
  st.markdown("""
36
  <style>
37
  .stApp {
 
47
  background-color: #1e2329;
48
  color: #ffffff;
49
  }
50
+ .directory-structure {
51
+ font-family: monospace;
52
+ white-space: pre;
53
+ background-color: #1e2329;
54
+ padding: 1rem;
55
+ border-radius: 0.5rem;
56
+ margin: 1rem 0;
57
+ }
58
+ .markdown-preview {
59
+ background-color: #1e2329;
60
+ padding: 1rem;
61
+ border-radius: 0.5rem;
62
+ margin: 1rem 0;
63
+ max-height: 500px;
64
+ overflow-y: auto;
65
+ }
66
  </style>
67
  """, unsafe_allow_html=True)
68
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  # セッション状態の初期化
70
  if 'repo_content' not in st.session_state:
71
  st.session_state.repo_content = None
72
+ if 'directory_structure' not in st.session_state:
73
+ st.session_state.directory_structure = None
74
+ if 'content_md' not in st.session_state:
75
+ st.session_state.content_md = None
76
+ if 'structure_md' not in st.session_state:
77
+ st.session_state.structure_md = None
78
  if 'temp_dir' not in st.session_state:
79
  st.session_state.temp_dir = None
80
  if 'llm_service' not in st.session_state:
 
88
  st.error(str(e))
89
  st.stop()
90
 
 
91
  st.title("🔍 リポジトリ解析・質問システム")
92
 
 
93
  with st.sidebar:
94
  st.subheader("📌 使い方")
95
  st.markdown("""
96
+ 1. GitHubリポジトリのURLを入力
97
+ 2. スキャンを実行
98
+ 3. ディレクトリ構造と内容を確認
99
+ 4. Markdownファイルをダウンロード
100
+ 5. コードについて質問
101
  """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
 
 
103
  repo_url = st.text_input(
104
  "GitHubリポジトリのURLを入力",
105
  placeholder="https://github.com/username/repository.git"
106
  )
107
 
 
108
  if st.button("スキャン開始", disabled=not repo_url):
109
  try:
110
+ with st.spinner('リポジトリを解析中...'):
111
+ generator = MarkdownGenerator(repo_url)
112
+ content_md, structure_md, files = generator.generate_markdowns()
113
+
114
+ writer = StreamlitFileWriter(Path("dummy"))
115
+ formatted_content = writer.create_markdown(files)
116
+
117
+ st.session_state.content_md = formatted_content
118
+ st.session_state.structure_md = structure_md
119
  st.session_state.repo_content = LLMService.format_code_content(files)
120
 
121
  st.success(f"スキャン完了: {len(files)}個のファイルを検出")
122
 
 
 
 
 
 
 
 
 
 
 
123
  st.session_state.llm_service.clear_history()
124
 
125
  except Exception as e:
126
  st.error(f"エラーが発生しました: {str(e)}")
127
 
128
+ if st.session_state.structure_md and st.session_state.content_md:
129
+ tab1, tab2 = st.tabs(["📁 ディレクトリ構造", "📄 ファイル内容"])
130
+
131
+ with tab1:
132
+ st.markdown(f'<div class="markdown-preview">{st.session_state.structure_md}</div>',
133
+ unsafe_allow_html=True)
134
+
135
+ st.download_button(
136
+ label="ディレクトリ構造をダウンロード",
137
+ data=st.session_state.structure_md,
138
+ file_name=f"directory_structure_{datetime.now().strftime('%Y%m%d_%H%M%S')}.md",
139
+ mime="text/markdown"
140
+ )
141
+
142
+ with tab2:
143
+ st.markdown(f'<div class="markdown-preview">{st.session_state.content_md}</div>',
144
+ unsafe_allow_html=True)
145
+
146
+ st.download_button(
147
+ label="ファイル内容をダウンロード",
148
+ data=st.session_state.content_md,
149
+ file_name=f"repository_content_{datetime.now().strftime('%Y%m%d_%H%M%S')}.md",
150
+ mime="text/markdown"
151
+ )
152
+
153
  if st.session_state.repo_content:
154
  st.divider()
155
  st.subheader("💭 コードについて質問する")
156
 
 
157
  for message in st.session_state.llm_service.conversation_history:
158
  if message.role == "assistant":
159
  st.markdown(f'<div class="chat-message assistant-message">{message.content}</div>',
 
182
  st.error(error)
183
  else:
184
  st.rerun()