/** * The English message catalog: every user-visible UI string the terminal * renders, keyed for {@link t}. The catalog is a plain record so missing * keys fail typecheck against the shared key union, not at runtime. * * @module @deepseek-ai/dsh-tui/locales/en */ export const en = { // Shared panel chrome 'panel.close': 'esc/q close', 'panel.moveEnterSelect': '↑↓ move · enter select · esc close', 'panel.moveEnterSelectBack': '↑↓ move · enter select · esc back · q close', 'panel.scrollEnds': '↑↓ scroll · pgup/pgdn page · g/G ends · esc/q close', 'panel.loading': 'loading…', 'panel.loadFailed': 'load failed', 'panel.noMatch': 'no matching entries', 'panel.emptyClose': 'esc close', 'panel.searchIdle': 'search: type to filter', 'panel.searchIdleStop': 'search: type to filter · esc stops', 'panel.searchPrefix': 'search: ', // /language panel 'language.title': '/language — interface language', 'language.hint': '↑↓ move · enter apply · esc/q close', // /theme panel 'theme.title': '/theme — color palette', 'theme.compact': '/theme · esc close', 'theme.current': 'current', 'theme.dark.label': 'dark', 'theme.dark.description': 'DeepSeek dark palette (default)', 'theme.light.label': 'light', 'theme.light.description': 'light palette for bright terminals', 'theme.prismatic.label': 'prismatic', 'theme.prismatic.description': 'neon synthwave palette (violet/magenta/cyan)', 'theme.rainbow.label': 'rainbow', 'theme.rainbow.description': 'randomized carnival palette (/rainbow to reroll)', 'theme.auto.label': 'auto', 'theme.auto.description': 'follow the terminal; dark until detection lands', // /history panel 'history.title.prompts': '/history · {count} prompts · type to filter', 'history.title.match': "/history · {matches} of {count} match '{query}'", 'history.filterHint': 'filter {state}, enter fills the composer', 'history.filterEmpty': '· type to search prompts', 'history.filterQuery': '· {query}', 'history.empty': 'no matching prompts', 'history.compact.none': 'no matching prompts', 'history.footer': '↑↓ move · g/G ends · enter fill · esc close', // /search panel 'search.title.type': '/search · type a query and press enter', 'search.title.hits': "/search · {count} hit for '{query}'", 'search.title.hitsPlural': "/search · {count} hits for '{query}'", 'search.hint': '{state} · enter searches or resumes', 'search.hintEmpty': 'type to search sessions', 'search.empty.idle': 'full-text search across every persisted session', 'search.empty.noHits': 'no matching sessions{loading}', 'search.compact.noResults': 'no results yet', 'search.compact.searching': 'searching…', 'search.compact.error': 'error: {message}', 'search.footer': '↑↓ move · enter search/resume · esc close', // /statusline panel 'header.hint': '/help · Esc interrupt · Ctrl+C quit', 'header.hintResumed': 'resumed · /help · Esc interrupt', 'statusline.title': '/statusline · items apply to the live status line below', 'statusline.item.model': 'model', 'statusline.item.model.desc': 'provider/model serving this session', 'statusline.item.cwd': 'cwd', 'statusline.item.cwd.desc': 'working-directory basename', 'statusline.item.mode': 'mode', 'statusline.item.mode.desc': 'agent preset composing the session', 'statusline.item.branch': 'branch', 'statusline.item.branch.desc': 'git branch inside a repository', 'statusline.item.context': 'context', 'statusline.item.context.desc': 'context-window occupancy meter', 'statusline.item.permission': 'permission', 'statusline.item.permission.desc': 'permission preset badge with cycle hint', 'statusline.item.plan': 'plan', 'statusline.item.plan.desc': 'plan-mode state mark', 'statusline.item.turns': 'turns', 'statusline.item.turns.desc': 'turn and step counters', 'statusline.item.durations': 'durations', 'statusline.item.durations.desc': 'llm/ttft/decode/tool wall time', 'statusline.item.cache': 'cache', 'statusline.item.cache.desc': 'cache-hit share of billed input', 'statusline.item.tokens': 'tokens', 'statusline.item.tokens.desc': 'cumulative input/output tokens', 'statusline.item.title': 'title', 'statusline.item.title.desc': 'session title or short id', 'statusline.item.goal': 'goal', 'statusline.item.goal.desc': 'live goal phase and round progress', 'statusline.item.sandbox': 'sandbox', 'statusline.item.sandbox.desc': 'divergent sandbox-mode override', // /schedule panel 'schedule.title': '/schedule · {count} active reminder', 'schedule.titlePlural': '/schedule · {count} active reminders', 'schedule.empty': 'no active reminders — the model creates them with schedule_create', // Transcript document panel (/resume details) 'document.loading': 'loading transcript…', 'attach.bar': 'observing · {label} · r reload · esc/ctrl+d back', 'attach.loading': 'loading {label}\'s conversation…', 'attach.status': 'subagent {label} · {id} · {turns} turns', 'notice.attachUnavailable': 'subagent attachment is unavailable in this profile', 'document.compact': 'transcript · esc close', 'document.expanded': 'expanded', 'document.refreshHint': 'r refresh', 'document.footerExpanded': 'lines {from}-{to}/{total} · ↑↓/pg/g/G{refresh} · esc/ctrl+d back', 'document.footer': 'lines {from}-{to}/{total} · ↑↓/pg/g/G · enter/f expand · t/esc close', // /review picker 'review.picker.title': '/review · choose a target', 'review.picker.uncommitted': 'Review uncommitted changes (staged / unstaged / new files)', 'review.picker.branch': 'Compare against a base branch (lists local branches)', 'review.picker.commit': 'Review a commit on the current branch (lists recent commits)', 'review.picker.custom': 'Custom review focus (type it)', 'review.picker.customHint': 'type your focus, then enter to start the review', 'review.picker.branches': '{filtered} of {total} branches', 'review.picker.commits': '{filtered} of {total} commits', 'review.picker.loadingBranches': 'loading branches…', 'review.picker.loadingCommits': 'loading commits…', 'review.picker.empty': 'no candidates', 'review.picker.noMatch': 'no matches', 'review.picker.loading': 'loading…', 'review.picker.loadFailed': 'load failed', 'review.picker.compact': 'pick a review target', 'review.picker.footer': '↑↓ move · enter select · esc back · q close', // Review result summary 'review.summary.untagged': 'untagged\u00d7{n}', 'review.summary.incorrect': 'patch incorrect', 'review.summary.correctClean': 'no issues found', 'review.summary.correct': 'patch correct', 'review.summary.noConclusion': 'review finished: no structured conclusion', 'review.summary.zero': 'review finished: 0 findings · {verdict}', 'review.summary.count': 'review finished: {count} findings ({parts})', 'review.summary.countVerdict': 'review finished: {count} findings ({parts}) · {verdict}', // Review runner notices 'review.notice.started': 'review started under read-only permissions', 'review.notice.failed': 'review failed: {message}', 'review.notice.unavailable': 'review unavailable: {message}', // LOCAL_COMMAND descriptions 'cmd.help': 'show this overlay', 'cmd.model': 'switch the model and manage providers', 'cmd.effort': 'adjust reasoning effort for the current model', 'cmd.mode': 'inspect or select the agent preset (/mode [preset])', 'cmd.permission': 'inspect or select the permission preset (/permission [preset])', 'cmd.new': 'create and switch to a fresh session (/new [preset])', 'cmd.fork': 'fork at the latest completed turn (/fork [event-seq])', 'cmd.resume': 'browse or switch root sessions (/resume [id|prefix])', 'cmd.search': 'full-text search across persisted sessions (/search [query])', 'cmd.plugin': 'inspect the live plugin composition', 'cmd.update': 'update dsh-code, the harness host, and profile plugins in one aligned step', 'cmd.jobs': 'inspect background jobs', 'cmd.schedule': 'inspect active reminders (created through schedule tools)', 'cmd.statusline': 'customize the status line items', 'cmd.theme': 'switch the color theme', 'cmd.language': 'switch the interface language (/language [en|zh])', 'cmd.rainbow': 'reroll or pin the rainbow palette (/rainbow [seed])', 'cmd.animation': 'toggle decorative animations; shimmer and activity stay live (/animation [on|off])', 'cmd.history': 'search and recall past prompts', 'cmd.queue': 'manage messages queued for the next turn', 'cmd.usage': 'show this session token usage', 'cmd.agents': 'inspect subagent sessions of this conversation', 'cmd.todos': 'inspect the full todo list', 'cmd.subagent': 'choose the model delegated subagents run on', 'cmd.vscode-keys': 'pass ctrl+r through the vs code terminal', 'cmd.delete': 'delete a session and its subagent threads', 'cmd.clear': 'clear the screen', 'cmd.export': 'export the transcript to markdown (/export [path])', 'cmd.title': 'rename this session (/title )', 'cmd.copy': 'copy the latest assistant response', 'cmd.diff': 'inspect Git changes (/diff [--staged|ref])', 'cmd.review': 'review Git changes with the diff pasted in this session (/review [note])', 'cmd.quit': 'exit', // Help overlay 'help.keysTitle': ' keys', 'help.key.submit': 'enter submit · ctrl+j / alt+enter newline · up/down history · tab complete', 'help.key.mentions': '@ mentions workspace files and sessions', 'help.key.inspector': 'ctrl+o history details · ctrl/alt+r thinking · shift+tab permission preset', 'help.key.cancel': 'esc interrupt the running turn · ctrl+c cancel / clear / quit · ctrl+d exit', 'help.key.queue': 'empty tab picks queue or steer · /queue manages queued messages · delete cancels the newest one', 'help.key.edit': 'ctrl+k cut to end of line · ctrl+u clear line · ctrl+a / ctrl+e line ends', 'help.commandsTitle': ' commands', 'help.skillsTitle': ' skills', 'help.footer': '↑↓ scroll · pgup/pgdn page · g/G ends · esc/q close', 'help.compact': '/help · esc/q close', 'panel.queue.title': '/queue — {count} queued · rows {from}-{to}', 'panel.queue.empty': ' no messages queued for the next turn', 'panel.queue.attachments': '[attachments: read-only]', 'panel.queue.footerBusy': '↑↓ select · enter steer · e edit text · d remove · esc/q close', 'panel.queue.footerIdle': '↑↓ select · e edit text · d remove · esc/q close', 'panel.queue.editFooter': 'type · ←→ move · enter save · esc cancel', 'panel.queue.compact': '/queue · esc/q close', 'panel.usage.title': '/usage — usage of this session', 'panel.usage.compact': '/usage · esc/q close', 'panel.usage.footer': '↑↓ scroll · pgup/pgdn page · g/G ends · esc/q close', 'panel.usage.totals': 'Totals (whole session)', 'panel.usage.uncached': 'uncached in', 'panel.usage.cacheWrite': 'cache write', 'panel.usage.cacheRead': 'cache read', 'panel.usage.output': 'out', 'panel.usage.total': 'total', 'panel.usage.cacheHit': 'cache hit', 'panel.usage.turns': 'Per turn', 'panel.usage.byModel': 'By model', 'panel.usage.colTurns': 'turns', 'panel.usage.unknownModel': 'unattributed', 'panel.usage.colTurn': 'turn', 'panel.usage.colTotal': 'total', 'panel.usage.colUncached': 'uncached', 'panel.usage.colCacheRead': 'cache R', 'panel.usage.colCacheHit': 'hit', 'panel.usage.colCacheWrite': 'cache W', 'panel.usage.colOut': 'out', 'panel.usage.colThink': 'think', 'panel.usage.colModel': 'model', 'panel.usage.partialNote': '+ marks a group where some turns did not report that bucket; only reported turns are counted', 'panel.usage.unavailable': 'token projections are not mounted in this deployment (dsh-token-meter is missing)', 'panel.usage.noTurns': 'no completed turn yet', 'status.cycleHint': '(shift+tab to cycle)', 'approval.compact': 'approval{queued} · enter/y allow · esc/n reject', 'approval.overflow': '… +{count} more lines · ctrl+o shows the full call in the transcript', 'question.compact.plan': 'plan review · esc cancel', 'question.compact.normal': 'question · esc cancel', 'approval.submitted': 'submitted…', 'approval.footer': '↑↓ choose · enter confirm · y/n/d quick · esc reject', 'question.footer': '↑↓ choose · 1-9 select · space toggle · enter submit · esc cancel', 'question.custom': 'type a custom answer', 'question.submitted': 'submitted…', 'question.customNoOptions': '↑↓/pgup/pgdn scroll · type answer · enter submit · esc interrupt', 'question.customOptions': '↑↓/pgup/pgdn scroll · type answer · enter submit · tab/esc or empty backspace: options', 'question.multiOptions': '↑↓ choose · pgup/pgdn scroll · space/1-9 toggle · enter submit · c custom · esc interrupt', 'question.singleOptions': '↑↓ choose · pgup/pgdn scroll · 1-9 pick · enter submit · c custom · esc interrupt', 'question.switch': ' · ←→/ctrl+p/n switch question', 'question.title.plan': '📋 plan review', 'question.title.normal': '❓ question', // Composer and status chrome 'composer.placeholder': 'type a message · / commands · @ mentions · tab steers', 'composer.placeholderSteer': 'steer into this turn · tab queues for the next one', 'notice.submitMode.queue': 'send \u2192 queue for the next turn', 'notice.submitMode.steer': 'send \u2192 steer into this turn (only while one runs; idle it sends normally)', // Transcript markers on a settled prompt that was not submitted idle. 'entry.delivery.queued': 'queued', 'entry.delivery.steered': 'steered', 'status.shiftTabHint': '(shift+tab to cycle)', 'status.label.turns': 'turns', 'status.label.steps': 'steps', 'status.label.modelTime': 'model', 'status.label.latency': 'latency', 'status.label.tokensPerSec': ' tokens/s', 'status.label.tool': 'tool', 'status.label.cache': 'cache', 'status.label.in': 'in', 'status.label.out': 'out', 'status.label.mode': '/mode', 'status.label.context': 'context', 'status.label.sandbox': 'sandbox', 'status.plan.on': 'plan on', 'status.plan.mark': '⧉ plan', 'status.goal.round': '◎ round {current}/{max}', 'status.goal.phase': '◎ {phase}', // Frozen band 'frozen.keysGoTo': 'keys go to {owner} · esc {action}', 'frozen.action.rejects': 'rejects', 'frozen.action.cancels': 'cancels', 'frozen.action.closes': 'closes', 'frozen.action.waits': 'waits', // Relative time (panel list timestamps) 'time.justNow': 'now', 'time.minutesAgo': '{n}m ago', 'time.hoursAgo': '{n}h ago', 'time.daysAgo': '{n}d ago', // Common notices 'notice.themeSaved': 'theme \u2192 {name}', 'notice.themeRainbow': 'theme \u2192 rainbow · seed {seed} · /rainbow to reroll', 'notice.rainbowRolled': 'rainbow · seed {seed} · /rainbow to reroll · /rainbow {seed} to pin', 'notice.languageSaved': 'language \u2192 {name}', 'notice.themeSaveFailed': 'theme save failed: {message}', 'notice.languageSaveFailed': 'language save failed: {message}', 'notice.alreadyActive': 'that session is already active', 'notice.permissionPresetsUnmounted': 'permission presets are not mounted in this composition', 'notice.queueCancelled': 'queued message cancelled', 'notice.queueActionFailed': 'queue action failed: {message}', 'notice.queueUnavailable': 'queued message is no longer pending', 'notice.queueSteerUnavailable': 'steering is available only while the turn is running', 'notice.queueEditEmpty': 'queued message cannot be empty', 'notice.queueEdited': 'queued message edited', 'notice.queueSteered': 'queued message moved into this turn', 'notice.historySaveFailed': 'history save failed: {message}', 'notice.turnCancelled': 'turn cancelled \u2014 Ctrl+C or /quit to exit', 'notice.turnCancelledKeepQueue': 'turn cancelled \u2014 pending messages are preserved \u00b7 Ctrl+C or /quit to exit', 'notice.noSessionYet': 'no session yet \u2014 submit a message to start', 'notice.usage.animation': 'usage: /animation [on|off]', 'notice.usage.language': 'usage: /language [en|zh]', 'notice.usage.rainbow': 'usage: /rainbow [seed]', 'notice.usage.bareCommand': 'usage: /{name}', 'notice.switchInProgress': 'switching sessions — send again once the new session is up, or /resume cancel', 'notice.imageCancelled': 'image submission cancelled', 'notice.themeConfigUnreadable': 'theme config unreadable, using dark: {message}', 'notice.languageConfigUnreadable': 'language config unreadable, using english: {message}', 'notice.animationsConfigUnreadable': 'decorative animation config unreadable, effects stay on: {message}', 'notice.statuslineConfigUnreadable': 'statusline config unreadable, using defaults: {message}', 'notice.sessionSearchUnavailable': 'session search is unavailable in this deployment', 'notice.subagentsReadOnly': 'subagent conversations are read-only', 'notice.statuslineSaveFailed': 'statusline save failed: {message}', 'notice.animationsSaveFailed': 'decorative animation save failed: {message}', 'notice.commandRegistryMissing': 'no command registry is mounted in this composition', 'notice.commandFallbackFailed': 'command fallback failed: {message}', 'notice.commandFailed': 'command failed: {message}', 'notice.invalidReference': 'invalid session reference: {message}', 'notice.messageFailed': '{kind} failed: {message}', 'notice.referenceFailed': 'session reference failed: {message}', 'notice.activationFailed': 'session activation failed: {message}', 'notice.creationFailed': 'session creation failed: {message}', 'notice.modeChanged': 'mode → {value}', 'notice.modeSwitchFailed': 'mode switch failed: {message}', 'notice.permissionChanged': 'permission → {value}', 'notice.permissionChangeFailed': 'permission change failed: {message}', 'notice.cancelFailed': 'cancel failed: {message}', 'notice.modeChangeFailed': 'mode change failed: {message}', 'notice.modelNotDefault': 'model switch applies to this session but was not saved as the default: {message}', 'notice.modelSelectionRejected': 'model selection rejected: {message} — reopen /model to pick again', 'notice.exported': 'exported to {path}', 'notice.exportFailed': 'export failed: {message}', 'notice.resumeFailed': 'resume failed: {message}', 'notice.forkFailed': 'fork failed: {message}', 'notice.sessionSwitchFailed': 'session switch failed: {message}', 'notice.sessionCreated': 'created {id} · mode {mode}', 'notice.sessionResumed': 'resumed {id} · mode {mode}', 'notice.sessionSwitchedDirty': 'switched to {id}, but {detail}', 'notice.flushFailed': 'previous session flush failed: {message}', 'notice.agentReleaseFailed': 'previous agent release failed: {message}', 'notice.copyEmpty': 'nothing to copy yet', 'notice.copied': 'copied latest response', 'notice.switchQueued': 'will switch to {label} when the current turn finishes · /resume cancel to abort', 'notice.reviewStarted': 'review started under read-only permissions', 'notice.reviewFailed': 'review failed: {message}', 'notice.reviewUnavailable': 'review unavailable: {message}', 'notice.startupImages': 'processing {count} startup image{plural}…', 'notice.startupImagesAttached': '{count} startup image{plural} attached', 'notice.initialPromptFailed': 'initial prompt failed: {message}', 'notice.rejected': 'rejected — type below what it should do differently (it steers the next step)', 'notice.attachmentAlready': '{name} is already attached', 'notice.attachmentsChecking': 'checking {count} attachment{plural}…', 'notice.attachmentsAlready': 'those attachments are already attached', 'notice.attachmentDraftChanged': 'draft changed at the attachment drop point; drop the files again', 'notice.attachmentsReady': '{count} attachment{plural} ready for the next message', 'notice.attachmentFailed': 'attachment failed: {message}', 'notice.imageChecking': 'checking image {name}…', 'notice.imageDraftChanged': 'draft changed around the image mention; select it again', 'notice.imageReady': '{name} ready for the next message', 'notice.imageFailed': 'image attachment failed: {message}', 'notice.cancelBeforeExit': 'cancel the running turn before exiting (Esc or Ctrl+C)', 'notice.commandAttachments': 'commands cannot carry attachments; the line will be sent to the model as a prompt', 'notice.copyFailed': 'copy failed: {message}', 'notice.vscodeKeysFailed': 'vscode-keys failed: {message}', 'notice.animationState': 'decorative animations {state}; activity indicators stay live', 'notice.deleteFailed': 'delete failed: {message}', 'notice.modelChangedPlaceholder': 'model → {model} · image history will be sent as text placeholders', 'notice.modelNextStep': 'model → next step uses {model}', 'notice.modelSwitchFailed': 'model switch failed: {message}', 'notice.loggedIn': 'logged in to {provider}; select a model', 'notice.loggedOut': 'logged out from {provider}', 'notice.providerSaved': 'provider configuration saved: {provider}{suffix}', 'notice.apiKeyRemoved': 'API key removed for {provider}', 'notice.providerRemoved': 'provider removed: {provider}', 'notice.providerUnavailable': 'provider configuration is unavailable in this profile', 'notice.apiKeyUnavailable': 'API key removal is unavailable in this profile', 'notice.providerRemovalUnavailable': 'provider removal is unavailable in this profile', 'notice.loginIdleOnly': 'provider login is available only while the agent is idle', 'notice.loginUnavailable': 'provider login is unavailable in this profile', 'notice.logoutUnavailable': 'provider logout is unavailable in this profile', 'notice.modeChangedSimple': 'mode → {value}', 'notice.permissionChangedSimple': 'permission → {value}', 'notice.subagentsChanged': 'subagents → {value}', 'notice.subagentsInherited': 'subagents → inherit current model', 'notice.subagentChangeFailed': 'subagent model change failed: {message}', 'notice.modelMissing': 'current model is not in the catalog', 'notice.effortUnavailable': 'reasoning levels temporarily unavailable (capability lookup failed) — try again', 'notice.modelLookupFailed': 'model lookup failed: {message}', 'notice.diffFailed': 'diff failed: {message}', // Additional panel chrome 'panel.footer.chooseSwitch': '↑↓ choose · enter switch · r refresh · esc close', 'panel.footer.chooseSelect': '↑↓ choose · enter select · r refresh · esc close', 'panel.footer.inspectDetails': '↑↓ inspect · enter details · r refresh · esc close', 'panel.footer.inspectRefresh': '↑↓ inspect · r refresh · esc close', 'panel.footer.resume': 'tab/←→ filters · ↑↓/pg navigate · ctrl+f search · e details · t transcript · enter resume', 'panel.footer.delete': 'tab/←→ filters · ↑↓/pg navigate · ctrl+f search · e details · t transcript · enter delete · esc close', 'panel.footer.transcript': 'lines {from}-{to}/{total} · ↑↓/pg/g/G · t/esc close', 'panel.footer.history': '↑↓ move · g/G ends · enter fill · esc close', 'panel.footer.review': '↑↓ move · enter select · esc back · q close', 'panel.footer.statusline': '↑↓ move · space toggle · ←→ reorder · d default · esc close', 'panel.footer.schedule': 'esc/q close{more} · the model schedules via schedule_create', 'panel.mode.title': '/mode · current {current}', 'panel.permission.title': '/permission · current {current}', 'panel.plugin.title': '/plugin · loader inspector', 'panel.jobs.title': '/jobs · background tasks · {count}', 'panel.resume.deleteTitle': 'permanently delete {target}? this cannot be undone · subagent threads go too', 'panel.resume.title': '/resume{mode}{search} · {toolbar}', 'panel.delete.title': '/delete{search} · {toolbar}', 'panel.noActiveReminders': 'no active reminders — the model schedules via schedule_create', 'panel.notMounted': 'not mounted', 'panel.broken': 'broken: {message}', 'panel.live': 'live', 'panel.parent': 'parent {id}', 'panel.deleteMode': 'delete mode', 'panel.searching': 'searching', 'panel.noPresets': 'no presets', 'panel.noPermissions': 'no permission presets', 'panel.noJobs': 'no background jobs', 'panel.diff.compact': '{title} · {files} files · esc/q close', 'panel.diff.noFiles': 'no files', 'panel.diff.footer': '↑/↓ scroll · g/G ends · esc/q close', 'panel.todos.compact': 'todos · esc/q close', 'panel.todos.title': 'todos · {done}/{total} done · {active} active · {pending} pending · rows {from}-{to}/{rows}', 'panel.todos.empty': 'no todos yet', 'panel.todos.footer': '↑↓ scroll · pgup/pgdn page · g/G ends · esc/q close', 'panel.verbose.compact': 'history details · ctrl+o / esc / q close', 'panel.verbose.footer': '←→ entry · ↑↓ scroll · pgup/pgdn page · g/G ends · ctrl+o/esc/q close', 'panel.model.compact': '/model · {state}{providers} · {tail}', 'panel.model.noMatch': "no models match '{query}'", 'panel.model.compactNoMatch': "no match for '{query}'", 'panel.model.loading': 'loading…', 'panel.model.error': 'error', 'panel.model.noModels': 'no models available', 'panel.model.selectTitle': '/model — select model', 'panel.model.matches': "{filtered} of {total} match '{query}'", 'panel.model.footer.filter': 'type to filter · r retry · esc/q close', 'panel.model.footer.filtered': 'backspace edits · esc close', 'panel.model.title': '/model — select model', 'panel.model.titleCount': '/model — select model · {index}/{total}', 'panel.model.titleMatches': "/model — select model · {filtered} of {total} match '{query}'", 'panel.model.footer.select': 'type to filter · ↑↓ move · pgup/pgdn page · enter select{providers} · r retry · esc/q close', 'panel.model.footer.filteredSelect': '↑↓ move · pgup/pgdn page · enter select · backspace edits · esc close', 'panel.model.providers': 'tab providers', 'panel.provider.failure': 'unavailable providers: {providers}', 'panel.provider.loading': 'loading providers…', 'panel.provider.empty': 'no configurable providers', 'panel.provider.notConfigured': 'not configured', 'panel.provider.configured': 'configured', 'panel.provider.keyMissing': 'key missing', 'panel.provider.keyStatusUnavailable': 'key status unavailable', 'panel.provider.auth': 'provider auth', 'panel.provider.active': 'active', 'panel.provider.dormant': 'dormant', 'panel.provider.readOnly': 'read-only', 'panel.provider.custom': 'custom', 'panel.provider.notConfiguredDivider': '── not configured ──', 'panel.provider.title': '/model — providers', 'panel.provider.titleCount': '/model — providers · {index}/{total}', 'panel.provider.key': 'key {value}', 'panel.provider.authConfigured': 'provider auth', 'panel.provider.noKey': 'key missing', 'panel.provider.noLogin': 'not configured', 'panel.provider.loginStatusUnavailable': 'login status unavailable: {message}', 'panel.provider.noConfiguredKey': 'this provider has no configured API key to remove', 'panel.provider.readOnlyKey': 'this API key is supplied read-only by the environment', 'panel.provider.notRemovable': 'this provider profile is not removable', 'panel.provider.noLoginFlow': 'this provider offers no interactive login flow', 'panel.provider.loginRunning': 'a login attempt is already running for this provider', 'panel.provider.noLoginRecord': 'this provider has no login record to remove', 'panel.provider.readOnlyLogin': 'this login record is read-only', 'panel.provider.notManaged': 'this provider is not managed by Harness settings', 'panel.providers.compact': '/model providers · enter configure · d remove key · esc back', 'panel.providers.footer': '↑↓ move · enter configure · d remove key · x remove provider · r retry · esc back', 'panel.update.compact': '/update · {summary}', 'panel.update.checking': 'checking…', 'panel.update.probeFailed': 'probe failed', 'panel.update.updating': 'updating…', 'panel.update.installed': 'installed — restart to activate', 'panel.update.failed': 'failed', 'panel.update.upToDate': 'up to date', 'panel.update.aheadOfNpm': 'newer than npm', 'panel.update.enter': 'enter updates', 'panel.update.blocked': 'blocked', 'panel.update.title': '/update · aligned upgrade', 'panel.auth.methodsFooter': '↑↓ choose · enter continue · esc/q back', 'panel.auth.answerFooter': 'enter answer · c copy URL/code · esc cancel login', 'panel.auth.title': '/model · login {provider}', 'panel.auth.waiting': 'waiting for provider…', 'panel.auth.compact': 'provider login · esc cancel', 'panel.auth.logoutCompact': 'y logout · n/esc back', 'panel.auth.logoutTitle': '/model · logout provider', 'panel.auth.removeRecord': 'remove {provider} login record', 'panel.auth.unchanged': 'provider endpoint and model configuration stay unchanged', 'panel.auth.working': 'working…', 'panel.auth.logoutFooter': 'y confirm · n/esc back', 'panel.setup.compact': 'provider setup · terminal too small · esc back', 'panel.setup.noDonors': 'no model with declared efforts yet; declare one with e, or hand-write settings', 'panel.setup.copyInto': 'copy verbatim into {id}', 'panel.setup.copyTitle': '/model — copy efforts', 'panel.setup.copyFooter': '↑↓ move · enter copy · esc back', 'panel.setup.mode.subscribe': 'Subscription', 'panel.setup.mode.key': 'Key', 'panel.setup.mode.login.plan': 'signed in · plan', 'panel.setup.mode.login.none': 'not signed in', 'panel.setup.mode.login.running': 'signing in…', 'panel.setup.mode.overridden': '⚠ the settings key overrides the plan sign-in', 'panel.setup.title': '/model — configure {provider}', 'panel.setup.footer': '↑↓ move · ←→ in/out · space remove · e efforts · c copy efforts · tab per channel (subscription = web sign-in, key = discover) · enter save · esc back', 'panel.discovery.compact': 'model discovery · terminal too small · esc back', 'panel.discovery.loading': 'discovering models…', 'panel.discovery.empty': 'the endpoint advertised no models; add ids by hand on the setup page', 'panel.discovery.summary': '{advertised} advertised · {newCount} new · {checked} checked', 'panel.discovery.title': '/model — discover {provider}', 'panel.discovery.footer': '↑↓ move · space check · enter adopt · f refetch · esc back', 'panel.update.footer.probe': 'checking… · esc close', 'panel.update.footer.error': 'r recheck · esc close', 'panel.update.footer.apply': 'updating… · ↑↓ scroll · esc waits', 'panel.update.footer.current': 'up to date · r recheck · esc close', 'panel.update.footer.ahead': 'newer than npm — not downgrading · r recheck · esc close', 'panel.update.footer.update': 'enter update · r recheck · esc close', 'panel.update.footer.blocked': 'blocked · r recheck · esc close', 'panel.footer.effortEmpty': 'esc back', 'panel.footer.effort': '↑↓ choose · enter apply · esc/q back', 'panel.effort.title': '/model — effort for {provider} · {model}', 'panel.effort.empty': 'this model advertises no reasoning effort levels — the provider default applies', 'panel.default': 'default', 'panel.footer.agents': '↑↓ choose · enter/t transcript · r refresh · esc close', 'panel.agents.title': '/agents · {live} live · {total} total', 'panel.document.title': 'transcript · {id}', 'panel.subagent.transcriptTitle': 'subagent · {id}', 'panel.footer.subagent': '↑↓ choose · enter apply · r refresh · esc close', 'panel.subagent.title': '/subagent — model for delegated agents', 'panel.subagent.override': ' · override {value}', 'panel.subagent.inherit': 'inherit — follow the current model (/model switches apply)', 'panel.statusline.compact': '/statusline · esc close', 'panel.schedule.compact': '/schedule · {summary}', 'panel.schedule.none': 'no active reminders', 'panel.schedule.more': ' · +{count} more', 'panel.schedule.footer': 'esc/q close{more} · the model schedules via schedule_create', } as const export type MessageKey = keyof typeof en export type MessageCatalog = Record