@agent-native/core 0.137.0 → 0.137.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +1 -1
- package/corpus/templates/analytics/app/components/AgentCompletionSound.tsx +105 -0
- package/corpus/templates/analytics/app/components/layout/Layout.tsx +44 -35
- package/corpus/templates/analytics/app/i18n-data.ts +38 -0
- package/corpus/templates/analytics/app/pages/Settings.tsx +53 -1
- package/corpus/templates/analytics/app/pages/settings/settings-search.ts +6 -0
- package/corpus/templates/analytics/changelog/2026-08-04-choose-whether-analytics-plays-a-bell-when-the-agent-finishe.md +6 -0
- package/corpus/templates/analytics/shared/analytics-user-prefs.ts +2 -0
- package/corpus/templates/slides/app/components/editor/AddSlidePopover.tsx +258 -0
- package/corpus/templates/slides/app/components/editor/EditorActionCluster.tsx +130 -0
- package/corpus/templates/slides/app/components/editor/EditorSidebar.tsx +25 -337
- package/corpus/templates/slides/app/components/editor/EditorToolbar.tsx +73 -53
- package/corpus/templates/slides/app/components/editor/NewDeckReferenceStep.tsx +321 -0
- package/corpus/templates/slides/app/components/editor/PromptDialog.tsx +32 -11
- package/corpus/templates/slides/app/components/editor/SlideContextToolbar.tsx +804 -0
- package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +101 -45
- package/corpus/templates/slides/app/components/editor/SlideOverflowWarning.tsx +7 -4
- package/corpus/templates/slides/app/components/editor/bullet-editing.ts +11 -3
- package/corpus/templates/slides/app/components/editor/commit-active-edit.ts +21 -0
- package/corpus/templates/slides/app/components/editor/list-editing.ts +219 -0
- package/corpus/templates/slides/app/components/editor/selection-overlay-measurement.ts +0 -3
- package/corpus/templates/slides/app/components/editor/slide-style.ts +199 -0
- package/corpus/templates/slides/app/global.css +14 -3
- package/corpus/templates/slides/app/i18n/en-US.ts +8 -1
- package/corpus/templates/slides/app/lib/recent-references.ts +82 -0
- package/corpus/templates/slides/app/pages/DeckEditor.tsx +51 -22
- package/corpus/templates/slides/app/pages/Index.tsx +236 -181
- package/corpus/templates/slides/changelog/2026-08-01-add-slide-moved-to-the-toolbar-and-the-slide-rail-is-now-mor.md +9 -0
- package/corpus/templates/slides/changelog/2026-08-01-add-slide-undo-redo-and-the-text-tool-now-lead-the-slide-too.md +9 -0
- package/corpus/templates/slides/changelog/2026-08-01-slide-styling-now-appears-in-a-contextual-toolbar-above-the-.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-01-the-slide-style-side-panel-is-retired-all-styling-now-lives-.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-03-the-slide-toolbar-is-denser-swatch-only-colors-dropdowns-for.md +10 -0
- package/corpus/templates/slides/changelog/2026-08-04-bullet-and-numbered-list-buttons-in-the-slide-toolbar-conver.md +6 -0
- package/corpus/templates/slides/changelog/2026-08-04-italic-and-underline-are-now-one-click-away-in-the-slide-too.md +6 -0
- package/dist/client/DefaultSpinner.d.ts +0 -12
- package/dist/client/DefaultSpinner.js +22 -2
- package/dist/client/onboarding/use-onboarding.js +3 -0
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/deploy/build.js +2 -1
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/progress/routes.d.ts +1 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +25 -9
- package/package.json +2 -2
- package/src/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +25 -9
- package/corpus/templates/slides/app/components/editor/SlideStyleInspector.tsx +0 -763
package/corpus/README.md
CHANGED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { appPath } from "@agent-native/core/client/api-path";
|
|
2
|
+
import { useActionQuery } from "@agent-native/core/client/hooks";
|
|
3
|
+
import { useEffect, useRef } from "react";
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
ANALYTICS_USER_PREFS_KEY,
|
|
7
|
+
type AnalyticsUserPrefs,
|
|
8
|
+
} from "../../shared/analytics-user-prefs";
|
|
9
|
+
|
|
10
|
+
const AGENT_COMPLETION_SOUND_URL = appPath("/agent-completion.mp3");
|
|
11
|
+
const DEFAULT_TAB_ID = "__default__";
|
|
12
|
+
|
|
13
|
+
function getTabId(detail: unknown): string {
|
|
14
|
+
if (
|
|
15
|
+
detail &&
|
|
16
|
+
typeof detail === "object" &&
|
|
17
|
+
"tabId" in detail &&
|
|
18
|
+
typeof detail.tabId === "string" &&
|
|
19
|
+
detail.tabId
|
|
20
|
+
) {
|
|
21
|
+
return detail.tabId;
|
|
22
|
+
}
|
|
23
|
+
return DEFAULT_TAB_ID;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Plays the shared Builder bell after a successful Analytics agent run. */
|
|
27
|
+
export function AgentCompletionSound() {
|
|
28
|
+
const { data: prefs, isError } = useActionQuery<AnalyticsUserPrefs>(
|
|
29
|
+
"get-user-pref",
|
|
30
|
+
{ key: ANALYTICS_USER_PREFS_KEY },
|
|
31
|
+
);
|
|
32
|
+
const soundEnabledRef = useRef(false);
|
|
33
|
+
const runningTabsRef = useRef(new Set<string>());
|
|
34
|
+
const autoContinuingTabsRef = useRef(new Set<string>());
|
|
35
|
+
const failedTabsRef = useRef(new Set<string>());
|
|
36
|
+
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
// Missing and unreadable preferences both keep the sound off until enabled.
|
|
39
|
+
soundEnabledRef.current = !isError && prefs?.bellSoundEnabled === true;
|
|
40
|
+
}, [isError, prefs]);
|
|
41
|
+
|
|
42
|
+
useEffect(() => {
|
|
43
|
+
const handleRunError = (event: Event) => {
|
|
44
|
+
const detail = (event as CustomEvent).detail;
|
|
45
|
+
failedTabsRef.current.add(getTabId(detail));
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const handleAutoContinue = (event: Event) => {
|
|
49
|
+
const detail = (event as CustomEvent).detail;
|
|
50
|
+
autoContinuingTabsRef.current.add(getTabId(detail));
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const handleChatRunning = (event: Event) => {
|
|
54
|
+
const detail = (event as CustomEvent).detail;
|
|
55
|
+
const tabId = getTabId(detail);
|
|
56
|
+
|
|
57
|
+
if (detail?.isRunning === true) {
|
|
58
|
+
autoContinuingTabsRef.current.delete(tabId);
|
|
59
|
+
failedTabsRef.current.delete(tabId);
|
|
60
|
+
runningTabsRef.current.add(tabId);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (
|
|
65
|
+
detail?.isRunning !== false ||
|
|
66
|
+
!runningTabsRef.current.delete(tabId)
|
|
67
|
+
) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const wasAutoContinued = autoContinuingTabsRef.current.delete(tabId);
|
|
72
|
+
const failed = failedTabsRef.current.delete(tabId);
|
|
73
|
+
if (
|
|
74
|
+
wasAutoContinued ||
|
|
75
|
+
failed ||
|
|
76
|
+
detail.reason === "failed" ||
|
|
77
|
+
detail.reason === "stopped" ||
|
|
78
|
+
!soundEnabledRef.current ||
|
|
79
|
+
typeof Audio === "undefined"
|
|
80
|
+
) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const audio = new Audio(AGENT_COMPLETION_SOUND_URL);
|
|
85
|
+
audio.volume = 0.5;
|
|
86
|
+
void audio.play().catch(() => {
|
|
87
|
+
// Browsers may reject playback until the user has interacted with the page.
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
window.addEventListener("agent-chat:run-error", handleRunError);
|
|
92
|
+
window.addEventListener("agent-chat:auto-continue", handleAutoContinue);
|
|
93
|
+
window.addEventListener("agentNative.chatRunning", handleChatRunning);
|
|
94
|
+
return () => {
|
|
95
|
+
window.removeEventListener("agent-chat:run-error", handleRunError);
|
|
96
|
+
window.removeEventListener(
|
|
97
|
+
"agent-chat:auto-continue",
|
|
98
|
+
handleAutoContinue,
|
|
99
|
+
);
|
|
100
|
+
window.removeEventListener("agentNative.chatRunning", handleChatRunning);
|
|
101
|
+
};
|
|
102
|
+
}, []);
|
|
103
|
+
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
} from "@/lib/chat-handoff";
|
|
23
23
|
import { TAB_ID } from "@/lib/tab-id";
|
|
24
24
|
|
|
25
|
+
import { AgentCompletionSound } from "../AgentCompletionSound";
|
|
25
26
|
import { Header } from "./Header";
|
|
26
27
|
import { HeaderActionsProvider } from "./HeaderActions";
|
|
27
28
|
import { MobileNav } from "./MobileNav";
|
|
@@ -138,7 +139,12 @@ function InteractiveLayout({ children }: LayoutProps) {
|
|
|
138
139
|
}
|
|
139
140
|
|
|
140
141
|
if (BARE_ROUTES.has(location.pathname)) {
|
|
141
|
-
return
|
|
142
|
+
return (
|
|
143
|
+
<>
|
|
144
|
+
<AgentCompletionSound />
|
|
145
|
+
{children}
|
|
146
|
+
</>
|
|
147
|
+
);
|
|
142
148
|
}
|
|
143
149
|
|
|
144
150
|
const contentFrame = (
|
|
@@ -177,40 +183,43 @@ function InteractiveLayout({ children }: LayoutProps) {
|
|
|
177
183
|
);
|
|
178
184
|
|
|
179
185
|
return (
|
|
180
|
-
|
|
181
|
-
<
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
<div className="agent-layout-main-surface flex min-w-0 flex-1 overflow-hidden">
|
|
187
|
-
{contentFrame}
|
|
186
|
+
<>
|
|
187
|
+
<AgentCompletionSound />
|
|
188
|
+
<HeaderActionsProvider>
|
|
189
|
+
<div className="agent-layout-shell flex h-screen w-full overflow-hidden bg-background text-foreground">
|
|
190
|
+
<div className="agent-layout-left-drawer hidden shrink-0 md:block">
|
|
191
|
+
<Sidebar />
|
|
188
192
|
</div>
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
t("chat.
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
193
|
+
{isAskRoute ? (
|
|
194
|
+
<div className="agent-layout-main-surface flex min-w-0 flex-1 overflow-hidden">
|
|
195
|
+
{contentFrame}
|
|
196
|
+
</div>
|
|
197
|
+
) : (
|
|
198
|
+
<AgentSidebar
|
|
199
|
+
position="right"
|
|
200
|
+
defaultOpen={false}
|
|
201
|
+
chatViewTransition
|
|
202
|
+
chatViewTransitionHandoff={chatHomeHandoffPending}
|
|
203
|
+
storageKey={ANALYTICS_CHAT_STORAGE_KEY}
|
|
204
|
+
browserTabId={TAB_ID}
|
|
205
|
+
openOnChatRunning={chatHomeHandoffActive}
|
|
206
|
+
onFullscreenRequest={openAskAgentFullscreen}
|
|
207
|
+
emptyStateText={t("chat.emptyState")}
|
|
208
|
+
agentPageHref="/agent"
|
|
209
|
+
suggestions={[
|
|
210
|
+
t("chat.suggestionArrGrowth"),
|
|
211
|
+
t("chat.suggestionChurn"),
|
|
212
|
+
t("chat.suggestionAnomalies"),
|
|
213
|
+
t("chat.suggestionMrr"),
|
|
214
|
+
]}
|
|
215
|
+
scope={analyticsScope}
|
|
216
|
+
composerSlot={<CreativeContextComposerChip />}
|
|
217
|
+
>
|
|
218
|
+
{contentFrame}
|
|
219
|
+
</AgentSidebar>
|
|
220
|
+
)}
|
|
221
|
+
</div>
|
|
222
|
+
</HeaderActionsProvider>
|
|
223
|
+
</>
|
|
215
224
|
);
|
|
216
225
|
}
|
|
@@ -198,6 +198,10 @@ const enUS = {
|
|
|
198
198
|
errorEmailNotificationsDescription:
|
|
199
199
|
"Send an email when a new JavaScript error is captured. Off by default.",
|
|
200
200
|
errorEmailNotificationsSaveFailed: "Couldn't save the email preference.",
|
|
201
|
+
bellSound: "Bell sound",
|
|
202
|
+
bellSoundDescription:
|
|
203
|
+
"Play a sound when the agent finishes a run. Off by default.",
|
|
204
|
+
bellSoundSaveFailed: "Couldn't save the sound preference.",
|
|
201
205
|
about: "About",
|
|
202
206
|
aboutDescription:
|
|
203
207
|
"Analytics is a tool for connecting data sources and building custom dashboards. Connect Google Analytics, BigQuery, Stripe, and more, then ask the agent to create dashboards.",
|
|
@@ -4261,6 +4265,9 @@ export const messagesByLocale = {
|
|
|
4261
4265
|
errorEmailNotificationsDescription:
|
|
4262
4266
|
"捕获新的 JavaScript 错误时发送电子邮件。默认关闭。",
|
|
4263
4267
|
errorEmailNotificationsSaveFailed: "无法保存电子邮件偏好设置。",
|
|
4268
|
+
bellSound: "提示音",
|
|
4269
|
+
bellSoundDescription: "代理完成运行时播放提示音。默认关闭。",
|
|
4270
|
+
bellSoundSaveFailed: "无法保存提示音偏好设置。",
|
|
4264
4271
|
about: "关于",
|
|
4265
4272
|
aboutDescription:
|
|
4266
4273
|
"Analytics 用于连接数据源并构建自定义仪表板。连接 Google Analytics、BigQuery、Stripe 等,然后让代理创建仪表板。",
|
|
@@ -4484,6 +4491,10 @@ export const messagesByLocale = {
|
|
|
4484
4491
|
"Envía un email cuando se capture un nuevo error de JavaScript. Desactivado de forma predeterminada.",
|
|
4485
4492
|
errorEmailNotificationsSaveFailed:
|
|
4486
4493
|
"No se pudo guardar la preferencia de email.",
|
|
4494
|
+
bellSound: "Sonido de campana",
|
|
4495
|
+
bellSoundDescription:
|
|
4496
|
+
"Reproduce un sonido cuando el agente termina una ejecución. Desactivado de forma predeterminada.",
|
|
4497
|
+
bellSoundSaveFailed: "No se pudo guardar la preferencia de sonido.",
|
|
4487
4498
|
about: "Acerca de",
|
|
4488
4499
|
aboutDescription:
|
|
4489
4500
|
"Analytics conecta fuentes de datos y crea paneles personalizados. Conecta Google Analytics, BigQuery, Stripe y más, y pide al agente que cree paneles.",
|
|
@@ -4712,6 +4723,10 @@ export const messagesByLocale = {
|
|
|
4712
4723
|
"Envoyer un e-mail lorsqu’une nouvelle erreur JavaScript est capturée. Désactivé par défaut.",
|
|
4713
4724
|
errorEmailNotificationsSaveFailed:
|
|
4714
4725
|
"Impossible d’enregistrer la préférence e-mail.",
|
|
4726
|
+
bellSound: "Son de notification",
|
|
4727
|
+
bellSoundDescription:
|
|
4728
|
+
"Jouer un son lorsque l’agent termine une exécution. Désactivé par défaut.",
|
|
4729
|
+
bellSoundSaveFailed: "Impossible d’enregistrer la préférence sonore.",
|
|
4715
4730
|
about: "À propos",
|
|
4716
4731
|
aboutDescription:
|
|
4717
4732
|
"Analytics connecte des sources de données et crée des tableaux de bord personnalisés. Connectez Google Analytics, BigQuery, Stripe et plus encore, puis demandez à l'agent de créer des tableaux de bord.",
|
|
@@ -4946,6 +4961,11 @@ export const messagesByLocale = {
|
|
|
4946
4961
|
"Eine E-Mail senden, wenn ein neuer JavaScript-Fehler erfasst wird. Standardmäßig deaktiviert.",
|
|
4947
4962
|
errorEmailNotificationsSaveFailed:
|
|
4948
4963
|
"Die E-Mail-Einstellung konnte nicht gespeichert werden.",
|
|
4964
|
+
bellSound: "Signalton",
|
|
4965
|
+
bellSoundDescription:
|
|
4966
|
+
"Einen Ton abspielen, wenn der Agent einen Lauf beendet. Standardmäßig deaktiviert.",
|
|
4967
|
+
bellSoundSaveFailed:
|
|
4968
|
+
"Die Toneinstellung konnte nicht gespeichert werden.",
|
|
4949
4969
|
about: "Info",
|
|
4950
4970
|
aboutDescription:
|
|
4951
4971
|
"Analytics verbindet Datenquellen und erstellt benutzerdefinierte Dashboards. Verbinde Google Analytics, BigQuery, Stripe und mehr und bitte den Agenten, Dashboards zu erstellen.",
|
|
@@ -5170,6 +5190,10 @@ export const messagesByLocale = {
|
|
|
5170
5190
|
errorEmailNotificationsDescription:
|
|
5171
5191
|
"新しい JavaScript エラーが記録されたときにメールを送信します。デフォルトではオフです。",
|
|
5172
5192
|
errorEmailNotificationsSaveFailed: "メール設定を保存できませんでした。",
|
|
5193
|
+
bellSound: "完了サウンド",
|
|
5194
|
+
bellSoundDescription:
|
|
5195
|
+
"エージェントが実行を完了したときにサウンドを再生します。デフォルトでオフです。",
|
|
5196
|
+
bellSoundSaveFailed: "サウンド設定を保存できませんでした。",
|
|
5173
5197
|
about: "概要",
|
|
5174
5198
|
aboutDescription:
|
|
5175
5199
|
"Analytics はデータソースを接続し、カスタムダッシュボードを作成するツールです。Google Analytics、BigQuery、Stripe などを接続し、エージェントにダッシュボード作成を依頼できます。",
|
|
@@ -5393,6 +5417,10 @@ export const messagesByLocale = {
|
|
|
5393
5417
|
errorEmailNotificationsDescription:
|
|
5394
5418
|
"새 JavaScript 오류가 캡처되면 이메일을 보냅니다. 기본값은 꺼져 있습니다.",
|
|
5395
5419
|
errorEmailNotificationsSaveFailed: "이메일 설정을 저장하지 못했습니다.",
|
|
5420
|
+
bellSound: "완료 소리",
|
|
5421
|
+
bellSoundDescription:
|
|
5422
|
+
"에이전트가 실행을 완료하면 소리를 재생합니다. 기본값은 꺼짐입니다.",
|
|
5423
|
+
bellSoundSaveFailed: "소리 설정을 저장하지 못했습니다.",
|
|
5396
5424
|
about: "정보",
|
|
5397
5425
|
aboutDescription:
|
|
5398
5426
|
"Analytics는 데이터 소스를 연결하고 사용자 지정 대시보드를 만드는 도구입니다. Google Analytics, BigQuery, Stripe 등을 연결한 뒤 에이전트에게 대시보드를 만들게 하세요.",
|
|
@@ -5621,6 +5649,10 @@ export const messagesByLocale = {
|
|
|
5621
5649
|
"Envie um e-mail quando um novo erro de JavaScript for capturado. Desativado por padrão.",
|
|
5622
5650
|
errorEmailNotificationsSaveFailed:
|
|
5623
5651
|
"Não foi possível salvar a preferência de e-mail.",
|
|
5652
|
+
bellSound: "Som de conclusão",
|
|
5653
|
+
bellSoundDescription:
|
|
5654
|
+
"Reproduzir um som quando o agente concluir uma execução. Desativado por padrão.",
|
|
5655
|
+
bellSoundSaveFailed: "Não foi possível salvar a preferência de som.",
|
|
5624
5656
|
about: "Sobre",
|
|
5625
5657
|
aboutDescription:
|
|
5626
5658
|
"Analytics conecta fontes de dados e cria dashboards personalizados. Conecte Google Analytics, BigQuery, Stripe e outros, depois peça ao agente para criar dashboards.",
|
|
@@ -5843,6 +5875,9 @@ export const messagesByLocale = {
|
|
|
5843
5875
|
errorEmailNotificationsDescription:
|
|
5844
5876
|
"नया JavaScript त्रुटि कैप्चर होने पर ईमेल भेजें। डिफ़ॉल्ट रूप से बंद।",
|
|
5845
5877
|
errorEmailNotificationsSaveFailed: "ईमेल प्राथमिकता सहेजी नहीं जा सकी।",
|
|
5878
|
+
bellSound: "पूर्णता ध्वनि",
|
|
5879
|
+
bellSoundDescription: "एजेंट के रन पूरा करने पर ध्वनि चलाएं। डिफ़ॉल्ट रूप से बंद।",
|
|
5880
|
+
bellSoundSaveFailed: "ध्वनि प्राथमिकता सहेजी नहीं जा सकी।",
|
|
5846
5881
|
about: "परिचय",
|
|
5847
5882
|
aboutDescription:
|
|
5848
5883
|
"Analytics डेटा स्रोतों को जोड़ने और कस्टम डैशबोर्ड बनाने का टूल है। Google Analytics, BigQuery, Stripe आदि जोड़ें, फिर एजेंट से डैशबोर्ड बनवाएं।",
|
|
@@ -6065,6 +6100,9 @@ export const messagesByLocale = {
|
|
|
6065
6100
|
errorEmailNotificationsDescription:
|
|
6066
6101
|
"إرسال بريد إلكتروني عند التقاط خطأ JavaScript جديد. معطّل افتراضيًا.",
|
|
6067
6102
|
errorEmailNotificationsSaveFailed: "تعذّر حفظ تفضيل البريد الإلكتروني.",
|
|
6103
|
+
bellSound: "صوت الجرس",
|
|
6104
|
+
bellSoundDescription: "تشغيل صوت عند اكتمال تشغيل الوكيل. معطّل افتراضيًا.",
|
|
6105
|
+
bellSoundSaveFailed: "تعذّر حفظ تفضيل الصوت.",
|
|
6068
6106
|
about: "حول",
|
|
6069
6107
|
aboutDescription:
|
|
6070
6108
|
"Analytics أداة لربط مصادر البيانات وبناء لوحات معلومات مخصصة. اربط Google Analytics وBigQuery وStripe وغيرها، ثم اطلب من الوكيل إنشاء اللوحات.",
|
|
@@ -54,18 +54,34 @@ export default function Settings() {
|
|
|
54
54
|
const [errorEmailEnabledOverride, setErrorEmailEnabledOverride] = useState<
|
|
55
55
|
boolean | null
|
|
56
56
|
>(null);
|
|
57
|
+
const [bellSoundEnabledOverride, setBellSoundEnabledOverride] = useState<
|
|
58
|
+
boolean | null
|
|
59
|
+
>(null);
|
|
57
60
|
|
|
58
61
|
useEffect(() => {
|
|
59
62
|
if (analyticsPrefs) {
|
|
60
63
|
setErrorEmailEnabledOverride(
|
|
61
64
|
analyticsPrefs.errorEmailNotifications === true,
|
|
62
65
|
);
|
|
66
|
+
setBellSoundEnabledOverride(analyticsPrefs.bellSoundEnabled === true);
|
|
63
67
|
}
|
|
64
68
|
}, [analyticsPrefs]);
|
|
65
69
|
|
|
66
70
|
const errorEmailEnabled =
|
|
67
71
|
errorEmailEnabledOverride ??
|
|
68
72
|
analyticsPrefs?.errorEmailNotifications === true;
|
|
73
|
+
const bellSoundEnabled =
|
|
74
|
+
bellSoundEnabledOverride ?? analyticsPrefs?.bellSoundEnabled === true;
|
|
75
|
+
|
|
76
|
+
const currentAnalyticsPrefs: AnalyticsUserPrefs = {
|
|
77
|
+
...(analyticsPrefs ?? {}),
|
|
78
|
+
...(errorEmailEnabledOverride === null
|
|
79
|
+
? {}
|
|
80
|
+
: { errorEmailNotifications: errorEmailEnabledOverride }),
|
|
81
|
+
...(bellSoundEnabledOverride === null
|
|
82
|
+
? {}
|
|
83
|
+
: { bellSoundEnabled: bellSoundEnabledOverride }),
|
|
84
|
+
};
|
|
69
85
|
|
|
70
86
|
const saveErrorEmailPreference = (enabled: boolean) => {
|
|
71
87
|
const previous = errorEmailEnabled;
|
|
@@ -73,7 +89,10 @@ export default function Settings() {
|
|
|
73
89
|
void saveAnalyticsPrefs
|
|
74
90
|
.mutateAsync({
|
|
75
91
|
key: ANALYTICS_USER_PREFS_KEY,
|
|
76
|
-
value: {
|
|
92
|
+
value: {
|
|
93
|
+
...currentAnalyticsPrefs,
|
|
94
|
+
errorEmailNotifications: enabled,
|
|
95
|
+
},
|
|
77
96
|
})
|
|
78
97
|
.catch((error) => {
|
|
79
98
|
setErrorEmailEnabledOverride(previous);
|
|
@@ -85,6 +104,24 @@ export default function Settings() {
|
|
|
85
104
|
});
|
|
86
105
|
};
|
|
87
106
|
|
|
107
|
+
const saveBellSoundPreference = (enabled: boolean) => {
|
|
108
|
+
const previous = bellSoundEnabled;
|
|
109
|
+
setBellSoundEnabledOverride(enabled);
|
|
110
|
+
void saveAnalyticsPrefs
|
|
111
|
+
.mutateAsync({
|
|
112
|
+
key: ANALYTICS_USER_PREFS_KEY,
|
|
113
|
+
value: { ...currentAnalyticsPrefs, bellSoundEnabled: enabled },
|
|
114
|
+
})
|
|
115
|
+
.catch((error) => {
|
|
116
|
+
setBellSoundEnabledOverride(previous);
|
|
117
|
+
toast.error(
|
|
118
|
+
error instanceof Error
|
|
119
|
+
? error.message
|
|
120
|
+
: t("settings.bellSoundSaveFailed"),
|
|
121
|
+
);
|
|
122
|
+
});
|
|
123
|
+
};
|
|
124
|
+
|
|
88
125
|
const extraTabs = useMemo<SettingsTabItem[]>(
|
|
89
126
|
() => [
|
|
90
127
|
{
|
|
@@ -170,6 +207,21 @@ export default function Settings() {
|
|
|
170
207
|
/>
|
|
171
208
|
}
|
|
172
209
|
/>
|
|
210
|
+
<SettingsRow
|
|
211
|
+
id="bell-sound"
|
|
212
|
+
label={t("settings.bellSound")}
|
|
213
|
+
description={t("settings.bellSoundDescription")}
|
|
214
|
+
control={
|
|
215
|
+
<Switch
|
|
216
|
+
aria-label={t("settings.bellSound")}
|
|
217
|
+
checked={bellSoundEnabled}
|
|
218
|
+
disabled={
|
|
219
|
+
analyticsPrefsLoading || saveAnalyticsPrefs.isPending
|
|
220
|
+
}
|
|
221
|
+
onCheckedChange={saveBellSoundPreference}
|
|
222
|
+
/>
|
|
223
|
+
}
|
|
224
|
+
/>
|
|
173
225
|
</SettingsGroup>
|
|
174
226
|
|
|
175
227
|
{replayStorageStatus.data?.configured ? (
|
|
@@ -57,6 +57,12 @@ export function buildAnalyticsGeneralSettingsSearchEntries(
|
|
|
57
57
|
keywords: "email notifications errors alerts javascript monitoring",
|
|
58
58
|
hash: "error-email-notifications",
|
|
59
59
|
},
|
|
60
|
+
{
|
|
61
|
+
id: "analytics-bell-sound",
|
|
62
|
+
label: t("settings.bellSound"),
|
|
63
|
+
keywords: "sound audio ding agent completion notification",
|
|
64
|
+
hash: "bell-sound",
|
|
65
|
+
},
|
|
60
66
|
{
|
|
61
67
|
id: "analytics-about",
|
|
62
68
|
label: t("settings.about"),
|
|
@@ -4,4 +4,6 @@ export const ANALYTICS_USER_PREFS_KEY = "analytics-user-prefs";
|
|
|
4
4
|
export type AnalyticsUserPrefs = {
|
|
5
5
|
/** New JavaScript error emails are opt-in. */
|
|
6
6
|
errorEmailNotifications?: boolean;
|
|
7
|
+
/** Play the completion sound when an agent run finishes successfully. */
|
|
8
|
+
bellSoundEnabled?: boolean;
|
|
7
9
|
};
|