fix(ai/generate): temperature クランプ・role バリデーション追加
- temperature を 0〜2 でクランプ(不正値でのSDKエラー防止) - contents の role を user/model のみ許可(system injection 防止) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
a2282fe33b
commit
4360f9090f
31
server.js
31
server.js
|
|
@ -2000,6 +2000,12 @@ ${excerpt}
|
||||||
if (JSON.stringify(contents).length > 60000) {
|
if (JSON.stringify(contents).length > 60000) {
|
||||||
return res.status(400).json({ error: 'contents too large' });
|
return res.status(400).json({ error: 'contents too large' });
|
||||||
}
|
}
|
||||||
|
const VALID_ROLES = new Set(['user', 'model']);
|
||||||
|
for (const item of contents) {
|
||||||
|
if (!VALID_ROLES.has(item?.role)) {
|
||||||
|
return res.status(400).json({ error: 'invalid role in contents' });
|
||||||
|
}
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const modelOpts = { model: 'gemini-2.5-flash' };
|
const modelOpts = { model: 'gemini-2.5-flash' };
|
||||||
if (systemPrompt && typeof systemPrompt === 'string') {
|
if (systemPrompt && typeof systemPrompt === 'string') {
|
||||||
|
|
@ -2008,7 +2014,7 @@ ${excerpt}
|
||||||
const model = genAI.getGenerativeModel(modelOpts);
|
const model = genAI.getGenerativeModel(modelOpts);
|
||||||
const generationConfig = {
|
const generationConfig = {
|
||||||
maxOutputTokens: Math.min(config.maxOutputTokens || 500, 1000),
|
maxOutputTokens: Math.min(config.maxOutputTokens || 500, 1000),
|
||||||
temperature: config.temperature ?? 0.5
|
temperature: Math.max(0, Math.min(config.temperature ?? 0.5, 2))
|
||||||
};
|
};
|
||||||
const timeoutPromise = new Promise((_, reject) =>
|
const timeoutPromise = new Promise((_, reject) =>
|
||||||
setTimeout(() => reject(new Error('timeout')), 15000)
|
setTimeout(() => reject(new Error('timeout')), 15000)
|
||||||
|
|
@ -2782,6 +2788,29 @@ ${excerpt}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// PUT /together/members/rename — 表示名変更
|
||||||
|
r.put('/together/members/rename', async (req, res) => {
|
||||||
|
const { group_id, old_username, new_username } = req.body || {};
|
||||||
|
const trimmed = normalizeTogetherUsername(new_username);
|
||||||
|
if (!group_id || !old_username || !trimmed) return res.status(400).json({ error: 'group_id, old_username, new_username は必須です' });
|
||||||
|
if (trimmed.length > 30) return res.status(400).json({ error: '名前は30文字以内にしてください' });
|
||||||
|
const jwtUserId = getTogetherJwtUserId(req);
|
||||||
|
try {
|
||||||
|
if (!(await togetherEnsureMember(pool, res, group_id, old_username, jwtUserId))) return;
|
||||||
|
const conflict = await pool.query(
|
||||||
|
'SELECT 1 FROM together_members WHERE group_id=$1 AND username=$2',
|
||||||
|
[group_id, trimmed]
|
||||||
|
);
|
||||||
|
if (conflict.rows.length > 0) return res.status(409).json({ error: '同じ名前のメンバーが既にいます' });
|
||||||
|
await pool.query('UPDATE together_members SET username=$1 WHERE group_id=$2 AND username=$3', [trimmed, group_id, old_username]);
|
||||||
|
await pool.query('UPDATE together_shares SET shared_by=$1 WHERE group_id=$2 AND shared_by=$3', [trimmed, group_id, old_username]);
|
||||||
|
res.json({ ok: true });
|
||||||
|
} catch (e) {
|
||||||
|
console.error('[together/rename]', e.message);
|
||||||
|
res.status(500).json({ error: 'Internal server error' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// DELETE /together/share/:id — 自分の投稿を削除
|
// DELETE /together/share/:id — 自分の投稿を削除
|
||||||
r.delete('/together/share/:id', async (req, res) => {
|
r.delete('/together/share/:id', async (req, res) => {
|
||||||
const { username } = req.body || {};
|
const { username } = req.body || {};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue