Skip to content

Commit c153b49

Browse files
authored
feat(frontend): add software requirements display for shell types (#259)
* feat(frontend): add software requirements display for shell types Added SoftwareRequirements component to show minimum version requirements for different shell types (ClaudeCode, Agno) when creating or editing shells. This helps users understand environment preparation requirements before validation. Changes: - Created SoftwareRequirements.tsx with version requirement data structure - Integrated component into ShellEdit to display requirements based on selected shell type - Added copy-to-clipboard functionality for check commands - Supports responsive layout (single column on mobile, dual column on desktop) - Added i18n translations for Chinese and English * refactor: Adjust the software requirements order and correct claude-code commands.
1 parent 1aca6e9 commit c153b49

File tree

5 files changed

+182
-8
lines changed

5 files changed

+182
-8
lines changed

executor/agents/image_validator/image_validator_agent.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,6 @@ class ImageValidatorAgent(Agent):
4848
"version_regex": r"(\d+\.\d+\.\d+)",
4949
"min_version": None,
5050
},
51-
{
52-
"name": "sqlite",
53-
"command": "sqlite3 --version",
54-
"version_regex": r"(\d+\.\d+\.\d+)",
55-
"min_version": "3.50.0",
56-
},
5751
{
5852
"name": "python",
5953
"command": "python3 --version",
@@ -68,6 +62,12 @@ class ImageValidatorAgent(Agent):
6862
"version_regex": r"Python (\d+\.\d+\.\d+)",
6963
"min_version": "3.12.0",
7064
},
65+
{
66+
"name": "sqlite",
67+
"command": "sqlite3 --version",
68+
"version_regex": r"(\d+\.\d+\.\d+)",
69+
"min_version": "3.50.0",
70+
}
7171
],
7272
}
7373

frontend/src/features/settings/components/ShellEdit.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {
2626
ValidationStage,
2727
ValidationStatusResponse,
2828
} from '@/apis/shells';
29+
import SoftwareRequirements from './SoftwareRequirements';
2930

3031
// Polling configuration
3132
const POLLING_INTERVAL = 2000; // 2 seconds
@@ -501,6 +502,14 @@ const ShellEdit: React.FC<ShellEditProps> = ({ shell, onClose, toast }) => {
501502
</SelectContent>
502503
</Select>
503504
<p className="text-xs text-text-muted">{t('shells.base_shell_hint')}</p>
505+
506+
{/* Software Requirements Display */}
507+
{baseShellRef && (() => {
508+
const selectedShell = baseShells.find(s => s.name === baseShellRef);
509+
return selectedShell ? (
510+
<SoftwareRequirements shellType={selectedShell.shellType} />
511+
) : null;
512+
})()}
504513
</div>
505514

506515
{/* Base Image */}
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
// SPDX-FileCopyrightText: 2025 Weibo, Inc.
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
'use client';
6+
7+
import React, { useState } from 'react';
8+
import { Button } from '@/components/ui/button';
9+
import { Card } from '@/components/ui/card';
10+
import { Badge } from '@/components/ui/badge';
11+
import { CheckIcon } from '@heroicons/react/24/outline';
12+
import { useTranslation } from '@/hooks/useTranslation';
13+
14+
// Software requirement data structure
15+
export interface SoftwareRequirement {
16+
name: string; // Software name (e.g., node, python, claude-code)
17+
command: string; // Check command (e.g., node --version)
18+
minVersion: string; // Minimum version requirement (e.g., 20.0.0)
19+
versionRegex?: string; // Version extraction regex (optional)
20+
required: boolean; // Whether it's required
21+
description?: string; // Software description (optional)
22+
}
23+
24+
// Shell type to requirements mapping
25+
const shellRequirements: Record<string, SoftwareRequirement[]> = {
26+
ClaudeCode: [
27+
{
28+
name: 'Node.js',
29+
command: 'node --version',
30+
minVersion: '20.0.0',
31+
required: true,
32+
description: 'JavaScript runtime for Claude Code CLI',
33+
},
34+
{
35+
name: 'Python',
36+
command: 'python --version',
37+
minVersion: '3.12.0',
38+
required: true,
39+
description: 'Python interpreter for agent execution',
40+
},
41+
{
42+
name: 'claude-code',
43+
command: 'claude --version',
44+
minVersion: '0.1.0',
45+
required: true,
46+
description: 'Claude Code CLI (recommended)',
47+
},
48+
],
49+
Agno: [
50+
{
51+
name: 'Python',
52+
command: 'python --version',
53+
minVersion: '3.12.0',
54+
required: true,
55+
description: 'Python interpreter for agent execution',
56+
},
57+
{
58+
name: 'SQLite',
59+
command: 'sqlite3 --version',
60+
minVersion: '3.50.0',
61+
required: true,
62+
description: 'Database for local data storage',
63+
},
64+
],
65+
Dify: [],
66+
};
67+
68+
interface SoftwareRequirementsProps {
69+
shellType: string; // Shell type (e.g., ClaudeCode, Agno, Dify)
70+
}
71+
72+
const SoftwareRequirements: React.FC<SoftwareRequirementsProps> = ({ shellType }) => {
73+
const { t } = useTranslation('common');
74+
const [copiedCommand, setCopiedCommand] = useState<string | null>(null);
75+
76+
// Get requirements for the shell type
77+
const requirements = shellRequirements[shellType] || [];
78+
79+
// No requirements to display
80+
if (requirements.length === 0) {
81+
return null;
82+
}
83+
84+
// Copy command to clipboard
85+
const copyCommand = async (command: string) => {
86+
try {
87+
await navigator.clipboard.writeText(command);
88+
setCopiedCommand(command);
89+
setTimeout(() => setCopiedCommand(null), 2000);
90+
} catch (error) {
91+
console.error('Failed to copy command:', error);
92+
}
93+
};
94+
95+
return (
96+
<Card className="mt-4 p-4 bg-surface border-border">
97+
<h3 className="text-base font-medium mb-2 text-text-primary">
98+
{t('shells.software_requirements_title')}
99+
</h3>
100+
<p className="text-xs text-text-muted mb-3">{t('shells.software_requirements_hint')}</p>
101+
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
102+
{requirements.map(req => (
103+
<div
104+
key={req.name}
105+
className="flex flex-col p-3 bg-muted rounded-lg hover:bg-hover transition-colors"
106+
>
107+
<div className="flex items-center justify-between mb-2">
108+
<div className="flex items-center gap-2 min-w-0 flex-1">
109+
{req.required ? (
110+
<Badge variant="error" className="text-xs shrink-0">
111+
{t('shells.required')}
112+
</Badge>
113+
) : (
114+
<Badge variant="secondary" className="text-xs shrink-0">
115+
{t('shells.optional')}
116+
</Badge>
117+
)}
118+
<span className="font-medium text-text-primary truncate">{req.name}</span>
119+
</div>
120+
<span className="text-text-muted text-xs shrink-0 ml-2">{req.minVersion}</span>
121+
</div>
122+
{req.description && <p className="text-xs text-text-muted mb-2">{req.description}</p>}
123+
<div className="flex items-center gap-2">
124+
<code className="text-xs bg-code-bg px-2 py-1 rounded text-text-secondary flex-1 truncate">
125+
{req.command}
126+
</code>
127+
<Button
128+
variant="ghost"
129+
size="sm"
130+
onClick={() => copyCommand(req.command)}
131+
className="shrink-0 h-7 px-2"
132+
title={t('shells.copy_command')}
133+
>
134+
{copiedCommand === req.command ? (
135+
<CheckIcon className="w-4 h-4 text-green-600" />
136+
) : (
137+
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
138+
<path
139+
strokeLinecap="round"
140+
strokeLinejoin="round"
141+
strokeWidth={2}
142+
d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"
143+
/>
144+
</svg>
145+
)}
146+
</Button>
147+
</div>
148+
</div>
149+
))}
150+
</div>
151+
</Card>
152+
);
153+
};
154+
155+
export default SoftwareRequirements;

frontend/src/i18n/locales/en/common.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,11 @@
595595
"base_image_and_shell_required": "Both base image and base shell are required for validation",
596596
"base_shell_not_found": "Selected base shell not found",
597597
"image_not_compatible": "Image is not compatible with the selected shell type"
598-
}
598+
},
599+
"software_requirements_title": "Software Requirements",
600+
"software_requirements_hint": "The following software must be pre-installed in your base image and meet minimum version requirements",
601+
"required": "Required",
602+
"optional": "Optional",
603+
"copy_command": "Copy command"
599604
}
600605
}

frontend/src/i18n/locales/zh-CN/common.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,11 @@
596596
"base_image_and_shell_required": "验证需要同时填写 Base Image 和基础 Shell",
597597
"base_shell_not_found": "未找到所选基础 Shell",
598598
"image_not_compatible": "镜像与所选 Shell 类型不兼容"
599-
}
599+
},
600+
"software_requirements_title": "软件版本要求",
601+
"software_requirements_hint": "以下软件需要在您的 Base Image 中预先安装并满足最低版本要求",
602+
"required": "必需",
603+
"optional": "可选",
604+
"copy_command": "复制命令"
600605
}
601606
}

0 commit comments

Comments
 (0)