feat(i18n): localize context-inspector surface across 7 locales
Localize the context-inspector surface across 7 locales for improved internationalization support.
This commit is contained in:
@@ -502,6 +502,52 @@ pub enum MessageId {
|
||||
CtxMenuHelpDesc,
|
||||
// Agent fanout card.
|
||||
FanoutCounts,
|
||||
|
||||
CtxInspTitle,
|
||||
CtxInspSessionContext,
|
||||
CtxInspSystemPrompt,
|
||||
CtxInspReferences,
|
||||
CtxInspRecentTools,
|
||||
CtxInspModel,
|
||||
CtxInspWorkspace,
|
||||
CtxInspSession,
|
||||
CtxInspContext,
|
||||
CtxInspTranscript,
|
||||
CtxInspWorkspaceStatus,
|
||||
CtxInspNotSampledYet,
|
||||
CtxInspOk,
|
||||
CtxInspHigh,
|
||||
CtxInspCritical,
|
||||
CtxInspIncluded,
|
||||
CtxInspAttached,
|
||||
CtxInspNotIncluded,
|
||||
CtxInspOutputCaptured,
|
||||
CtxInspNoOutputYet,
|
||||
CtxInspNoSystemPrompt,
|
||||
CtxInspNoReferences,
|
||||
CtxInspNoToolActivity,
|
||||
CtxInspAltVHint,
|
||||
CtxInspCells,
|
||||
CtxInspApiMessages,
|
||||
CtxInspActive,
|
||||
CtxInspCell,
|
||||
CtxInspMoreReferences,
|
||||
CtxInspStablePrefix,
|
||||
CtxInspVolatileWorkingSet,
|
||||
CtxInspFirstLine,
|
||||
CtxInspTotal,
|
||||
CtxInspTextPromptLayers,
|
||||
CtxInspSingleTextBlob,
|
||||
CtxInspBlocks,
|
||||
CtxInspBlock,
|
||||
CtxInspTokens,
|
||||
CtxInspLayers,
|
||||
CtxInspNone,
|
||||
CtxInspEmpty,
|
||||
CtxInspCacheFriendly,
|
||||
CtxInspChangesByTurn,
|
||||
CtxInspStablePrefixOnly,
|
||||
CtxInspCacheTip,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@@ -779,6 +825,51 @@ pub const ALL_MESSAGE_IDS: &[MessageId] = &[
|
||||
MessageId::CtxMenuHelp,
|
||||
MessageId::CtxMenuHelpDesc,
|
||||
MessageId::FanoutCounts,
|
||||
MessageId::CtxInspTitle,
|
||||
MessageId::CtxInspSessionContext,
|
||||
MessageId::CtxInspSystemPrompt,
|
||||
MessageId::CtxInspReferences,
|
||||
MessageId::CtxInspRecentTools,
|
||||
MessageId::CtxInspModel,
|
||||
MessageId::CtxInspWorkspace,
|
||||
MessageId::CtxInspSession,
|
||||
MessageId::CtxInspContext,
|
||||
MessageId::CtxInspTranscript,
|
||||
MessageId::CtxInspWorkspaceStatus,
|
||||
MessageId::CtxInspNotSampledYet,
|
||||
MessageId::CtxInspOk,
|
||||
MessageId::CtxInspHigh,
|
||||
MessageId::CtxInspCritical,
|
||||
MessageId::CtxInspIncluded,
|
||||
MessageId::CtxInspAttached,
|
||||
MessageId::CtxInspNotIncluded,
|
||||
MessageId::CtxInspOutputCaptured,
|
||||
MessageId::CtxInspNoOutputYet,
|
||||
MessageId::CtxInspNoSystemPrompt,
|
||||
MessageId::CtxInspNoReferences,
|
||||
MessageId::CtxInspNoToolActivity,
|
||||
MessageId::CtxInspAltVHint,
|
||||
MessageId::CtxInspCells,
|
||||
MessageId::CtxInspApiMessages,
|
||||
MessageId::CtxInspActive,
|
||||
MessageId::CtxInspCell,
|
||||
MessageId::CtxInspMoreReferences,
|
||||
MessageId::CtxInspStablePrefix,
|
||||
MessageId::CtxInspVolatileWorkingSet,
|
||||
MessageId::CtxInspFirstLine,
|
||||
MessageId::CtxInspTotal,
|
||||
MessageId::CtxInspTextPromptLayers,
|
||||
MessageId::CtxInspSingleTextBlob,
|
||||
MessageId::CtxInspBlocks,
|
||||
MessageId::CtxInspBlock,
|
||||
MessageId::CtxInspTokens,
|
||||
MessageId::CtxInspLayers,
|
||||
MessageId::CtxInspNone,
|
||||
MessageId::CtxInspEmpty,
|
||||
MessageId::CtxInspCacheFriendly,
|
||||
MessageId::CtxInspChangesByTurn,
|
||||
MessageId::CtxInspStablePrefixOnly,
|
||||
MessageId::CtxInspCacheTip,
|
||||
];
|
||||
|
||||
pub fn tr(locale: Locale, id: MessageId) -> &'static str {
|
||||
@@ -1365,6 +1456,55 @@ fn english(id: MessageId) -> &'static str {
|
||||
MessageId::FanoutCounts => {
|
||||
"{done} done · {running} running · {failed} failed · {pending} pending"
|
||||
}
|
||||
|
||||
MessageId::CtxInspTitle => "Context inspector",
|
||||
MessageId::CtxInspSessionContext => "Session Context",
|
||||
MessageId::CtxInspSystemPrompt => "System Prompt Structure",
|
||||
MessageId::CtxInspReferences => "References",
|
||||
MessageId::CtxInspRecentTools => "Recent Tools",
|
||||
MessageId::CtxInspModel => "Model",
|
||||
MessageId::CtxInspWorkspace => "Workspace",
|
||||
MessageId::CtxInspSession => "Session",
|
||||
MessageId::CtxInspContext => "Context",
|
||||
MessageId::CtxInspTranscript => "Transcript",
|
||||
MessageId::CtxInspWorkspaceStatus => "Workspace status",
|
||||
MessageId::CtxInspNotSampledYet => "not sampled yet",
|
||||
MessageId::CtxInspOk => "ok",
|
||||
MessageId::CtxInspHigh => "high",
|
||||
MessageId::CtxInspCritical => "critical",
|
||||
MessageId::CtxInspIncluded => "included",
|
||||
MessageId::CtxInspAttached => "attached",
|
||||
MessageId::CtxInspNotIncluded => "not included",
|
||||
MessageId::CtxInspOutputCaptured => "output captured",
|
||||
MessageId::CtxInspNoOutputYet => "no output yet",
|
||||
MessageId::CtxInspNoSystemPrompt => "No system prompt set.",
|
||||
MessageId::CtxInspNoReferences => "No file, directory, or media references recorded yet.",
|
||||
MessageId::CtxInspNoToolActivity => "No tool activity recorded yet.",
|
||||
MessageId::CtxInspAltVHint => "Open the matching card and press Alt+V for full details.",
|
||||
MessageId::CtxInspCells => "cells",
|
||||
MessageId::CtxInspApiMessages => "API messages",
|
||||
MessageId::CtxInspActive => "active",
|
||||
MessageId::CtxInspCell => "cell",
|
||||
MessageId::CtxInspMoreReferences => "more reference(s)",
|
||||
MessageId::CtxInspStablePrefix => "Stable prefix",
|
||||
MessageId::CtxInspVolatileWorkingSet => "Volatile working set",
|
||||
MessageId::CtxInspFirstLine => "First line",
|
||||
MessageId::CtxInspTotal => "Total",
|
||||
MessageId::CtxInspTextPromptLayers => "Text prompt layers",
|
||||
MessageId::CtxInspSingleTextBlob => "Single text blob",
|
||||
MessageId::CtxInspBlocks => "block(s)",
|
||||
MessageId::CtxInspBlock => "block",
|
||||
MessageId::CtxInspTokens => "tokens",
|
||||
MessageId::CtxInspLayers => "layer(s)",
|
||||
MessageId::CtxInspNone => "none",
|
||||
MessageId::CtxInspEmpty => "(empty)",
|
||||
MessageId::CtxInspCacheFriendly => "cache-friendly",
|
||||
MessageId::CtxInspChangesByTurn => "changes by session/turn",
|
||||
MessageId::CtxInspStablePrefixOnly => "stable prefix only",
|
||||
MessageId::CtxInspCacheTip => {
|
||||
"Tip: Stable prefix blocks are DeepSeek V4 prefix-cache eligible. \
|
||||
Volatile working-set changes break the cache only for the tail."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1815,6 +1955,54 @@ fn vietnamese(id: MessageId) -> Option<&'static str> {
|
||||
MessageId::FanoutCounts => {
|
||||
"{done} hoàn thành · {running} đang chạy · {failed} thất bại · {pending} chờ"
|
||||
}
|
||||
|
||||
MessageId::CtxInspTitle => "Trình kiểm tra ngữ cảnh",
|
||||
MessageId::CtxInspSessionContext => "Ngữ cảnh phiên",
|
||||
MessageId::CtxInspSystemPrompt => "Cấu trúc lời nhắc hệ thống",
|
||||
MessageId::CtxInspReferences => "Tham chiếu",
|
||||
MessageId::CtxInspRecentTools => "Công cụ gần đây",
|
||||
MessageId::CtxInspModel => "Mô hình",
|
||||
MessageId::CtxInspWorkspace => "Không gian làm việc",
|
||||
MessageId::CtxInspSession => "Phiên",
|
||||
MessageId::CtxInspContext => "Ngữ cảnh",
|
||||
MessageId::CtxInspTranscript => "Bảng ghi",
|
||||
MessageId::CtxInspWorkspaceStatus => "Trạng thái không gian làm việc",
|
||||
MessageId::CtxInspNotSampledYet => "chưa lấy mẫu",
|
||||
MessageId::CtxInspOk => "ổn",
|
||||
MessageId::CtxInspHigh => "cao",
|
||||
MessageId::CtxInspCritical => "nghiêm trọng",
|
||||
MessageId::CtxInspIncluded => "đã bao gồm",
|
||||
MessageId::CtxInspAttached => "đã đính kèm",
|
||||
MessageId::CtxInspNotIncluded => "không bao gồm",
|
||||
MessageId::CtxInspOutputCaptured => "đã thu được đầu ra",
|
||||
MessageId::CtxInspNoOutputYet => "chưa có đầu ra",
|
||||
MessageId::CtxInspNoSystemPrompt => "Chưa có lời nhắc hệ thống.",
|
||||
MessageId::CtxInspNoReferences => "Chưa có tham chiếu tệp, thư mục hoặc phương tiện nào.",
|
||||
MessageId::CtxInspNoToolActivity => "Chưa có hoạt động công cụ nào.",
|
||||
MessageId::CtxInspAltVHint => "Mở thẻ phù hợp và nhấn Alt+V để biết chi tiết.",
|
||||
MessageId::CtxInspCells => "ô",
|
||||
MessageId::CtxInspApiMessages => "tin nhắn API",
|
||||
MessageId::CtxInspActive => "đang hoạt động",
|
||||
MessageId::CtxInspCell => "ô",
|
||||
MessageId::CtxInspMoreReferences => "các tham chiếu khác",
|
||||
MessageId::CtxInspStablePrefix => "Khối ổn định",
|
||||
MessageId::CtxInspVolatileWorkingSet => "Vùng làm việc thay đổi",
|
||||
MessageId::CtxInspFirstLine => "Dòng đầu",
|
||||
MessageId::CtxInspTotal => "Tổng",
|
||||
MessageId::CtxInspTextPromptLayers => "Lớp văn bản gợi ý",
|
||||
MessageId::CtxInspSingleTextBlob => "Văn bản khối đơn",
|
||||
MessageId::CtxInspBlocks => "khối",
|
||||
MessageId::CtxInspBlock => "khối",
|
||||
MessageId::CtxInspTokens => "token",
|
||||
MessageId::CtxInspLayers => "lớp",
|
||||
MessageId::CtxInspNone => "không",
|
||||
MessageId::CtxInspEmpty => "(trống)",
|
||||
MessageId::CtxInspCacheFriendly => "thân thiện với bộ nhớ đệm",
|
||||
MessageId::CtxInspChangesByTurn => "thay đổi theo phiên/lượt",
|
||||
MessageId::CtxInspStablePrefixOnly => "chỉ có tiền tố ổn định",
|
||||
MessageId::CtxInspCacheTip => {
|
||||
"Gợi ý: Các khối ổn định đủ điều kiện cho bộ nhớ đệm tiền tố DeepSeek V4. Thay đổi vùng làm việc chỉ phá vỡ bộ nhớ đệm ở phần cuối."
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1831,6 +2019,54 @@ fn traditional_chinese(id: MessageId) -> Option<&'static str> {
|
||||
MessageId::FanoutCounts => {
|
||||
"{done} 已完成 · {running} 運行中 · {failed} 失敗 · {pending} 等待中"
|
||||
}
|
||||
|
||||
MessageId::CtxInspTitle => "上下文檢查器",
|
||||
MessageId::CtxInspSessionContext => "會話上下文",
|
||||
MessageId::CtxInspSystemPrompt => "系統提示結構",
|
||||
MessageId::CtxInspReferences => "引用",
|
||||
MessageId::CtxInspRecentTools => "最近使用的工具",
|
||||
MessageId::CtxInspModel => "模型",
|
||||
MessageId::CtxInspWorkspace => "工作區",
|
||||
MessageId::CtxInspSession => "會話",
|
||||
MessageId::CtxInspContext => "上下文",
|
||||
MessageId::CtxInspTranscript => "記錄",
|
||||
MessageId::CtxInspWorkspaceStatus => "工作區狀態",
|
||||
MessageId::CtxInspNotSampledYet => "尚未取樣",
|
||||
MessageId::CtxInspOk => "正常",
|
||||
MessageId::CtxInspHigh => "較高",
|
||||
MessageId::CtxInspCritical => "嚴重",
|
||||
MessageId::CtxInspIncluded => "已包含",
|
||||
MessageId::CtxInspAttached => "已附加",
|
||||
MessageId::CtxInspNotIncluded => "未包含",
|
||||
MessageId::CtxInspOutputCaptured => "已捕獲輸出",
|
||||
MessageId::CtxInspNoOutputYet => "尚無輸出",
|
||||
MessageId::CtxInspNoSystemPrompt => "未設定系統提示。",
|
||||
MessageId::CtxInspNoReferences => "尚未記錄任何檔案、目錄或媒體引用。",
|
||||
MessageId::CtxInspNoToolActivity => "尚未記錄任何工具活動。",
|
||||
MessageId::CtxInspAltVHint => "開啟對應的卡片並按 Alt+V 檢視詳細資訊。",
|
||||
MessageId::CtxInspCells => "儲存格",
|
||||
MessageId::CtxInspApiMessages => "API 訊息",
|
||||
MessageId::CtxInspActive => "作用中",
|
||||
MessageId::CtxInspCell => "儲存格",
|
||||
MessageId::CtxInspMoreReferences => "其他引用",
|
||||
MessageId::CtxInspStablePrefix => "穩定前綴",
|
||||
MessageId::CtxInspVolatileWorkingSet => "易變工作集",
|
||||
MessageId::CtxInspFirstLine => "第一行",
|
||||
MessageId::CtxInspTotal => "總計",
|
||||
MessageId::CtxInspTextPromptLayers => "文字提示層",
|
||||
MessageId::CtxInspSingleTextBlob => "單一文字塊",
|
||||
MessageId::CtxInspBlocks => "個區塊",
|
||||
MessageId::CtxInspBlock => "個區塊",
|
||||
MessageId::CtxInspTokens => "個 token",
|
||||
MessageId::CtxInspLayers => "個層",
|
||||
MessageId::CtxInspNone => "無",
|
||||
MessageId::CtxInspEmpty => "(空)",
|
||||
MessageId::CtxInspCacheFriendly => "快取友好",
|
||||
MessageId::CtxInspChangesByTurn => "按會話/輪次變化",
|
||||
MessageId::CtxInspStablePrefixOnly => "僅穩定前綴",
|
||||
MessageId::CtxInspCacheTip => {
|
||||
"提示:穩定前綴區塊符合 DeepSeek V4 前綴快取條件。易變工作集的更改僅會破壞快取尾部。"
|
||||
}
|
||||
other => chinese_simplified(other)?,
|
||||
})
|
||||
}
|
||||
@@ -2242,6 +2478,56 @@ fn japanese(id: MessageId) -> Option<&'static str> {
|
||||
MessageId::FanoutCounts => {
|
||||
"{done} 完了 · {running} 実行中 · {failed} 失敗 · {pending} 待機"
|
||||
}
|
||||
|
||||
MessageId::CtxInspTitle => "コンテキストインスペクタ",
|
||||
MessageId::CtxInspSessionContext => "セッションコンテキスト",
|
||||
MessageId::CtxInspSystemPrompt => "システムプロンプト構造",
|
||||
MessageId::CtxInspReferences => "参照",
|
||||
MessageId::CtxInspRecentTools => "最近のツール",
|
||||
MessageId::CtxInspModel => "モデル",
|
||||
MessageId::CtxInspWorkspace => "ワークスペース",
|
||||
MessageId::CtxInspSession => "セッション",
|
||||
MessageId::CtxInspContext => "コンテキスト",
|
||||
MessageId::CtxInspTranscript => "トランスクリプト",
|
||||
MessageId::CtxInspWorkspaceStatus => "ワークスペース状態",
|
||||
MessageId::CtxInspNotSampledYet => "未サンプリング",
|
||||
MessageId::CtxInspOk => "良好",
|
||||
MessageId::CtxInspHigh => "高い",
|
||||
MessageId::CtxInspCritical => "深刻",
|
||||
MessageId::CtxInspIncluded => "含まれている",
|
||||
MessageId::CtxInspAttached => "添付済み",
|
||||
MessageId::CtxInspNotIncluded => "含まれていない",
|
||||
MessageId::CtxInspOutputCaptured => "出力取得済み",
|
||||
MessageId::CtxInspNoOutputYet => "未出力",
|
||||
MessageId::CtxInspNoSystemPrompt => "システムプロンプトが設定されていません。",
|
||||
MessageId::CtxInspNoReferences => {
|
||||
"ファイル、ディレクトリ、メディアの参照はまだ記録されていません。"
|
||||
}
|
||||
MessageId::CtxInspNoToolActivity => "ツールアクティビティはまだ記録されていません。",
|
||||
MessageId::CtxInspAltVHint => "該当するカードを開き、Alt+V を押すと詳細が表示されます。",
|
||||
MessageId::CtxInspCells => "セル",
|
||||
MessageId::CtxInspApiMessages => "API メッセージ",
|
||||
MessageId::CtxInspActive => "アクティブ",
|
||||
MessageId::CtxInspCell => "セル",
|
||||
MessageId::CtxInspMoreReferences => "その他の参照",
|
||||
MessageId::CtxInspStablePrefix => "安定プレフィックス",
|
||||
MessageId::CtxInspVolatileWorkingSet => "揮発性ワーキングセット",
|
||||
MessageId::CtxInspFirstLine => "最初の行",
|
||||
MessageId::CtxInspTotal => "合計",
|
||||
MessageId::CtxInspTextPromptLayers => "テキストプロンプトレイヤー",
|
||||
MessageId::CtxInspSingleTextBlob => "単一テキストブロブ",
|
||||
MessageId::CtxInspBlocks => "ブロック",
|
||||
MessageId::CtxInspBlock => "ブロック",
|
||||
MessageId::CtxInspTokens => "トークン",
|
||||
MessageId::CtxInspLayers => "レイヤー",
|
||||
MessageId::CtxInspNone => "なし",
|
||||
MessageId::CtxInspEmpty => "(空)",
|
||||
MessageId::CtxInspCacheFriendly => "キャッシュフレンドリー",
|
||||
MessageId::CtxInspChangesByTurn => "セッション/ターンごとに変更",
|
||||
MessageId::CtxInspStablePrefixOnly => "安定プレフィックスのみ",
|
||||
MessageId::CtxInspCacheTip => {
|
||||
"ヒント:安定プレフィックスブロックはDeepSeek V4プレフィックスキャッシュの対象です。揮発性ワーキングセットの変更は末尾のキャッシュのみを破壊します。"
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -2596,6 +2882,54 @@ fn chinese_simplified(id: MessageId) -> Option<&'static str> {
|
||||
MessageId::FanoutCounts => {
|
||||
"{done} 已完成 · {running} 运行中 · {failed} 失败 · {pending} 等待中"
|
||||
}
|
||||
|
||||
MessageId::CtxInspTitle => "上下文检查器",
|
||||
MessageId::CtxInspSessionContext => "会话上下文",
|
||||
MessageId::CtxInspSystemPrompt => "系统提示结构",
|
||||
MessageId::CtxInspReferences => "引用",
|
||||
MessageId::CtxInspRecentTools => "最近使用的工具",
|
||||
MessageId::CtxInspModel => "模型",
|
||||
MessageId::CtxInspWorkspace => "工作区",
|
||||
MessageId::CtxInspSession => "会话",
|
||||
MessageId::CtxInspContext => "上下文",
|
||||
MessageId::CtxInspTranscript => "记录",
|
||||
MessageId::CtxInspWorkspaceStatus => "工作区状态",
|
||||
MessageId::CtxInspNotSampledYet => "尚未采样",
|
||||
MessageId::CtxInspOk => "正常",
|
||||
MessageId::CtxInspHigh => "较高",
|
||||
MessageId::CtxInspCritical => "严重",
|
||||
MessageId::CtxInspIncluded => "已包含",
|
||||
MessageId::CtxInspAttached => "已附加",
|
||||
MessageId::CtxInspNotIncluded => "未包含",
|
||||
MessageId::CtxInspOutputCaptured => "已捕获输出",
|
||||
MessageId::CtxInspNoOutputYet => "尚无输出",
|
||||
MessageId::CtxInspNoSystemPrompt => "未设置系统提示。",
|
||||
MessageId::CtxInspNoReferences => "尚未记录任何文件、目录或媒体引用。",
|
||||
MessageId::CtxInspNoToolActivity => "尚未记录任何工具活动。",
|
||||
MessageId::CtxInspAltVHint => "打开对应的卡片并按 Alt+V 查看详细信息。",
|
||||
MessageId::CtxInspCells => "单元格",
|
||||
MessageId::CtxInspApiMessages => "API 消息",
|
||||
MessageId::CtxInspActive => "活动中",
|
||||
MessageId::CtxInspCell => "单元格",
|
||||
MessageId::CtxInspMoreReferences => "更多引用",
|
||||
MessageId::CtxInspStablePrefix => "稳定前缀",
|
||||
MessageId::CtxInspVolatileWorkingSet => "易变工作集",
|
||||
MessageId::CtxInspFirstLine => "第一行",
|
||||
MessageId::CtxInspTotal => "总计",
|
||||
MessageId::CtxInspTextPromptLayers => "文本提示层",
|
||||
MessageId::CtxInspSingleTextBlob => "单一文本块",
|
||||
MessageId::CtxInspBlocks => "个区块",
|
||||
MessageId::CtxInspBlock => "个区块",
|
||||
MessageId::CtxInspTokens => "个 token",
|
||||
MessageId::CtxInspLayers => "个层",
|
||||
MessageId::CtxInspNone => "无",
|
||||
MessageId::CtxInspEmpty => "(空)",
|
||||
MessageId::CtxInspCacheFriendly => "缓存友好",
|
||||
MessageId::CtxInspChangesByTurn => "按会话/轮次变化",
|
||||
MessageId::CtxInspStablePrefixOnly => "仅稳定前缀",
|
||||
MessageId::CtxInspCacheTip => {
|
||||
"提示:稳定前缀区块符合 DeepSeek V4 前缀缓存条件。易变工作集的更改仅会破坏缓存尾部。"
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3028,6 +3362,58 @@ fn portuguese_brazil(id: MessageId) -> Option<&'static str> {
|
||||
MessageId::FanoutCounts => {
|
||||
"{done} concluído · {running} executando · {failed} falhou · {pending} pendente"
|
||||
}
|
||||
|
||||
MessageId::CtxInspTitle => "Inspetor de contexto",
|
||||
MessageId::CtxInspSessionContext => "Contexto da sessão",
|
||||
MessageId::CtxInspSystemPrompt => "Estrutura do prompt do sistema",
|
||||
MessageId::CtxInspReferences => "Referências",
|
||||
MessageId::CtxInspRecentTools => "Ferramentas recentes",
|
||||
MessageId::CtxInspModel => "Modelo",
|
||||
MessageId::CtxInspWorkspace => "Espaço de trabalho",
|
||||
MessageId::CtxInspSession => "Sessão",
|
||||
MessageId::CtxInspContext => "Contexto",
|
||||
MessageId::CtxInspTranscript => "Transcrição",
|
||||
MessageId::CtxInspWorkspaceStatus => "Status do espaço de trabalho",
|
||||
MessageId::CtxInspNotSampledYet => "ainda não amostrado",
|
||||
MessageId::CtxInspOk => "ok",
|
||||
MessageId::CtxInspHigh => "alto",
|
||||
MessageId::CtxInspCritical => "crítico",
|
||||
MessageId::CtxInspIncluded => "incluído",
|
||||
MessageId::CtxInspAttached => "anexado",
|
||||
MessageId::CtxInspNotIncluded => "não incluído",
|
||||
MessageId::CtxInspOutputCaptured => "saída capturada",
|
||||
MessageId::CtxInspNoOutputYet => "nenhuma saída ainda",
|
||||
MessageId::CtxInspNoSystemPrompt => "Nenhum prompt de sistema definido.",
|
||||
MessageId::CtxInspNoReferences => {
|
||||
"Nenhuma referência de arquivo, diretório ou mídia registrada ainda."
|
||||
}
|
||||
MessageId::CtxInspNoToolActivity => "Nenhuma atividade de ferramenta registrada ainda.",
|
||||
MessageId::CtxInspAltVHint => {
|
||||
"Abra o cartão correspondente e pressione Alt+V para detalhes completos."
|
||||
}
|
||||
MessageId::CtxInspCells => "células",
|
||||
MessageId::CtxInspApiMessages => "mensagens da API",
|
||||
MessageId::CtxInspActive => "ativo",
|
||||
MessageId::CtxInspCell => "célula",
|
||||
MessageId::CtxInspMoreReferences => "mais referência(s)",
|
||||
MessageId::CtxInspStablePrefix => "Prefixo estável",
|
||||
MessageId::CtxInspVolatileWorkingSet => "Conjunto de trabalho volátil",
|
||||
MessageId::CtxInspFirstLine => "Primeira linha",
|
||||
MessageId::CtxInspTotal => "Total",
|
||||
MessageId::CtxInspTextPromptLayers => "Camadas de prompt de texto",
|
||||
MessageId::CtxInspSingleTextBlob => "Bloco de texto único",
|
||||
MessageId::CtxInspBlocks => "bloco(s)",
|
||||
MessageId::CtxInspBlock => "bloco",
|
||||
MessageId::CtxInspTokens => "token(s)",
|
||||
MessageId::CtxInspLayers => "camada(s)",
|
||||
MessageId::CtxInspNone => "nenhum",
|
||||
MessageId::CtxInspEmpty => "(vazio)",
|
||||
MessageId::CtxInspCacheFriendly => "amigável ao cache",
|
||||
MessageId::CtxInspChangesByTurn => "muda por sessão/turno",
|
||||
MessageId::CtxInspStablePrefixOnly => "apenas prefixo estável",
|
||||
MessageId::CtxInspCacheTip => {
|
||||
"Dica: Blocos de prefixo estável são elegíveis para cache de prefixo DeepSeek V4. Alterações no conjunto de trabalho volátil quebram o cache apenas no final."
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3470,6 +3856,58 @@ fn spanish_latin_america(id: MessageId) -> Option<&'static str> {
|
||||
MessageId::FanoutCounts => {
|
||||
"{done} completado · {running} ejecutando · {failed} falló · {pending} pendiente"
|
||||
}
|
||||
|
||||
MessageId::CtxInspTitle => "Inspector de contexto",
|
||||
MessageId::CtxInspSessionContext => "Contexto de la sesión",
|
||||
MessageId::CtxInspSystemPrompt => "Estructura del prompt del sistema",
|
||||
MessageId::CtxInspReferences => "Referencias",
|
||||
MessageId::CtxInspRecentTools => "Herramientas recientes",
|
||||
MessageId::CtxInspModel => "Modelo",
|
||||
MessageId::CtxInspWorkspace => "Espacio de trabajo",
|
||||
MessageId::CtxInspSession => "Sesión",
|
||||
MessageId::CtxInspContext => "Contexto",
|
||||
MessageId::CtxInspTranscript => "Transcripción",
|
||||
MessageId::CtxInspWorkspaceStatus => "Estado del espacio de trabajo",
|
||||
MessageId::CtxInspNotSampledYet => "aún no muestreado",
|
||||
MessageId::CtxInspOk => "bien",
|
||||
MessageId::CtxInspHigh => "alto",
|
||||
MessageId::CtxInspCritical => "crítico",
|
||||
MessageId::CtxInspIncluded => "incluido",
|
||||
MessageId::CtxInspAttached => "adjunto",
|
||||
MessageId::CtxInspNotIncluded => "no incluido",
|
||||
MessageId::CtxInspOutputCaptured => "salida capturada",
|
||||
MessageId::CtxInspNoOutputYet => "sin salida aún",
|
||||
MessageId::CtxInspNoSystemPrompt => "No hay prompt de sistema establecido.",
|
||||
MessageId::CtxInspNoReferences => {
|
||||
"Aún no se han registrado referencias de archivos, directorios o medios."
|
||||
}
|
||||
MessageId::CtxInspNoToolActivity => "Aún no se ha registrado actividad de herramientas.",
|
||||
MessageId::CtxInspAltVHint => {
|
||||
"Abra la tarjeta correspondiente y presione Alt+V para ver los detalles completos."
|
||||
}
|
||||
MessageId::CtxInspCells => "celdas",
|
||||
MessageId::CtxInspApiMessages => "mensajes de API",
|
||||
MessageId::CtxInspActive => "activo",
|
||||
MessageId::CtxInspCell => "celda",
|
||||
MessageId::CtxInspMoreReferences => "más referencia(s)",
|
||||
MessageId::CtxInspStablePrefix => "Prefijo estable",
|
||||
MessageId::CtxInspVolatileWorkingSet => "Conjunto de trabajo volátil",
|
||||
MessageId::CtxInspFirstLine => "Primera línea",
|
||||
MessageId::CtxInspTotal => "Total",
|
||||
MessageId::CtxInspTextPromptLayers => "Capas de prompt de texto",
|
||||
MessageId::CtxInspSingleTextBlob => "Bloque de texto único",
|
||||
MessageId::CtxInspBlocks => "bloque(s)",
|
||||
MessageId::CtxInspBlock => "bloque",
|
||||
MessageId::CtxInspTokens => "token(es)",
|
||||
MessageId::CtxInspLayers => "capa(s)",
|
||||
MessageId::CtxInspNone => "ninguno",
|
||||
MessageId::CtxInspEmpty => "(vacío)",
|
||||
MessageId::CtxInspCacheFriendly => "amigable con caché",
|
||||
MessageId::CtxInspChangesByTurn => "cambia por sesión/turno",
|
||||
MessageId::CtxInspStablePrefixOnly => "solo prefijo estable",
|
||||
MessageId::CtxInspCacheTip => {
|
||||
"Consejo: Los bloques de prefijo estable son elegibles para caché de prefijo DeepSeek V4. Los cambios en el conjunto de trabajo volátil solo rompen la caché al final."
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ use std::collections::HashSet;
|
||||
use std::fmt::Write;
|
||||
|
||||
use crate::compaction::estimate_input_tokens_conservative;
|
||||
use crate::localization::{Locale, MessageId, tr};
|
||||
use crate::models::{
|
||||
LEGACY_DEEPSEEK_CONTEXT_WINDOW_TOKENS, SystemPrompt, context_window_for_model,
|
||||
};
|
||||
@@ -71,10 +72,10 @@ enum PromptLayerKind {
|
||||
}
|
||||
|
||||
impl PromptLayerKind {
|
||||
fn label(self) -> &'static str {
|
||||
fn label(self, locale: Locale) -> &'static str {
|
||||
match self {
|
||||
Self::Static => "cache-friendly",
|
||||
Self::Dynamic => "changes by session/turn",
|
||||
Self::Static => tr(locale, MessageId::CtxInspCacheFriendly),
|
||||
Self::Dynamic => tr(locale, MessageId::CtxInspChangesByTurn),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,47 +88,67 @@ struct PromptTextLayer<'a> {
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn build_context_inspector_text(app: &App) -> String {
|
||||
pub fn build_context_inspector_text(app: &App, locale: Locale) -> String {
|
||||
let mut out = String::new();
|
||||
let usage = context_usage(app);
|
||||
let status = context_status(usage.2);
|
||||
let (used, max, percent) = usage;
|
||||
|
||||
let _ = writeln!(out, "Session Context");
|
||||
let _ = writeln!(out, "{}", tr(locale, MessageId::CtxInspSessionContext));
|
||||
let _ = writeln!(out, "---------------");
|
||||
let _ = writeln!(out, "Model: {}", app.model);
|
||||
let _ = writeln!(
|
||||
out,
|
||||
"Workspace: {}",
|
||||
"{}: {}",
|
||||
tr(locale, MessageId::CtxInspModel),
|
||||
app.model
|
||||
);
|
||||
let _ = writeln!(
|
||||
out,
|
||||
"{}: {}",
|
||||
tr(locale, MessageId::CtxInspWorkspace),
|
||||
crate::utils::display_path(&app.workspace)
|
||||
);
|
||||
if let Some(session_id) = app.current_session_id.as_deref() {
|
||||
let _ = writeln!(out, "Session: {session_id}");
|
||||
let _ = writeln!(
|
||||
out,
|
||||
"{}: {session_id}",
|
||||
tr(locale, MessageId::CtxInspSession)
|
||||
);
|
||||
}
|
||||
let (used, max, percent) = usage;
|
||||
let status_label = match context_status(percent) {
|
||||
ContextPressure::Critical => tr(locale, MessageId::CtxInspCritical),
|
||||
ContextPressure::High => tr(locale, MessageId::CtxInspHigh),
|
||||
ContextPressure::Ok => tr(locale, MessageId::CtxInspOk),
|
||||
};
|
||||
let tokens_unit = tr(locale, MessageId::CtxInspTokens);
|
||||
let _ = writeln!(
|
||||
out,
|
||||
"Context: {status} - ~{used}/{max} tokens ({percent:.1}%)"
|
||||
"{ctx_label}: {status_label} - ~{used}/{max} {tokens_unit} ({percent:.1}%)",
|
||||
ctx_label = tr(locale, MessageId::CtxInspContext),
|
||||
);
|
||||
let cells = tr(locale, MessageId::CtxInspCells);
|
||||
let api_msgs = tr(locale, MessageId::CtxInspApiMessages);
|
||||
let _ = writeln!(
|
||||
out,
|
||||
"Transcript: {} cells, {} API messages",
|
||||
"{label}: {} {cells}, {} {api_msgs}",
|
||||
app.history.len(),
|
||||
app.api_messages.len()
|
||||
app.api_messages.len(),
|
||||
label = tr(locale, MessageId::CtxInspTranscript),
|
||||
);
|
||||
let _ = writeln!(
|
||||
out,
|
||||
"Workspace status: {}",
|
||||
"{}: {}",
|
||||
tr(locale, MessageId::CtxInspWorkspaceStatus),
|
||||
app.workspace_context
|
||||
.as_deref()
|
||||
.unwrap_or("not sampled yet")
|
||||
.unwrap_or(tr(locale, MessageId::CtxInspNotSampledYet))
|
||||
);
|
||||
|
||||
let _ = writeln!(out);
|
||||
push_system_prompt_structure(&mut out, app);
|
||||
push_system_prompt_structure(&mut out, app, locale);
|
||||
let _ = writeln!(out);
|
||||
push_references(&mut out, &app.session_context_references);
|
||||
push_references(&mut out, &app.session_context_references, locale);
|
||||
let _ = writeln!(out);
|
||||
push_tools(&mut out, app);
|
||||
push_tools(&mut out, app, locale);
|
||||
|
||||
out
|
||||
}
|
||||
@@ -143,20 +164,26 @@ fn context_usage(app: &App) -> (usize, u32, f64) {
|
||||
(used, max, percent)
|
||||
}
|
||||
|
||||
fn context_status(percent: f64) -> &'static str {
|
||||
enum ContextPressure {
|
||||
Ok,
|
||||
High,
|
||||
Critical,
|
||||
}
|
||||
|
||||
fn context_status(percent: f64) -> ContextPressure {
|
||||
if percent >= CONTEXT_CRITICAL_THRESHOLD_PERCENT {
|
||||
"critical"
|
||||
ContextPressure::Critical
|
||||
} else if percent >= CONTEXT_WARNING_THRESHOLD_PERCENT {
|
||||
"high"
|
||||
ContextPressure::High
|
||||
} else {
|
||||
"ok"
|
||||
ContextPressure::Ok
|
||||
}
|
||||
}
|
||||
|
||||
/// Inspect the system prompt structure, split into cache-friendly stable
|
||||
/// prefix blocks and the volatile working-set tail block.
|
||||
fn push_system_prompt_structure(out: &mut String, app: &App) {
|
||||
let _ = writeln!(out, "System Prompt Structure");
|
||||
fn push_system_prompt_structure(out: &mut String, app: &App, locale: Locale) {
|
||||
let _ = writeln!(out, "{}", tr(locale, MessageId::CtxInspSystemPrompt));
|
||||
let _ = writeln!(out, "-----------------------");
|
||||
|
||||
// Conservative token estimate: ~3 chars per token (consistent with
|
||||
@@ -170,6 +197,22 @@ fn push_system_prompt_structure(out: &mut String, app: &App) {
|
||||
None => 0,
|
||||
};
|
||||
|
||||
let stable_lbl = tr(locale, MessageId::CtxInspStablePrefix);
|
||||
let volatile_lbl = tr(locale, MessageId::CtxInspVolatileWorkingSet);
|
||||
let first_line_lbl = tr(locale, MessageId::CtxInspFirstLine);
|
||||
let total_lbl = tr(locale, MessageId::CtxInspTotal);
|
||||
let text_prompt_lbl = tr(locale, MessageId::CtxInspTextPromptLayers);
|
||||
let single_blob_lbl = tr(locale, MessageId::CtxInspSingleTextBlob);
|
||||
let blocks_unit = tr(locale, MessageId::CtxInspBlocks);
|
||||
let block_unit = tr(locale, MessageId::CtxInspBlock);
|
||||
let tokens_unit = tr(locale, MessageId::CtxInspTokens);
|
||||
let layers_unit = tr(locale, MessageId::CtxInspLayers);
|
||||
let none_lbl = tr(locale, MessageId::CtxInspNone);
|
||||
let empty_lbl = tr(locale, MessageId::CtxInspEmpty);
|
||||
let cache_friendly = tr(locale, MessageId::CtxInspCacheFriendly);
|
||||
let changes_by_turn = tr(locale, MessageId::CtxInspChangesByTurn);
|
||||
let stable_only = tr(locale, MessageId::CtxInspStablePrefixOnly);
|
||||
let no_system_prompt = tr(locale, MessageId::CtxInspNoSystemPrompt);
|
||||
match &app.system_prompt {
|
||||
Some(SystemPrompt::Blocks(blocks)) => {
|
||||
let working_set_idx = blocks
|
||||
@@ -189,24 +232,24 @@ fn push_system_prompt_structure(out: &mut String, app: &App) {
|
||||
|
||||
let _ = writeln!(
|
||||
out,
|
||||
" Stable prefix: {stable_count} block(s), ~{stable_tokens} tokens [cache-friendly]"
|
||||
" {stable_lbl}: {stable_count} {blocks_unit}, ~{stable_tokens} {tokens_unit} [{cache_friendly}]"
|
||||
);
|
||||
if let Some(block) = working_block {
|
||||
let _ = writeln!(
|
||||
out,
|
||||
" Volatile working set: 1 block, ~{working_tokens} tokens [changes every turn]"
|
||||
" {volatile_lbl}: 1 {block_unit}, ~{working_tokens} {tokens_unit} [{changes_by_turn}]"
|
||||
);
|
||||
let _ = writeln!(
|
||||
out,
|
||||
" First line: {}",
|
||||
block.text.lines().next().unwrap_or("(empty)")
|
||||
" {first_line_lbl}: {}",
|
||||
block.text.lines().next().unwrap_or(empty_lbl)
|
||||
);
|
||||
} else {
|
||||
let _ = writeln!(out, " Volatile working set: none");
|
||||
let _ = writeln!(out, " {volatile_lbl}: {none_lbl}");
|
||||
}
|
||||
let _ = writeln!(
|
||||
out,
|
||||
" Total: {} block(s), ~{total_est} tokens",
|
||||
" {total_lbl}: {} {blocks_unit}, ~{total_est} {tokens_unit}",
|
||||
blocks.len()
|
||||
);
|
||||
}
|
||||
@@ -219,37 +262,32 @@ fn push_system_prompt_structure(out: &mut String, app: &App) {
|
||||
{
|
||||
let _ = writeln!(
|
||||
out,
|
||||
" Text prompt layers: {} layer(s), ~{total_est} tokens",
|
||||
" {text_prompt_lbl}: {} {layers_unit}, ~{total_est} {tokens_unit}",
|
||||
layers.len()
|
||||
);
|
||||
for layer in layers {
|
||||
let tokens = text_tokens(layer.body);
|
||||
let kind_lbl = layer.kind.label(locale);
|
||||
let _ = writeln!(
|
||||
out,
|
||||
" - {}: ~{} tokens [{}]",
|
||||
" - {}: ~{tokens} {tokens_unit} [{kind_lbl}]",
|
||||
layer.name,
|
||||
tokens,
|
||||
layer.kind.label()
|
||||
);
|
||||
}
|
||||
} else {
|
||||
let _ = writeln!(
|
||||
out,
|
||||
" Single text blob (~{total_est} tokens) [stable prefix only]"
|
||||
" {single_blob_lbl} (~{total_est} {tokens_unit}) [{stable_only}]"
|
||||
);
|
||||
}
|
||||
}
|
||||
None => {
|
||||
let _ = writeln!(out, " No system prompt set.");
|
||||
let _ = writeln!(out, " {no_system_prompt}");
|
||||
}
|
||||
}
|
||||
|
||||
// Cache-economics hint
|
||||
let _ = writeln!(
|
||||
out,
|
||||
" Tip: Stable prefix blocks are DeepSeek V4 prefix-cache eligible. \
|
||||
Volatile working-set changes break the cache only for the tail."
|
||||
);
|
||||
let _ = writeln!(out, " {}", tr(locale, MessageId::CtxInspCacheTip));
|
||||
}
|
||||
|
||||
fn split_text_prompt_layers(text: &str) -> Vec<PromptTextLayer<'_>> {
|
||||
@@ -288,8 +326,8 @@ fn split_text_prompt_layers(text: &str) -> Vec<PromptTextLayer<'_>> {
|
||||
layers
|
||||
}
|
||||
|
||||
fn push_references(out: &mut String, references: &[SessionContextReference]) {
|
||||
let _ = writeln!(out, "References");
|
||||
fn push_references(out: &mut String, references: &[SessionContextReference], locale: Locale) {
|
||||
let _ = writeln!(out, "{}", tr(locale, MessageId::CtxInspReferences));
|
||||
let _ = writeln!(out, "----------");
|
||||
|
||||
let mut seen = HashSet::new();
|
||||
@@ -306,7 +344,11 @@ fn push_references(out: &mut String, references: &[SessionContextReference]) {
|
||||
if rendered >= MAX_REFERENCE_ROWS {
|
||||
let remaining = references.len().saturating_sub(rendered);
|
||||
if remaining > 0 {
|
||||
let _ = writeln!(out, "- ... {remaining} more reference(s)");
|
||||
let _ = writeln!(
|
||||
out,
|
||||
"- ... {remaining} {}",
|
||||
tr(locale, MessageId::CtxInspMoreReferences)
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -317,12 +359,12 @@ fn push_references(out: &mut String, references: &[SessionContextReference]) {
|
||||
};
|
||||
let state = if reference.included {
|
||||
if reference.expanded {
|
||||
"included"
|
||||
tr(locale, MessageId::CtxInspIncluded)
|
||||
} else {
|
||||
"attached"
|
||||
tr(locale, MessageId::CtxInspAttached)
|
||||
}
|
||||
} else {
|
||||
"not included"
|
||||
tr(locale, MessageId::CtxInspNotIncluded)
|
||||
};
|
||||
let detail = reference
|
||||
.detail
|
||||
@@ -339,15 +381,12 @@ fn push_references(out: &mut String, references: &[SessionContextReference]) {
|
||||
}
|
||||
|
||||
if rendered == 0 {
|
||||
let _ = writeln!(
|
||||
out,
|
||||
"- No file, directory, or media references recorded yet."
|
||||
);
|
||||
let _ = writeln!(out, "- {}", tr(locale, MessageId::CtxInspNoReferences));
|
||||
}
|
||||
}
|
||||
|
||||
fn push_tools(out: &mut String, app: &App) {
|
||||
let _ = writeln!(out, "Recent Tools");
|
||||
fn push_tools(out: &mut String, app: &App, locale: Locale) {
|
||||
let _ = writeln!(out, "{}", tr(locale, MessageId::CtxInspRecentTools));
|
||||
let _ = writeln!(out, "------------");
|
||||
|
||||
let mut rows: Vec<(usize, &ToolDetailRecord)> = app
|
||||
@@ -359,7 +398,8 @@ fn push_tools(out: &mut String, app: &App) {
|
||||
|
||||
let mut rendered = 0usize;
|
||||
for detail in app.active_tool_details.values() {
|
||||
push_tool_row(out, "active", detail);
|
||||
let location = tr(locale, MessageId::CtxInspActive);
|
||||
push_tool_row(out, locale, location, detail);
|
||||
rendered += 1;
|
||||
if rendered >= MAX_TOOL_ROWS {
|
||||
return;
|
||||
@@ -369,26 +409,23 @@ fn push_tools(out: &mut String, app: &App) {
|
||||
.into_iter()
|
||||
.take(MAX_TOOL_ROWS.saturating_sub(rendered))
|
||||
{
|
||||
let location = format!("cell {cell_idx}");
|
||||
push_tool_row(out, &location, detail);
|
||||
let location = format!("{} {cell_idx}", tr(locale, MessageId::CtxInspCell));
|
||||
push_tool_row(out, locale, &location, detail);
|
||||
rendered += 1;
|
||||
}
|
||||
|
||||
if rendered == 0 {
|
||||
let _ = writeln!(out, "- No tool activity recorded yet.");
|
||||
let _ = writeln!(out, "- {}", tr(locale, MessageId::CtxInspNoToolActivity));
|
||||
} else {
|
||||
let _ = writeln!(
|
||||
out,
|
||||
"- Open the matching card and press Alt+V for full details."
|
||||
);
|
||||
let _ = writeln!(out, "- {}", tr(locale, MessageId::CtxInspAltVHint));
|
||||
}
|
||||
}
|
||||
|
||||
fn push_tool_row(out: &mut String, location: &str, detail: &ToolDetailRecord) {
|
||||
fn push_tool_row(out: &mut String, locale: Locale, location: &str, detail: &ToolDetailRecord) {
|
||||
let output_state = if detail.output.as_deref().is_some_and(|out| !out.is_empty()) {
|
||||
"output captured"
|
||||
tr(locale, MessageId::CtxInspOutputCaptured)
|
||||
} else {
|
||||
"no output yet"
|
||||
tr(locale, MessageId::CtxInspNoOutputYet)
|
||||
};
|
||||
let _ = writeln!(
|
||||
out,
|
||||
@@ -420,6 +457,8 @@ mod tests {
|
||||
use crate::tui::history::HistoryCell;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::localization::Locale;
|
||||
|
||||
fn test_app() -> App {
|
||||
App::new(
|
||||
TuiOptions {
|
||||
@@ -450,7 +489,7 @@ mod tests {
|
||||
#[test]
|
||||
fn inspector_formats_empty_state() {
|
||||
let app = test_app();
|
||||
let text = build_context_inspector_text(&app);
|
||||
let text = build_context_inspector_text(&app, Locale::En);
|
||||
assert!(text.contains("Session Context"));
|
||||
assert!(text.contains("No file, directory, or media references recorded yet."));
|
||||
assert!(text.contains("No tool activity recorded yet."));
|
||||
@@ -477,7 +516,7 @@ mod tests {
|
||||
},
|
||||
});
|
||||
|
||||
let text = build_context_inspector_text(&app);
|
||||
let text = build_context_inspector_text(&app, Locale::En);
|
||||
assert!(text.contains("[file] @src/main.rs -> /tmp/project/src/main.rs"));
|
||||
}
|
||||
|
||||
@@ -492,7 +531,7 @@ mod tests {
|
||||
}],
|
||||
});
|
||||
|
||||
let text = build_context_inspector_text(&app);
|
||||
let text = build_context_inspector_text(&app, Locale::En);
|
||||
assert!(text.contains("Context: critical"), "{text}");
|
||||
}
|
||||
|
||||
@@ -503,7 +542,7 @@ mod tests {
|
||||
app.auto_model = true;
|
||||
app.last_effective_model = Some("deepseek-v4-pro".to_string());
|
||||
|
||||
let text = build_context_inspector_text(&app);
|
||||
let text = build_context_inspector_text(&app, Locale::En);
|
||||
assert!(text.contains("Model: auto"), "{text}");
|
||||
assert!(text.contains("/1000000 tokens"), "{text}");
|
||||
}
|
||||
@@ -511,7 +550,7 @@ mod tests {
|
||||
#[test]
|
||||
fn inspector_no_system_prompt_shows_section() {
|
||||
let app = test_app();
|
||||
let text = build_context_inspector_text(&app);
|
||||
let text = build_context_inspector_text(&app, Locale::En);
|
||||
assert!(text.contains("System Prompt Structure"));
|
||||
assert!(text.contains("No system prompt set."));
|
||||
}
|
||||
@@ -533,7 +572,7 @@ mod tests {
|
||||
},
|
||||
]));
|
||||
|
||||
let text = build_context_inspector_text(&app);
|
||||
let text = build_context_inspector_text(&app, Locale::En);
|
||||
assert!(text.contains("System Prompt Structure"));
|
||||
assert!(
|
||||
text.contains("Stable prefix: 1 block"),
|
||||
@@ -548,7 +587,7 @@ mod tests {
|
||||
"cache hint for stable: {text}"
|
||||
);
|
||||
assert!(
|
||||
text.contains("[changes every turn]"),
|
||||
text.contains("[changes by session/turn]"),
|
||||
"volatile marker: {text}"
|
||||
);
|
||||
assert!(
|
||||
@@ -574,7 +613,7 @@ mod tests {
|
||||
},
|
||||
]));
|
||||
|
||||
let text = build_context_inspector_text(&app);
|
||||
let text = build_context_inspector_text(&app, Locale::En);
|
||||
assert!(text.contains("Stable prefix: 2 block(s)"));
|
||||
assert!(text.contains("Volatile working set: none"));
|
||||
}
|
||||
@@ -586,7 +625,7 @@ mod tests {
|
||||
"You are CodeWhale.\n\n<project_instructions source=\"AGENTS.md\">\nRules\n</project_instructions>\n\n## Project Context Pack\n{}\n\n## Environment\n- lang: en\n\n## Skills\n- rust\n\n## Context Management\nKeep compact\n\n## Compact\nTemplate\n\n## Repo Working Set\nsrc/".to_string(),
|
||||
));
|
||||
|
||||
let text = build_context_inspector_text(&app);
|
||||
let text = build_context_inspector_text(&app, Locale::En);
|
||||
assert!(text.contains("System Prompt Structure"));
|
||||
assert!(text.contains("Text prompt layers"));
|
||||
assert!(text.contains("Global system prefix"));
|
||||
@@ -605,8 +644,60 @@ mod tests {
|
||||
let mut app = test_app();
|
||||
app.system_prompt = Some(SystemPrompt::Text("You are CodeWhale.".to_string()));
|
||||
|
||||
let text = build_context_inspector_text(&app);
|
||||
let text = build_context_inspector_text(&app, Locale::En);
|
||||
assert!(text.contains("Single text blob"));
|
||||
assert!(text.contains("stable prefix only"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inspector_localizes_to_zh_hans() {
|
||||
use crate::models::SystemBlock;
|
||||
let mut app = test_app();
|
||||
app.system_prompt = Some(SystemPrompt::Blocks(vec![
|
||||
SystemBlock {
|
||||
block_type: "text".to_string(),
|
||||
text: "## Base\nYou are CodeWhale.".to_string(),
|
||||
cache_control: None,
|
||||
},
|
||||
SystemBlock {
|
||||
block_type: "text".to_string(),
|
||||
text: format!("{WORKING_SET_MARKER}\nsrc/main.rs changed"),
|
||||
cache_control: None,
|
||||
},
|
||||
]));
|
||||
let text = build_context_inspector_text(&app, Locale::ZhHans);
|
||||
|
||||
// Positive: key ZhHans labels present
|
||||
assert!(text.contains("会话上下文"), "session header: {text}");
|
||||
assert!(text.contains("模型"), "model label: {text}");
|
||||
assert!(text.contains("工作区"), "workspace: {text}");
|
||||
assert!(text.contains("系统提示结构"), "sysprompt section: {text}");
|
||||
assert!(text.contains("稳定前缀"), "stable prefix: {text}");
|
||||
assert!(text.contains("易变工作集"), "volatile ws: {text}");
|
||||
assert!(text.contains("第一行"), "first line: {text}");
|
||||
assert!(text.contains("总计"), "total line: {text}");
|
||||
assert!(text.contains("引用"), "references: {text}");
|
||||
assert!(text.contains("最近使用的工具"), "tools: {text}");
|
||||
assert!(text.contains("个区块"), "blocks unit: {text}");
|
||||
assert!(text.contains("个 token"), "tokens unit: {text}");
|
||||
assert!(text.contains("缓存友好"), "cache-friendly: {text}");
|
||||
assert!(text.contains("提示"), "cache tip: {text}");
|
||||
|
||||
// Negative: no English labels leak
|
||||
assert!(!text.contains("Session Context"), "EN session leaked");
|
||||
assert!(!text.contains("Model:"), "EN model leaked");
|
||||
assert!(!text.contains("cells"), "EN cells leaked");
|
||||
assert!(!text.contains("API messages"), "EN API msgs leaked");
|
||||
assert!(!text.contains("Stable prefix"), "EN stable prefix leaked");
|
||||
assert!(
|
||||
!text.contains("Volatile working set"),
|
||||
"EN volatile ws leaked"
|
||||
);
|
||||
assert!(!text.contains("First line"), "EN first line leaked");
|
||||
assert!(!text.contains("Total:"), "EN total leaked");
|
||||
assert!(!text.contains("Text prompt layers"), "EN layers leaked");
|
||||
assert!(!text.contains("cache-friendly"), "EN cache-friendly leaked");
|
||||
assert!(!text.contains("more reference"), "EN more refs leaked");
|
||||
assert!(!text.contains("no output yet"), "EN no output leaked");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ use crate::core::events::Event as EngineEvent;
|
||||
use crate::core::ops::{Op, USER_SHELL_TOOL_ID_PREFIX};
|
||||
use crate::hooks::{HookEvent, HookExecutor};
|
||||
use crate::llm_client::LlmClient;
|
||||
use crate::localization::{MessageId, tr};
|
||||
use crate::models::{
|
||||
ContentBlock, Message, MessageRequest, SystemPrompt, Usage, context_window_for_model,
|
||||
};
|
||||
@@ -5325,9 +5326,9 @@ pub(crate) fn open_context_inspector(app: &mut App) {
|
||||
.last_transcript_area
|
||||
.map(|area| area.width)
|
||||
.unwrap_or(80);
|
||||
let content = build_context_inspector_text(app);
|
||||
let content = build_context_inspector_text(app, app.ui_locale);
|
||||
app.view_stack.push(PagerView::from_text(
|
||||
"Context inspector",
|
||||
tr(app.ui_locale, MessageId::CtxInspTitle),
|
||||
&content,
|
||||
width.saturating_sub(2),
|
||||
));
|
||||
|
||||
Reference in New Issue
Block a user