@@ -17,7 +17,7 @@ import { LOCALSTORAGE_KEY } from '@/context/config';
1717import { useTranslation } from '@/context/I18nContext' ;
1818import { useTheme } from '@/context/ThemeContext' ;
1919import { buildAIFileContextList } from '@/engine/ai/contextBuilder' ;
20- import { useProject } from '@/engine/core/project ' ;
20+ import { fileRepository } from '@/engine/core/fileRepository ' ;
2121import { useAI } from '@/hooks/ai/useAI' ;
2222import { useChatSpace } from '@/hooks/ai/useChatSpace' ;
2323import { useAIReview } from '@/hooks/useAIReview' ;
@@ -98,9 +98,6 @@ export default function AIPanel({ projectFiles, currentProject, currentProjectId
9898
9999 // レビュー機能
100100 const { openAIReviewTab, closeAIReviewTab } = useAIReview ( ) ;
101-
102- // プロジェクト操作
103- const { saveFile, clearAIReview } = useProject ( ) ;
104101
105102
106103 // プロジェクトファイルが変更されたときにコンテキストを更新
@@ -206,43 +203,55 @@ export default function AIPanel({ projectFiles, currentProject, currentProjectId
206203 } ;
207204
208205 // レビューを開く(ストレージから履歴を取得してタブに渡す)
206+ // NOTE: NEW-ARCHITECTURE.mdに従い、aiEntryにはprojectIdを必ず含める
209207 const handleOpenReview = async (
210208 filePath : string ,
211209 originalContent : string ,
212210 suggestedContent : string
213211 ) => {
212+ const projectId = currentProject ?. id ;
213+
214214 try {
215- if ( currentProject ?. id ) {
215+ if ( projectId ) {
216216 const { getAIReviewEntry } = await import ( '@/engine/storage/aiStorageAdapter' ) ;
217- const entry = await getAIReviewEntry ( currentProject . id , filePath ) ;
218- openAIReviewTab ( filePath , originalContent , suggestedContent , entry || undefined ) ;
217+ const entry = await getAIReviewEntry ( projectId , filePath ) ;
218+
219+ // 既存エントリがない場合でも、projectIdを含む最小限のaiEntryを作成
220+ const aiEntry = entry || { projectId, filePath } ;
221+ openAIReviewTab ( filePath , originalContent , suggestedContent , aiEntry ) ;
219222 return ;
220223 }
221224 } catch ( e ) {
222225 console . warn ( '[AIPanel] Failed to load AI review entry:' , e ) ;
223226 }
224227
228+ // currentProjectがない場合はprojectIdなしで開く(fallback)
225229 openAIReviewTab ( filePath , originalContent , suggestedContent ) ;
226230 } ;
227231
228232 // 変更を適用(suggestedContent -> contentへコピー)
229- // Terminalと同じアプローチ:fileRepositoryに保存し、イベントシステムに任せる
233+ // NOTE: NEW-ARCHITECTURE.mdに従い、fileRepositoryを直接使用
230234 const handleApplyChanges = async ( filePath : string , newContent : string ) => {
231- if ( ! currentProject || ! saveFile ) return ;
235+ const projectId = currentProject ?. id ;
236+
237+ if ( ! projectId ) {
238+ console . error ( '[AIPanel] No projectId available, cannot apply changes' ) ;
239+ // TODO: alertの代わりにトースト通知を使用する
240+ alert ( 'プロジェクトが選択されていません' ) ;
241+ return ;
242+ }
232243
233244 try {
234245 console . log ( '[AIPanel] Applying changes to:' , filePath ) ;
235246
236- // Use the saveFile from useProject() (consistent with Terminal/project flow).
237- // This delegates to the project layer which in turn calls fileRepository and
238- // ensures any side-effects (sync, indexing) happen consistently.
239- await saveFile ( filePath , newContent ) ;
247+ // fileRepositoryを直接使用してファイルを保存(NEW-ARCHITECTURE.mdに従う)
248+ await fileRepository . saveFileByPath ( projectId , filePath , newContent ) ;
240249
241250 // Clear AI review metadata for this file (non-blocking)
242- if ( clearAIReview ) {
243- clearAIReview ( filePath ) . catch ( ( e : Error ) => {
244- console . warn ( '[AIPanel] clearAIReview failed (non-critical):' , e ) ;
245- } ) ;
251+ try {
252+ await fileRepository . clearAIReview ( projectId , filePath ) ;
253+ } catch ( e ) {
254+ console . warn ( '[AIPanel] clearAIReview failed (non-critical):' , e ) ;
246255 }
247256
248257 // Remove this file from the assistant editResponse in the current chat space
@@ -279,13 +288,16 @@ export default function AIPanel({ projectFiles, currentProject, currentProjectId
279288
280289 // 変更を破棄
281290 const handleDiscardChanges = async ( filePath : string ) => {
291+ const projectId = currentProject ?. id ;
292+
282293 try {
283294 // Close the review tab immediately so UI updates.
284295 closeAIReviewTab ( filePath ) ;
285296 // Finally clear ai review metadata for this file
286- if ( clearAIReview ) {
297+ if ( projectId ) {
287298 try {
288- await clearAIReview ( filePath ) ;
299+ await fileRepository . init ( ) ;
300+ await fileRepository . clearAIReview ( projectId , filePath ) ;
289301 } catch ( e ) {
290302 console . warn ( '[AIPanel] clearAIReview failed after discard:' , e ) ;
291303 }
@@ -460,24 +472,26 @@ export default function AIPanel({ projectFiles, currentProject, currentProjectId
460472 isProcessing = { isProcessing }
461473 emptyMessage = { mode === 'ask' ? t ( 'AI.ask' ) : t ( 'AI.edit' ) }
462474 onRevert = { async ( message : ChatSpaceMessage ) => {
475+ const projectId = currentProject ?. id ;
463476 try {
464- if ( ! currentProject ?. id || ! saveFile ) return ;
477+ if ( ! projectId ) return ;
465478 if ( message . type !== 'assistant' || message . mode !== 'edit' || ! message . editResponse ) return ;
466479
467480 const { getAIReviewEntry, updateAIReviewEntry } = await import ( '@/engine/storage/aiStorageAdapter' ) ;
468481
469482 const files = message . editResponse . changedFiles || [ ] ;
470483 for ( const f of files ) {
471484 try {
472- const entry = await getAIReviewEntry ( currentProject . id , f . path ) ;
485+ const entry = await getAIReviewEntry ( projectId , f . path ) ;
473486 if ( entry && entry . originalSnapshot ) {
474- await saveFile ( f . path , entry . originalSnapshot ) ;
487+ // fileRepositoryを直接使用してファイルを保存
488+ await fileRepository . saveFileByPath ( projectId , f . path , entry . originalSnapshot ) ;
475489
476490 // mark entry reverted and add history
477491 const hist = Array . isArray ( entry . history ) ? entry . history : [ ] ;
478492 const historyEntry = { id : `revert-${ Date . now ( ) } ` , timestamp : new Date ( ) , content : entry . originalSnapshot , note : `reverted via chat ${ message . id } ` } ;
479493 try {
480- await updateAIReviewEntry ( currentProject . id , f . path , {
494+ await updateAIReviewEntry ( projectId , f . path , {
481495 status : 'reverted' ,
482496 history : [ historyEntry , ...hist ] ,
483497 } ) ;
0 commit comments