mirror of
https://github.com/farion1231/cc-switch.git
synced 2026-07-28 08:44:41 +08:00
Merge branch 'main' into fix/common-config-sync-improvements
This commit is contained in:
@@ -20,7 +20,7 @@ import type { Provider } from "@/types";
|
||||
import type { AppId } from "@/lib/api";
|
||||
import { providersApi } from "@/lib/api/providers";
|
||||
import { useDragSort } from "@/hooks/useDragSort";
|
||||
import { useStreamCheck } from "@/hooks/useStreamCheck";
|
||||
// import { useStreamCheck } from "@/hooks/useStreamCheck"; // 测试功能已隐藏
|
||||
import { ProviderCard } from "@/components/providers/ProviderCard";
|
||||
import { ProviderEmptyState } from "@/components/providers/ProviderEmptyState";
|
||||
import {
|
||||
@@ -93,8 +93,8 @@ export function ProviderList({
|
||||
[appId, opencodeLiveIds],
|
||||
);
|
||||
|
||||
// 流式健康检查
|
||||
const { checkProvider, isChecking } = useStreamCheck(appId);
|
||||
// 流式健康检查 - 功能已隐藏
|
||||
// const { checkProvider, isChecking } = useStreamCheck(appId);
|
||||
|
||||
// 故障转移相关
|
||||
const { data: isAutoFailoverEnabled } = useAutoFailoverEnabled(appId);
|
||||
@@ -139,9 +139,10 @@ export function ProviderList({
|
||||
[appId, addToQueue, removeFromQueue],
|
||||
);
|
||||
|
||||
const handleTest = (provider: Provider) => {
|
||||
checkProvider(provider.id, provider.name);
|
||||
};
|
||||
// handleTest 功能已隐藏 - 供应商请求格式复杂难以统一测试
|
||||
// const handleTest = (provider: Provider) => {
|
||||
// checkProvider(provider.id, provider.name);
|
||||
// };
|
||||
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [isSearchOpen, setIsSearchOpen] = useState(false);
|
||||
@@ -229,8 +230,9 @@ export function ProviderList({
|
||||
onConfigureUsage={onConfigureUsage}
|
||||
onOpenWebsite={onOpenWebsite}
|
||||
onOpenTerminal={onOpenTerminal}
|
||||
onTest={appId !== "opencode" ? handleTest : undefined}
|
||||
isTesting={isChecking(provider.id)}
|
||||
// onTest 功能已隐藏 - 供应商请求格式复杂难以统一测试
|
||||
// onTest={appId !== "opencode" ? handleTest : undefined}
|
||||
isTesting={false} // isChecking(provider.id) - 测试功能已隐藏
|
||||
isProxyRunning={isProxyRunning}
|
||||
isProxyTakeover={isProxyTakeover}
|
||||
// 故障转移相关:联动状态
|
||||
|
||||
@@ -70,7 +70,7 @@ export function SessionItem({
|
||||
<div className="flex items-center gap-1 text-[11px] text-muted-foreground">
|
||||
<Clock className="size-3" />
|
||||
<span>
|
||||
{lastActive ? formatRelativeTime(lastActive) : t("common.unknown")}
|
||||
{lastActive ? formatRelativeTime(lastActive, t) : t("common.unknown")}
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
@@ -10,9 +10,7 @@ import {
|
||||
MessageSquare,
|
||||
Clock,
|
||||
FolderOpen,
|
||||
Terminal,
|
||||
X,
|
||||
SquareTerminal,
|
||||
} from "lucide-react";
|
||||
import { useSessionMessagesQuery, useSessionsQuery } from "@/lib/query";
|
||||
import { sessionsApi } from "@/lib/api";
|
||||
@@ -24,7 +22,6 @@ import {
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
|
||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
@@ -37,13 +34,6 @@ import {
|
||||
import { extractErrorMessage } from "@/utils/errorUtils";
|
||||
import { isMac } from "@/lib/platform";
|
||||
import { ProviderIcon } from "@/components/ProviderIcon";
|
||||
import {
|
||||
AlacrittyIcon,
|
||||
GhosttyIcon,
|
||||
ITermIcon,
|
||||
KittyIcon,
|
||||
WezTermIcon,
|
||||
} from "@/components/icons/TerminalIcons";
|
||||
import { SessionItem } from "./SessionItem";
|
||||
import { SessionMessageItem } from "./SessionMessageItem";
|
||||
import { SessionTocDialog, SessionTocSidebar } from "./SessionToc";
|
||||
@@ -56,16 +46,6 @@ import {
|
||||
getSessionKey,
|
||||
} from "./utils";
|
||||
|
||||
const TERMINAL_TARGET_KEY = "session_manager_terminal_target";
|
||||
|
||||
type TerminalTarget =
|
||||
| "terminal"
|
||||
| "iterm"
|
||||
| "ghostty"
|
||||
| "kitty"
|
||||
| "wezterm"
|
||||
| "alacritty";
|
||||
|
||||
type ProviderFilter = "all" | "codex" | "claude";
|
||||
|
||||
export function SessionManagerPage() {
|
||||
@@ -85,26 +65,6 @@ export function SessionManagerPage() {
|
||||
const [search, setSearch] = useState("");
|
||||
const [providerFilter, setProviderFilter] = useState<ProviderFilter>("all");
|
||||
const [selectedKey, setSelectedKey] = useState<string | null>(null);
|
||||
const [terminalTarget, setTerminalTarget] =
|
||||
useState<TerminalTarget>("terminal");
|
||||
const [isLoaded, setIsLoaded] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const storedTarget = window.localStorage.getItem(
|
||||
TERMINAL_TARGET_KEY
|
||||
) as TerminalTarget | null;
|
||||
if (storedTarget) {
|
||||
setTerminalTarget(storedTarget);
|
||||
}
|
||||
|
||||
setIsLoaded(true);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (isLoaded) {
|
||||
window.localStorage.setItem(TERMINAL_TARGET_KEY, terminalTarget);
|
||||
}
|
||||
}, [terminalTarget, isLoaded]);
|
||||
|
||||
// 使用 FlexSearch 全文搜索
|
||||
const { search: searchSessions } = useSessionSearch({
|
||||
@@ -205,7 +165,6 @@ export function SessionManagerPage() {
|
||||
|
||||
try {
|
||||
await sessionsApi.launchTerminal({
|
||||
target: terminalTarget,
|
||||
command: selectedSession.resumeCommand,
|
||||
cwd: selectedSession.projectDir ?? undefined,
|
||||
});
|
||||
@@ -288,7 +247,7 @@ export function SessionManagerPage() {
|
||||
<Search className="size-3.5" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>搜索会话</TooltipContent>
|
||||
<TooltipContent>{t("sessionManager.searchSessions")}</TooltipContent>
|
||||
</Tooltip>
|
||||
|
||||
<Select
|
||||
@@ -482,7 +441,7 @@ export function SessionManagerPage() {
|
||||
{selectedSession.projectDir}
|
||||
</p>
|
||||
<p className="text-muted-foreground mt-1">
|
||||
点击复制路径
|
||||
{t("sessionManager.clickToCopyPath")}
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
@@ -493,84 +452,32 @@ export function SessionManagerPage() {
|
||||
{/* 右侧:操作按钮组 */}
|
||||
<div className="flex items-center gap-2 shrink-0">
|
||||
{isMac() && (
|
||||
<>
|
||||
<Select
|
||||
value={terminalTarget}
|
||||
onValueChange={(value) =>
|
||||
setTerminalTarget(value as TerminalTarget)
|
||||
}
|
||||
>
|
||||
<SelectTrigger className="h-8 min-w-[110px] w-auto text-xs px-2.5">
|
||||
<Terminal className="size-3 mr-1.5" />
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent align="end">
|
||||
<SelectItem value="terminal">
|
||||
<div className="flex items-center gap-2">
|
||||
<SquareTerminal className="size-3.5" />
|
||||
<span>Terminal</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
<SelectItem value="iterm">
|
||||
<div className="flex items-center gap-2">
|
||||
<ITermIcon className="size-3.5" />
|
||||
<span>iTerm2 (Untested)</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
<SelectItem value="ghostty">
|
||||
<div className="flex items-center gap-2">
|
||||
<GhosttyIcon className="size-3.5" />
|
||||
<span>Ghostty</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
<SelectItem value="kitty">
|
||||
<div className="flex items-center gap-2">
|
||||
<KittyIcon className="size-3.5" />
|
||||
<span>Kitty</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
<SelectItem value="wezterm">
|
||||
<div className="flex items-center gap-2">
|
||||
<WezTermIcon className="size-3.5" />
|
||||
<span>WezTerm (Untested)</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
<SelectItem value="alacritty">
|
||||
<div className="flex items-center gap-2">
|
||||
<AlacrittyIcon className="size-3.5" />
|
||||
<span>Alacritty (Untested)</span>
|
||||
</div>
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
size="sm"
|
||||
className="gap-1.5"
|
||||
onClick={() => void handleResume()}
|
||||
disabled={!selectedSession.resumeCommand}
|
||||
>
|
||||
<Play className="size-3.5" />
|
||||
<span className="hidden sm:inline">
|
||||
{t("sessionManager.resume", {
|
||||
defaultValue: "恢复会话",
|
||||
})}
|
||||
</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{selectedSession.resumeCommand
|
||||
? t("sessionManager.resumeTooltip", {
|
||||
defaultValue: "在终端中恢复此会话",
|
||||
})
|
||||
: t("sessionManager.noResumeCommand", {
|
||||
defaultValue: "此会话无法恢复",
|
||||
})}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
size="sm"
|
||||
className="gap-1.5"
|
||||
onClick={() => void handleResume()}
|
||||
disabled={!selectedSession.resumeCommand}
|
||||
>
|
||||
<Play className="size-3.5" />
|
||||
<span className="hidden sm:inline">
|
||||
{t("sessionManager.resume", {
|
||||
defaultValue: "恢复会话",
|
||||
})}
|
||||
</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
{selectedSession.resumeCommand
|
||||
? t("sessionManager.resumeTooltip", {
|
||||
defaultValue: "在终端中恢复此会话",
|
||||
})
|
||||
: t("sessionManager.noResumeCommand", {
|
||||
defaultValue: "此会话无法恢复",
|
||||
})}
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -59,7 +59,7 @@ export function SessionMessageItem({
|
||||
</Tooltip>
|
||||
<div className="flex items-center justify-between text-xs mb-1.5 pr-6">
|
||||
<span className={cn("font-semibold", getRoleTone(message.role))}>
|
||||
{getRoleLabel(message.role)}
|
||||
{getRoleLabel(message.role, t)}
|
||||
</span>
|
||||
{message.ts && (
|
||||
<span className="text-muted-foreground">
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { List, X } from "lucide-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { ScrollArea } from "@/components/ui/scroll-area";
|
||||
@@ -26,6 +27,7 @@ export function SessionTocSidebar({
|
||||
items,
|
||||
onItemClick,
|
||||
}: SessionTocSidebarProps) {
|
||||
const { t } = useTranslation();
|
||||
if (items.length <= 2) return null;
|
||||
|
||||
return (
|
||||
@@ -33,7 +35,7 @@ export function SessionTocSidebar({
|
||||
<div className="p-3 border-b">
|
||||
<div className="flex items-center gap-1.5 text-xs font-medium text-muted-foreground">
|
||||
<List className="size-3.5" />
|
||||
<span>对话目录</span>
|
||||
<span>{t("sessionManager.tocTitle")}</span>
|
||||
</div>
|
||||
</div>
|
||||
<ScrollArea className="h-[calc(100%-40px)]">
|
||||
@@ -74,6 +76,7 @@ export function SessionTocDialog({
|
||||
open,
|
||||
onOpenChange,
|
||||
}: SessionTocDialogProps) {
|
||||
const { t } = useTranslation();
|
||||
if (items.length <= 2) return null;
|
||||
|
||||
return (
|
||||
@@ -95,11 +98,11 @@ export function SessionTocDialog({
|
||||
<DialogHeader className="px-4 py-3 relative border-b">
|
||||
<DialogTitle className="flex items-center gap-2 text-base font-semibold">
|
||||
<List className="size-4 text-primary" />
|
||||
对话目录
|
||||
{t("sessionManager.tocTitle")}
|
||||
</DialogTitle>
|
||||
<DialogClose
|
||||
className="absolute right-3 top-1/2 -translate-y-1/2 rounded-full p-1.5 hover:bg-muted transition-colors focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2"
|
||||
aria-label="关闭"
|
||||
aria-label={t("common.close")}
|
||||
>
|
||||
<X className="size-4 text-muted-foreground" />
|
||||
</DialogClose>
|
||||
|
||||
@@ -17,7 +17,10 @@ export const formatTimestamp = (value?: number) => {
|
||||
return new Date(value).toLocaleString();
|
||||
};
|
||||
|
||||
export const formatRelativeTime = (value?: number) => {
|
||||
export const formatRelativeTime = (
|
||||
value: number | undefined,
|
||||
t: (key: string, options?: Record<string, unknown>) => string
|
||||
) => {
|
||||
if (!value) return "";
|
||||
const now = Date.now();
|
||||
const diff = now - value;
|
||||
@@ -25,10 +28,10 @@ export const formatRelativeTime = (value?: number) => {
|
||||
const hours = Math.floor(diff / 3600000);
|
||||
const days = Math.floor(diff / 86400000);
|
||||
|
||||
if (minutes < 1) return "刚刚";
|
||||
if (minutes < 60) return `${minutes} 分钟前`;
|
||||
if (hours < 24) return `${hours} 小时前`;
|
||||
if (days < 7) return `${days} 天前`;
|
||||
if (minutes < 1) return t("sessionManager.justNow");
|
||||
if (minutes < 60) return t("sessionManager.minutesAgo", { count: minutes });
|
||||
if (hours < 24) return t("sessionManager.hoursAgo", { count: hours });
|
||||
if (days < 7) return t("sessionManager.daysAgo", { count: days });
|
||||
return new Date(value).toLocaleDateString();
|
||||
};
|
||||
|
||||
@@ -57,12 +60,15 @@ export const getRoleTone = (role: string) => {
|
||||
return "text-muted-foreground";
|
||||
};
|
||||
|
||||
export const getRoleLabel = (role: string) => {
|
||||
export const getRoleLabel = (
|
||||
role: string,
|
||||
t: (key: string) => string
|
||||
) => {
|
||||
const normalized = role.toLowerCase();
|
||||
if (normalized === "assistant") return "AI";
|
||||
if (normalized === "user") return "用户";
|
||||
if (normalized === "system") return "系统";
|
||||
if (normalized === "tool") return "工具";
|
||||
if (normalized === "user") return t("sessionManager.roleUser");
|
||||
if (normalized === "system") return t("sessionManager.roleSystem");
|
||||
if (normalized === "tool") return t("sessionManager.roleTool");
|
||||
return role;
|
||||
};
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ const MACOS_TERMINALS = [
|
||||
{ value: "alacritty", labelKey: "settings.terminal.options.macos.alacritty" },
|
||||
{ value: "kitty", labelKey: "settings.terminal.options.macos.kitty" },
|
||||
{ value: "ghostty", labelKey: "settings.terminal.options.macos.ghostty" },
|
||||
{ value: "wezterm", labelKey: "settings.terminal.options.macos.wezterm" },
|
||||
] as const;
|
||||
|
||||
const WINDOWS_TERMINALS = [
|
||||
|
||||
@@ -5,6 +5,7 @@ import React, {
|
||||
useMemo,
|
||||
useState,
|
||||
} from "react";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
|
||||
type Theme = "light" | "dark" | "system";
|
||||
|
||||
@@ -94,6 +95,54 @@ export function ThemeProvider({
|
||||
return () => mediaQuery.removeEventListener("change", handleChange);
|
||||
}, [theme]);
|
||||
|
||||
// Sync native window theme (Windows/macOS title bar)
|
||||
useEffect(() => {
|
||||
if (typeof window === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
let isCancelled = false;
|
||||
|
||||
const updateNativeTheme = async (nativeTheme: string) => {
|
||||
if (isCancelled) return;
|
||||
try {
|
||||
await invoke("set_window_theme", { theme: nativeTheme });
|
||||
} catch (e) {
|
||||
// Ignore errors (e.g., when not running in Tauri)
|
||||
console.debug("Failed to set native window theme:", e);
|
||||
}
|
||||
};
|
||||
|
||||
// Determine current effective theme
|
||||
if (theme === "system") {
|
||||
const isDark =
|
||||
window.matchMedia &&
|
||||
window.matchMedia("(prefers-color-scheme: dark)").matches;
|
||||
updateNativeTheme(isDark ? "dark" : "light");
|
||||
} else {
|
||||
updateNativeTheme(theme);
|
||||
}
|
||||
|
||||
// Listen to system theme changes for native window when in "system" mode
|
||||
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
||||
const handleChange = () => {
|
||||
if (theme === "system" && !isCancelled) {
|
||||
updateNativeTheme(mediaQuery.matches ? "dark" : "light");
|
||||
}
|
||||
};
|
||||
|
||||
if (theme === "system") {
|
||||
mediaQuery.addEventListener("change", handleChange);
|
||||
}
|
||||
|
||||
return () => {
|
||||
isCancelled = true;
|
||||
if (theme === "system") {
|
||||
mediaQuery.removeEventListener("change", handleChange);
|
||||
}
|
||||
};
|
||||
}, [theme]);
|
||||
|
||||
const value = useMemo<ThemeContextValue>(
|
||||
() => ({
|
||||
theme,
|
||||
|
||||
@@ -308,7 +308,8 @@
|
||||
"iterm2": "iTerm2",
|
||||
"alacritty": "Alacritty",
|
||||
"kitty": "Kitty",
|
||||
"ghostty": "Ghostty"
|
||||
"ghostty": "Ghostty",
|
||||
"wezterm": "WezTerm"
|
||||
},
|
||||
"windows": {
|
||||
"cmd": "Command Prompt",
|
||||
@@ -412,6 +413,7 @@
|
||||
"title": "Session Manager",
|
||||
"subtitle": "Manage Codex and Claude Code sessions",
|
||||
"searchPlaceholder": "Search by content, directory, or ID",
|
||||
"searchSessions": "Search sessions",
|
||||
"providerFilterAll": "All",
|
||||
"sessionList": "Sessions",
|
||||
"loadingSessions": "Loading sessions...",
|
||||
@@ -435,7 +437,16 @@
|
||||
"copySourcePath": "Copy source file",
|
||||
"sourcePathCopied": "Source file copied",
|
||||
"loadingMessages": "Loading transcript...",
|
||||
"emptySession": "No messages available"
|
||||
"emptySession": "No messages available",
|
||||
"clickToCopyPath": "Click to copy path",
|
||||
"tocTitle": "Contents",
|
||||
"justNow": "Just now",
|
||||
"minutesAgo": "{{count}} min ago",
|
||||
"hoursAgo": "{{count}} hr ago",
|
||||
"daysAgo": "{{count}} days ago",
|
||||
"roleUser": "User",
|
||||
"roleSystem": "System",
|
||||
"roleTool": "Tool"
|
||||
},
|
||||
"console": {
|
||||
"providerSwitchReceived": "Received provider switch event:",
|
||||
|
||||
@@ -308,7 +308,8 @@
|
||||
"iterm2": "iTerm2",
|
||||
"alacritty": "Alacritty",
|
||||
"kitty": "Kitty",
|
||||
"ghostty": "Ghostty"
|
||||
"ghostty": "Ghostty",
|
||||
"wezterm": "WezTerm"
|
||||
},
|
||||
"windows": {
|
||||
"cmd": "コマンドプロンプト",
|
||||
@@ -412,6 +413,7 @@
|
||||
"title": "セッション管理",
|
||||
"subtitle": "Codex / Claude Code のセッションを管理",
|
||||
"searchPlaceholder": "内容・ディレクトリ・ID で検索",
|
||||
"searchSessions": "セッションを検索",
|
||||
"providerFilterAll": "すべて",
|
||||
"sessionList": "セッション一覧",
|
||||
"loadingSessions": "セッションを読み込み中...",
|
||||
@@ -435,7 +437,16 @@
|
||||
"copySourcePath": "元ファイルをコピー",
|
||||
"sourcePathCopied": "元ファイルをコピーしました",
|
||||
"loadingMessages": "内容を読み込み中...",
|
||||
"emptySession": "表示できる内容がありません"
|
||||
"emptySession": "表示できる内容がありません",
|
||||
"clickToCopyPath": "クリックしてパスをコピー",
|
||||
"tocTitle": "目次",
|
||||
"justNow": "たった今",
|
||||
"minutesAgo": "{{count}}分前",
|
||||
"hoursAgo": "{{count}}時間前",
|
||||
"daysAgo": "{{count}}日前",
|
||||
"roleUser": "ユーザー",
|
||||
"roleSystem": "システム",
|
||||
"roleTool": "ツール"
|
||||
},
|
||||
"console": {
|
||||
"providerSwitchReceived": "プロバイダー切り替えイベントを受信:",
|
||||
|
||||
@@ -308,7 +308,8 @@
|
||||
"iterm2": "iTerm2",
|
||||
"alacritty": "Alacritty",
|
||||
"kitty": "Kitty",
|
||||
"ghostty": "Ghostty"
|
||||
"ghostty": "Ghostty",
|
||||
"wezterm": "WezTerm"
|
||||
},
|
||||
"windows": {
|
||||
"cmd": "命令提示符",
|
||||
@@ -412,6 +413,7 @@
|
||||
"title": "会话管理",
|
||||
"subtitle": "管理 Codex 与 Claude Code 会话记录",
|
||||
"searchPlaceholder": "搜索会话内容、目录或 ID",
|
||||
"searchSessions": "搜索会话",
|
||||
"providerFilterAll": "全部",
|
||||
"sessionList": "会话列表",
|
||||
"loadingSessions": "加载会话中...",
|
||||
@@ -435,7 +437,16 @@
|
||||
"copySourcePath": "复制原始文件",
|
||||
"sourcePathCopied": "原始文件已复制",
|
||||
"loadingMessages": "加载会话内容中...",
|
||||
"emptySession": "该会话暂无可展示内容"
|
||||
"emptySession": "该会话暂无可展示内容",
|
||||
"clickToCopyPath": "点击复制路径",
|
||||
"tocTitle": "对话目录",
|
||||
"justNow": "刚刚",
|
||||
"minutesAgo": "{{count}} 分钟前",
|
||||
"hoursAgo": "{{count}} 小时前",
|
||||
"daysAgo": "{{count}} 天前",
|
||||
"roleUser": "用户",
|
||||
"roleSystem": "系统",
|
||||
"roleTool": "工具"
|
||||
},
|
||||
"console": {
|
||||
"providerSwitchReceived": "收到供应商切换事件:",
|
||||
|
||||
@@ -14,14 +14,12 @@ export const sessionsApi = {
|
||||
},
|
||||
|
||||
async launchTerminal(options: {
|
||||
target: string;
|
||||
command: string;
|
||||
cwd?: string | null;
|
||||
customConfig?: string | null;
|
||||
}): Promise<boolean> {
|
||||
const { target, command, cwd, customConfig } = options;
|
||||
const { command, cwd, customConfig } = options;
|
||||
return await invoke("launch_session_terminal", {
|
||||
target,
|
||||
command,
|
||||
cwd,
|
||||
customConfig,
|
||||
|
||||
Reference in New Issue
Block a user