mirror of
https://github.com/OpenHands/OpenHands.git
synced 2026-03-22 13:47:19 +08:00
feat: add sound and browser notifications for agent state changes (#6530)
Co-authored-by: openhands <openhands@all-hands.dev> Co-authored-by: amanape <83104063+amanape@users.noreply.github.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { render, screen, within } from "@testing-library/react";
|
||||
import { screen, within } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { renderWithProviders } from "test-utils";
|
||||
import { TrajectoryActions } from "#/components/features/trajectory/trajectory-actions";
|
||||
|
||||
describe("TrajectoryActions", () => {
|
||||
@@ -14,7 +15,7 @@ describe("TrajectoryActions", () => {
|
||||
});
|
||||
|
||||
it("should render correctly", () => {
|
||||
render(
|
||||
renderWithProviders(
|
||||
<TrajectoryActions
|
||||
onPositiveFeedback={onPositiveFeedback}
|
||||
onNegativeFeedback={onNegativeFeedback}
|
||||
@@ -25,10 +26,11 @@ describe("TrajectoryActions", () => {
|
||||
const actions = screen.getByTestId("feedback-actions");
|
||||
within(actions).getByTestId("positive-feedback");
|
||||
within(actions).getByTestId("negative-feedback");
|
||||
within(actions).getByTestId("export-trajectory");
|
||||
});
|
||||
|
||||
it("should call onPositiveFeedback when positive feedback is clicked", async () => {
|
||||
render(
|
||||
renderWithProviders(
|
||||
<TrajectoryActions
|
||||
onPositiveFeedback={onPositiveFeedback}
|
||||
onNegativeFeedback={onNegativeFeedback}
|
||||
@@ -43,7 +45,7 @@ describe("TrajectoryActions", () => {
|
||||
});
|
||||
|
||||
it("should call onNegativeFeedback when negative feedback is clicked", async () => {
|
||||
render(
|
||||
renderWithProviders(
|
||||
<TrajectoryActions
|
||||
onPositiveFeedback={onPositiveFeedback}
|
||||
onNegativeFeedback={onNegativeFeedback}
|
||||
@@ -58,7 +60,7 @@ describe("TrajectoryActions", () => {
|
||||
});
|
||||
|
||||
it("should call onExportTrajectory when negative feedback is clicked", async () => {
|
||||
render(
|
||||
renderWithProviders(
|
||||
<TrajectoryActions
|
||||
onPositiveFeedback={onPositiveFeedback}
|
||||
onNegativeFeedback={onNegativeFeedback}
|
||||
|
||||
BIN
frontend/src/assets/notification.mp3
Normal file
BIN
frontend/src/assets/notification.mp3
Normal file
Binary file not shown.
@@ -9,12 +9,21 @@ import {
|
||||
useWsClient,
|
||||
WsClientProviderStatus,
|
||||
} from "#/context/ws-client-provider";
|
||||
import { useNotification } from "#/hooks/useNotification";
|
||||
import { browserTab } from "#/utils/browser-tab";
|
||||
|
||||
const notificationStates = [
|
||||
AgentState.AWAITING_USER_INPUT,
|
||||
AgentState.FINISHED,
|
||||
AgentState.AWAITING_USER_CONFIRMATION,
|
||||
];
|
||||
|
||||
export function AgentStatusBar() {
|
||||
const { t, i18n } = useTranslation();
|
||||
const { curAgentState } = useSelector((state: RootState) => state.agent);
|
||||
const { curStatusMessage } = useSelector((state: RootState) => state.status);
|
||||
const { status } = useWsClient();
|
||||
const { notify } = useNotification();
|
||||
|
||||
const [statusMessage, setStatusMessage] = React.useState<string>("");
|
||||
|
||||
@@ -45,13 +54,40 @@ export function AgentStatusBar() {
|
||||
updateStatusMessage();
|
||||
}, [curStatusMessage.id]);
|
||||
|
||||
// Handle window focus/blur
|
||||
React.useEffect(() => {
|
||||
if (typeof window === "undefined") return undefined;
|
||||
|
||||
const handleFocus = () => {
|
||||
browserTab.stopNotification();
|
||||
};
|
||||
|
||||
window.addEventListener("focus", handleFocus);
|
||||
return () => {
|
||||
window.removeEventListener("focus", handleFocus);
|
||||
browserTab.stopNotification();
|
||||
};
|
||||
}, []);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (status === WsClientProviderStatus.DISCONNECTED) {
|
||||
setStatusMessage("Connecting...");
|
||||
} else {
|
||||
setStatusMessage(AGENT_STATUS_MAP[curAgentState].message);
|
||||
if (notificationStates.includes(curAgentState)) {
|
||||
const message = t(AGENT_STATUS_MAP[curAgentState].message);
|
||||
notify(t(AGENT_STATUS_MAP[curAgentState].message), {
|
||||
body: t(`Agent state changed to ${curAgentState}`),
|
||||
playSound: true,
|
||||
});
|
||||
|
||||
// Update browser tab if window exists and is not focused
|
||||
if (typeof document !== "undefined" && !document.hasFocus()) {
|
||||
browserTab.startNotification(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [curAgentState]);
|
||||
}, [curAgentState, notify, t]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center">
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
import ThumbsUpIcon from "#/icons/thumbs-up.svg?react";
|
||||
import ThumbDownIcon from "#/icons/thumbs-down.svg?react";
|
||||
import ExportIcon from "#/icons/export.svg?react";
|
||||
@@ -14,22 +15,27 @@ export function TrajectoryActions({
|
||||
onNegativeFeedback,
|
||||
onExportTrajectory,
|
||||
}: TrajectoryActionsProps) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div data-testid="feedback-actions" className="flex gap-1">
|
||||
<TrajectoryActionButton
|
||||
testId="positive-feedback"
|
||||
onClick={onPositiveFeedback}
|
||||
icon={<ThumbsUpIcon width={15} height={15} />}
|
||||
tooltip={t("BUTTON$MARK_HELPFUL")}
|
||||
/>
|
||||
<TrajectoryActionButton
|
||||
testId="negative-feedback"
|
||||
onClick={onNegativeFeedback}
|
||||
icon={<ThumbDownIcon width={15} height={15} />}
|
||||
tooltip={t("BUTTON$MARK_NOT_HELPFUL")}
|
||||
/>
|
||||
<TrajectoryActionButton
|
||||
testId="export-trajectory"
|
||||
onClick={onExportTrajectory}
|
||||
icon={<ExportIcon width={15} height={15} />}
|
||||
tooltip={t("BUTTON$EXPORT_CONVERSATION")}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
import { Tooltip } from "@heroui/react";
|
||||
|
||||
interface TrajectoryActionButtonProps {
|
||||
testId?: string;
|
||||
onClick: () => void;
|
||||
icon: React.ReactNode;
|
||||
tooltip?: string;
|
||||
}
|
||||
|
||||
export function TrajectoryActionButton({
|
||||
testId,
|
||||
onClick,
|
||||
icon,
|
||||
tooltip,
|
||||
}: TrajectoryActionButtonProps) {
|
||||
return (
|
||||
const button = (
|
||||
<button
|
||||
type="button"
|
||||
data-testid={testId}
|
||||
@@ -19,4 +23,14 @@ export function TrajectoryActionButton({
|
||||
{icon}
|
||||
</button>
|
||||
);
|
||||
|
||||
if (tooltip) {
|
||||
return (
|
||||
<Tooltip content={tooltip} closeDelay={100}>
|
||||
{button}
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ const saveSettingsMutationFn = async (settings: Partial<PostSettings>) => {
|
||||
github_token: settings.github_token,
|
||||
unset_github_token: settings.unset_github_token,
|
||||
enable_default_condenser: settings.ENABLE_DEFAULT_CONDENSER,
|
||||
enable_sound_notifications: settings.ENABLE_SOUND_NOTIFICATIONS,
|
||||
user_consents_to_analytics: settings.user_consents_to_analytics,
|
||||
};
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ const getSettingsQueryFn = async () => {
|
||||
REMOTE_RUNTIME_RESOURCE_FACTOR: apiSettings.remote_runtime_resource_factor,
|
||||
GITHUB_TOKEN_IS_SET: apiSettings.github_token_is_set,
|
||||
ENABLE_DEFAULT_CONDENSER: apiSettings.enable_default_condenser,
|
||||
ENABLE_SOUND_NOTIFICATIONS: apiSettings.enable_sound_notifications,
|
||||
USER_CONSENTS_TO_ANALYTICS: apiSettings.user_consents_to_analytics,
|
||||
};
|
||||
};
|
||||
|
||||
56
frontend/src/hooks/useNotification.ts
Normal file
56
frontend/src/hooks/useNotification.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { useCallback, useRef } from "react";
|
||||
import notificationSound from "../assets/notification.mp3";
|
||||
import { useCurrentSettings } from "../context/settings-context";
|
||||
|
||||
export const useNotification = () => {
|
||||
const { settings } = useCurrentSettings();
|
||||
const audioRef = useRef<HTMLAudioElement | undefined>(undefined);
|
||||
|
||||
// Initialize audio only in browser environment
|
||||
if (typeof window !== "undefined" && !audioRef.current) {
|
||||
audioRef.current = new Audio(notificationSound);
|
||||
audioRef.current.volume = 0.5;
|
||||
}
|
||||
|
||||
const notify = useCallback(
|
||||
async (
|
||||
title: string,
|
||||
options?: NotificationOptions & { playSound?: boolean },
|
||||
): Promise<Notification | undefined> => {
|
||||
if (typeof window === "undefined") return undefined;
|
||||
|
||||
// Only play sound if:
|
||||
// 1. Explicitly requested via playSound option
|
||||
// 2. Sound notifications are enabled in settings
|
||||
// 3. Audio is available
|
||||
// 4. Not a settings-related notification
|
||||
if (
|
||||
options?.playSound === true && // Must be explicitly true
|
||||
settings?.ENABLE_SOUND_NOTIFICATIONS &&
|
||||
audioRef.current &&
|
||||
!title.includes("BUTTON$") // Don't play for button/settings actions
|
||||
) {
|
||||
// Reset and play sound
|
||||
audioRef.current.currentTime = 0;
|
||||
audioRef.current.play().catch(() => {
|
||||
// Ignore autoplay errors
|
||||
});
|
||||
}
|
||||
|
||||
if (Notification.permission === "default") {
|
||||
await Notification.requestPermission();
|
||||
}
|
||||
|
||||
if (Notification.permission === "granted") {
|
||||
// Remove playSound from options before passing to Notification
|
||||
const { playSound, ...notificationOptions } = options || {};
|
||||
return new Notification(title, notificationOptions);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
},
|
||||
[settings?.ENABLE_SOUND_NOTIFICATIONS],
|
||||
);
|
||||
|
||||
return { notify };
|
||||
};
|
||||
316
frontend/src/i18n/declaration.ts
Normal file
316
frontend/src/i18n/declaration.ts
Normal file
@@ -0,0 +1,316 @@
|
||||
// this file generate by script, don't modify it manually!!!
|
||||
export enum I18nKey {
|
||||
APP$TITLE = "APP$TITLE",
|
||||
BROWSER$TITLE = "BROWSER$TITLE",
|
||||
BROWSER$EMPTY_MESSAGE = "BROWSER$EMPTY_MESSAGE",
|
||||
SETTINGS$TITLE = "SETTINGS$TITLE",
|
||||
PROJECT$START_NEW = "PROJECT$START_NEW",
|
||||
PROJECT$NEW = "PROJECT$NEW",
|
||||
ACCOUNT_SETTINGS$TITLE = "ACCOUNT_SETTINGS$TITLE",
|
||||
WORKSPACE$TITLE = "WORKSPACE$TITLE",
|
||||
WORKSPACE$TERMINAL_TAB_LABEL = "WORKSPACE$TERMINAL_TAB_LABEL",
|
||||
TERMINAL$WAITING_FOR_CLIENT = "TERMINAL$WAITING_FOR_CLIENT",
|
||||
CODE_EDITOR$FILE_SAVED_SUCCESSFULLY = "CODE_EDITOR$FILE_SAVED_SUCCESSFULLY",
|
||||
CODE_EDITOR$SAVING_LABEL = "CODE_EDITOR$SAVING_LABEL",
|
||||
CODE_EDITOR$SAVE_LABEL = "CODE_EDITOR$SAVE_LABEL",
|
||||
CODE_EDITOR$OPTIONS = "CODE_EDITOR$OPTIONS",
|
||||
CODE_EDITOR$FILE_SAVE_ERROR = "CODE_EDITOR$FILE_SAVE_ERROR",
|
||||
CODE_EDITOR$EMPTY_MESSAGE = "CODE_EDITOR$EMPTY_MESSAGE",
|
||||
FILE_SERVICE$SELECT_FILE_ERROR = "FILE_SERVICE$SELECT_FILE_ERROR",
|
||||
FILE_SERVICE$UPLOAD_FILES_ERROR = "FILE_SERVICE$UPLOAD_FILES_ERROR",
|
||||
FILE_SERVICE$LIST_FILES_ERROR = "FILE_SERVICE$LIST_FILES_ERROR",
|
||||
FILE_SERVICE$SAVE_FILE_ERROR = "FILE_SERVICE$SAVE_FILE_ERROR",
|
||||
SUGGESTIONS$INCREASE_TEST_COVERAGE = "SUGGESTIONS$INCREASE_TEST_COVERAGE",
|
||||
SUGGESTIONS$AUTO_MERGE_PRS = "SUGGESTIONS$AUTO_MERGE_PRS",
|
||||
SUGGESTIONS$FIX_README = "SUGGESTIONS$FIX_README",
|
||||
SUGGESTIONS$CLEAN_DEPENDENCIES = "SUGGESTIONS$CLEAN_DEPENDENCIES",
|
||||
FILE_SERVICE$INVALID_FILE_PATH = "FILE_SERVICE$INVALID_FILE_PATH",
|
||||
WORKSPACE$PLANNER_TAB_LABEL = "WORKSPACE$PLANNER_TAB_LABEL",
|
||||
WORKSPACE$JUPYTER_TAB_LABEL = "WORKSPACE$JUPYTER_TAB_LABEL",
|
||||
WORKSPACE$CODE_EDITOR_TAB_LABEL = "WORKSPACE$CODE_EDITOR_TAB_LABEL",
|
||||
WORKSPACE$BROWSER_TAB_LABEL = "WORKSPACE$BROWSER_TAB_LABEL",
|
||||
VSCODE$OPEN = "VSCODE$OPEN",
|
||||
INCREASE_TEST_COVERAGE = "INCREASE_TEST_COVERAGE",
|
||||
AUTO_MERGE_PRS = "AUTO_MERGE_PRS",
|
||||
FIX_README = "FIX_README",
|
||||
CLEAN_DEPENDENCIES = "CLEAN_DEPENDENCIES",
|
||||
CONFIGURATION$OPENHANDS_WORKSPACE_DIRECTORY_INPUT_LABEL = "CONFIGURATION$OPENHANDS_WORKSPACE_DIRECTORY_INPUT_LABEL",
|
||||
LLM$PROVIDER = "LLM$PROVIDER",
|
||||
LLM$SELECT_PROVIDER_PLACEHOLDER = "LLM$SELECT_PROVIDER_PLACEHOLDER",
|
||||
API$KEY = "API$KEY",
|
||||
API$DONT_KNOW_KEY = "API$DONT_KNOW_KEY",
|
||||
BUTTON$SAVE = "BUTTON$SAVE",
|
||||
BUTTON$CLOSE = "BUTTON$CLOSE",
|
||||
BUTTON$RESET_TO_DEFAULTS = "BUTTON$RESET_TO_DEFAULTS",
|
||||
MODAL$CONFIRM_RESET_TITLE = "MODAL$CONFIRM_RESET_TITLE",
|
||||
MODAL$CONFIRM_RESET_MESSAGE = "MODAL$CONFIRM_RESET_MESSAGE",
|
||||
MODAL$END_SESSION_TITLE = "MODAL$END_SESSION_TITLE",
|
||||
MODAL$END_SESSION_MESSAGE = "MODAL$END_SESSION_MESSAGE",
|
||||
BUTTON$END_SESSION = "BUTTON$END_SESSION",
|
||||
BUTTON$CANCEL = "BUTTON$CANCEL",
|
||||
LANGUAGE$LABEL = "LANGUAGE$LABEL",
|
||||
GITHUB$TOKEN_LABEL = "GITHUB$TOKEN_LABEL",
|
||||
GITHUB$TOKEN_OPTIONAL = "GITHUB$TOKEN_OPTIONAL",
|
||||
GITHUB$GET_TOKEN = "GITHUB$GET_TOKEN",
|
||||
COMMON$HERE = "COMMON$HERE",
|
||||
ANALYTICS$ENABLE = "ANALYTICS$ENABLE",
|
||||
GITHUB$TOKEN_INVALID = "GITHUB$TOKEN_INVALID",
|
||||
BUTTON$DISCONNECT = "BUTTON$DISCONNECT",
|
||||
GITHUB$CONFIGURE_REPOS = "GITHUB$CONFIGURE_REPOS",
|
||||
COMMON$CLICK_FOR_INSTRUCTIONS = "COMMON$CLICK_FOR_INSTRUCTIONS",
|
||||
LLM$SELECT_MODEL_PLACEHOLDER = "LLM$SELECT_MODEL_PLACEHOLDER",
|
||||
LLM$MODEL = "LLM$MODEL",
|
||||
CONFIGURATION$OPENHANDS_WORKSPACE_DIRECTORY_INPUT_PLACEHOLDER = "CONFIGURATION$OPENHANDS_WORKSPACE_DIRECTORY_INPUT_PLACEHOLDER",
|
||||
CONFIGURATION$MODAL_TITLE = "CONFIGURATION$MODAL_TITLE",
|
||||
CONFIGURATION$MODEL_SELECT_LABEL = "CONFIGURATION$MODEL_SELECT_LABEL",
|
||||
CONFIGURATION$MODEL_SELECT_PLACEHOLDER = "CONFIGURATION$MODEL_SELECT_PLACEHOLDER",
|
||||
CONFIGURATION$AGENT_SELECT_LABEL = "CONFIGURATION$AGENT_SELECT_LABEL",
|
||||
CONFIGURATION$AGENT_SELECT_PLACEHOLDER = "CONFIGURATION$AGENT_SELECT_PLACEHOLDER",
|
||||
CONFIGURATION$LANGUAGE_SELECT_LABEL = "CONFIGURATION$LANGUAGE_SELECT_LABEL",
|
||||
CONFIGURATION$LANGUAGE_SELECT_PLACEHOLDER = "CONFIGURATION$LANGUAGE_SELECT_PLACEHOLDER",
|
||||
CONFIGURATION$SECURITY_SELECT_LABEL = "CONFIGURATION$SECURITY_SELECT_LABEL",
|
||||
CONFIGURATION$SECURITY_SELECT_PLACEHOLDER = "CONFIGURATION$SECURITY_SELECT_PLACEHOLDER",
|
||||
CONFIGURATION$MODAL_CLOSE_BUTTON_LABEL = "CONFIGURATION$MODAL_CLOSE_BUTTON_LABEL",
|
||||
CONFIGURATION$MODAL_SAVE_BUTTON_LABEL = "CONFIGURATION$MODAL_SAVE_BUTTON_LABEL",
|
||||
CONFIGURATION$MODAL_RESET_BUTTON_LABEL = "CONFIGURATION$MODAL_RESET_BUTTON_LABEL",
|
||||
STATUS$CONNECTED_TO_SERVER = "STATUS$CONNECTED_TO_SERVER",
|
||||
PROJECT$NEW_PROJECT = "PROJECT$NEW_PROJECT",
|
||||
BROWSER$SCREENSHOT = "BROWSER$SCREENSHOT",
|
||||
TIME$MINUTES_AGO = "TIME$MINUTES_AGO",
|
||||
TIME$HOURS_AGO = "TIME$HOURS_AGO",
|
||||
TIME$DAYS_AGO = "TIME$DAYS_AGO",
|
||||
SETTINGS_FORM$RUNTIME_SIZE_LABEL = "SETTINGS_FORM$RUNTIME_SIZE_LABEL",
|
||||
CONFIGURATION$SETTINGS_NEED_UPDATE_MESSAGE = "CONFIGURATION$SETTINGS_NEED_UPDATE_MESSAGE",
|
||||
CONFIGURATION$AGENT_LOADING = "CONFIGURATION$AGENT_LOADING",
|
||||
CONFIGURATION$AGENT_RUNNING = "CONFIGURATION$AGENT_RUNNING",
|
||||
CONFIGURATION$ERROR_FETCH_MODELS = "CONFIGURATION$ERROR_FETCH_MODELS",
|
||||
CONFIGURATION$SETTINGS_NOT_FOUND = "CONFIGURATION$SETTINGS_NOT_FOUND",
|
||||
CONNECT_TO_GITHUB_BY_TOKEN_MODAL$TERMS_OF_SERVICE = "CONNECT_TO_GITHUB_BY_TOKEN_MODAL$TERMS_OF_SERVICE",
|
||||
SESSION$SERVER_CONNECTED_MESSAGE = "SESSION$SERVER_CONNECTED_MESSAGE",
|
||||
SESSION$SESSION_HANDLING_ERROR_MESSAGE = "SESSION$SESSION_HANDLING_ERROR_MESSAGE",
|
||||
SESSION$SESSION_CONNECTION_ERROR_MESSAGE = "SESSION$SESSION_CONNECTION_ERROR_MESSAGE",
|
||||
SESSION$SOCKET_NOT_INITIALIZED_ERROR_MESSAGE = "SESSION$SOCKET_NOT_INITIALIZED_ERROR_MESSAGE",
|
||||
EXPLORER$UPLOAD_ERROR_MESSAGE = "EXPLORER$UPLOAD_ERROR_MESSAGE",
|
||||
EXPLORER$LABEL_DROP_FILES = "EXPLORER$LABEL_DROP_FILES",
|
||||
EXPLORER$LABEL_WORKSPACE = "EXPLORER$LABEL_WORKSPACE",
|
||||
EXPLORER$EMPTY_WORKSPACE_MESSAGE = "EXPLORER$EMPTY_WORKSPACE_MESSAGE",
|
||||
EXPLORER$LOADING_WORKSPACE_MESSAGE = "EXPLORER$LOADING_WORKSPACE_MESSAGE",
|
||||
EXPLORER$REFRESH_ERROR_MESSAGE = "EXPLORER$REFRESH_ERROR_MESSAGE",
|
||||
EXPLORER$UPLOAD_SUCCESS_MESSAGE = "EXPLORER$UPLOAD_SUCCESS_MESSAGE",
|
||||
EXPLORER$NO_FILES_UPLOADED_MESSAGE = "EXPLORER$NO_FILES_UPLOADED_MESSAGE",
|
||||
EXPLORER$UPLOAD_PARTIAL_SUCCESS_MESSAGE = "EXPLORER$UPLOAD_PARTIAL_SUCCESS_MESSAGE",
|
||||
EXPLORER$UPLOAD_UNEXPECTED_RESPONSE_MESSAGE = "EXPLORER$UPLOAD_UNEXPECTED_RESPONSE_MESSAGE",
|
||||
EXPLORER$VSCODE_SWITCHING_MESSAGE = "EXPLORER$VSCODE_SWITCHING_MESSAGE",
|
||||
EXPLORER$VSCODE_SWITCHING_ERROR_MESSAGE = "EXPLORER$VSCODE_SWITCHING_ERROR_MESSAGE",
|
||||
LOAD_SESSION$MODAL_TITLE = "LOAD_SESSION$MODAL_TITLE",
|
||||
LOAD_SESSION$MODAL_CONTENT = "LOAD_SESSION$MODAL_CONTENT",
|
||||
LOAD_SESSION$RESUME_SESSION_MODAL_ACTION_LABEL = "LOAD_SESSION$RESUME_SESSION_MODAL_ACTION_LABEL",
|
||||
LOAD_SESSION$START_NEW_SESSION_MODAL_ACTION_LABEL = "LOAD_SESSION$START_NEW_SESSION_MODAL_ACTION_LABEL",
|
||||
FEEDBACK$MODAL_TITLE = "FEEDBACK$MODAL_TITLE",
|
||||
FEEDBACK$MODAL_CONTENT = "FEEDBACK$MODAL_CONTENT",
|
||||
FEEDBACK$EMAIL_LABEL = "FEEDBACK$EMAIL_LABEL",
|
||||
FEEDBACK$CONTRIBUTE_LABEL = "FEEDBACK$CONTRIBUTE_LABEL",
|
||||
FEEDBACK$SHARE_LABEL = "FEEDBACK$SHARE_LABEL",
|
||||
FEEDBACK$CANCEL_LABEL = "FEEDBACK$CANCEL_LABEL",
|
||||
FEEDBACK$EMAIL_PLACEHOLDER = "FEEDBACK$EMAIL_PLACEHOLDER",
|
||||
FEEDBACK$PASSWORD_COPIED_MESSAGE = "FEEDBACK$PASSWORD_COPIED_MESSAGE",
|
||||
FEEDBACK$GO_TO_FEEDBACK = "FEEDBACK$GO_TO_FEEDBACK",
|
||||
FEEDBACK$PASSWORD = "FEEDBACK$PASSWORD",
|
||||
FEEDBACK$INVALID_EMAIL_FORMAT = "FEEDBACK$INVALID_EMAIL_FORMAT",
|
||||
FEEDBACK$FAILED_TO_SHARE = "FEEDBACK$FAILED_TO_SHARE",
|
||||
FEEDBACK$COPY_LABEL = "FEEDBACK$COPY_LABEL",
|
||||
FEEDBACK$SHARING_SETTINGS_LABEL = "FEEDBACK$SHARING_SETTINGS_LABEL",
|
||||
SECURITY$UNKNOWN_ANALYZER_LABEL = "SECURITY$UNKNOWN_ANALYZER_LABEL",
|
||||
INVARIANT$UPDATE_POLICY_LABEL = "INVARIANT$UPDATE_POLICY_LABEL",
|
||||
INVARIANT$UPDATE_SETTINGS_LABEL = "INVARIANT$UPDATE_SETTINGS_LABEL",
|
||||
INVARIANT$SETTINGS_LABEL = "INVARIANT$SETTINGS_LABEL",
|
||||
INVARIANT$ASK_CONFIRMATION_RISK_SEVERITY_LABEL = "INVARIANT$ASK_CONFIRMATION_RISK_SEVERITY_LABEL",
|
||||
INVARIANT$DONT_ASK_FOR_CONFIRMATION_LABEL = "INVARIANT$DONT_ASK_FOR_CONFIRMATION_LABEL",
|
||||
INVARIANT$INVARIANT_ANALYZER_LABEL = "INVARIANT$INVARIANT_ANALYZER_LABEL",
|
||||
INVARIANT$INVARIANT_ANALYZER_MESSAGE = "INVARIANT$INVARIANT_ANALYZER_MESSAGE",
|
||||
INVARIANT$CLICK_TO_LEARN_MORE_LABEL = "INVARIANT$CLICK_TO_LEARN_MORE_LABEL",
|
||||
INVARIANT$POLICY_LABEL = "INVARIANT$POLICY_LABEL",
|
||||
INVARIANT$LOG_LABEL = "INVARIANT$LOG_LABEL",
|
||||
INVARIANT$EXPORT_TRACE_LABEL = "INVARIANT$EXPORT_TRACE_LABEL",
|
||||
INVARIANT$TRACE_EXPORTED_MESSAGE = "INVARIANT$TRACE_EXPORTED_MESSAGE",
|
||||
INVARIANT$POLICY_UPDATED_MESSAGE = "INVARIANT$POLICY_UPDATED_MESSAGE",
|
||||
INVARIANT$SETTINGS_UPDATED_MESSAGE = "INVARIANT$SETTINGS_UPDATED_MESSAGE",
|
||||
CHAT_INTERFACE$INITIALIZING_AGENT_LOADING_MESSAGE = "CHAT_INTERFACE$INITIALIZING_AGENT_LOADING_MESSAGE",
|
||||
CHAT_INTERFACE$AGENT_INIT_MESSAGE = "CHAT_INTERFACE$AGENT_INIT_MESSAGE",
|
||||
CHAT_INTERFACE$AGENT_RUNNING_MESSAGE = "CHAT_INTERFACE$AGENT_RUNNING_MESSAGE",
|
||||
CHAT_INTERFACE$AGENT_AWAITING_USER_INPUT_MESSAGE = "CHAT_INTERFACE$AGENT_AWAITING_USER_INPUT_MESSAGE",
|
||||
CHAT_INTERFACE$AGENT_RATE_LIMITED_MESSAGE = "CHAT_INTERFACE$AGENT_RATE_LIMITED_MESSAGE",
|
||||
CHAT_INTERFACE$AGENT_PAUSED_MESSAGE = "CHAT_INTERFACE$AGENT_PAUSED_MESSAGE",
|
||||
LANDING$TITLE = "LANDING$TITLE",
|
||||
LANDING$SUBTITLE = "LANDING$SUBTITLE",
|
||||
LANDING$START_HELP = "LANDING$START_HELP",
|
||||
LANDING$START_HELP_LINK = "LANDING$START_HELP_LINK",
|
||||
SUGGESTIONS$HELLO_WORLD = "SUGGESTIONS$HELLO_WORLD",
|
||||
SUGGESTIONS$TODO_APP = "SUGGESTIONS$TODO_APP",
|
||||
SUGGESTIONS$HACKER_NEWS = "SUGGESTIONS$HACKER_NEWS",
|
||||
LANDING$CHANGE_PROMPT = "LANDING$CHANGE_PROMPT",
|
||||
GITHUB$CONNECT = "GITHUB$CONNECT",
|
||||
GITHUB$NO_RESULTS = "GITHUB$NO_RESULTS",
|
||||
GITHUB$ADD_MORE_REPOS = "GITHUB$ADD_MORE_REPOS",
|
||||
GITHUB$YOUR_REPOS = "GITHUB$YOUR_REPOS",
|
||||
GITHUB$PUBLIC_REPOS = "GITHUB$PUBLIC_REPOS",
|
||||
DOWNLOAD$PREPARING = "DOWNLOAD$PREPARING",
|
||||
DOWNLOAD$DOWNLOADING = "DOWNLOAD$DOWNLOADING",
|
||||
DOWNLOAD$FOUND_FILES = "DOWNLOAD$FOUND_FILES",
|
||||
DOWNLOAD$SCANNING = "DOWNLOAD$SCANNING",
|
||||
DOWNLOAD$FILES_PROGRESS = "DOWNLOAD$FILES_PROGRESS",
|
||||
DOWNLOAD$CANCEL = "DOWNLOAD$CANCEL",
|
||||
ACTION$CONFIRM = "ACTION$CONFIRM",
|
||||
ACTION$REJECT = "ACTION$REJECT",
|
||||
BADGE$BETA = "BADGE$BETA",
|
||||
AGENT$RESUME_TASK = "AGENT$RESUME_TASK",
|
||||
AGENT$PAUSE_TASK = "AGENT$PAUSE_TASK",
|
||||
TOS$ACCEPT = "TOS$ACCEPT",
|
||||
TOS$TERMS = "TOS$TERMS",
|
||||
USER$ACCOUNT_SETTINGS = "USER$ACCOUNT_SETTINGS",
|
||||
JUPYTER$OUTPUT_LABEL = "JUPYTER$OUTPUT_LABEL",
|
||||
BUTTON$STOP = "BUTTON$STOP",
|
||||
LANDING$ATTACH_IMAGES = "LANDING$ATTACH_IMAGES",
|
||||
LANDING$OPEN_REPO = "LANDING$OPEN_REPO",
|
||||
LANDING$IMPORT_PROJECT = "LANDING$IMPORT_PROJECT",
|
||||
LANDING$UPLOAD_ZIP = "LANDING$UPLOAD_ZIP",
|
||||
LANDING$RECENT_CONVERSATION = "LANDING$RECENT_CONVERSATION",
|
||||
LANDING$OR = "LANDING$OR",
|
||||
SUGGESTIONS$TEST_COVERAGE = "SUGGESTIONS$TEST_COVERAGE",
|
||||
SUGGESTIONS$AUTO_MERGE = "SUGGESTIONS$AUTO_MERGE",
|
||||
CHAT_INTERFACE$AGENT_STOPPED_MESSAGE = "CHAT_INTERFACE$AGENT_STOPPED_MESSAGE",
|
||||
CHAT_INTERFACE$AGENT_FINISHED_MESSAGE = "CHAT_INTERFACE$AGENT_FINISHED_MESSAGE",
|
||||
CHAT_INTERFACE$AGENT_REJECTED_MESSAGE = "CHAT_INTERFACE$AGENT_REJECTED_MESSAGE",
|
||||
CHAT_INTERFACE$AGENT_ERROR_MESSAGE = "CHAT_INTERFACE$AGENT_ERROR_MESSAGE",
|
||||
CHAT_INTERFACE$AGENT_AWAITING_USER_CONFIRMATION_MESSAGE = "CHAT_INTERFACE$AGENT_AWAITING_USER_CONFIRMATION_MESSAGE",
|
||||
CHAT_INTERFACE$AGENT_ACTION_USER_CONFIRMED_MESSAGE = "CHAT_INTERFACE$AGENT_ACTION_USER_CONFIRMED_MESSAGE",
|
||||
CHAT_INTERFACE$AGENT_ACTION_USER_REJECTED_MESSAGE = "CHAT_INTERFACE$AGENT_ACTION_USER_REJECTED_MESSAGE",
|
||||
CHAT_INTERFACE$INPUT_PLACEHOLDER = "CHAT_INTERFACE$INPUT_PLACEHOLDER",
|
||||
CHAT_INTERFACE$INPUT_CONTINUE_MESSAGE = "CHAT_INTERFACE$INPUT_CONTINUE_MESSAGE",
|
||||
CHAT_INTERFACE$USER_ASK_CONFIRMATION = "CHAT_INTERFACE$USER_ASK_CONFIRMATION",
|
||||
CHAT_INTERFACE$USER_CONFIRMED = "CHAT_INTERFACE$USER_CONFIRMED",
|
||||
CHAT_INTERFACE$USER_REJECTED = "CHAT_INTERFACE$USER_REJECTED",
|
||||
CHAT_INTERFACE$INPUT_SEND_MESSAGE_BUTTON_CONTENT = "CHAT_INTERFACE$INPUT_SEND_MESSAGE_BUTTON_CONTENT",
|
||||
CHAT_INTERFACE$CHAT_MESSAGE_COPIED = "CHAT_INTERFACE$CHAT_MESSAGE_COPIED",
|
||||
CHAT_INTERFACE$CHAT_MESSAGE_COPY_FAILED = "CHAT_INTERFACE$CHAT_MESSAGE_COPY_FAILED",
|
||||
CHAT_INTERFACE$TOOLTIP_COPY_MESSAGE = "CHAT_INTERFACE$TOOLTIP_COPY_MESSAGE",
|
||||
CHAT_INTERFACE$TOOLTIP_SEND_MESSAGE = "CHAT_INTERFACE$TOOLTIP_SEND_MESSAGE",
|
||||
CHAT_INTERFACE$TOOLTIP_UPLOAD_IMAGE = "CHAT_INTERFACE$TOOLTIP_UPLOAD_IMAGE",
|
||||
CHAT_INTERFACE$INITIAL_MESSAGE = "CHAT_INTERFACE$INITIAL_MESSAGE",
|
||||
CHAT_INTERFACE$ASSISTANT = "CHAT_INTERFACE$ASSISTANT",
|
||||
CHAT_INTERFACE$TO_BOTTOM = "CHAT_INTERFACE$TO_BOTTOM",
|
||||
CHAT_INTERFACE$MESSAGE_ARIA_LABEL = "CHAT_INTERFACE$MESSAGE_ARIA_LABEL",
|
||||
CHAT_INTERFACE$CHAT_CONVERSATION = "CHAT_INTERFACE$CHAT_CONVERSATION",
|
||||
CHAT_INTERFACE$UNKNOWN_SENDER = "CHAT_INTERFACE$UNKNOWN_SENDER",
|
||||
SECURITY_ANALYZER$UNKNOWN_RISK = "SECURITY_ANALYZER$UNKNOWN_RISK",
|
||||
SECURITY_ANALYZER$LOW_RISK = "SECURITY_ANALYZER$LOW_RISK",
|
||||
SECURITY_ANALYZER$MEDIUM_RISK = "SECURITY_ANALYZER$MEDIUM_RISK",
|
||||
SECURITY_ANALYZER$HIGH_RISK = "SECURITY_ANALYZER$HIGH_RISK",
|
||||
SETTINGS$MODEL_TOOLTIP = "SETTINGS$MODEL_TOOLTIP",
|
||||
SETTINGS$AGENT_TOOLTIP = "SETTINGS$AGENT_TOOLTIP",
|
||||
SETTINGS$LANGUAGE_TOOLTIP = "SETTINGS$LANGUAGE_TOOLTIP",
|
||||
SETTINGS$DISABLED_RUNNING = "SETTINGS$DISABLED_RUNNING",
|
||||
SETTINGS$API_KEY_PLACEHOLDER = "SETTINGS$API_KEY_PLACEHOLDER",
|
||||
SETTINGS$CONFIRMATION_MODE = "SETTINGS$CONFIRMATION_MODE",
|
||||
SETTINGS$CONFIRMATION_MODE_TOOLTIP = "SETTINGS$CONFIRMATION_MODE_TOOLTIP",
|
||||
SETTINGS$AGENT_SELECT_ENABLED = "SETTINGS$AGENT_SELECT_ENABLED",
|
||||
SETTINGS$SECURITY_ANALYZER = "SETTINGS$SECURITY_ANALYZER",
|
||||
PLANNER$EMPTY_MESSAGE = "PLANNER$EMPTY_MESSAGE",
|
||||
FEEDBACK$PUBLIC_LABEL = "FEEDBACK$PUBLIC_LABEL",
|
||||
FEEDBACK$PRIVATE_LABEL = "FEEDBACK$PRIVATE_LABEL",
|
||||
STATUS$STARTING_RUNTIME = "STATUS$STARTING_RUNTIME",
|
||||
STATUS$STARTING_CONTAINER = "STATUS$STARTING_CONTAINER",
|
||||
STATUS$PREPARING_CONTAINER = "STATUS$PREPARING_CONTAINER",
|
||||
STATUS$CONTAINER_STARTED = "STATUS$CONTAINER_STARTED",
|
||||
ACCOUNT_SETTINGS_MODAL$DISCONNECT = "ACCOUNT_SETTINGS_MODAL$DISCONNECT",
|
||||
ACCOUNT_SETTINGS_MODAL$SAVE = "ACCOUNT_SETTINGS_MODAL$SAVE",
|
||||
ACCOUNT_SETTINGS_MODAL$CLOSE = "ACCOUNT_SETTINGS_MODAL$CLOSE",
|
||||
ACCOUNT_SETTINGS_MODAL$GITHUB_TOKEN_INVALID = "ACCOUNT_SETTINGS_MODAL$GITHUB_TOKEN_INVALID",
|
||||
CONNECT_TO_GITHUB_MODAL$GET_YOUR_TOKEN = "CONNECT_TO_GITHUB_MODAL$GET_YOUR_TOKEN",
|
||||
CONNECT_TO_GITHUB_MODAL$HERE = "CONNECT_TO_GITHUB_MODAL$HERE",
|
||||
CONNECT_TO_GITHUB_MODAL$CONNECT = "CONNECT_TO_GITHUB_MODAL$CONNECT",
|
||||
CONNECT_TO_GITHUB_MODAL$CLOSE = "CONNECT_TO_GITHUB_MODAL$CLOSE",
|
||||
CONNECT_TO_GITHUB_BY_TOKEN_MODAL$BY_CONNECTING_YOU_AGREE = "CONNECT_TO_GITHUB_BY_TOKEN_MODAL$BY_CONNECTING_YOU_AGREE",
|
||||
CONNECT_TO_GITHUB_BY_TOKEN_MODAL$CONTINUE = "CONNECT_TO_GITHUB_BY_TOKEN_MODAL$CONTINUE",
|
||||
LOADING_PROJECT$LOADING = "LOADING_PROJECT$LOADING",
|
||||
CUSTOM_INPUT$OPTIONAL_LABEL = "CUSTOM_INPUT$OPTIONAL_LABEL",
|
||||
SETTINGS_FORM$CUSTOM_MODEL_LABEL = "SETTINGS_FORM$CUSTOM_MODEL_LABEL",
|
||||
SETTINGS_FORM$BASE_URL_LABEL = "SETTINGS_FORM$BASE_URL_LABEL",
|
||||
SETTINGS_FORM$API_KEY_LABEL = "SETTINGS_FORM$API_KEY_LABEL",
|
||||
SETTINGS_FORM$DONT_KNOW_API_KEY_LABEL = "SETTINGS_FORM$DONT_KNOW_API_KEY_LABEL",
|
||||
SETTINGS_FORM$CLICK_HERE_FOR_INSTRUCTIONS_LABEL = "SETTINGS_FORM$CLICK_HERE_FOR_INSTRUCTIONS_LABEL",
|
||||
SETTINGS_FORM$AGENT_LABEL = "SETTINGS_FORM$AGENT_LABEL",
|
||||
SETTINGS_FORM$SECURITY_ANALYZER_LABEL = "SETTINGS_FORM$SECURITY_ANALYZER_LABEL",
|
||||
SETTINGS_FORM$ENABLE_CONFIRMATION_MODE_LABEL = "SETTINGS_FORM$ENABLE_CONFIRMATION_MODE_LABEL",
|
||||
SETTINGS_FORM$SAVE_LABEL = "SETTINGS_FORM$SAVE_LABEL",
|
||||
SETTINGS_FORM$CLOSE_LABEL = "SETTINGS_FORM$CLOSE_LABEL",
|
||||
SETTINGS_FORM$RESET_TO_DEFAULTS_LABEL = "SETTINGS_FORM$RESET_TO_DEFAULTS_LABEL",
|
||||
SETTINGS_FORM$CANCEL_LABEL = "SETTINGS_FORM$CANCEL_LABEL",
|
||||
SETTINGS_FORM$END_SESSION_LABEL = "SETTINGS_FORM$END_SESSION_LABEL",
|
||||
SETTINGS_FORM$CHANGING_WORKSPACE_WARNING_MESSAGE = "SETTINGS_FORM$CHANGING_WORKSPACE_WARNING_MESSAGE",
|
||||
SETTINGS_FORM$ARE_YOU_SURE_LABEL = "SETTINGS_FORM$ARE_YOU_SURE_LABEL",
|
||||
SETTINGS_FORM$ALL_INFORMATION_WILL_BE_DELETED_MESSAGE = "SETTINGS_FORM$ALL_INFORMATION_WILL_BE_DELETED_MESSAGE",
|
||||
PROJECT_MENU_DETAILS_PLACEHOLDER$NEW_PROJECT_LABEL = "PROJECT_MENU_DETAILS_PLACEHOLDER$NEW_PROJECT_LABEL",
|
||||
PROJECT_MENU_DETAILS_PLACEHOLDER$CONNECT_TO_GITHUB = "PROJECT_MENU_DETAILS_PLACEHOLDER$CONNECT_TO_GITHUB",
|
||||
PROJECT_MENU_DETAILS_PLACEHOLDER$CONNECTED = "PROJECT_MENU_DETAILS_PLACEHOLDER$CONNECTED",
|
||||
PROJECT_MENU_DETAILS$AGO_LABEL = "PROJECT_MENU_DETAILS$AGO_LABEL",
|
||||
STATUS$ERROR_LLM_AUTHENTICATION = "STATUS$ERROR_LLM_AUTHENTICATION",
|
||||
STATUS$ERROR_LLM_SERVICE_UNAVAILABLE = "STATUS$ERROR_LLM_SERVICE_UNAVAILABLE",
|
||||
STATUS$ERROR_LLM_INTERNAL_SERVER_ERROR = "STATUS$ERROR_LLM_INTERNAL_SERVER_ERROR",
|
||||
STATUS$ERROR_RUNTIME_DISCONNECTED = "STATUS$ERROR_RUNTIME_DISCONNECTED",
|
||||
STATUS$LLM_RETRY = "STATUS$LLM_RETRY",
|
||||
AGENT_ERROR$BAD_ACTION = "AGENT_ERROR$BAD_ACTION",
|
||||
AGENT_ERROR$ACTION_TIMEOUT = "AGENT_ERROR$ACTION_TIMEOUT",
|
||||
PROJECT_MENU_CARD_CONTEXT_MENU$CONNECT_TO_GITHUB_LABEL = "PROJECT_MENU_CARD_CONTEXT_MENU$CONNECT_TO_GITHUB_LABEL",
|
||||
PROJECT_MENU_CARD_CONTEXT_MENU$PUSH_TO_GITHUB_LABEL = "PROJECT_MENU_CARD_CONTEXT_MENU$PUSH_TO_GITHUB_LABEL",
|
||||
PROJECT_MENU_CARD_CONTEXT_MENU$DOWNLOAD_FILES_LABEL = "PROJECT_MENU_CARD_CONTEXT_MENU$DOWNLOAD_FILES_LABEL",
|
||||
PROJECT_MENU_CARD$OPEN = "PROJECT_MENU_CARD$OPEN",
|
||||
ACTION_BUTTON$RESUME = "ACTION_BUTTON$RESUME",
|
||||
ACTION_BUTTON$PAUSE = "ACTION_BUTTON$PAUSE",
|
||||
BROWSER$SCREENSHOT_ALT = "BROWSER$SCREENSHOT_ALT",
|
||||
ERROR_TOAST$CLOSE_BUTTON_LABEL = "ERROR_TOAST$CLOSE_BUTTON_LABEL",
|
||||
FILE_EXPLORER$UPLOAD = "FILE_EXPLORER$UPLOAD",
|
||||
FILE_EXPLORER$REFRESH_WORKSPACE = "FILE_EXPLORER$REFRESH_WORKSPACE",
|
||||
FILE_EXPLORER$OPEN_WORKSPACE = "FILE_EXPLORER$OPEN_WORKSPACE",
|
||||
FILE_EXPLORER$CLOSE_WORKSPACE = "FILE_EXPLORER$CLOSE_WORKSPACE",
|
||||
ACTION_MESSAGE$RUN = "ACTION_MESSAGE$RUN",
|
||||
ACTION_MESSAGE$RUN_IPYTHON = "ACTION_MESSAGE$RUN_IPYTHON",
|
||||
ACTION_MESSAGE$READ = "ACTION_MESSAGE$READ",
|
||||
ACTION_MESSAGE$EDIT = "ACTION_MESSAGE$EDIT",
|
||||
ACTION_MESSAGE$WRITE = "ACTION_MESSAGE$WRITE",
|
||||
ACTION_MESSAGE$BROWSE = "ACTION_MESSAGE$BROWSE",
|
||||
OBSERVATION_MESSAGE$RUN = "OBSERVATION_MESSAGE$RUN",
|
||||
OBSERVATION_MESSAGE$RUN_IPYTHON = "OBSERVATION_MESSAGE$RUN_IPYTHON",
|
||||
OBSERVATION_MESSAGE$READ = "OBSERVATION_MESSAGE$READ",
|
||||
OBSERVATION_MESSAGE$EDIT = "OBSERVATION_MESSAGE$EDIT",
|
||||
OBSERVATION_MESSAGE$WRITE = "OBSERVATION_MESSAGE$WRITE",
|
||||
OBSERVATION_MESSAGE$BROWSE = "OBSERVATION_MESSAGE$BROWSE",
|
||||
EXPANDABLE_MESSAGE$SHOW_DETAILS = "EXPANDABLE_MESSAGE$SHOW_DETAILS",
|
||||
EXPANDABLE_MESSAGE$HIDE_DETAILS = "EXPANDABLE_MESSAGE$HIDE_DETAILS",
|
||||
AI_SETTINGS$TITLE = "AI_SETTINGS$TITLE",
|
||||
SETTINGS$DESCRIPTION = "SETTINGS$DESCRIPTION",
|
||||
SETTINGS$WARNING = "SETTINGS$WARNING",
|
||||
SIDEBAR$SETTINGS = "SIDEBAR$SETTINGS",
|
||||
SIDEBAR$DOCS = "SIDEBAR$DOCS",
|
||||
SUGGESTIONS$ADD_DOCS = "SUGGESTIONS$ADD_DOCS",
|
||||
SUGGESTIONS$ADD_DOCKERFILE = "SUGGESTIONS$ADD_DOCKERFILE",
|
||||
STATUS$CONNECTED = "STATUS$CONNECTED",
|
||||
BROWSER$NO_PAGE_LOADED = "BROWSER$NO_PAGE_LOADED",
|
||||
USER$AVATAR_PLACEHOLDER = "USER$AVATAR_PLACEHOLDER",
|
||||
ACCOUNT_SETTINGS$SETTINGS = "ACCOUNT_SETTINGS$SETTINGS",
|
||||
ACCOUNT_SETTINGS$LOGOUT = "ACCOUNT_SETTINGS$LOGOUT",
|
||||
SETTINGS_FORM$ADVANCED_OPTIONS_LABEL = "SETTINGS_FORM$ADVANCED_OPTIONS_LABEL",
|
||||
CONVERSATION$NO_CONVERSATIONS = "CONVERSATION$NO_CONVERSATIONS",
|
||||
LANDING$SELECT_REPO = "LANDING$SELECT_REPO",
|
||||
BUTTON$SEND = "BUTTON$SEND",
|
||||
STATUS$WAITING_FOR_CLIENT = "STATUS$WAITING_FOR_CLIENT",
|
||||
SUGGESTIONS$WHAT_TO_BUILD = "SUGGESTIONS$WHAT_TO_BUILD",
|
||||
SETTINGS_FORM$ENABLE_DEFAULT_CONDENSER_SWITCH_LABEL = "SETTINGS_FORM$ENABLE_DEFAULT_CONDENSER_SWITCH_LABEL",
|
||||
BUTTON$ENABLE_SOUND = "BUTTON$ENABLE_SOUND",
|
||||
BUTTON$DISABLE_SOUND = "BUTTON$DISABLE_SOUND",
|
||||
BUTTON$MARK_HELPFUL = "BUTTON$MARK_HELPFUL",
|
||||
BUTTON$MARK_NOT_HELPFUL = "BUTTON$MARK_NOT_HELPFUL",
|
||||
NOTIFICATION$SOUND_ENABLED = "NOTIFICATION$SOUND_ENABLED",
|
||||
NOTIFICATION$SOUND_DISABLED = "NOTIFICATION$SOUND_DISABLED",
|
||||
BUTTON$EXPORT_CONVERSATION = "BUTTON$EXPORT_CONVERSATION",
|
||||
}
|
||||
@@ -4573,6 +4573,51 @@
|
||||
"en": "Enable Memory Condenser",
|
||||
"zh-TW": "啟用記憶體壓縮器"
|
||||
},
|
||||
"BUTTON$MARK_HELPFUL": {
|
||||
"en": "Mark this solution as helpful",
|
||||
"zh-CN": "标记此解决方案有帮助",
|
||||
"zh-TW": "標記此解決方案有幫助",
|
||||
"de": "Diese Lösung als hilfreich markieren",
|
||||
"ko-KR": "이 해결책이 도움이 되었다고 표시",
|
||||
"no": "Marker denne løsningen som nyttig",
|
||||
"it": "Segna questa soluzione come utile",
|
||||
"pt": "Marcar esta solução como útil",
|
||||
"es": "Marcar esta solución como útil",
|
||||
"ar": "وضع علامة على هذا الحل كمفيد",
|
||||
"fr": "Marquer cette solution comme utile",
|
||||
"tr": "Bu çözümü yararlı olarak işaretle",
|
||||
"ja": "このソリューションが役立つと評価"
|
||||
},
|
||||
"BUTTON$MARK_NOT_HELPFUL": {
|
||||
"en": "Mark this solution as not helpful",
|
||||
"zh-CN": "标记此解决方案没有帮助",
|
||||
"zh-TW": "標記此解決方案沒有幫助",
|
||||
"de": "Diese Lösung als nicht hilfreich markieren",
|
||||
"ko-KR": "이 해결책이 도움이 되지 않았다고 표시",
|
||||
"no": "Marker denne løsningen som ikke nyttig",
|
||||
"it": "Segna questa soluzione come non utile",
|
||||
"pt": "Marcar esta solução como não útil",
|
||||
"es": "Marcar esta solución como no útil",
|
||||
"ar": "وضع علامة على هذا الحل كغير مفيد",
|
||||
"fr": "Marquer cette solution comme non utile",
|
||||
"tr": "Bu çözümü yararlı değil olarak işaretle",
|
||||
"ja": "このソリューションが役立たないと評価"
|
||||
},
|
||||
"BUTTON$EXPORT_CONVERSATION": {
|
||||
"en": "Export conversation",
|
||||
"zh-CN": "导出对话",
|
||||
"zh-TW": "導出對話",
|
||||
"de": "Konversation exportieren",
|
||||
"ko-KR": "대화 내보내기",
|
||||
"no": "Eksporter samtale",
|
||||
"it": "Esporta conversazione",
|
||||
"pt": "Exportar conversa",
|
||||
"es": "Exportar conversación",
|
||||
"ar": "تصدير المحادثة",
|
||||
"fr": "Exporter la conversation",
|
||||
"tr": "Konuşmayı dışa aktar",
|
||||
"ja": "会話をエクスポート"
|
||||
},
|
||||
"BILLING$CLICK_TO_TOP_UP": {
|
||||
"en": "Add funds to Your Account",
|
||||
"ja": "アカウントに資金を追加",
|
||||
|
||||
@@ -20,6 +20,7 @@ export const MOCK_DEFAULT_USER_SETTINGS: ApiSettings | PostApiSettings = {
|
||||
DEFAULT_SETTINGS.REMOTE_RUNTIME_RESOURCE_FACTOR,
|
||||
github_token_is_set: DEFAULT_SETTINGS.GITHUB_TOKEN_IS_SET,
|
||||
enable_default_condenser: DEFAULT_SETTINGS.ENABLE_DEFAULT_CONDENSER,
|
||||
enable_sound_notifications: DEFAULT_SETTINGS.ENABLE_SOUND_NOTIFICATIONS,
|
||||
user_consents_to_analytics: DEFAULT_SETTINGS.USER_CONSENTS_TO_ANALYTICS,
|
||||
};
|
||||
|
||||
|
||||
@@ -104,6 +104,8 @@ function AccountSettings() {
|
||||
formData.get("enable-analytics-switch")?.toString() === "on";
|
||||
const enableMemoryCondenser =
|
||||
formData.get("enable-memory-condenser-switch")?.toString() === "on";
|
||||
const enableSoundNotifications =
|
||||
formData.get("enable-sound-notifications-switch")?.toString() === "on";
|
||||
|
||||
saveSettings(
|
||||
{
|
||||
@@ -112,6 +114,7 @@ function AccountSettings() {
|
||||
LANGUAGE: languageValue,
|
||||
user_consents_to_analytics: userConsentsToAnalytics,
|
||||
ENABLE_DEFAULT_CONDENSER: enableMemoryCondenser,
|
||||
ENABLE_SOUND_NOTIFICATIONS: enableSoundNotifications,
|
||||
LLM_MODEL: customLlmModel || fullLlmModel,
|
||||
LLM_BASE_URL: formData.get("base-url-input")?.toString() || "",
|
||||
LLM_API_KEY:
|
||||
@@ -398,6 +401,14 @@ function AccountSettings() {
|
||||
>
|
||||
Enable analytics
|
||||
</SettingsSwitch>
|
||||
|
||||
<SettingsSwitch
|
||||
testId="enable-sound-notifications-switch"
|
||||
name="enable-sound-notifications-switch"
|
||||
defaultIsToggled={!!settings.ENABLE_SOUND_NOTIFICATIONS}
|
||||
>
|
||||
Enable sound notifications
|
||||
</SettingsSwitch>
|
||||
</section>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -13,6 +13,7 @@ export const DEFAULT_SETTINGS: Settings = {
|
||||
REMOTE_RUNTIME_RESOURCE_FACTOR: 1,
|
||||
GITHUB_TOKEN_IS_SET: false,
|
||||
ENABLE_DEFAULT_CONDENSER: true,
|
||||
ENABLE_SOUND_NOTIFICATIONS: false,
|
||||
USER_CONSENTS_TO_ANALYTICS: false,
|
||||
};
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ export type Settings = {
|
||||
REMOTE_RUNTIME_RESOURCE_FACTOR: number | null;
|
||||
GITHUB_TOKEN_IS_SET: boolean;
|
||||
ENABLE_DEFAULT_CONDENSER: boolean;
|
||||
ENABLE_SOUND_NOTIFICATIONS: boolean;
|
||||
USER_CONSENTS_TO_ANALYTICS: boolean | null;
|
||||
};
|
||||
|
||||
@@ -23,6 +24,7 @@ export type ApiSettings = {
|
||||
remote_runtime_resource_factor: number | null;
|
||||
github_token_is_set: boolean;
|
||||
enable_default_condenser: boolean;
|
||||
enable_sound_notifications: boolean;
|
||||
user_consents_to_analytics: boolean | null;
|
||||
};
|
||||
|
||||
|
||||
57
frontend/src/utils/browser-tab.ts
Normal file
57
frontend/src/utils/browser-tab.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
let originalTitle = "";
|
||||
let titleInterval: number | undefined;
|
||||
|
||||
const isBrowser =
|
||||
typeof window !== "undefined" && typeof document !== "undefined";
|
||||
|
||||
export const browserTab = {
|
||||
startNotification(message: string) {
|
||||
if (!isBrowser) return;
|
||||
|
||||
// Store original title if not already stored
|
||||
if (!originalTitle) {
|
||||
originalTitle = document.title;
|
||||
}
|
||||
|
||||
// Clear any existing interval
|
||||
if (titleInterval) {
|
||||
this.stopNotification();
|
||||
}
|
||||
|
||||
// Alternate between original title and notification message
|
||||
titleInterval = window.setInterval(() => {
|
||||
document.title =
|
||||
document.title === originalTitle ? message : originalTitle;
|
||||
}, 1000);
|
||||
|
||||
// Set favicon to indicate notification
|
||||
const favicon = document.querySelector(
|
||||
'link[rel="icon"]',
|
||||
) as HTMLLinkElement;
|
||||
if (favicon) {
|
||||
favicon.href = favicon.href.includes("?notification")
|
||||
? favicon.href
|
||||
: `${favicon.href}?notification`;
|
||||
}
|
||||
},
|
||||
|
||||
stopNotification() {
|
||||
if (!isBrowser) return;
|
||||
|
||||
if (titleInterval) {
|
||||
window.clearInterval(titleInterval);
|
||||
titleInterval = undefined;
|
||||
}
|
||||
if (originalTitle) {
|
||||
document.title = originalTitle;
|
||||
}
|
||||
|
||||
// Reset favicon
|
||||
const favicon = document.querySelector(
|
||||
'link[rel="icon"]',
|
||||
) as HTMLLinkElement;
|
||||
if (favicon) {
|
||||
favicon.href = favicon.href.replace("?notification", "");
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -23,6 +23,7 @@ class Settings(BaseModel):
|
||||
remote_runtime_resource_factor: int | None = None
|
||||
github_token: SecretStr | None = None
|
||||
enable_default_condenser: bool = False
|
||||
enable_sound_notifications: bool = False
|
||||
user_consents_to_analytics: bool | None = None
|
||||
|
||||
@field_serializer('llm_api_key')
|
||||
|
||||
Reference in New Issue
Block a user