@max-null/dsh-skill-mcp-center 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/service.d.ts +9 -0
- package/dist/service.js +39 -10
- package/package.json +1 -1
- package/release-notes.md +20 -0
package/dist/service.d.ts
CHANGED
|
@@ -74,6 +74,15 @@ export interface McpConfig {
|
|
|
74
74
|
url?: string;
|
|
75
75
|
headers?: Record<string, string>;
|
|
76
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Scan one root for SKILL.md entries and parse their frontmatter.
|
|
79
|
+
* @param root - directory to scan; a missing root yields no skills.
|
|
80
|
+
* @param source - discovery source label recorded on every skill found.
|
|
81
|
+
* @param writable - whether the surface may rewrite these SKILL.md files.
|
|
82
|
+
* @param provider - provider label recorded on every skill found.
|
|
83
|
+
* @returns the skills this root contributes, in directory order.
|
|
84
|
+
*/
|
|
85
|
+
export declare function scanSkillRoot(root: string, source: string, writable?: boolean, provider?: string): Promise<SkillView[]>;
|
|
77
86
|
export declare class SkillMcpService extends Service {
|
|
78
87
|
static inject: string[];
|
|
79
88
|
private readonly officialSkillDirs;
|
package/dist/service.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { Service } from '@deepseek-ai/cordis';
|
|
10
10
|
import { existsSync } from 'node:fs';
|
|
11
|
-
import { readdir, readFile, writeFile } from 'node:fs/promises';
|
|
11
|
+
import { readdir, readFile, stat, writeFile } from 'node:fs/promises';
|
|
12
12
|
import { homedir } from 'node:os';
|
|
13
13
|
import { join, sep } from 'node:path';
|
|
14
14
|
import { fileURLToPath } from 'node:url';
|
|
@@ -65,16 +65,45 @@ function ownNodeModules() {
|
|
|
65
65
|
const at = here.lastIndexOf(marker);
|
|
66
66
|
return at < 0 ? null : here.slice(0, at + marker.length - 1);
|
|
67
67
|
}
|
|
68
|
-
/**
|
|
69
|
-
|
|
68
|
+
/**
|
|
69
|
+
* Absolute SKILL.md path for one root entry, or null when the entry is neither
|
|
70
|
+
* a directory nor a Markdown file.
|
|
71
|
+
*
|
|
72
|
+
* `readdir`'s Dirent reports lstat semantics: a Windows directory junction —
|
|
73
|
+
* and equally a POSIX symlink to a directory — is `isDirectory() === false`
|
|
74
|
+
* with `isSymbolicLink() === true`, so the Dirent alone cannot tell a linked
|
|
75
|
+
* directory from a plain file. Only entries the Dirent leaves open reach the
|
|
76
|
+
* `stat` probe, which follows the link to its target type and so keeps the
|
|
77
|
+
* common true-directory case at zero extra syscalls. A broken link fails that
|
|
78
|
+
* probe (ENOENT) and yields null rather than a path nothing can read.
|
|
79
|
+
* @param root - directory being scanned.
|
|
80
|
+
* @param entry - one `readdir(root, { withFileTypes: true })` entry.
|
|
81
|
+
* @returns the SKILL.md path this entry names, or null when it names no skill.
|
|
82
|
+
*/
|
|
83
|
+
async function skillPathFor(root, entry) {
|
|
84
|
+
const full = join(root, entry.name);
|
|
85
|
+
let isDirectory = entry.isDirectory();
|
|
86
|
+
if (!isDirectory && !entry.isFile()) {
|
|
87
|
+
try {
|
|
88
|
+
isDirectory = (await stat(full)).isDirectory();
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return null; // broken link: the target is gone
|
|
92
|
+
}
|
|
93
|
+
}
|
|
70
94
|
if (isDirectory)
|
|
71
|
-
return join(
|
|
72
|
-
|
|
73
|
-
return join(root, name);
|
|
74
|
-
return null;
|
|
95
|
+
return join(full, 'SKILL.md');
|
|
96
|
+
return entry.name.endsWith('.md') ? full : null;
|
|
75
97
|
}
|
|
76
|
-
/**
|
|
77
|
-
|
|
98
|
+
/**
|
|
99
|
+
* Scan one root for SKILL.md entries and parse their frontmatter.
|
|
100
|
+
* @param root - directory to scan; a missing root yields no skills.
|
|
101
|
+
* @param source - discovery source label recorded on every skill found.
|
|
102
|
+
* @param writable - whether the surface may rewrite these SKILL.md files.
|
|
103
|
+
* @param provider - provider label recorded on every skill found.
|
|
104
|
+
* @returns the skills this root contributes, in directory order.
|
|
105
|
+
*/
|
|
106
|
+
export async function scanSkillRoot(root, source, writable = true, provider = 'filesystem') {
|
|
78
107
|
let entries;
|
|
79
108
|
try {
|
|
80
109
|
entries = await readdir(root, { withFileTypes: true });
|
|
@@ -84,7 +113,7 @@ async function scanSkillRoot(root, source, writable = true, provider = 'filesyst
|
|
|
84
113
|
}
|
|
85
114
|
const skills = [];
|
|
86
115
|
for (const entry of entries) {
|
|
87
|
-
const skillPath = skillPathFor(root, entry
|
|
116
|
+
const skillPath = await skillPathFor(root, entry);
|
|
88
117
|
if (skillPath === null)
|
|
89
118
|
continue;
|
|
90
119
|
let text;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@max-null/dsh-skill-mcp-center",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.3",
|
|
4
4
|
"description": "Skill & MCP management center for DeepSeek Harness — manage skills and MCP servers in Settings, live MCP status in the sidebar",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"publishConfig": {
|
package/release-notes.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Release Notes — @max-null/dsh-skill-mcp-center
|
|
2
2
|
|
|
3
|
+
## 0.5.3 (2026-10-02)
|
|
4
|
+
|
|
5
|
+
### 修复
|
|
6
|
+
|
|
7
|
+
- **Windows 下技能列表整体为空**。`~/.dsh/skills` 下的条目是目录 junction 或符号
|
|
8
|
+
链接时,`scanSkillRoot()` 拿 `Dirent.isDirectory()` 当形态判据——而 Dirent 是
|
|
9
|
+
lstat 语义,junction 报 `isDirectory() === false` / `isSymbolicLink() === true`,
|
|
10
|
+
于是 `skillPathFor()` 返回 null,每个链接型技能在 `continue` 处被丢弃。技能本身
|
|
11
|
+
完好可读,只是扫不到,面板上表现为列表为空。
|
|
12
|
+
|
|
13
|
+
判据改为**分层**:Dirent 能明确作答时直接采信(真目录走 `isDirectory()`、真文件
|
|
14
|
+
走 `isFile()`),只有链接与文件系统报 `DT_UNKNOWN` 的形态才跟随一次 `stat`。真
|
|
15
|
+
目录因此仍是零额外系统调用。断链在 `stat` 处失败即跳过,同根其它技能不受影响。
|
|
16
|
+
这不是 Windows 专用分支——junction 与 POSIX 符号链接走同一条路。
|
|
17
|
+
|
|
18
|
+
### 兼容性
|
|
19
|
+
|
|
20
|
+
- 无接口变更:`listSkills()` 的出入参、端点集合与请求信封均未改,只是扫描判据放宽。
|
|
21
|
+
新增 5 条单测覆盖真目录 / `.md` 文件 / 链接指向目录 / 断链 / 非技能条目。
|
|
22
|
+
|
|
3
23
|
## 0.5.2 (2026-09-29)
|
|
4
24
|
|
|
5
25
|
### 变更
|