From 4bed9ad0d128f2550ca6cf723e570b4719a02fb6 Mon Sep 17 00:00:00 2001 From: ika-2-2 <219417869+ika-2-2@users.noreply.github.com> Date: Sun, 10 Aug 2025 07:55:07 +0900 Subject: [PATCH 1/3] =?UTF-8?q?=E3=83=AB=E3=83=BC=E3=83=88=E3=83=91?= =?UTF-8?q?=E3=82=B9=E3=82=92=E5=A4=89=E6=9B=B4=E3=81=97=E3=80=81=E4=BC=9A?= =?UTF-8?q?=E8=A9=B1=E9=96=A2=E9=80=A3=E3=81=AE=E3=82=A8=E3=83=B3=E3=83=89?= =?UTF-8?q?=E3=83=9D=E3=82=A4=E3=83=B3=E3=83=88=E3=82=92=E3=80=8C/conversa?= =?UTF-8?q?tion=E3=80=8D=E3=81=AB=E6=9B=B4=E6=96=B0=E3=80=82=E3=83=A6?= =?UTF-8?q?=E3=83=BC=E3=82=B6=E3=83=BC=E3=81=AE=E7=99=BA=E8=A8=80=E6=95=B0?= =?UTF-8?q?=E3=81=AE=E6=9D=A1=E4=BB=B6=E3=82=928=E5=9B=9E=E3=81=AB?= =?UTF-8?q?=E5=A4=89=E6=9B=B4=E3=81=97=E3=80=81=E3=83=97=E3=83=AD=E3=83=B3?= =?UTF-8?q?=E3=83=97=E3=83=88=E3=81=AE=E5=86=85=E5=AE=B9=E3=82=92=E6=98=8E?= =?UTF-8?q?=E7=A2=BA=E5=8C=96=E3=80=82=E3=82=A8=E3=83=A9=E3=83=BC=E3=83=A1?= =?UTF-8?q?=E3=83=83=E3=82=BB=E3=83=BC=E3=82=B8=E3=81=AB=E8=A9=B3=E7=B4=B0?= =?UTF-8?q?=E6=83=85=E5=A0=B1=E3=82=92=E8=BF=BD=E5=8A=A0=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/api/src/index.ts | 2 +- apps/api/src/services/conversationsService.ts | 2 +- apps/api/src/services/prompts.ts | 12 +++++++++--- apps/extension/src/components/ModelResponse.tsx | 6 +++++- 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/apps/api/src/index.ts b/apps/api/src/index.ts index 222d306..f2cb6e5 100644 --- a/apps/api/src/index.ts +++ b/apps/api/src/index.ts @@ -62,7 +62,7 @@ app.use("*", async (c, next) => { // GitHub認証関連のルートを登録 app.route("/github", githubRouter); -app.route("/", conversations); +app.route("/conversation", conversations); app.route("/policies", policies); diff --git a/apps/api/src/services/conversationsService.ts b/apps/api/src/services/conversationsService.ts index 41c1c8a..760cfef 100644 --- a/apps/api/src/services/conversationsService.ts +++ b/apps/api/src/services/conversationsService.ts @@ -205,7 +205,7 @@ export class ConversationService { // `requirements`フェーズで、ユーザーの発言が6回に達し、かつ最近拒否されていない場合のみ移行を提案 if ( session.phase === "requirements" && - userMessagesInPhase >= 5 && + userMessagesInPhase >= 8 && !recentlyRejectedTransition ) { console.log( diff --git a/apps/api/src/services/prompts.ts b/apps/api/src/services/prompts.ts index c6888e4..e4bc7c5 100644 --- a/apps/api/src/services/prompts.ts +++ b/apps/api/src/services/prompts.ts @@ -55,11 +55,17 @@ export const PROMPT_TEMPLATE = ` 3. 上記**3つのの3つの必須項目について、それぞれ**1つずつ**主要な回答をユーザーから引き出しなさい。**、それ以上深掘りせず、速やかに'[TRANSITION_SUGGESTION]'を出力しなさい。 ### フェーズが "requirements" の場合 -**目的**: アイデアを実現するために必要な主要機能やインターフェースを洗い出すこと。 +**目的**: アイデアを実現するために必要な機能要件・非機能要件を洗い出すこと。 +**深掘りポイント**: 以下の3つのポイントのみに絞り、各ポイント最大2-3回の質問で完了させる。 +1. 主要機能の洗い出し(最低限必要な機能) +2. ユーザーインターフェース(どんな画面や操作が必要か) +3. 非機能要件(技術スタック、セキュリティ、UXなど) + **行動**: 1. もし前のフェーズから移行した直後であれば、「ありがとうございます。では、このアプリに必要な機能を一緒に考えていきましょう。まずは思いつくままに、どんな機能がほしいかリストアップしてもらえますか?」という文章が自動で送信される。 -2. ユーザーから提示された機能について、「主要機能とスコープ」「利用者との接点(インターフェース)」「外部環境と依存関係」の3つの必須項目について、それぞれ**1つずつ**主要な回答をユーザーから引き出しなさい。 -3. 上記3つの必須項目について、**3つすべて**主要な回答をユーザーから引き出しなさい。 +2. 対話履歴を参考に、上記3つのポイントのうち、まだ十分に深掘りできていない項目について、具体的な質問を生成しなさい。 +3. 各ポイントについて2-3回質問したら、そのポイントは完了とみなし、次のポイントに進むか、3つすべて完了していれば'[TRANSITION_SUGGESTION]'とだけ返しなさい。 +4. 現在どのポイントについて質問しているかを「主要機能について教えてください」のように明示しなさい。 ### フェーズが "tasks" の場合 **目的**: これまでの対話内容をまとめ、最終成果物の生成をユーザーに確認してもらうこと。 diff --git a/apps/extension/src/components/ModelResponse.tsx b/apps/extension/src/components/ModelResponse.tsx index d734bbf..3192a98 100644 --- a/apps/extension/src/components/ModelResponse.tsx +++ b/apps/extension/src/components/ModelResponse.tsx @@ -54,7 +54,11 @@ export const ModelResponse = memo((props: ModelResponseProps) => { ); } catch (error) { console.error("Issue登録に失敗しました:", error); - alert("Issue登録に失敗しました。もう一度お試しください。"); + let errorMessage = "Issue登録に失敗しました。"; + if (error instanceof Error) { + errorMessage = `Issue登録に失敗しました。\n詳細: ${error.message}`; + } + alert(`${errorMessage}\n\nもう一度お試しください。`); } finally { setIsCreatingIssues(false); setShowRepositorySelection(false); From 280804ab5c8db35b30ab8da7638f0c8fe3e439ed Mon Sep 17 00:00:00 2001 From: ika-2-2 <219417869+ika-2-2@users.noreply.github.com> Date: Sun, 10 Aug 2025 11:49:08 +0900 Subject: [PATCH 2/3] =?UTF-8?q?=E8=A6=81=E4=BB=B6=E5=AE=9A=E7=BE=A9?= =?UTF-8?q?=E6=9B=B8=E7=94=9F=E6=88=90=E6=A9=9F=E8=83=BD=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0=E3=80=82=E6=96=B0=E3=81=97=E3=81=84=E3=82=A8=E3=83=B3?= =?UTF-8?q?=E3=83=89=E3=83=9D=E3=82=A4=E3=83=B3=E3=83=88=E3=82=92=E5=AE=9F?= =?UTF-8?q?=E8=A3=85=E3=81=97=E3=80=81=E3=83=A6=E3=83=BC=E3=82=B6=E3=83=BC?= =?UTF-8?q?=E3=81=AE=E7=99=BA=E8=A8=80=E3=81=AB=E5=BF=9C=E3=81=98=E3=81=A6?= =?UTF-8?q?=E8=A6=81=E4=BB=B6=E5=AE=9A=E7=BE=A9=E6=9B=B8=E3=82=92=E7=94=9F?= =?UTF-8?q?=E6=88=90=E3=81=99=E3=82=8B=E3=83=AD=E3=82=B8=E3=83=83=E3=82=AF?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0=E3=80=82UI=E3=81=AB=E8=A6=81?= =?UTF-8?q?=E4=BB=B6=E5=AE=9A=E7=BE=A9=E6=9B=B8=E7=94=9F=E6=88=90=E3=83=9C?= =?UTF-8?q?=E3=82=BF=E3=83=B3=E3=82=92=E5=AE=9F=E8=A3=85=E3=81=97=E3=80=81?= =?UTF-8?q?=E3=82=BB=E3=83=83=E3=82=B7=E3=83=A7=E3=83=B3ID=E3=81=AE?= =?UTF-8?q?=E3=83=81=E3=82=A7=E3=83=83=E3=82=AF=E3=82=92=E8=A1=8C=E3=81=86?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=E4=BF=AE=E6=AD=A3=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/api/src/routes/conversation.ts | 31 +++++++++++++++++++ apps/api/src/services/conversationsService.ts | 21 +++++++++++-- .../src/hooks/api/generateRequirements.ts | 15 +++++++++ apps/extension/src/sidepanel/AppLayout.tsx | 22 +++++++++++-- 4 files changed, 85 insertions(+), 4 deletions(-) create mode 100644 apps/extension/src/hooks/api/generateRequirements.ts diff --git a/apps/api/src/routes/conversation.ts b/apps/api/src/routes/conversation.ts index 168ca55..e5311cb 100644 --- a/apps/api/src/routes/conversation.ts +++ b/apps/api/src/routes/conversation.ts @@ -101,6 +101,37 @@ conversations.get("/:sessionId/issues", async (c) => { } }); +conversations.post("/:sessionId/generate-requirements", async (c) => { + const userId = c.get("userId"); + if (!userId) return c.json({ error: "Unauthorized" }, 401); + + const { sessionId } = c.req.param(); + const svc = new ConversationService(c.env.GEMINI_API_KEY ?? "", c.env.DB); + + // 所有者チェック + const owner = await svc.getSessionOwner(sessionId); + if (owner !== userId) return c.json({ error: "Forbidden" }, 403); + + try { + const requirementsDoc = + await svc.generateRequirementsDocFromSession(sessionId); + const response = `これまでの対話を基に、要件定義書を生成しました。\n\n${requirementsDoc}`; + + // AIメッセージとしてDBに保存 + const aiMessage = await svc.saveMessage(sessionId, "ai", response); + return c.json({ success: true, data: aiMessage }); + } catch (error) { + console.error("Failed to generate requirements document:", error); + return c.json( + { + error: "Failed to generate requirements document", + details: error instanceof Error ? error.message : "Unknown error", + }, + 500, + ); + } +}); + conversations.post("/auth/logout", async (c) => { const userId = c.get("userId"); const GITHUB_CLIENT_ID = c.env.GITHUB_CLIENT_ID; diff --git a/apps/api/src/services/conversationsService.ts b/apps/api/src/services/conversationsService.ts index 760cfef..48667d8 100644 --- a/apps/api/src/services/conversationsService.ts +++ b/apps/api/src/services/conversationsService.ts @@ -57,6 +57,23 @@ export class ConversationService { sessionId: string, userMessage: string, ): Promise { + if (userMessage === "要件定義書を生成") { + try { + const requirementsDoc = + await this.generateRequirementsDocFromSession(sessionId); + const response = + "これまでの対話を基に、要件定義書を生成しました。\n\n" + + requirementsDoc; + return this.saveMessage(sessionId, "ai", response); + } catch (error) { + console.error("要件定義書生成中にエラー:", error); + return this.saveMessage( + sessionId, + "ai", + "申し訳ありません、要件定義書の生成中にエラーが発生しました。もう少し対話を進めてから再試行してください。", + ); + } + } // 1. ユーザーメッセージをDBに保存 await this.saveMessage(sessionId, "user", userMessage); @@ -275,7 +292,7 @@ export class ConversationService { } // 要件定義書を生成するメソッド - private async generateRequirementsDocFromSession( + public async generateRequirementsDocFromSession( sessionId: string, ): Promise { const session = await this.getSession(sessionId); @@ -506,7 +523,7 @@ export class ConversationService { } // メッセージをDBに保存 - private async saveMessage( + public async saveMessage( sessionId: string, role: "user" | "ai", content: string, diff --git a/apps/extension/src/hooks/api/generateRequirements.ts b/apps/extension/src/hooks/api/generateRequirements.ts new file mode 100644 index 0000000..4a23ff8 --- /dev/null +++ b/apps/extension/src/hooks/api/generateRequirements.ts @@ -0,0 +1,15 @@ +import { client } from "@/utils/client"; +import { useCallback } from "react"; + +export const useGenerateRequirements = () => { + const generateRequirements = useCallback(async (sessionId: string) => { + console.log("API呼び出し: sessionId =", sessionId); + const response = await client.post( + `conversation/${sessionId}/generate-requirements`, + ); + console.log("API応答:", response); + return (response as { data: { success: boolean; data: any } }).data; + }, []); + + return { generateRequirements }; +}; diff --git a/apps/extension/src/sidepanel/AppLayout.tsx b/apps/extension/src/sidepanel/AppLayout.tsx index 589d0a9..72baeb7 100644 --- a/apps/extension/src/sidepanel/AppLayout.tsx +++ b/apps/extension/src/sidepanel/AppLayout.tsx @@ -1,3 +1,5 @@ +import { useChatStore } from "@/store/chatStore"; + interface AppLayoutProps { children: React.ReactNode; } @@ -5,6 +7,20 @@ interface AppLayoutProps { export const AppLayout = (props: AppLayoutProps) => { const { children } = props; + const sessionId = useChatStore((s) => s.sessionId); + const sendMessage = useChatStore((s) => s.sendMessage); + + const handleGenerateRequirements = async () => { + console.log("要件定義書生成ボタンがクリックされました"); + console.log("現在のセッションID", sessionId); + if (!sessionId) { + alert("セッションが見つかりません。会話を開始してください。"); + return; + } + + sendMessage("要件定義書を生成"); + }; + return (
@@ -24,10 +40,12 @@ export const AppLayout = (props: AppLayoutProps) => { > A - {/* TODO: 3点リーダー */} + {/* 要件定義書生成ボタン */} From 983fd2376802790881bfc69cfe1730eafbe59b02 Mon Sep 17 00:00:00 2001 From: nka21 Date: Sun, 10 Aug 2025 11:55:56 +0900 Subject: [PATCH 3/3] lint fix --- apps/extension/src/sidepanel/AppLayout.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/extension/src/sidepanel/AppLayout.tsx b/apps/extension/src/sidepanel/AppLayout.tsx index df3f9e4..8fa6f96 100644 --- a/apps/extension/src/sidepanel/AppLayout.tsx +++ b/apps/extension/src/sidepanel/AppLayout.tsx @@ -55,8 +55,6 @@ export const AppLayout = (props: AppLayoutProps) => { > -