add imrpvoed

This commit is contained in:
okendoken 2026-02-16 22:33:36 +01:00
parent 0f7e69c43e
commit 0eb918c893
4 changed files with 102 additions and 26 deletions

View File

@ -91,9 +91,10 @@ If you change extension code, click `Reload` on this extension page.
Popup shows: Popup shows:
- Saved file paths - Saved file paths
- AI suggestions per detected post: - AI suggestions per detected post (6 total):
- short response - improved short + medium
- medium response - critical short + medium
- suggested short + medium
- Any AI error details - Any AI error details
History in popup: History in popup:
@ -146,4 +147,3 @@ Common options:
`chrome://*`, Web Store, and some protected tabs cannot be scripted. `chrome://*`, Web Store, and some protected tabs cannot be scripted.
- No AI results in popup: - No AI results in popup:
verify server started with `--ai`. verify server started with `--ai`.

View File

@ -50,12 +50,38 @@ function renderResult(entryOrResp) {
for (const p of resp.ai_result.ai.posts) { for (const p of resp.ai_result.ai.posts) {
const idx = typeof p.index === "number" ? p.index : "?"; const idx = typeof p.index === "number" ? p.index : "?";
const postText = (p.post_text || "").replace(/\s+/g, " ").trim(); const postText = (p.post_text || "").replace(/\s+/g, " ").trim();
const short = (p.short_response || "").replace(/\s+/g, " ").trim();
const medium = (p.medium_response || "").replace(/\s+/g, " ").trim(); // Back-compat with older saved results.
const hasNew =
"improved_short" in p ||
"improved_medium" in p ||
"critical_short" in p ||
"critical_medium" in p ||
"suggested_short" in p ||
"suggested_medium" in p;
const improvedShort = (p.improved_short || "").replace(/\s+/g, " ").trim();
const improvedMedium = (p.improved_medium || "").replace(/\s+/g, " ").trim();
const criticalShort = (p.critical_short || "").replace(/\s+/g, " ").trim();
const criticalMedium = (p.critical_medium || "").replace(/\s+/g, " ").trim();
const suggestedShort = (p.suggested_short || "").replace(/\s+/g, " ").trim();
const suggestedMedium = (p.suggested_medium || "").replace(/\s+/g, " ").trim();
const shortLegacy = (p.short_response || "").replace(/\s+/g, " ").trim();
const mediumLegacy = (p.medium_response || "").replace(/\s+/g, " ").trim();
lines.push(""); lines.push("");
lines.push(`#${idx} Post: ${clampString(postText, 180)}`); lines.push(`#${idx} Post: ${clampString(postText, 180)}`);
lines.push(` Short: ${short}`); if (hasNew) {
lines.push(` Medium: ${medium}`); lines.push(` improved (short): ${improvedShort}`);
lines.push(` improved (medium): ${improvedMedium}`);
lines.push(` Critical (short): ${criticalShort}`);
lines.push(` Critical (medium): ${criticalMedium}`);
lines.push(` Suggested (short): ${suggestedShort}`);
lines.push(` Suggested (medium): ${suggestedMedium}`);
} else {
lines.push(` Short: ${shortLegacy}`);
lines.push(` Medium: ${mediumLegacy}`);
}
} }
if (resp.ai_result.ai_path) lines.push(`\nAI file: ${resp.ai_result.ai_path}`); if (resp.ai_result.ai_path) lines.push(`\nAI file: ${resp.ai_result.ai_path}`);
} else { } else {

View File

@ -116,8 +116,12 @@ def _sanitize_ai_payload(ai: dict, page_url: str, page_title: str) -> dict:
{ {
"index": int(p.get("index", i)), "index": int(p.get("index", i)),
"post_text": _ea_sanitize_text(p.get("post_text", "")), "post_text": _ea_sanitize_text(p.get("post_text", "")),
"short_response": _ea_sanitize_text(p.get("short_response", "")), "improved_short": _ea_sanitize_text(p.get("improved_short", "")),
"medium_response": _ea_sanitize_text(p.get("medium_response", "")), "improved_medium": _ea_sanitize_text(p.get("improved_medium", "")),
"critical_short": _ea_sanitize_text(p.get("critical_short", "")),
"critical_medium": _ea_sanitize_text(p.get("critical_medium", "")),
"suggested_short": _ea_sanitize_text(p.get("suggested_short", "")),
"suggested_medium": _ea_sanitize_text(p.get("suggested_medium", "")),
} }
) )
out["posts"] = cleaned_posts out["posts"] = cleaned_posts
@ -141,10 +145,23 @@ def _response_schema(max_posts: int) -> dict:
"properties": { "properties": {
"index": {"type": "integer"}, "index": {"type": "integer"},
"post_text": {"type": "string"}, "post_text": {"type": "string"},
"short_response": {"type": "string"}, "improved_short": {"type": "string"},
"medium_response": {"type": "string"}, "improved_medium": {"type": "string"},
"critical_short": {"type": "string"},
"critical_medium": {"type": "string"},
"suggested_short": {"type": "string"},
"suggested_medium": {"type": "string"},
}, },
"required": ["index", "post_text", "short_response", "medium_response"], "required": [
"index",
"post_text",
"improved_short",
"improved_medium",
"critical_short",
"critical_medium",
"suggested_short",
"suggested_medium",
],
}, },
}, },
"notes": {"type": "string"}, "notes": {"type": "string"},
@ -204,16 +221,24 @@ def main(argv: list[str]) -> int:
"goal": "Draft replies to each distinct post currently visible on the page.", "goal": "Draft replies to each distinct post currently visible on the page.",
"definition_of_post": "A single feed item / post / story / comment root visible on-screen right now. If it's a single-article page, treat the main article as one post.", "definition_of_post": "A single feed item / post / story / comment root visible on-screen right now. If it's a single-article page, treat the main article as one post.",
"output_requirements": { "output_requirements": {
"short_response": "1-2 sentences, direct, useful, no fluff.", #"ironic": "Lightly ironic, laughing at us humans (not cruel).",
"medium_response": "3-6 sentences, more context, still concise.", "improved": "Proofreading-style improvements, preserving the original words as much as possible. Improving in medium version.",
"style": "Follow the system instructions for voice/tone. If unclear what the post says, be honest and ask a question instead of guessing.", "critical": "Bold/critical: politely questions the premise or assumptions.",
"suggested": "Best style you think fits (helpful/witty/clarifying/etc).",
"short": "1-2 sentences, direct, useful, no fluff.",
"medium": "3-6 sentences, more context, still concise.",
"style": "Follow the system instructions for voice/tone. Apply EXTRA_INSTRUCTIONS to all responses. If unclear what the post says, be honest and ask a question instead of guessing.",
}, },
}, },
} }
prompt_text = ( prompt_text = (
"You will receive (1) a screenshot of the current viewport and (2) extracted visible page content.\n" "You will receive (1) a screenshot of the current viewport and (2) extracted visible page content.\n"
"Identify each distinct post visible on the page and draft two reply options per post.\n" "Identify each distinct post visible on the page and draft SIX reply options per post:\n"
"- improved_short, improved_medium\n"
"- critical_short, critical_medium\n"
"- suggested_short, suggested_medium\n"
"All six must follow the system instructions and EXTRA_INSTRUCTIONS.\n"
"Do not invent facts not present in the screenshot/content.\n" "Do not invent facts not present in the screenshot/content.\n"
"Return JSON matching the provided schema. Include all top-level keys: page_url, page_title, posts, notes.\n" "Return JSON matching the provided schema. Include all top-level keys: page_url, page_title, posts, notes.\n"
"If a value is unknown, use an empty string.\n\n" "If a value is unknown, use an empty string.\n\n"

View File

@ -141,8 +141,12 @@ def _sanitize_ai_payload(ai: dict, page_url: str, page_title: str) -> dict:
{ {
"index": int(p.get("index", i)), "index": int(p.get("index", i)),
"post_text": _ea_sanitize_text(p.get("post_text", "")), "post_text": _ea_sanitize_text(p.get("post_text", "")),
"short_response": _ea_sanitize_text(p.get("short_response", "")), "improved_short": _ea_sanitize_text(p.get("improved_short", "")),
"medium_response": _ea_sanitize_text(p.get("medium_response", "")), "improved_medium": _ea_sanitize_text(p.get("improved_medium", "")),
"critical_short": _ea_sanitize_text(p.get("critical_short", "")),
"critical_medium": _ea_sanitize_text(p.get("critical_medium", "")),
"suggested_short": _ea_sanitize_text(p.get("suggested_short", "")),
"suggested_medium": _ea_sanitize_text(p.get("suggested_medium", "")),
} }
) )
out["posts"] = cleaned_posts out["posts"] = cleaned_posts
@ -165,10 +169,23 @@ def _response_schema(max_posts: int) -> dict:
"properties": { "properties": {
"index": {"type": "integer"}, "index": {"type": "integer"},
"post_text": {"type": "string"}, "post_text": {"type": "string"},
"short_response": {"type": "string"}, "improved_short": {"type": "string"},
"medium_response": {"type": "string"}, "improved_medium": {"type": "string"},
"critical_short": {"type": "string"},
"critical_medium": {"type": "string"},
"suggested_short": {"type": "string"},
"suggested_medium": {"type": "string"},
}, },
"required": ["index", "post_text", "short_response", "medium_response"], "required": [
"index",
"post_text",
"improved_short",
"improved_medium",
"critical_short",
"critical_medium",
"suggested_short",
"suggested_medium",
],
}, },
}, },
"notes": {"type": "string"}, "notes": {"type": "string"},
@ -219,16 +236,24 @@ def _maybe_generate_ai(server, png_path: Path, meta: dict, content: object) -> d
"goal": "Draft replies to each distinct post currently visible on the page.", "goal": "Draft replies to each distinct post currently visible on the page.",
"definition_of_post": "A single feed item / post / story / comment root visible on-screen right now. If it's a single-article page, treat the main article as one post.", "definition_of_post": "A single feed item / post / story / comment root visible on-screen right now. If it's a single-article page, treat the main article as one post.",
"output_requirements": { "output_requirements": {
"short_response": "1-2 sentences, direct, useful, no fluff.", # "ironic": "Lightly ironic, laughing at us humans (not cruel).",
"medium_response": "3-6 sentences, more context, still concise.", "improved": "Proofreading-style improvements, preserving the original words as much as possible. Improving in medium version.",
"style": "Follow the system instructions for voice/tone. If unclear what the post says, be honest and ask a question instead of guessing.", "critical": "Bold/critical: politely questions the premise or assumptions.",
"suggested": "Best style you think fits (helpful/witty/clarifying/etc).",
"short": "1-2 sentences, direct, useful, no fluff.",
"medium": "3-6 sentences, more context, still concise.",
"style": "Follow the system instructions for voice/tone. Apply EXTRA_INSTRUCTIONS to all responses. If unclear what the post says, be honest and ask a question instead of guessing.",
}, },
}, },
} }
prompt_text = ( prompt_text = (
"You will receive (1) a screenshot of the current viewport and (2) extracted visible page content.\n" "You will receive (1) a screenshot of the current viewport and (2) extracted visible page content.\n"
"Identify each distinct post visible on the page and draft two reply options per post.\n" "Identify each distinct post visible on the page and draft SIX reply options per post:\n"
"- improved_short, improved_medium\n"
"- critical_short, critical_medium\n"
"- suggested_short, suggested_medium\n"
"All six must follow the system instructions and EXTRA_INSTRUCTIONS.\n"
"Do not invent facts not present in the screenshot/content.\n" "Do not invent facts not present in the screenshot/content.\n"
"Return JSON matching the provided schema. Include all top-level keys: page_url, page_title, posts, notes.\n" "Return JSON matching the provided schema. Include all top-level keys: page_url, page_title, posts, notes.\n"
"If a value is unknown, use an empty string.\n\n" "If a value is unknown, use an empty string.\n\n"