| 1 | import { NoticeCard } from "../components/Transcript"; |
| 2 | import { t } from "../lib/i18n"; |
| 3 | import { localizedNoticeText, type Item } from "../lib/useController"; |
| 4 | import { browserMockScenarioParam } from "../lib/mockScenarios"; |
| 5 | |
| 6 | export function noticePreviewMockEnabled(): boolean { |
| 7 | const value = browserMockScenarioParam(); |
| 8 | return value === "notice" || value === "notices" || value === "notice-preview"; |
| 9 | } |
| 10 | |
| 11 | function noticePreviewItems(): Item[] { |
| 12 | const notice = (index: number, level: "info" | "warn", text: string, detail: string, code?: string): Item => ({ |
| 13 | kind: "notice", |
| 14 | id: `notice-preview-${index}`, |
| 15 | level, |
| 16 | text: localizedNoticeText(text, code), |
| 17 | detail, |
| 18 | }); |
| 19 | return [ |
| 20 | { |
| 21 | kind: "notice", |
| 22 | id: "notice-preview-delivery", |
| 23 | level: "info", |
| 24 | variant: "delivery", |
| 25 | title: t("notice.deliveryIncompleteTitle"), |
| 26 | text: t("notice.deliveryIncompleteBody"), |
| 27 | detail: "legacy delivery record; current runs let the model judge completion", |
| 28 | action: "continue_delivery", |
| 29 | }, |
| 30 | notice(1, "info", "No visible answer was produced; asking the assistant to respond again.", "empty final answer blocked: qwen3.7-plus returned no visible answer text (finish=stop, reasoning=2314 chars); retrying", "empty_final"), |
| 31 | notice(2, "info", "The assistant answered before taking action; asking it to use the required tools.", "executor handoff: assistant produced a proposal before running required repository commands; nudged to execute", "executor_handoff"), |
| 32 | notice(3, "info", "Tool round limit reached; asking the assistant to summarize progress.", "tool budget reached after 128 tool calls; requesting a progress summary before continuing", "tool_budget"), |
| 33 | notice(4, "info", "The same tool call has been requested several times.", "repeat reminder at count 3; the tool remains available", "loop_guard"), |
| 34 | notice(5, "info", "Context is getting large; preserving cache until cleanup is needed.", "context window 82% full; deferred cleanup to preserve reusable prompt cache"), |
| 35 | notice(6, "info", "Context cleanup skipped for now.", "cleanup skipped: recent turn included unresolved user approval state"), |
| 36 | notice(7, "info", "Automatic context cleanup paused because the context window is too small.", "configured compact threshold exceeds current model context window; auto cleanup paused for this model"), |
| 37 | notice(8, "info", "Context was compacted without a generated summary.", "compaction completed after upstream summary generation returned empty content; retained transcript checkpoint"), |
| 38 | notice(9, "info", "A previous external call has an unknown result.", "inspect external state before repeating a side effect; tools remain available"), |
| 39 | notice(16, "warn", "background export failed: needs attention", "background export failed: session archive upload returned 503 after 3 retries"), |
| 40 | notice(17, "warn", "Job artifact migration failed.", "artifact migration failed for job job_123: checksum mismatch while moving output.zip"), |
| 41 | notice(18, "warn", "Background job teardown timed out.", "job job_123 did not stop within 10s; process is still marked running by the supervisor"), |
| 42 | notice(19, "warn", "Some plan-mode tool settings were ignored.", "plan-mode tool settings ignored: unsupported tool allowlist entry \"browser.screenshot\""), |
| 43 | notice(20, "warn", "Some plan-mode command settings were ignored.", "plan-mode command settings ignored: invalid read-only prefix \"npm && test\""), |
| 44 | notice(21, "warn", "Config migration did not complete.", "config migration failed at providers.defaultModel: unknown provider reference \"old/deepseek\""), |
| 45 | notice(22, "warn", "Selected model is missing its API key.", "selected model deepseek/deepseek-v4-pro requires DEEPSEEK_API_KEY, but no key is configured"), |
| 46 | notice(23, "warn", "An MCP server failed to start.", "mcp server \"github\" failed to start: command not found: mcp-server-github"), |
| 47 | notice(24, "warn", "Some MCP servers failed to start; run /mcp for details.", "mcp startup failures: github(command not found), linear(authentication expired)"), |
| 48 | notice(25, "warn", "Guardian was disabled because its model was not found.", "guardian model \"glm-5-guard\" is not present in the configured provider catalog"), |
| 49 | notice(26, "warn", "Guardian was disabled because it could not start.", "guardian startup failed: provider returned 401 unauthorized"), |
| 50 | ]; |
| 51 | } |
| 52 | |
| 53 | export function NoticePreviewPanel() { |
| 54 | return ( |
| 55 | <div |
| 56 | style={{ |
| 57 | flex: "1 1 auto", |
| 58 | minHeight: 0, |
| 59 | overflow: "auto", |
| 60 | padding: "44px 24px 128px", |
| 61 | }} |
| 62 | > |
| 63 | <div style={{ maxWidth: 920, margin: "0 auto" }}> |
| 64 | {noticePreviewItems().map((item) => { |
| 65 | if (item.kind !== "notice") return null; |
| 66 | return ( |
| 67 | <NoticeCard |
| 68 | key={item.id} |
| 69 | item={item} |
| 70 | onAction={item.action ? () => undefined : undefined} |
| 71 | onAccept={item.action === "continue_delivery" ? () => undefined : undefined} |
| 72 | /> |
| 73 | ); |
| 74 | })} |
| 75 | </div> |
| 76 | </div> |
| 77 | ); |
| 78 | } |
| 79 |