Skip to main content

atomcode_core/i18n/
messages.rs

1pub enum Msg<'a> {
2    // WelcomeWizard
3    WelcomeBannerLine1,
4    WelcomeBannerLine2,
5    WelcomeOptionCodingPlan,
6    WelcomeOptionCodingPlanHint,
7    WelcomeOptionConfigureManually,
8    WelcomeOptionConfigureManuallyHint,
9    WelcomeOptionSkip,
10    WelcomeOptionSkipHint,
11
12    // ── /codingplan ──
13    CodingPlanSetupFailed { error: &'a str },
14    /// Emitted inline by /codingplan and `atomcode codingplan` when the
15    /// stored OAuth token comes back 401 from the CodingPlan API
16    /// mid-flow. We re-run the same OAuth dance `/login` uses, save the
17    /// fresh token, and retry the whole setup once — this line tells
18    /// the user that's what's about to happen so the second
19    /// "Open this URL in any browser…" block isn't a surprise.
20    CpReauthAfter401,
21    /// Emitted by the OpenAI provider when an AtomGit-gateway chat
22    /// request returns 401 and our one automatic refresh_token attempt
23    /// either failed or the retried request still came back 401. The
24    /// raw server message ("Gitcode auth: token rejected") is not
25    /// useful to end users — this replaces it with an actionable hint
26    /// pointing at `/login`. Non-atomgit gateways still surface the
27    /// verbatim server error so user-supplied API keys (sk-...) get
28    /// the diagnostic detail.
29    ChatAuthExpired,
30    // SetupReport renderer (core/coding_plan/setup.rs)
31    CpSetupHeader,
32    CpLoggedIn { who: &'a str, username: &'a str, email: &'a str },
33    CpStepSkipped { reason: &'a str },
34    CpLoginFailed { error: &'a str },
35    CpClaimed { message: &'a str, plan_type: &'a str },
36    CpClaimSuccessFallback,
37    CpAlreadyClaimed { reason: &'a str },
38    CpClaimFailed { error: &'a str },
39    /// Per-tier cascade row — winning tier, fresh claim.
40    /// Example (zh-CN): `  ✓ CodingPlan Lite 领取成功`
41    CpClaimTierSucceeded { tier: &'a str },
42    /// Per-tier cascade row — winning tier, server reported the user
43    /// already holds this tier or higher (`duplicate=true`).
44    CpClaimTierAlreadyHeld { tier: &'a str },
45    /// Per-tier cascade row — tier was refused (2xx with success=
46    /// false / 5xx / transport). `reason` is the server's human-
47    /// readable message (e.g. `额度已满`, `暂无开放`) or a short
48    /// rendering of the transport error.
49    CpClaimTierFailed { tier: &'a str, reason: &'a str },
50    CpAddedProviders { count: usize, plural_s: &'a str },
51    /// Locked-model row. `name` is expected to be pre-decorated with
52    /// U+0336 combining strikethrough by the caller (see
53    /// `coding_plan::setup::strikethrough`), so the template itself
54    /// stays a plain `format!` and survives every renderer's CSI
55    /// scrubber without needing SGR escapes.
56    CpLocked { name: &'a str },
57    CpProviderRow { provider: &'a str, model: &'a str, default_suffix: &'a str },
58    CpDefaultSuffix,
59    CpVisionAuto { kind: &'a str },
60    CpVisionUserSupplied { kind: &'a str },
61    CpVisionCleared,
62    CpModelsSkipped { reason: &'a str },
63    CpModelsFailed { error: &'a str },
64    CpStatusHeader,
65    CpPlanPending { plan: &'a str },
66    CpPlanActive {
67        plan: &'a str,
68        expires_at: &'a str,
69        remaining_days: i32,
70        total_days: i32,
71    },
72    CpUsageLine { usage: &'a str, reset_at: &'a str, duration: &'a str },
73    CpWindowQuotaExhausted,
74    CpWindowQuotaHint { hint: &'a str },
75    CpStatusFetchSkipped { reason: &'a str },
76    CpStatusFetchFailed { error: &'a str },
77    /// Open-source build attempted to use a CodingPlan provider. The
78    /// signing capability is not present in this build, so the request
79    /// can't reach the AtomGit LLM gateway. Surface a clear hint
80    /// pointing to the official Releases page.
81    CpOfficialBuildRequired,
82    /// Official build, but no stored auth (or auth has empty
83    /// `user.id` / `access_token`). The signing path needs these
84    /// fields to derive a per-user key; without them the request
85    /// can't be signed. Surface a "please run `/codingplan` to log
86    /// in" hint instead of the misleading "official build required"
87    /// message — the user IS on an official build.
88    CpAuthRequired,
89    /// Server returned `ATOMCODE_SIG_STALE` — the request's signed
90    /// timestamp is outside the ±5min window the gateway accepts.
91    /// Typically caused by an unsynced local clock.
92    CpSignStaleClockSkew,
93    /// Server returned `ATOMCODE_SIG_REPLAY` even after the client's
94    /// one automatic retry with a fresh nonce. Surface a "please retry
95    /// the command" hint — usually self-heals on the next attempt.
96    CpSignReplayPersisted,
97    /// Server returned `ATOMCODE_SIG_INVALID` AND the alg_version is
98    /// no longer in the server's `accepted_versions` set — the client
99    /// binary is too old. Force-upgrade hint.
100    CpSignVersionTooOld,
101    /// Server returned `426 Upgrade Required` — emergency rotation
102    /// playbook in progress; this build cannot continue without
103    /// upgrading.
104    CpUpgradeRequired,
105
106    // i18n self-errors
107    ErrUnsupportedLocale { input: &'a str },
108
109    // ── Status bar (build_status) ──
110    StatusNoProvider,
111    StatusUpgradeHint { version: &'a str },
112    StatusModelNotConfigured,
113    /// macOS / Linux variant: "Image in clipboard · ctrl+v to paste".
114    /// Ctrl+V is intercepted by Windows Terminal / conhost before
115    /// reaching atomcode, so Windows builds emit
116    /// `StatusClipboardImageHintSlash` instead.
117    StatusClipboardImageHint,
118    /// Windows variant: "Image in clipboard · /paste". Tells the
119    /// user to fall back on the `/paste` slash command, which works
120    /// in every terminal regardless of host keybinds.
121    StatusClipboardImageHintSlash,
122
123    // ── /status command body ──
124    StatusBody { model: &'a str, dir: &'a str, config: &'a str, tokens: usize },
125    StatusCpNotSignedIn,
126    StatusCpFetchFailed { error: &'a str },
127    StatusCpNoActive,
128    StatusCpLine {
129        plan: &'a str,
130        expires_at: &'a str,
131        remaining_days: i32,
132        total_days: i32,
133    },
134    StatusCpUsage { usage: &'a str, reset_at: &'a str, seconds: i64 },
135    StatusCpWindowExhausted,
136    StatusCpWindowHint { hint: &'a str },
137    StatusInstructionFilesHeader,
138    StatusInstructionPresent { path: &'a str, label: &'a str },
139    StatusInstructionMissing { label: &'a str },
140
141    // ── /login completion ──
142    LoginSignedInWithCpHint { name: &'a str, username: &'a str },
143
144    // ── Help / commands ──
145    HelpAvailableCommands,
146    /// Full keyboard-shortcuts reference dumped to scrollback by the
147    /// `/keys` slash command. Carries every line of the panel as a
148    /// single multi-line string so translators can adjust column
149    /// alignment per locale without rebuilding rows in Rust.
150    KeybindingsHelp,
151
152    // ── Provider wizard ──
153    ProviderWizardHeader,
154    ProviderWizardCancelled,
155    ProviderMenuAdd,
156    ProviderMenuAddDesc,
157    ProviderMenuEdit,
158    ProviderMenuEditDesc,
159    ProviderMenuDelete,
160    ProviderMenuDeleteDesc,
161    ProviderMenuSetDefault,
162    ProviderMenuSetDefaultDesc,
163    ProviderNoProviders,
164    ProviderDeleteConfirm { name: &'a str },
165    ProviderDeleted { name: &'a str },
166    ProviderDeleteKept,
167    ProviderDefaultSet { name: &'a str },
168    ProviderAdded { name: &'a str, model: &'a str },
169    ProviderUpdated { name: &'a str },
170    ProviderStepName,
171    ProviderStepType,
172    ProviderStepTypeWithHint { current: &'a str },
173    ProviderStepBaseUrl,
174    ProviderStepBaseUrlWithHint { current: &'a str },
175    ProviderDefaultHint,
176    ProviderStepApiKey,
177    ProviderStepApiKeyWithHint { hint: &'a str },
178    ProviderStepApiKeySet,
179    ProviderStepApiKeyUnset,
180    ProviderStepModel,
181    ProviderStepModelWithHint { current: &'a str },
182    ProviderNameEmpty,
183    ProviderUnknownType,
184    ProviderUnknownTypeEdit,
185    ProviderModelEmpty,
186    ProviderEditKeep,
187
188    // ── Model picker ──
189    ModelSwitched { provider: &'a str, model: &'a str },
190
191    // ── Session picker ──
192    SessionLoadFailed { error: &'a str },
193    SessionResumedLabel { name: &'a str },
194    SessionTimeJustNow,
195    SessionTimeMinAgo { n: u64 },
196    SessionTimeHourAgo { n: u64 },
197    SessionTimeDayAgo { n: u64 },
198    SessionMsgCount { count: usize },
199    SessionNameEmpty,
200    SessionNameTooLong { max: usize },
201    SessionNameControlChars,
202    SessionListFailed { error: &'a str },
203    SessionRenamed { old: &'a str, new: &'a str },
204    SessionSaveFailed { error: &'a str },
205    SessionNoneSelected,
206    SessionRenameEditing { buffer: &'a str },
207
208    // ── Dir picker ──
209    DirCurrent,
210    DirNotExists { path: &'a str },
211    DirChanged { path: &'a str },
212    DirNotADirectory { path: &'a str },
213
214    // ── Issue wizard ──
215    IssueCancelled,
216    IssueNewOn { owner: &'a str, repo: &'a str },
217    IssueStep1,
218    IssueStep2,
219    IssueTitleConfirmed { title: &'a str },
220    IssueRequiredField { field: &'a str },
221    IssueCreated { number: u64, title: &'a str, url: &'a str },
222    IssueCreateFailed { error: &'a str },
223
224    // ── Language ──
225    /// Confirmation rendered to scrollback after the user picks a
226    /// locale via `/language` (modal or arg). Already includes the
227    /// leading "  " indent and trailing "\n" so the call site is just
228    /// `renderer.render(UiLine::CommandOutput(t(Msg::LanguageSwitched
229    /// { ... }).into_owned()))`.
230    LanguageSwitched { label: &'a str, locale: &'a str },
231
232    // ── Idle / onboarding hints ──
233    /// "type something, or press " (text before the slash)
234    IdleHintPrefix,
235    /// "/" (the slash shortcut itself — kept separate for accent styling)
236    IdleHintSlash,
237    /// " to browse commands" (text after the slash)
238    IdleHintSuffix,
239    /// Complete plain-text version: "type something, or press / to browse commands"
240    IdleHintFull,
241    /// "/provider" command label
242    IdleHintProvider,
243    /// "to add a custom model" (text after /provider)
244    IdleHintProviderSuffix,
245    /// Complete plain-text version: "/provider  to add a custom model"
246    IdleHintProviderFull,
247    /// "/codingplan" command label
248    IdleHintCodingplan,
249    /// "to claim a free token quota" (text after /codingplan)
250    IdleHintCodingplanSuffix,
251    /// Complete plain-text version: "/codingplan  to claim a free token quota"
252    IdleHintCodingplanFull,
253
254    // ── Slash-command high-frequency messages ──
255    CmdSwitchedPlanMode,
256    CmdSwitchedBuildMode,
257    CmdNewSession,
258    CmdNoProviders,
259    CmdNoSessions,
260    CmdUnknownCommand { name: &'a str },
261    CmdLoginFailed { error: &'a str },
262    CmdLogoutDone,
263    CmdLogoutFailed { error: &'a str },
264    CmdWhoamiNotSignedIn,
265    CmdReloadDone { provider: &'a str, model: &'a str },
266    CmdReloadFailed { error: &'a str },
267    CmdUndoNotSupported,
268    CmdNoChanges,
269    CmdCheckingUpdate,
270    CmdNoActiveProvider,
271
272    // ── Approval prompt ──
273    ApprovalPromptAlt { tool: &'a str, detail: &'a str },
274    ApprovalWaitingLabel,
275    ApprovalAllow,
276    ApprovalAlways,
277    ApprovalDeny,
278
279    // ── Cancelled / Error prefix ──
280    Cancelled,
281    ErrorPrefix { msg: &'a str },
282
283    // ── Upgrade messages ──
284    UpgradeSuccess { from: &'a str, to: &'a str },
285    UpgradeManifestFetched { version: &'a str },
286    UpgradeDownloading { pct: i32, bytes: u64, total: u64 },
287    UpgradeVerifying,
288    UpgradeReplacing,
289    UpgradeDone { version: &'a str, backup: &'a str },
290    UpgradeAlreadyLatest { current: &'a str, latest: &'a str },
291    UpgradeFailed { error: &'a str },
292    UpgradeRolledBack { exe: &'a str, backup: &'a str },
293
294    // ── Terminal keyboard hints ──
295    KbdHintMacos,
296    KbdHintOther,
297
298    // ── JediTerm / conhost fallback ──
299    JediTermFallback,
300    LegacyConhostFallback,
301
302    // ── Background task ──
303    BackgroundComplete { turns: usize },
304    BackgroundFailed { turns: usize },
305    BackgroundFilesEdited,
306
307    // ── /config command ──
308    ConfigProviderLabel { provider: &'a str, path: &'a str },
309
310    // ── /cost command ──
311    CostReport {
312        prompt: usize,
313        completion: usize,
314        cached: usize,
315        cache_rate: usize,
316        total: usize,
317        cost: &'a str,
318    },
319
320    // ── /think command ──
321    ThinkStatus { status: &'a str, budget: u32, provider: &'a str },
322    ThinkEnabled { budget: u32 },
323    ThinkDisabled,
324    ThinkBudgetSet { n: u32 },
325    ThinkBudgetTooSmall { n: u32 },
326    ThinkBudgetUsage,
327    ThinkUsage,
328
329    // ── /remember, /forget ──
330    RememberUsage,
331    ForgetUsage,
332
333    // ── /background ──
334    BackgroundUsage,
335
336    // ── /init ──
337    InitAlreadyExists { path: &'a str },
338    InitWrote { path: &'a str, bytes: usize },
339    InitFailed { error: &'a str },
340
341    // ── /cd ──
342    CdWorkingDir { cwd: &'a str },
343
344    // ── /diff ──
345    DiffFailed { error: &'a str },
346
347    // ── /upgrade ──
348    UpgradeUnknownArg { arg: &'a str },
349
350    // ── /skills ──
351    SkillsNone,
352    SkillsAvailable,
353    SkillUnknown { name: &'a str },
354
355    // ── /mcp ──
356    McpReloading { count: usize },
357    McpConnecting,
358    McpConnectingServer { name: &'a str },
359    McpNoServersConfigured,
360    McpClearedReconnecting { removed: usize },
361    McpClearedNoServers { removed: usize },
362    McpToolsUsage,
363    McpToolsListing { server: &'a str },
364    McpNoRegistry,
365    McpServersHeader,
366    McpReloadFailed { error: &'a str },
367    // /mcp login / logout
368    McpOAuthLoginUsage,
369    McpOAuthLogoutUsage,
370    McpOAuthLoadConfigFailed { error: &'a str },
371    McpOAuthServerNotFound { server: &'a str },
372    McpOAuthStarting { server: &'a str },
373    McpOAuthSaved { provider: &'a str, server: &'a str },
374    McpOAuthFailed { error: &'a str },
375    McpOAuthTokenRemoved { server: &'a str },
376    McpOAuthNoToken { server: &'a str },
377    McpOAuthLogoutFailed { error: &'a str },
378    // MCP / LSP server connect feedback (event handler output)
379    McpServerConnected { name: &'a str },
380    McpServerFailed { name: &'a str, error: &'a str },
381    LspServerStarted { name: &'a str, ext: &'a str },
382    LspServerFailed { name: &'a str, ext: &'a str, error: &'a str },
383
384    // ── /worktree ──
385    WorktreeUsage,
386    WorktreeCreateUsage,
387    WorktreeCreated { branch: &'a str, base: &'a str, path: &'a str },
388    WorktreeCreateFailed { error: &'a str },
389    WorktreeNoActive,
390    WorktreeListFailed { error: &'a str },
391    WorktreeActiveHeader,
392    WorktreeHasChanges,
393    WorktreeClean,
394    WorktreeCurrent,
395    WorktreeDoneBack { path: &'a str },
396    WorktreeDoneMergeHint { branch: &'a str },
397    WorktreeNoSession,
398    WorktreeCleanupUsage,
399    WorktreeCleaned { branch: &'a str },
400    WorktreeCleanedSwitched { path: &'a str },
401    WorktreeCleanupUncommitted { branch: &'a str },
402    WorktreeCleanupFailed { error: &'a str },
403
404    // ── /help commands (custom commands subcommand) ──
405    HelpCustomCommandsHeader,
406    HelpCustomNone,
407    HelpCustomCreateHint,
408    HelpSourceGlobal,
409    HelpSourceProject,
410
411    // ── /setup ──
412    /// Header line: "✅ Setup complete — 3 installed, 1 skipped, 0 failed · 120ms"
413    SetupHeader { installed: usize, skipped: usize, failed: usize, duration_ms: u64 },
414    /// "Installed:" section label in setup report.
415    SetupInstalledLabel,
416    /// "Skipped:" section label in setup report.
417    SetupSkippedLabel,
418    /// "Failed:" section label in setup report.
419    SetupFailedLabel,
420    /// Per-item installed row: "  ✓ skill:atomcode-automation-recommender → /path"
421    SetupInstalledRow { kind: &'a str, slug: &'a str, path: &'a str },
422    /// Per-item skipped row: "  - skill:xyz (hash match)"
423    SetupSkippedRow { kind: &'a str, slug: &'a str, reason: &'a str },
424    /// Per-item failed row: "  ✗ mcp:xyz — error message"
425    SetupFailedRow { kind: &'a str, slug: &'a str, error: &'a str },
426    /// "💡 Tip: Run /setup …" — first-run hint shown above the prompt
427    /// when the project has no setup state yet.
428    CmdSetupTip,
429    /// "Running atomcode setup..." — shown while setup is in progress.
430    CmdSetupRunning,
431    /// "Skills reloaded — N available" — after setup completes and skills are reloaded.
432    CmdSetupSkillsReloaded { count: usize },
433    /// "setup error: {e}" — when setup::run returns an error.
434    CmdSetupError { error: &'a str },
435    /// "Running setup skill..." — after seeds installed and skill is auto-invoked.
436    CmdSetupRunningSkill,
437    /// "Setup skill not found..." — when the setup skill cannot be resolved or expanded.
438    CmdSetupSkillMissing,
439
440    // ── /plugin ──
441    PluginUsage,
442    PluginMarketplaceUsage,
443    PluginInstallUsage,
444    PluginUninstallUsage,
445    PluginNoMarketplaces,
446    PluginMarketplacesHeader,
447    PluginNoInstalled,
448    PluginInstalledHeader,
449    PluginMarketplaceCloning { url: &'a str },
450    PluginMarketplaceRemoved { name: &'a str },
451    PluginMarketplaceRemoveFailed { error: &'a str },
452    PluginMarketplaceUpdating { name: &'a str },
453    PluginMarketplaceListFailed { error: &'a str },
454    PluginInstalling { plugin: &'a str, marketplace: &'a str },
455    PluginUninstalled { plugin: &'a str, marketplace: &'a str },
456    PluginUninstallFailed { error: &'a str },
457    PluginListFailed { error: &'a str },
458
459    // ── Command descriptions (for help_text dynamic lookup) ──
460    CmdDescSetup,
461    CmdDescCodingplan,
462    CmdDescResume,
463    CmdDescRename,
464    CmdDescLogin,
465    CmdDescLogout,
466    CmdDescWhoami,
467    CmdDescModel,
468    CmdDescProvider,
469    CmdDescStatus,
470    CmdDescConfig,
471    CmdDescReload,
472    CmdDescCd,
473    CmdDescInit,
474    CmdDescBg,
475    CmdDescBackground,
476    CmdDescDiff,
477    CmdDescClear,
478    CmdDescSession,
479    CmdDescCost,
480    CmdDescContext,
481    CmdDescCompact,
482    CmdDescRemember,
483    CmdDescForget,
484    CmdDescMemory,
485    CmdDescMcp,
486    CmdDescUndo,
487    CmdDescWorktree,
488    CmdDescUpgrade,
489    CmdDescIssue,
490    CmdDescPlan,
491    CmdDescBuild,
492    CmdDescThink,
493    CmdDescHelp,
494    CmdDescKeys,
495    CmdDescLanguage,
496    CmdDescQuit,
497    CmdDescSkills,
498    CmdDescPlugin,
499    /// Description for the `/paste` slash command — pulls a clipboard
500    /// image and attaches it as `[Image #N]`. Exists for Windows
501    /// users whose Ctrl+V is swallowed by Windows Terminal / conhost
502    /// before reaching the app, but works on every platform.
503    CmdDescPaste,
504    /// `/paste` failed because the clipboard holds no image. Shown
505    /// in scrollback as an error line so the user isn't left
506    /// wondering whether the command did anything.
507    CmdPasteNoImage,
508
509    // ── config save failed ──
510    ConfigSaveFailed { error: &'a str },
511
512    // ── OnboardingWizard (multi-step first-run + `/welcome`). Spec:
513    //    docs/superpowers/specs/2026-05-11-welcome-wizard-redesign-design.md
514    OnboardingStepHeaderWelcome,
515    OnboardingStepHeaderLanguage,
516    OnboardingStepHeaderSetup,
517    OnboardingPanelTitle,
518    OnboardingIntroVersionLine { v: &'a str },
519    OnboardingIntroBullet1,
520    OnboardingIntroBullet2,
521    OnboardingIntroBullet3,
522    OnboardingIntroPressEnter,
523    OnboardingIntroCtrlC,
524    OnboardingIntroCompactTagline,
525    OnboardingLanguageTitleBilingual,
526    OnboardingLanguagePrompt,
527    OnboardingLanguageOptionAuto,
528    OnboardingLanguageOptionEn,
529    OnboardingLanguageOptionZhCn,
530    OnboardingSetupTitle,
531    OnboardingNavHint,
532    OnboardingConfirmClear,
533    CmdWelcomeDescription,
534
535    /// Vision preprocessor success banner. Shown as a body line right
536    /// after a VL turn finishes, in the form
537    ///   `✓ VL recognised image, returned N chars`
538    /// (English) /
539    ///   `✓ VL 识别图片成功,返回 N chars`
540    /// (zh-CN). The model key trails as a dim suffix in the renderer
541    /// — kept out of this message so the wrapper styling stays
542    /// renderer-side.
543    VisionPreprocessSuccess { char_count: usize },
544
545    /// TurnComplete separator summary, e.g.
546    ///   `✓ Shipped · 3 rounds · 2 tools · 6.8s · 285 tokens`
547    /// `done` is a playful English verb from `DONE_LABELS` — kept
548    /// English in every locale because translated cute verbs read
549    /// awkward; the structural words (`rounds`/`tools`/`tokens`)
550    /// localise. `duration` is a pre-formatted human string (e.g.
551    /// "6.8s").
552    TurnSummary {
553        done: &'a str,
554        turn_count: usize,
555        tool_call_count: usize,
556        duration: &'a str,
557        total_tokens: usize,
558    },
559
560    // ── OAuth login chrome (/login + /codingplan share these) ──
561    /// Header above the QR block when scanning with WeChat is the
562    /// expected flow. Includes the leading "  " indent and trailing
563    /// "\n\n" paragraph break that the caller used to inline.
564    LoginQrHeader,
565    /// Separator + URL prelude shown below the QR block when both
566    /// QR and URL fallback are available. Leading "\n\n  " and
567    /// trailing "\n  " are part of the template.
568    LoginUrlAfterQr,
569    /// QR + URL both unavailable (Unicode-incapable terminal AND a
570    /// platform where URL-based login doesn't work, e.g. OHOS).
571    LoginNoQrNoUrl,
572    /// URL-only header when QR can't render but URL login works.
573    /// Leading "  " indent and trailing "\n  " before the URL.
574    LoginUrlOnly,
575    /// Footer line: "Press ESC to cancel" with surrounding
576    /// blank-line padding.
577    LoginCancelHint,
578
579    // ── /context report ──
580    CtxUsageHeader,
581    CtxUsageNoTurns,
582    CtxUsageWaiting,
583    CtxProvider,
584    CtxCtxName,
585    CtxLabelSystemPrompt,
586    CtxLabelToolDefs,
587    CtxLabelColdZone,
588    CtxLabelMessages,
589    CtxLabelFree,
590    CtxMessagesInWindow { n: usize },
591    CtxSystemPromptHeader,
592    CtxSystemPromptEmpty,
593    /// Used in the "used/window tokens (pct)" line below the bar.
594    CtxTokensSuffix,
595
596    // ── /compact ──
597    CompactNothingShort,
598    CompactStarting,
599    CompactNothingNoSavings { before: &'a str, after: &'a str },
600    CompactDropped { messages: usize, before: &'a str, after: &'a str },
601
602    /// Surfaced when the user pastes/attaches an image but the active
603    /// model can't accept images AND no `vision_preprocessor_provider`
604    /// is configured. `model` is the current model identifier.
605    ModelNoImageSupport { model: &'a str },
606
607    /// Confirmation hint after the first Ctrl+C on an empty buffer.
608    /// "  (press Ctrl+C again to exit)\n" — leading indent + trailing
609    /// newline are part of the template.
610    CtrlCAgainToExit,
611
612    /// Startup hint shown on terminals where Kitty CSI-u keyboard
613    /// disambiguation isn't available, telling the user the
614    /// guaranteed-works `\<Enter>` multi-line trick. Multi-line
615    /// payload with leading indent + trailing paragraph break.
616    HintMultiLineInput,
617
618    // ── /bg (background sessions) ──
619    /// Help text for `/bg help`. Multi-line string with leading indent
620    /// and trailing newlines baked in.
621    BgHelp,
622    /// Empty state for `/bg list`.
623    BgListEmpty,
624    /// Table header for `/bg list`. Trailing newline baked in.
625    BgListHeader,
626    /// Row format for `/bg list`. `state` is the localised state label,
627    /// `age` is the humanised age string, `summary` is the session name.
628    BgListRow { slot: usize, short_id: &'a str, state: &'a str, age: &'a str, summary: &'a str },
629    /// Localised label for `RuntimeState::Running`.
630    BgStateRunning,
631    /// Localised label for `RuntimeState::Idle`.
632    BgStateIdle,
633    /// Localised label for `RuntimeState::Done`.
634    BgStateDone,
635    /// Localised label for `RuntimeState::Cancelled`.
636    BgStateCancelled,
637    /// Localised label for `RuntimeState::Error`.
638    BgStateError,
639    /// Age string: less than 60 seconds.
640    BgAgeNow,
641    /// Age string: minutes. `n` is the number of minutes.
642    BgAgeMinutes { n: u64 },
643    /// Age string: hours. `n` is the number of hours.
644    BgAgeHours { n: u64 },
645    /// Age string: days. `n` is the number of days.
646    BgAgeDays { n: u64 },
647    /// Error: too many background slots. `max` is the slot limit.
648    BgSlotLimitReached { max: usize },
649    /// Output after `/bg` sends the current session to background.
650    /// `new_id` is the new foreground session short id,
651    /// `slot` is the background slot number,
652    /// `old_id` is the backgrounded session short id,
653    /// `state` is the localised runtime state.
654    BgBackgroundCurrent { new_id: &'a str, slot: usize, old_id: &'a str, state: &'a str },
655    /// Error: invalid slot number. `slot` is the requested slot,
656    /// `available` is the number of available slots.
657    BgInvalidSlot { slot: usize, available: usize },
658    /// Error: background slot has no runtime client.
659    BgNoRuntimeClient,
660    /// Output after `/bg <N>` resumes a background session.
661    /// `slot` is the resumed slot, `short_id` is the session short id.
662    BgResumed { slot: usize, short_id: &'a str },
663    /// When resuming moves the previous foreground into a background slot.
664    /// `slot` is the new background slot number.
665    BgPreviousForegroundMoved { slot: usize },
666    /// Output after `/bg drop <N>`. `slot` is the dropped slot,
667    /// `short_id` is the session short id.
668    BgDropped { slot: usize, short_id: &'a str },
669    /// Output after `/background <task>` starts a one-shot task.
670    /// `slot` is the background slot, `short_id` is the session short id.
671    BgTaskStarted { slot: usize, short_id: &'a str },
672    /// Background task timed out. `secs` is the timeout in seconds.
673    BgTaskTimedOut { secs: u64 },
674    /// Background task internal error. `error` is the error message.
675    BgTaskError { error: &'a str },
676    /// Background task was cancelled.
677    BgTaskCancelled,
678    /// Background task finished but produced no summary text.
679    BgTaskNoSummary,
680}