- 待发箱抽屉: ChatInput ⏰ 入口 + OutboxDrawer + useAiOutbox IPC 封装
- U2 进度语义三层: 内容层(最近动作) + 静默三档降速脉冲, 永不自动判死
- 流式心跳自愈: 竞态窗口旧任务迟到完成事件误收敛的自愈判定(949 前端兜底)
- 953 截断提示: 末条气泡渲染截断标记 + 继续输出按钮, 事件契约透传
368 lines
17 KiB
TypeScript
368 lines
17 KiB
TypeScript
export default {
|
||
aiChat: {
|
||
// ── Multi-Agent parallel execution ──
|
||
conflictsPending: '{n} conflicts to resolve',
|
||
acceptA: 'Accept A',
|
||
acceptB: 'Accept B',
|
||
mergeBoth: 'Merge Both',
|
||
manualResolve: 'Manual',
|
||
|
||
// ── Conversation sidebar ──
|
||
sidebarTitle: 'Chats',
|
||
newConversation: 'New chat',
|
||
doubleClickToRename: 'Double-click to rename',
|
||
generating: 'Generating…',
|
||
archive: 'Archive',
|
||
unarchive: 'Unarchive',
|
||
pinConversation: 'Pin',
|
||
unpinConversation: 'Unpin',
|
||
// UX走查 P3-1/P2-6: rename entry in the "..." menu (search-mode parity + keyboard reach)
|
||
renameConversation: 'Rename',
|
||
moreActions: 'More actions',
|
||
archived: 'Archived',
|
||
archivedCount: 'Archived ({n})',
|
||
recoverableCount: 'Recoverable ({n})',
|
||
recoverableHint: 'Task parked safely; click to resume',
|
||
// ── Unattended engine badge (TopBar; shown while on, red badge resets the breaker) ──
|
||
unattendedOn: 'Unattended',
|
||
unattendedExecuting: 'working',
|
||
unattendedTripped: 'Unattended halted',
|
||
unattendedBadgeHint: 'Unattended mode is on. Click to open settings',
|
||
unattendedResetHint: 'Auto-halted after repeated start failures. Click to reset and resume',
|
||
recoverableDone: 'Task resumed, running in background',
|
||
recoverableFail: 'Recover failed: {msg}',
|
||
emptyConversation: 'No conversations',
|
||
// UX-06 §3.1: conversation search (live title filter, Ctrl+K to focus)
|
||
searchPlaceholder: 'Search chats…',
|
||
searchEmpty: 'No matching chats',
|
||
searchShortcutHint: 'Ctrl+K',
|
||
|
||
// ── Time grouping (sidebar) ──
|
||
today: 'Today',
|
||
yesterday: 'Yesterday',
|
||
earlier: 'Earlier',
|
||
groupEmpty: 'None',
|
||
|
||
// ── Header buttons ──
|
||
conversationList: 'Chat list',
|
||
maximize: 'Maximize',
|
||
pendingApprovalCount: '{n} pending',
|
||
pendingApprovalHint: 'Click to jump to the first pending approval',
|
||
// UX walkthrough B1: approval card arrived while user scrolled up; no forced scroll, hint only (5s dedup in ToolCardList)
|
||
newApprovalPending: 'New approval pending',
|
||
restoreSidebar: 'Restore sidebar',
|
||
sidebarResizeHint: 'Drag to resize sidebar',
|
||
detachWindow: 'Detach window',
|
||
reattachToMain: 'Reattach to main panel',
|
||
closePanel: 'Close panel',
|
||
dockRight: 'Dock to main window right',
|
||
undock: 'Undock',
|
||
pinOnTop: 'Pin on top',
|
||
unpin: 'Unpin',
|
||
closeWindow: 'Close window',
|
||
// I9(2026-10-05) text/code file attachment
|
||
pickFileTitle: 'Select text/code files',
|
||
textFileFilter: 'Text/code files',
|
||
fileTooLargeTruncated: 'File too large, truncated on insert',
|
||
fileReadFailed: 'Failed to read file, skipped',
|
||
shortcutsTitle: 'Keyboard shortcuts',
|
||
scNewConv: 'New conversation',
|
||
scFocusInput: 'Focus message input',
|
||
scRegenerate: 'Regenerate last reply',
|
||
scClearChat: 'Clear current conversation',
|
||
scSearch: 'Focus conversation search',
|
||
scToggleSidebar: 'Toggle sidebar',
|
||
scCloseOverlay: 'Close dialog / panel',
|
||
|
||
// ── Approval overlay (global top-right) ──
|
||
approvalWaitingTitle: 'Approval required',
|
||
approvalWaitingDesc: 'Click to review and handle',
|
||
|
||
// ── System-level approval popup (standalone window, visible when app unfocused) ──
|
||
popupTitle: 'Approval pending',
|
||
popupTagPath: 'Path auth',
|
||
popupTagRisk: 'Risk action',
|
||
popupOpenPanel: 'Open approval panel',
|
||
// 空态文案:正常空态会被 maybeAutoClose 即时关窗,此 hint 仅 close 失败时兜底
|
||
popupEmptyHint: 'Closing…',
|
||
|
||
// ── Provider status ──
|
||
clickToSwitchProvider: 'Click to switch provider',
|
||
// UX walkthrough B5: topbar switching shares the same IPC as Settings "set as default" (ai_set_provider rewrites is_default), label it honestly
|
||
providerSwitchSetsDefault: 'Click to switch provider (also sets it as the global default)',
|
||
providerNotConfigured: 'No AI provider configured. Please add one in settings.',
|
||
notConfigured: 'Not configured',
|
||
|
||
// ── F-01 阶段6: model picker (auto/specify toggle + dropdown) ──
|
||
autoMode: 'Auto',
|
||
specifyMode: 'Specify',
|
||
autoModeHint: 'Auto mode: router picks the best model per scenario',
|
||
specifyModeHint: 'Specify mode: use the selected model, overriding the router (main chat only)',
|
||
selectModel: 'Select model',
|
||
noModels: 'No models available. Please fetch in settings.',
|
||
|
||
// ── Empty states example prompt cards + no-provider guidance) ──
|
||
emptyNoProvider: 'No AI provider configured',
|
||
emptyNoProviderHint: 'Please add a provider in settings to start chatting',
|
||
emptyTitle: 'Chat with AI assistant',
|
||
emptyHint: 'Try "create a project" or "list all tasks"',
|
||
// Example prompt cards: click to fill and send (4 prompts, DevFlow scenarios)
|
||
examplePrompt1: 'Analyze this project’s dependencies',
|
||
examplePrompt2: 'Help me write a workflow node',
|
||
examplePrompt3: 'List all current tasks',
|
||
examplePrompt4: 'Generate a project idea',
|
||
goToSettings: 'Open settings',
|
||
goToSettingsHint: 'The detached window cannot open settings directly. Configure AI providers on the main window’s Settings page.',
|
||
goToSettingsOpened: 'Settings opened in the main window',
|
||
goToTaskHint: 'The detached window cannot open tasks directly. View task details in the main window.',
|
||
|
||
// ── Provider switch feedback ──
|
||
providerSwitched: 'Switched to {model}',
|
||
providerSwitchHint: 'Current model: {model}',
|
||
|
||
// ── Back to bottom ──
|
||
backToBottom: 'Back to bottom',
|
||
|
||
// ── Pending queue ──
|
||
queueTitle: 'Queued {n}/10',
|
||
clearQueue: 'Clear',
|
||
// UI-4 (board 943): clear-queue confirm (one click wipes all queued items, unrecoverable)
|
||
clearQueueConfirm: 'Clear all queued messages? This cannot be undone',
|
||
// queue item edit + send now
|
||
queueEdit: 'Edit',
|
||
queueSave: 'Save',
|
||
queueCancel: 'Cancel',
|
||
queueSendNow: 'Send now',
|
||
// 3c UX batch addition (I4 queue backfill: pull a queued item back into the input box)
|
||
queueBackfill: 'Backfill',
|
||
|
||
// ── Skill ──
|
||
clearSkill: 'Clear skill',
|
||
skillBadgeTip: 'Injected full skill playbook: {name}',
|
||
placeholderWithSkill: 'Skill selected. Type arguments and press Enter',
|
||
placeholderDefault: "Type a message... (/ for skills, {'@'} to mention)",
|
||
skillNoMatch: 'No matching skill',
|
||
skillNotLoaded: 'No local skills loaded',
|
||
|
||
// ── @ entity mention (@ opens popover, select inserts [Type:Name] token) ──
|
||
mentionHint: "{'@'} to mention project/task",
|
||
mentionGroupProject: 'Projects',
|
||
mentionGroupTask: 'Tasks',
|
||
mentionGroupIdea: 'Ideas',
|
||
mentionNoMatch: 'No matching entity',
|
||
mentionEmpty: 'No project/task to mention',
|
||
|
||
// ── Send ──
|
||
stopGenerating: 'Stop generating',
|
||
// L2 状态机停止按钮三态(ConvState 派生)
|
||
stopping: 'Stopping',
|
||
stopFailedRetry: 'Stop failed, click to retry',
|
||
|
||
// ── Input hint ──
|
||
inputHint: 'Enter to send · Shift+Enter for newline',
|
||
|
||
// ── F-260614-05 Phase 2b: image input (paste / drag-drop) ──
|
||
pickImage: 'Pick image',
|
||
pickImageTitle: 'Pick image (or paste / drag-drop)',
|
||
imageFilter: 'Image files',
|
||
removeImage: 'Remove image',
|
||
imagePreviewAlt: 'Pending image',
|
||
imageTooLarge: 'Image too large (max 10MB), skipped',
|
||
imageLimit: 'Up to {n} images, extras ignored',
|
||
imageReadFailed: 'Failed to read image',
|
||
imageIgnoredWarn: 'Current model does not support images; they will be ignored on send',
|
||
imageOnlyBlocked: 'Current model does not support images; switch to a vision model or add some text',
|
||
|
||
// ── Confirm dialog ──
|
||
confirmDeleteConversation: 'Delete chat "{title}"? This cannot be undone.',
|
||
// stronger warning when deleting the currently active conversation
|
||
confirmDeleteActiveConversation: '"{title}" is the chat you are currently viewing. Deleting it will clear the current view and cannot be undone. Continue?',
|
||
clearChat: 'Clear',
|
||
confirmClearChat: 'Are you sure you want to clear all messages in this chat? This cannot be undone.',
|
||
toastSendFail: 'Send failed: {msg}',
|
||
|
||
// ── Message copy ──
|
||
copyMsg: 'Copy message',
|
||
copied: 'Copied',
|
||
copyFailed: 'Copy failed',
|
||
// Copy bubble as image (html2canvas → clipboard; falls back to download)
|
||
copyAsImage: 'Copy as image',
|
||
copiedAsImage: 'Copied as image',
|
||
copyAsImageFailed: 'Failed to copy as image',
|
||
|
||
// ── Message actions bar ──
|
||
// regenerateUnavailable: Ctrl+R / retry paths still call store.regenerate(); precheck toast key
|
||
// (I6 revert removed the UI button only — key still referenced by useAiSend.ts, review 2026-10-05 ②)
|
||
regenerateUnavailable: 'No reply to regenerate',
|
||
regenerateFailed: 'Regenerate failed: {msg}',
|
||
// fetch_url "Install obscura via AI" button triggers sendMessage; failure toast (mirrors editMessageFailed)
|
||
sendFailed: 'Send failed: {msg}',
|
||
|
||
// ── edit last user message and regenerate ──
|
||
editMessage: 'Edit',
|
||
editMessageFailed: 'Edit failed: {msg}',
|
||
editNotLastUser: 'Only the last user message can be edited',
|
||
// UX walkthrough B3: editMessage IPC takes no parts; editing would silently drop images, block at entry
|
||
editImageBlocked: 'This message contains images and cannot be edited (regenerating would lose them)',
|
||
placeholderEditing: 'Edit message then Enter to regenerate (Esc to cancel)',
|
||
|
||
// ── Error bubble actions (UX-03 / ) ──
|
||
retry: 'Retry',
|
||
goToSettingsAction: 'Open settings',
|
||
|
||
// ── max iterations reached pause action card ──
|
||
maxRoundsReached: 'Max rounds reached. Continue?',
|
||
maxRoundsHint: 'Continue runs another full round; stop ends with current results',
|
||
continueLoop: 'Continue',
|
||
stopLoop: 'Stop',
|
||
continueLoopFailed: 'Continue failed: {msg}',
|
||
stopLoopFailed: 'Stop failed: {msg}',
|
||
|
||
// ── L1 help protocol (aichat experience & agent capability redesign §2.3, 2026-06-21): circuit-breaker help card ──
|
||
helpRequiredAck: 'Choice noted. Please rephrase your request to try another approach / continue',
|
||
|
||
// ── F-260619-03 Phase B: path authorization dialog (LLM accessing dir outside whitelist) ──
|
||
dirAuthRequired: 'Path authorization required',
|
||
dirAuthHint: '{tool} wants to access: {path}',
|
||
dirAuthOnce: 'This time',
|
||
dirAuthSession: 'This session',
|
||
dirAuthAlways: 'Always',
|
||
dirAuthDeny: 'Deny',
|
||
dirAuthFailed: 'Authorization failed: {msg}',
|
||
// M5:path deny second confirmation (deny is irreversible — tool returns Err, loop continues without retry; asymmetry with approve, prevents mis-clicks)
|
||
dirAuthDenyConfirm: 'Deny authorization? The tool will fail immediately and will not be retried this round.',
|
||
// Persistent bypass banner shown at the top of the chat area while "trust all directories" is on
|
||
pathAuthBypassBanner: 'Authorization fully bypassed (including sensitive directories): AI can access any file directly',
|
||
|
||
// ── Input Augmentation layer: mention/skill injection feedback ──
|
||
// search_files blind search denied by whitelist fallback (no auth dialog; prompt user to use @mention or absolute path)
|
||
searchFilesBlocked: "search_files only works inside authorized dirs. Use {'@'}[project] to reference or provide an absolute path.",
|
||
// /skill hot reload (ai_reload_skills IPC) success toast
|
||
skillReloaded: 'Skills reloaded',
|
||
// @mention entity resolve failed (id points to a project/task/idea/skill that was deleted or unavailable)
|
||
mentionUnresolved: 'The mentioned {kind} was deleted or is unavailable',
|
||
// Same-name skill conflict (scan_skills returns conflicts; frontend warns, injection takes first by skills>commands>plugins priority)
|
||
skillConflict: 'Skill "{name}" has multiple definitions; using skills priority',
|
||
|
||
// ── ⑥.4 Phase 4: @project expansion summary (input area preview) ──
|
||
enrichmentBadge: '📎 Referenced "{project}" ({tasks} tasks, {ideas} ideas)',
|
||
enrichmentExpand: 'Show context preview',
|
||
enrichmentCollapse: 'Hide context preview',
|
||
enrichmentLabel: 'Context preview',
|
||
|
||
|
||
// ── F-15 phase 2: manual context management (clear / compress) ──
|
||
// Buttons (Header action area: trash + compress icon)
|
||
clearContext: 'Clear context',
|
||
compressContext: 'Compress context',
|
||
// Confirm dialog (clear is semantically irreversible; history archived, not deleted)
|
||
// Title "Clear context" folded into the lead sentence; stress irreversible + archived segment + AI no longer sees history
|
||
clearContextConfirm: 'Clear context? This action is irreversible. The current chat context will be archived as a segment (the AI will no longer see these history messages). New chats are not affected.',
|
||
// Danger button label for the confirm dialog (ConfirmDialog dangerLabel); falls back to common.confirm if omitted
|
||
clearContextDangerLabel: 'Clear',
|
||
// Collapsed separator (consecutive same-status merged into one bar; {n}=merged message count)
|
||
contextArchived: 'Archived {n} messages',
|
||
compressed: 'Context compressed',
|
||
compressing: 'Compressing…',
|
||
clearSuccess: 'Context cleared',
|
||
compressSuccess: 'Context compressed',
|
||
// B4: one-shot auto-compress notice (loop auto-compress no longer fully silent)
|
||
autoCompressed: 'Context auto-compressed (earlier messages folded into summary)',
|
||
compressError: 'Compression failed: {msg}',
|
||
clearError: 'Clear failed: {msg}',
|
||
initError: 'AI panel init failed: {msg} (reopen panel to retry)',
|
||
initDegraded: 'List load failed, continuing in degraded mode: {msg}',
|
||
// Separator expand / collapse
|
||
expand: 'Expand',
|
||
collapse: 'Collapse',
|
||
// Compressed summary block label (before the system summary message when expanded)
|
||
compressedSummaryLabel: 'Context summary',
|
||
|
||
// ── TopBar bottom context badges (tooltip + L3 full context popover labels) ──
|
||
viewGoals: 'View goals',
|
||
runningTasks: 'Running background tasks',
|
||
runningRounds: '{n} rounds running',
|
||
untitledConversation: 'Untitled conversation',
|
||
recoverableTask: 'Interrupted · recoverable',
|
||
recoverNow: 'Resume',
|
||
viewHistory: 'View history messages',
|
||
viewSummary: 'View context summary',
|
||
viewContext: 'View AI context',
|
||
contextSystemPrompt: 'System Prompt',
|
||
contextEnvironment: 'Environment',
|
||
contextCompressedSummary: 'Compressed Summary',
|
||
contextEnrichment: 'Enriched Context',
|
||
contextCountUnit: 'items',
|
||
|
||
// ── EnrichmentPanel ──
|
||
enrichmentDismiss: 'Unlink',
|
||
|
||
// ── AE-2025-04 Session Trust ──
|
||
// Auto-approval toast (same-session already approved same-kind op: same tool + same dir)
|
||
autoApprovedToast: 'Auto-approved: {tool}({dir})',
|
||
|
||
// ── Skill injection feedback (success/failure light toast for /skill resolve) ──
|
||
skillInjectedToast: 'Skill "{name}" injected',
|
||
skillNotFoundToast: 'Skill {name} not found',
|
||
|
||
// ── CIStatus.vue (commit CI checks status card) ──
|
||
ciTitle: 'CI Checks',
|
||
ciNFailed: '{n} failed',
|
||
ciNPending: '{n} pending',
|
||
ciNPassed: '{n} passed',
|
||
|
||
// ── MessageList token detail popover (per-fee breakdown: input/cache hit/output/reasoning) ──
|
||
tokenDetailTitle: 'Token usage details',
|
||
estimated: 'estimated',
|
||
tokenInLabel: 'Input (cache miss, full price)',
|
||
tokenCacheLabel: 'Cache hit (low price)',
|
||
tokenOutLabel: 'Output',
|
||
// #12 conversation-cumulative tokens (token detail popover footer)
|
||
tokenConvTotal: 'Conversation total',
|
||
tokenConvTotalIn: 'Total in',
|
||
tokenConvTotalOut: 'Total out',
|
||
tokenReasonLabel: 'Reasoning',
|
||
tokenCacheRateLabel: 'Cache hit rate',
|
||
tokenModelLabel: 'Model',
|
||
tokenUsageNoteLabel: 'Usage note',
|
||
tokenUsageNote: 'prompt_tokens missing, shown as estimated',
|
||
|
||
// ── TopBar goal/project context labels ──
|
||
goalsCount: 'Goals ({n})',
|
||
none: 'None',
|
||
projectLabel: "{'@'}Projects",
|
||
|
||
// ── 3c UX batch addition (I5 classified send-failure messages): friendly text by
|
||
// error kind; {msg} keeps the raw error string for troubleshooting ──
|
||
sendErrRateLimit: 'Rate limit reached, please retry later (error: {msg})',
|
||
sendErrQuota: 'AI quota or balance insufficient, check your provider account (error: {msg})',
|
||
sendErrNetwork: 'Network error or timeout, check your connection and retry (error: {msg})',
|
||
|
||
// ── UX-P3 chat polish additions ──
|
||
editEmptyBlocked: 'Edit content is empty, submission cancelled',
|
||
skillNoMatchQuery: 'No skill matches "{q}", send blocked',
|
||
backfillOverwriteConfirm: 'The input box has an unsent draft; backfilling will overwrite it. Continue?',
|
||
|
||
// ── Outbox / scheduled messages (OutboxDrawer + ChatInput clock entry, design 2026-10-10 §3.4) ──
|
||
outboxEntry: 'Scheduled messages',
|
||
outboxTitle: 'Scheduled & Outbox',
|
||
outboxEmpty: 'No scheduled or queued messages',
|
||
outboxNewTitle: 'New scheduled message',
|
||
outboxNewPlaceholder: 'Content to send on schedule',
|
||
outboxTimeLabel: 'Send time',
|
||
outboxCreate: 'Schedule',
|
||
outboxReschedule: 'Reschedule',
|
||
outboxSendNow: 'Send now',
|
||
outboxCancel: 'Cancel',
|
||
outboxQueueAsap: 'ASAP',
|
||
outboxStatusPending: 'Pending',
|
||
outboxStatusSending: 'Sending',
|
||
outboxStatusSent: 'Sent',
|
||
outboxStatusFailed: 'Failed',
|
||
outboxStatusCanceled: 'Canceled',
|
||
outboxActionFail: 'Action failed, please retry',
|
||
outboxDuePast: 'Scheduled time must be in the future',
|
||
outboxNeedConv: 'No target conversation; create one first',
|
||
},
|
||
}
|