diff --git a/web/static/css/style.css b/web/static/css/style.css
index 6cd1fb3f..5900c44c 100644
--- a/web/static/css/style.css
+++ b/web/static/css/style.css
@@ -5556,6 +5556,80 @@ header {
padding-bottom: 0;
}
+/* Skill 包内文件树:区分不可点击的文件夹与可点击的文件 */
+#skill-package-tree {
+ flex: 0 0 240px;
+ max-height: 440px;
+ overflow: auto;
+ border: 1px solid var(--border-color);
+ border-radius: 6px;
+ padding: 6px 4px;
+ font-size: 13px;
+ line-height: 1.4;
+}
+
+.skill-package-tree-hint {
+ display: block;
+ font-size: 12px;
+ color: var(--text-muted);
+ margin: 4px 0 8px;
+ line-height: 1.45;
+}
+
+.skill-tree-row {
+ display: flex;
+ align-items: flex-start;
+ gap: 6px;
+ padding: 5px 8px;
+ border-radius: 4px;
+ margin-bottom: 1px;
+ min-width: 0;
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
+ font-size: 12px;
+ word-break: break-all;
+ line-height: 1.35;
+}
+
+.skill-tree-dir {
+ color: var(--text-muted);
+ cursor: default;
+ user-select: none;
+ font-weight: 500;
+ opacity: 0.88;
+}
+
+.skill-tree-dir .skill-tree-icon {
+ opacity: 0.65;
+}
+
+.skill-tree-file {
+ color: var(--text-primary);
+ cursor: pointer;
+ transition: background 0.15s ease;
+}
+
+.skill-tree-file:hover {
+ background: rgba(0, 102, 255, 0.08);
+}
+
+.skill-tree-file.is-selected {
+ font-weight: 600;
+ background: rgba(99, 102, 241, 0.12);
+ color: var(--accent-color);
+}
+
+.skill-tree-icon {
+ flex-shrink: 0;
+ width: 1.15em;
+ text-align: center;
+ line-height: 1.35;
+}
+
+.skill-tree-label {
+ min-width: 0;
+ flex: 1;
+}
+
.pagination-fixed {
background: var(--bg-primary);
margin-top: 0;
diff --git a/web/static/i18n/en-US.json b/web/static/i18n/en-US.json
index 894eec8c..d1a40773 100644
--- a/web/static/i18n/en-US.json
+++ b/web/static/i18n/en-US.json
@@ -2257,6 +2257,9 @@
"descriptionPlaceholder": "Short description",
"descriptionHint": "Maps to the description field in SKILL.md YAML (when creating/editing SKILL.md)",
"packageFiles": "Package files",
+ "packageFilesHint": "Click a file to edit; folders are labels only and cannot be opened",
+ "folderHint": "Folder (not editable)",
+ "clickToEdit": "Click to edit this file",
"editingFile": "Editing",
"newFile": "New file",
"newFilePlaceholder": "Relative path, e.g. FORMS.md or scripts/extra.sh",
diff --git a/web/static/i18n/zh-CN.json b/web/static/i18n/zh-CN.json
index 129da128..616472a9 100644
--- a/web/static/i18n/zh-CN.json
+++ b/web/static/i18n/zh-CN.json
@@ -2246,6 +2246,9 @@
"descriptionPlaceholder": "Skill的简短描述",
"descriptionHint": "对应 SKILL.md 中 YAML 的 description 字段(创建/编辑 SKILL.md 时使用)",
"packageFiles": "包内文件",
+ "packageFilesHint": "点击文件进行编辑;文件夹仅作分组展示,不可点击",
+ "folderHint": "文件夹(不可编辑)",
+ "clickToEdit": "点击编辑此文件",
"editingFile": "正在编辑",
"newFile": "新建文件",
"newFilePlaceholder": "新文件路径,如 FORMS.md 或 scripts/extra.sh",
diff --git a/web/static/js/monitor.js b/web/static/js/monitor.js
index 2cc3ec96..84089de5 100644
--- a/web/static/js/monitor.js
+++ b/web/static/js/monitor.js
@@ -3637,10 +3637,15 @@ function buildMcpTimelineSvg(points, rangeKey) {
const tickIdx = points.length <= 2
? points.map((_, i) => i)
: [0, Math.floor((points.length - 1) / 2), points.length - 1];
- const xLabels = tickIdx.map((idx) => {
+ const xLabels = tickIdx.map((idx, ti) => {
const c = coords[idx];
const label = formatMcpTimelineLabel(c.p.t, rangeKey, locale);
- return `