fix(web): hide the AI chat shortcut from the cheatsheet on OSS (#14399)

This commit is contained in:
Shrinath Rao
2026-09-22 10:00:42 +00:00
committed by GitHub
parent 4df5de8ba3
commit 7b5761785e
20 changed files with 44 additions and 22 deletions
@@ -15539,7 +15539,6 @@
"actions": {
"actionsRefresh": "3cf8d66227384dc2",
"aiChatClose": "a619ab8971872dcf",
"aiChatExpand": "cb569c3ed515eb89",
"aiChatToggle": "e5000da4d3f67a4c",
"aiToolsetsRefresh": "3cf8d66227384dc2",
"alertDestinationsAdd": "d0eb0b5fd8a15847",
@@ -261,6 +261,7 @@ const capabilities = computed<ShortcutCapabilities>(() => ({
incidentsEnabled: Boolean(store.state.zoConfig?.incidents_enabled),
modelPricingEnabled: Boolean(store.state.zoConfig?.model_pricing_enabled),
rbacEnabled: Boolean(store.state.zoConfig?.rbac_enabled),
aiEnabled: Boolean(store.state.zoConfig?.ai_enabled),
}));
const open = computed({
@@ -315,11 +316,14 @@ const allModules = computed<DisplayModule[]>(() => {
return [
{
title: t(group.pageKey, PAGE_TITLE_PARAMS[group.pageKey] ?? {}),
entries: group.shortcuts.map((s) => ({
id: s.id,
display: entryDisplay(s),
label: t(s.descriptionKey),
})),
entries: group.shortcuts
// Entry-level gate mirrors the feature's real availability (e.g. the AI chat shortcut only works on enterprise with ai_enabled).
.filter((s) => !s.visible || s.visible(caps))
.map((s) => ({
id: s.id,
display: entryDisplay(s),
label: t(s.descriptionKey),
})),
},
];
}),
@@ -13,6 +13,7 @@ const OSS: ShortcutCapabilities = {
incidentsEnabled: false,
modelPricingEnabled: false,
rbacEnabled: false,
aiEnabled: false,
};
const ENTERPRISE: ShortcutCapabilities = {
isEnterprise: true,
@@ -22,6 +23,7 @@ const ENTERPRISE: ShortcutCapabilities = {
incidentsEnabled: true,
modelPricingEnabled: true,
rbacEnabled: true,
aiEnabled: true,
};
const CLOUD: ShortcutCapabilities = {
isEnterprise: false,
@@ -31,6 +33,7 @@ const CLOUD: ShortcutCapabilities = {
incidentsEnabled: true,
modelPricingEnabled: true,
rbacEnabled: true,
aiEnabled: true,
};
/** Mirrors ShortcutCheatsheet: a page shows unless its gate rejects the caps. */
@@ -50,6 +53,15 @@ function visibleModuleTitles(caps: ShortcutCapabilities): string[] {
);
}
/** Entry-level gate, mirroring ShortcutCheatsheet: an entry shows unless its own gate rejects the caps. */
function entryVisible(id: string, caps: ShortcutCapabilities): boolean {
for (const g of SHORTCUT_REGISTRY) {
const e = g.shortcuts.find((s) => s.id === id);
if (e) return !e.visible || e.visible(caps);
}
throw new Error(`entry ${id} not registered`);
}
const GATED_IN_OSS = [
"shortcuts.pages.searchSchedulers",
"shortcuts.pages.alertSources",
@@ -177,3 +189,21 @@ describe("shortcut cheatsheet OSS gating", () => {
expect(cloudNonMeta.has("shortcuts.pages.orgManagement")).toBe(false);
});
});
describe("aiChatToggle entry visibility", () => {
it("is hidden on OSS (the shortcut is never registered there)", () => {
expect(entryVisible("aiChatToggle", OSS)).toBe(false);
});
it("is hidden on cloud — the AI chat shortcut is enterprise-only", () => {
expect(entryVisible("aiChatToggle", CLOUD)).toBe(false);
});
it("is hidden on enterprise when ai_enabled is off (the handler no-ops)", () => {
expect(entryVisible("aiChatToggle", { ...ENTERPRISE, aiEnabled: false })).toBe(false);
});
it("is shown only on enterprise with ai_enabled on", () => {
expect(entryVisible("aiChatToggle", ENTERPRISE)).toBe(true);
});
});
@@ -42,6 +42,8 @@ export interface ShortcutEntry {
display?: string;
/** Fire even while a text input has focus (see `Shortcut.allowInInput`). */
allowInInput?: boolean;
/** Hide this entry in the cheatsheet unless the edition/config exposes it. */
visible?: (caps: ShortcutCapabilities) => boolean;
}
export interface ShortcutGroup {
@@ -63,6 +65,7 @@ export interface ShortcutCapabilities {
incidentsEnabled: boolean;
modelPricingEnabled: boolean;
rbacEnabled: boolean;
aiEnabled: boolean;
}
export interface ShortcutModule {
@@ -86,6 +89,7 @@ const incidents = (c: ShortcutCapabilities) => enterpriseOrCloud(c) && c.inciden
const onlineEvals = (c: ShortcutCapabilities) => enterpriseOrCloud(c) && c.onlineEvalsEnabled;
const modelPricing = (c: ShortcutCapabilities) => enterpriseOrCloud(c) && c.modelPricingEnabled;
const rbac = (c: ShortcutCapabilities) => enterpriseOrCloud(c) && c.rbacEnabled;
const aiChat = (c: ShortcutCapabilities) => c.isEnterprise && c.aiEnabled;
// Cluster-scoped admin surfaces only render inside the _meta org.
const metaAdmin = (c: ShortcutCapabilities) => c.isEnterprise && c.isMetaOrg;
const cloudMetaAdmin = (c: ShortcutCapabilities) => c.isCloud && c.isMetaOrg;
@@ -207,6 +211,7 @@ export const SHORTCUT_REGISTRY: ShortcutGroup[] = [
keyForWindows: "ctrl+b",
keyForMac: "meta+b",
descriptionKey: "shortcuts.actions.aiChatToggle",
visible: aiChat,
},
],
},
-1
View File
@@ -15164,7 +15164,6 @@
"syntheticsTokensRefresh": "تحديث قائمة الرموز",
"aiChatToggle": "تبديل دردشة الذكاء الاصطناعي",
"aiChatClose": "إغلاق دردشة الذكاء الاصطناعي",
"aiChatExpand": "توسيع/تقويم دردشة الذكاء الاصطناعي",
"logsSaveView": "عرض حفظ كملف محفوظ",
"logsExport": "نتائج التصدير CSV",
"tracesCopyUrl": "رابط مشاركة التتبع للنسخ",
-1
View File
@@ -15164,7 +15164,6 @@
"syntheticsTokensRefresh": "Tokenliste aktualisieren",
"aiChatToggle": "KI-Chat umschalten",
"aiChatClose": "KI-Chat schließen",
"aiChatExpand": "KI-Chat erweitern/einklappen",
"logsSaveView": "Als gespeicherte Ansicht speichern",
"logsExport": "Ergebnisse als CSV exportieren",
"tracesCopyUrl": "Trace-Share-URL kopieren",
-1
View File
@@ -15164,7 +15164,6 @@
"syntheticsTokensRefresh": "Refresh token list",
"aiChatToggle": "Toggle AI chat",
"aiChatClose": "Close AI chat",
"aiChatExpand": "Expand/collapse AI chat",
"logsSaveView": "Save as saved view",
"logsExport": "Export results as CSV",
"tracesCopyUrl": "Copy trace share URL",
-1
View File
@@ -15164,7 +15164,6 @@
"syntheticsTokensRefresh": "Actualizar lista de tokens",
"aiChatToggle": "Alternar el chat de IA",
"aiChatClose": "Cerrar chat de IA",
"aiChatExpand": "Expandir/contraer chat de IA",
"logsSaveView": "Guardar como vista guardada",
"logsExport": "Exportar los resultados como CSV",
"tracesCopyUrl": "Copiar URL para compartir la traza",
-1
View File
@@ -15164,7 +15164,6 @@
"syntheticsTokensRefresh": "Actualiser la liste des jetons",
"aiChatToggle": "Activer/désactiver le chat IA",
"aiChatClose": "Fermer le chat IA",
"aiChatExpand": "Développer/réduire le chat IA",
"logsSaveView": "Enregistrer en tant que vue enregistrée",
"logsExport": "Exporter les résultats au format CSV",
"tracesCopyUrl": "Copier l'URL de partage de la trace",
-1
View File
@@ -15164,7 +15164,6 @@
"syntheticsTokensRefresh": "Aggiorna elenco token",
"aiChatToggle": "Attiva la chat AI",
"aiChatClose": "Chiudi chat AI",
"aiChatExpand": "Espandi/comprimi chat AI",
"logsSaveView": "Salva come visualizzazione salvata",
"logsExport": "Esporta i risultati in formato CSV",
"tracesCopyUrl": "Copia URL di condivisione della traccia",
-1
View File
@@ -15164,7 +15164,6 @@
"syntheticsTokensRefresh": "トークンリストを更新",
"aiChatToggle": "AI チャットを切り替える",
"aiChatClose": "AI チャットを閉じる",
"aiChatExpand": "AI チャットを展開/折りたたむ",
"logsSaveView": "保存済みビューとして保存",
"logsExport": "結果を CSV としてエクスポート",
"tracesCopyUrl": "トレース共有URLをコピー",
-1
View File
@@ -15164,7 +15164,6 @@
"syntheticsTokensRefresh": "토큰 목록 새로고침",
"aiChatToggle": "AI 채팅 켜기/끄기",
"aiChatClose": "AI 채팅 닫기",
"aiChatExpand": "AI 채팅 펼치기/접기",
"logsSaveView": "저장된 뷰로 저장",
"logsExport": "결과를 CSV로 내보내기",
"tracesCopyUrl": "트레이스 공유 URL 복사",
-1
View File
@@ -15164,7 +15164,6 @@
"syntheticsTokensRefresh": "Tokenlijst vernieuwen",
"aiChatToggle": "AI-chat inschakelen",
"aiChatClose": "AI-chat sluiten",
"aiChatExpand": "AI-chat uitvouwen/invouwen",
"logsSaveView": "Opslaan als opgeslagen weergave",
"logsExport": "Exporteer resultaten als CSV",
"tracesCopyUrl": "Kopieer trace-deel-URL",
-1
View File
@@ -15164,7 +15164,6 @@
"syntheticsTokensRefresh": "Odśwież listę tokenów",
"aiChatToggle": "Przełącz czat AI",
"aiChatClose": "Zamknij czat AI",
"aiChatExpand": "Rozwiń/zwiń czat AI",
"logsSaveView": "Zapisz jako zapisany widok",
"logsExport": "Eksportuj wyniki jako CSV",
"tracesCopyUrl": "Kopiuj URL do udostępnienia śladu",
-1
View File
@@ -15164,7 +15164,6 @@
"syntheticsTokensRefresh": "Atualizar lista de tokens",
"aiChatToggle": "Alternar bate-papo com IA",
"aiChatClose": "Fechar chat de IA",
"aiChatExpand": "Expandir/recolher chat de IA",
"logsSaveView": "Salvar como visualização salva",
"logsExport": "Exportar resultados como CSV",
"tracesCopyUrl": "Copiar URL de compartilhamento do rastreamento",
-1
View File
@@ -15164,7 +15164,6 @@
"syntheticsTokensRefresh": "Обновить список токенов",
"aiChatToggle": "Переключить AI-чат",
"aiChatClose": "Закрыть чат ИИ",
"aiChatExpand": "Развернуть/свернуть чат ИИ",
"logsSaveView": "Сохранить как сохранённое представление",
"logsExport": "Экспортировать результаты в CSV",
"tracesCopyUrl": "Скопировать общую ссылку на трассировку",
-1
View File
@@ -15164,7 +15164,6 @@
"syntheticsTokensRefresh": "Belirteç listesini yenile",
"aiChatToggle": "AI sohbetini aç/kapat",
"aiChatClose": "AI sohbetini kapat",
"aiChatExpand": "AI sohbetini genişlet/daralt",
"logsSaveView": "Kayıtlı görünüm olarak kaydet",
"logsExport": "Sonuçları CSV olarak dışa aktarın",
"tracesCopyUrl": "İz paylaşım URL'sini kopyala",
-1
View File
@@ -15164,7 +15164,6 @@
"syntheticsTokensRefresh": "Làm mới danh sách token",
"aiChatToggle": "Bật/tắt trò chuyện AI",
"aiChatClose": "Đóng trò chuyện AI",
"aiChatExpand": "Mở rộng/thu gọn trò chuyện AI",
"logsSaveView": "Lưu dưới dạng chế độ xem đã lưu",
"logsExport": "Xuất kết quả dưới dạng CSV",
"tracesCopyUrl": "Sao chép URL chia sẻ dấu vết",
-1
View File
@@ -15164,7 +15164,6 @@
"syntheticsTokensRefresh": "刷新令牌列表",
"aiChatToggle": "切换 AI 聊天",
"aiChatClose": "关闭 AI 聊天",
"aiChatExpand": "展开/折叠 AI 聊天",
"logsSaveView": "另存为已保存视图",
"logsExport": "将结果导出为 CSV",
"tracesCopyUrl": "复制追踪分享链接",
-1
View File
@@ -15159,7 +15159,6 @@
"syntheticsTokensRefresh": "重新整理 Token 清單",
"aiChatToggle": "切換AI聊天",
"aiChatClose": "關閉 AI 聊天",
"aiChatExpand": "展開/收合 AI 聊天",
"logsSaveView": "另存為已儲存檢視",
"logsExport": "匯出結果為CSV",
"tracesCopyUrl": "複製追蹤分享網址",