fix: address PR Agent review findings across 6 files

Restrict PR Agent workflow to trusted collaborators on PR comments only,
fix UTF-8 byte counting in gallery-pack, correct portrait-to-landscape
fallback orientation, track inserted freeform beats in visitedBeatIds,
allow clearing stored TTS key, and guard empty-string fuzzy match in
style selector.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
yuanzonghao
2026-06-07 14:40:37 +08:00
parent 74479c1aa6
commit 4972243a93
5 changed files with 19 additions and 9 deletions
+6 -2
View File
@@ -11,7 +11,9 @@ jobs:
if: > if: >
github.event_name == 'pull_request' || github.event_name == 'pull_request' ||
(github.event_name == 'issue_comment' && (github.event_name == 'issue_comment' &&
startsWith(github.event.comment.body, '/')) github.event.issue.pull_request &&
startsWith(github.event.comment.body, '/') &&
contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association))
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
issues: write issues: write
@@ -36,7 +38,9 @@ jobs:
if: > if: >
github.event_name == 'pull_request' || github.event_name == 'pull_request' ||
(github.event_name == 'issue_comment' && (github.event_name == 'issue_comment' &&
startsWith(github.event.comment.body, '/')) github.event.issue.pull_request &&
startsWith(github.event.comment.body, '/') &&
contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association))
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
issues: write issues: write
+1 -1
View File
@@ -27,7 +27,7 @@ export async function POST(req: Request): Promise<Response> {
return Response.json({ error: "Bad JSON" }, { status: 400 }); return Response.json({ error: "Bad JSON" }, { status: 400 });
} }
if (docStr.length > MAX_DOC_BYTES) { if (new TextEncoder().encode(docStr).byteLength > MAX_DOC_BYTES) {
return Response.json( return Response.json(
{ error: "图集数据太大,无法打包分享" }, { error: "图集数据太大,无法打包分享" },
{ status: 413 }, { status: 413 },
+7 -2
View File
@@ -1171,7 +1171,10 @@ function PlayInner() {
if (sessionOrientation === "portrait") { if (sessionOrientation === "portrait") {
console.warn(`[play] portrait firstact missing for ${cardName} (HTTP ${r.status}), falling back to landscape`); console.warn(`[play] portrait firstact missing for ${cardName} (HTTP ${r.status}), falling back to landscape`);
const fb = await fetch(`/home/firstact/${encodeURIComponent(cardName)}.json`); const fb = await fetch(`/home/firstact/${encodeURIComponent(cardName)}.json`);
if (fb.ok) return (await fb.json()) as PrebakedFirstAct; if (fb.ok) {
const fallback = (await fb.json()) as PrebakedFirstAct;
return { ...fallback, scene: { ...fallback.scene, orientation: "landscape" as const } };
}
} }
throw new Error(`找不到精选剧情:${cardName}`); throw new Error(`找不到精选剧情:${cardName}`);
}, },
@@ -1500,10 +1503,12 @@ function PlayInner() {
...currentScene, ...currentScene,
beats: [...currentScene.beats, newBeat], beats: [...currentScene.beats, newBeat],
}; };
const nextVisited = [...visitedBeatsRef.current, newBeatId];
visitedBeatsRef.current = nextVisited;
const nextSession: Session = { const nextSession: Session = {
...session, ...session,
history: session.history.map((h, i, arr) => history: session.history.map((h, i, arr) =>
i === arr.length - 1 ? { ...h, scene: patched } : h, i === arr.length - 1 ? { ...h, scene: patched, visitedBeatIds: nextVisited } : h,
), ),
characters: mergeCharactersPreserveVoice( characters: mergeCharactersPreserveVoice(
session.characters, session.characters,
+2 -3
View File
@@ -100,10 +100,9 @@ export function SettingsModal({
const presetId = keyType === "payg" ? PAYG_PRESET_ID : regionId; const presetId = keyType === "payg" ? PAYG_PRESET_ID : regionId;
writeStoredTtsConfig({ presetId, apiKey: key }); writeStoredTtsConfig({ presetId, apiKey: key });
ttsConfigured = true; ttsConfigured = true;
} else if (!ttsAlreadyConfigured) {
ttsConfigured = false;
} else { } else {
ttsConfigured = true; clearStoredTtsConfig();
ttsConfigured = false;
} }
onSaved({ ttsConfigured, playerName: name, visionClickEnabled: visionClick }); onSaved({ ttsConfigured, playerName: name, visionClickEnabled: visionClick });
+3 -1
View File
@@ -28,7 +28,9 @@ export async function selectStyle(
if (STYLE_MAP[picked]) { if (STYLE_MAP[picked]) {
return STYLE_MAP[picked]; return STYLE_MAP[picked];
} }
const fuzzy = STYLE_NAMES.find((s) => picked.includes(s) || s.includes(picked)); const fuzzy = picked
? STYLE_NAMES.find((s) => picked.includes(s) || s.includes(picked))
: undefined;
if (fuzzy) { if (fuzzy) {
return STYLE_MAP[fuzzy]!; return STYLE_MAP[fuzzy]!;
} }