
実装
読み込み中...
2026/3/19
2026/3/19
2026/3/19
2026/3/19
2026/3/19
2026/3/19
2026/3/19
2026/3/15
2026/3/15
2026/2/26
// ❌ DBから取得したファイル名をそのままpath.joinに渡している
const promptFileName = character.promptFile;
const promptPath = path.join(process.cwd(), "src/prompts", promptFileName);
fs.readFileSync(promptPath, "utf-8");
// character.promptFile が "../../etc/passwd" だったら?
// ✅ path.basename() でディレクトリトラバーサルを防止
const promptFileName = path.basename(character.promptFile);
const promptPath = path.join(process.cwd(), "src/prompts", promptFileName);
// ❌ async処理中にsessionIdRef.currentが別のセッションに上書きされる
const sendMessage = useCallback(async (content: string) => {
if (!sessionIdRef.current) return;
await saveMessage(sessionIdRef.current, "user", content);
const { text } = await getChatResponse(content); // 数秒かかる
// ↑ この間にキャラ変更 → sessionIdRef.current が変わる
await saveMessage(sessionIdRef.current, "assistant", text); // 別セッションに保存!
}, []);
// ✅ 関数冒頭でローカル変数にコピー
const sendMessage = useCallback(async (content: string) => {
const currentSessionId = sessionIdRef.current; // ここで固定
if (!currentSessionId) return;
await saveMessage(currentSessionId, "user", content);
const { text } = await getChatResponse(content);
await saveMessage(currentSessionId, "assistant", text); // 安全
}, []);
// ❌ キャラが見つからない → early return → ユーザーには何も見えない
const character = await getCharacterBySlug(selectedSlug);
if (!character) return; // 永遠にチャットが使えない状態に
// ✅ デフォルトキャラにフォールバック
const character =
(await getCharacterBySlug(selectedSlug)) ??
(await getCharacterBySlug("akari"));
if (!character) return; // 両方なければ諦める(ありえないはず)
// ❌ session未取得時にもクエリが走る
const { data } = useQuery({
queryKey: ["characters", session?.user?.id],
queryFn: () => getCharacters(session?.user?.id), // undefined で呼ばれる
});
// ✅ enabled で制御
const { data } = useQuery({
queryKey: ["characters", session?.user?.id],
queryFn: () => getCharacters(session?.user?.id),
enabled: !!session?.user?.id, // userIdがあるときだけ
});
DBの値でもファイルパスに使うなら path.basename() で正規化する
async関数内でuseRefを使うなら、冒頭でローカル変数にコピーする
early returnにはフォールバックを用意し、ユーザーが詰む状態を作らない
useQueryのenabledで不要なフェッチを防ぐ