feat(terminal-dashboard): add session name (tag) field for grouping

- Add tag/name input field to CliConfigModal with auto-generation
- Auto-generate format: {tool}-{HHmmss} (e.g., gemini-143052)
- Add regenerate button for quick name changes
- Add i18n keys for new fields (en/zh)

Sessions are now grouped by tag in the sidebar for better organization.
This commit is contained in:
catlog22
2026-02-20 21:56:47 +08:00
parent f8ff9eaa7f
commit 7e5d47fe8d
3 changed files with 69 additions and 3 deletions

View File

@@ -5,7 +5,7 @@
import * as React from 'react';
import { useIntl } from 'react-intl';
import { FolderOpen } from 'lucide-react';
import { FolderOpen, RefreshCw } from 'lucide-react';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/Button';
import { Input } from '@/components/ui/Input';
@@ -37,6 +37,8 @@ export interface CliSessionConfig {
launchMode: LaunchMode;
preferredShell: ShellKind;
workingDir: string;
/** Session tag for grouping (auto-generated if not provided) */
tag: string;
}
export interface CliConfigModalProps {
@@ -58,6 +60,16 @@ const MODEL_OPTIONS: Record<CliTool, string[]> = {
const AUTO_MODEL_VALUE = '__auto__';
/**
* Generate a tag name: {tool}-{HHmmss}
* Example: gemini-143052
*/
function generateTag(tool: CliTool): string {
const now = new Date();
const time = now.toTimeString().slice(0, 8).replace(/:/g, '');
return `${tool}-${time}`;
}
export function CliConfigModal({
isOpen,
onClose,
@@ -74,19 +86,34 @@ export function CliConfigModal({
typeof navigator !== 'undefined' && navigator.platform.toLowerCase().includes('win') ? 'cmd' : 'bash'
);
const [workingDir, setWorkingDir] = React.useState<string>(defaultWorkingDir ?? '');
const [tag, setTag] = React.useState<string>('');
const [isSubmitting, setIsSubmitting] = React.useState(false);
const [error, setError] = React.useState<string | null>(null);
const modelOptions = React.useMemo(() => MODEL_OPTIONS[tool] ?? [], [tool]);
// Generate new tag when modal opens or tool changes
const regenerateTag = React.useCallback(() => {
setTag(generateTag(tool));
}, [tool]);
React.useEffect(() => {
if (!isOpen) return;
// Reset to a safe default each time the modal is opened.
const nextWorkingDir = defaultWorkingDir ?? '';
setWorkingDir(nextWorkingDir);
setError(null);
}, [isOpen, defaultWorkingDir]);
regenerateTag();
}, [isOpen, defaultWorkingDir, regenerateTag]);
// Update tag prefix when tool changes
React.useEffect(() => {
if (tag) {
const suffix = tag.split('-').pop() || '';
setTag(`${tool}-${suffix}`);
}
}, [tool]);
const handleToolChange = (nextTool: string) => {
const next = nextTool as CliTool;
@@ -109,6 +136,8 @@ export function CliConfigModal({
return;
}
const finalTag = tag.trim() || generateTag(tool);
setIsSubmitting(true);
setError(null);
try {
@@ -118,6 +147,7 @@ export function CliConfigModal({
launchMode,
preferredShell,
workingDir: dir,
tag: finalTag,
});
onClose();
} catch (err) {
@@ -139,6 +169,35 @@ export function CliConfigModal({
</DialogHeader>
<div className="space-y-4 py-4">
{/* Tag / Name */}
<div className="space-y-2">
<Label htmlFor="cli-config-tag">
{formatMessage({ id: 'terminalDashboard.cliConfig.tag', defaultMessage: 'Session Name' })}
</Label>
<div className="flex gap-2">
<Input
id="cli-config-tag"
value={tag}
onChange={(e) => setTag(e.target.value)}
placeholder={formatMessage({ id: 'terminalDashboard.cliConfig.tagPlaceholder', defaultMessage: 'e.g., gemini-143052' })}
disabled={isSubmitting}
className="flex-1"
/>
<Button
type="button"
variant="outline"
onClick={regenerateTag}
disabled={isSubmitting}
title={formatMessage({ id: 'terminalDashboard.cliConfig.regenerateTag', defaultMessage: 'Regenerate name' })}
>
<RefreshCw className="w-4 h-4" />
</Button>
</div>
<p className="text-xs text-muted-foreground">
{formatMessage({ id: 'terminalDashboard.cliConfig.tagHint', defaultMessage: 'Auto-generated as {tool}-{time}. Used for grouping sessions.' })}
</p>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
{/* Tool */}
<div className="space-y-2">
@@ -271,4 +330,3 @@ export function CliConfigModal({
}
export default CliConfigModal;

View File

@@ -90,6 +90,10 @@
"cliConfig": {
"title": "Create CLI Session",
"description": "Configure tool, model, mode, shell, and working directory.",
"tag": "Session Name",
"tagPlaceholder": "e.g., gemini-143052",
"tagHint": "Auto-generated as {tool}-{time}. Used for grouping sessions.",
"regenerateTag": "Regenerate name",
"tool": "Tool",
"model": "Model",
"modelAuto": "Auto",

View File

@@ -90,6 +90,10 @@
"cliConfig": {
"title": "创建 CLI 会话",
"description": "配置工具、模型、模式、Shell 与工作目录。",
"tag": "会话名称",
"tagPlaceholder": "例如gemini-143052",
"tagHint": "自动生成格式:{工具}-{时间}。用于会话分组显示。",
"regenerateTag": "重新生成名称",
"tool": "工具",
"model": "模型",
"modelAuto": "自动",