@skillfm/local 2.0.4 → 2.0.6
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/agent-hints.d.ts.map +1 -1
- package/dist/agent-hints.js +29 -14
- package/dist/agent-hints.js.map +1 -1
- package/dist/doctor.d.ts +26 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +184 -0
- package/dist/doctor.js.map +1 -1
- package/dist/guard/bin.js +0 -0
- package/dist/guard/cli.d.ts.map +1 -1
- package/dist/guard/cli.js +26 -0
- package/dist/guard/cli.js.map +1 -1
- package/dist/harness/kernels/deny-pipeline.d.ts +21 -0
- package/dist/harness/kernels/deny-pipeline.d.ts.map +1 -0
- package/dist/harness/kernels/deny-pipeline.js +225 -0
- package/dist/harness/kernels/deny-pipeline.js.map +1 -0
- package/dist/harness/kernels/hook-file.d.ts +16 -0
- package/dist/harness/kernels/hook-file.d.ts.map +1 -0
- package/dist/harness/kernels/hook-file.js +229 -0
- package/dist/harness/kernels/hook-file.js.map +1 -0
- package/dist/harness/kernels/json-merge.d.ts +45 -0
- package/dist/harness/kernels/json-merge.d.ts.map +1 -0
- package/dist/harness/kernels/json-merge.js +123 -0
- package/dist/harness/kernels/json-merge.js.map +1 -0
- package/dist/harness/kernels/mcp-only.d.ts +23 -0
- package/dist/harness/kernels/mcp-only.d.ts.map +1 -0
- package/dist/harness/kernels/mcp-only.js +215 -0
- package/dist/harness/kernels/mcp-only.js.map +1 -0
- package/dist/harness/kernels/protocol-reject.d.ts +18 -0
- package/dist/harness/kernels/protocol-reject.d.ts.map +1 -0
- package/dist/harness/kernels/protocol-reject.js +117 -0
- package/dist/harness/kernels/protocol-reject.js.map +1 -0
- package/dist/harness/kernels/registry.d.ts +56 -0
- package/dist/harness/kernels/registry.d.ts.map +1 -0
- package/dist/harness/kernels/registry.js +139 -0
- package/dist/harness/kernels/registry.js.map +1 -0
- package/dist/harness/kernels/types.d.ts +86 -0
- package/dist/harness/kernels/types.d.ts.map +1 -0
- package/dist/harness/kernels/types.js +21 -0
- package/dist/harness/kernels/types.js.map +1 -0
- package/dist/index.js +467 -19
- package/dist/index.js.map +1 -1
- package/dist/mcp-output/builder.d.ts +24 -0
- package/dist/mcp-output/builder.d.ts.map +1 -0
- package/dist/mcp-output/builder.js +99 -0
- package/dist/mcp-output/builder.js.map +1 -0
- package/dist/mcp-output/deny-review.d.ts +64 -0
- package/dist/mcp-output/deny-review.d.ts.map +1 -0
- package/dist/mcp-output/deny-review.js +212 -0
- package/dist/mcp-output/deny-review.js.map +1 -0
- package/dist/mcp-output/types.d.ts +64 -0
- package/dist/mcp-output/types.d.ts.map +1 -0
- package/dist/mcp-output/types.js +21 -0
- package/dist/mcp-output/types.js.map +1 -0
- package/dist/skill-md/template.d.ts +30 -0
- package/dist/skill-md/template.d.ts.map +1 -0
- package/dist/skill-md/template.js +194 -0
- package/dist/skill-md/template.js.map +1 -0
- package/dist/skill-md/writer.d.ts +30 -0
- package/dist/skill-md/writer.d.ts.map +1 -0
- package/dist/skill-md/writer.js +129 -0
- package/dist/skill-md/writer.js.map +1 -0
- package/package.json +3 -2
- package/dist/lang.d.ts +0 -21
- package/dist/lang.d.ts.map +0 -1
- package/dist/lang.js +0 -62
- package/dist/lang.js.map +0 -1
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BSO M9 v0.3 — Layer 3 共用工具:JSON 文件 idempotent merge + backup
|
|
3
|
+
*
|
|
4
|
+
* 抽出原 writers.ts mergeClaudeSettings 中的通用模式,让 hook-file /
|
|
5
|
+
* deny-pipeline / mcp-only 三个 kernel 共享一套逻辑。
|
|
6
|
+
*
|
|
7
|
+
* 行为:
|
|
8
|
+
* - 文件不存在 → 创建,action='created'
|
|
9
|
+
* - 文件存在 → backup 到 ~/.skillfm/backups/<ts>/,深度合并 patch
|
|
10
|
+
* - 已注册(marker 命中)→ skip,action='already-registered'
|
|
11
|
+
* - 文件不是合法 JSON → 抛 SKILLFM.HARNESS.PARSE_FAILED
|
|
12
|
+
*/
|
|
13
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, } from 'node:fs';
|
|
14
|
+
import { dirname } from 'node:path';
|
|
15
|
+
import { backupFileBeforeWrite } from '../../soul-security.js';
|
|
16
|
+
import { HarnessWriterError } from '../writers.js';
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// 主入口
|
|
19
|
+
// ============================================================================
|
|
20
|
+
export function mergeJsonFile(opts) {
|
|
21
|
+
const { filePath, isAlreadyRegistered, mergePatch, dryRun } = opts;
|
|
22
|
+
const existed = existsSync(filePath);
|
|
23
|
+
const original = existed ? readFileSync(filePath, 'utf-8') : '';
|
|
24
|
+
let data;
|
|
25
|
+
if (existed && original.trim()) {
|
|
26
|
+
try {
|
|
27
|
+
const parsed = JSON.parse(original);
|
|
28
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
29
|
+
data = parsed;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
throw new Error('top-level must be object');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
throw new HarnessWriterError('SKILLFM.HARNESS.PARSE_FAILED', `${filePath} 不是合法 JSON object: ${err.message}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
data = opts.emptyJson ? opts.emptyJson() : {};
|
|
41
|
+
}
|
|
42
|
+
if (isAlreadyRegistered(data)) {
|
|
43
|
+
return {
|
|
44
|
+
path: filePath,
|
|
45
|
+
action: 'already-registered',
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
mergePatch(data);
|
|
49
|
+
if (dryRun) {
|
|
50
|
+
return {
|
|
51
|
+
path: filePath,
|
|
52
|
+
action: existed ? 'merged' : 'created',
|
|
53
|
+
details: 'dry-run, no write',
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
let backupPath;
|
|
57
|
+
if (existed) {
|
|
58
|
+
try {
|
|
59
|
+
const r = backupFileBeforeWrite(filePath, original);
|
|
60
|
+
backupPath = r.backup_path;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// backup 失败不致命
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
68
|
+
}
|
|
69
|
+
const out = JSON.stringify(data, null, 2) + '\n';
|
|
70
|
+
writeFileSync(filePath, out, { encoding: 'utf-8', mode: 0o644 });
|
|
71
|
+
return {
|
|
72
|
+
path: filePath,
|
|
73
|
+
action: existed ? 'merged' : 'created',
|
|
74
|
+
backup: backupPath,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
// ============================================================================
|
|
78
|
+
// 通用 helper:在数组内 idempotent append(按 marker 字符串去重)
|
|
79
|
+
// ============================================================================
|
|
80
|
+
/**
|
|
81
|
+
* 检查 array 中是否已有任何 entry 的 stringify 含 marker(粗粒度去重)。
|
|
82
|
+
*/
|
|
83
|
+
export function arrayHasMarker(array, marker) {
|
|
84
|
+
if (!Array.isArray(array))
|
|
85
|
+
return false;
|
|
86
|
+
return array.some((item) => {
|
|
87
|
+
try {
|
|
88
|
+
return JSON.stringify(item).includes(marker);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Ensure path `data[k1][k2]...` exists as object, return innermost ref.
|
|
97
|
+
*/
|
|
98
|
+
export function ensureObjectPath(data, ...keys) {
|
|
99
|
+
let cur = data;
|
|
100
|
+
for (const k of keys) {
|
|
101
|
+
if (!cur[k] || typeof cur[k] !== 'object' || Array.isArray(cur[k])) {
|
|
102
|
+
cur[k] = {};
|
|
103
|
+
}
|
|
104
|
+
cur = cur[k];
|
|
105
|
+
}
|
|
106
|
+
return cur;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Ensure path `data[k1][k2]...` exists as array, return ref.
|
|
110
|
+
*/
|
|
111
|
+
export function ensureArrayPath(data, ...keys) {
|
|
112
|
+
if (keys.length === 0) {
|
|
113
|
+
throw new Error('ensureArrayPath requires at least one key');
|
|
114
|
+
}
|
|
115
|
+
const last = keys[keys.length - 1];
|
|
116
|
+
const head = keys.slice(0, -1);
|
|
117
|
+
const parent = head.length > 0 ? ensureObjectPath(data, ...head) : data;
|
|
118
|
+
if (!Array.isArray(parent[last])) {
|
|
119
|
+
parent[last] = [];
|
|
120
|
+
}
|
|
121
|
+
return parent[last];
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=json-merge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-merge.js","sourceRoot":"","sources":["../../../src/harness/kernels/json-merge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BSO M9 v0.3 — KernelC: mcp-only
|
|
3
|
+
*
|
|
4
|
+
* Refs:
|
|
5
|
+
* - docs/prd/PRD-BSO-M9-HARNESS-HOOKS.md §3.4.2 KernelC
|
|
6
|
+
* - docs/research/EMERGING-AGENT-PRODUCTS-2026-04-19.md Cat B
|
|
7
|
+
*
|
|
8
|
+
* 覆盖:Claude Desktop / 5ire / Tome / Witsy
|
|
9
|
+
* 共同模式:host 不支持 PreToolUse hook,但所有 MCP tool 调用必经 SkillFM
|
|
10
|
+
* MCP server → sidecar。强制力**完全来自 Layer 2**(M9.5 MCP Protocol-Reject)。
|
|
11
|
+
*
|
|
12
|
+
* 安装动作:仅注册 SkillFM MCP server 到 host config。
|
|
13
|
+
* 强制力评估:Layer 2 上线前 = observe-only;Layer 2 上线后 = protocol-fallback。
|
|
14
|
+
*/
|
|
15
|
+
import type { HostInfo, KernelAdapter } from './types.js';
|
|
16
|
+
export declare const mcpOnlyAdapter: KernelAdapter;
|
|
17
|
+
/**
|
|
18
|
+
* 全候选扫描:对所有 mcp-only 目标做存在性探测。
|
|
19
|
+
* `skillfm init` 默认走 detector 命中的 host;但用户 desktop 可能同时装 5ire+Witsy
|
|
20
|
+
* 等多个 client。提供本工具让 doctor / `skillfm init --scan-mcp-hosts` 用。
|
|
21
|
+
*/
|
|
22
|
+
export declare function scanMcpOnlyHosts(): HostInfo[];
|
|
23
|
+
//# sourceMappingURL=mcp-only.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-only.d.ts","sourceRoot":"","sources":["../../../src/harness/kernels/mcp-only.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AASH,OAAO,KAAK,EAGV,QAAQ,EAGR,aAAa,EACd,MAAM,YAAY,CAAC;AA8HpB,eAAO,MAAM,cAAc,EAAE,aA2F5B,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,QAAQ,EAAE,CAM7C"}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BSO M9 v0.3 — KernelC: mcp-only
|
|
3
|
+
*
|
|
4
|
+
* Refs:
|
|
5
|
+
* - docs/prd/PRD-BSO-M9-HARNESS-HOOKS.md §3.4.2 KernelC
|
|
6
|
+
* - docs/research/EMERGING-AGENT-PRODUCTS-2026-04-19.md Cat B
|
|
7
|
+
*
|
|
8
|
+
* 覆盖:Claude Desktop / 5ire / Tome / Witsy
|
|
9
|
+
* 共同模式:host 不支持 PreToolUse hook,但所有 MCP tool 调用必经 SkillFM
|
|
10
|
+
* MCP server → sidecar。强制力**完全来自 Layer 2**(M9.5 MCP Protocol-Reject)。
|
|
11
|
+
*
|
|
12
|
+
* 安装动作:仅注册 SkillFM MCP server 到 host config。
|
|
13
|
+
* 强制力评估:Layer 2 上线前 = observe-only;Layer 2 上线后 = protocol-fallback。
|
|
14
|
+
*/
|
|
15
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
16
|
+
import { homedir, platform } from 'node:os';
|
|
17
|
+
import { join } from 'node:path';
|
|
18
|
+
import { ensureObjectPath, mergeJsonFile, } from './json-merge.js';
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// 平台路径解析
|
|
21
|
+
// ============================================================================
|
|
22
|
+
function platformPath(spec) {
|
|
23
|
+
const home = homedir();
|
|
24
|
+
const pl = platform();
|
|
25
|
+
const get = (s) => s
|
|
26
|
+
? s
|
|
27
|
+
.replace(/^~\//, `${home}/`)
|
|
28
|
+
.replace(/%APPDATA%/g, process.env.APPDATA || join(home, 'AppData', 'Roaming'))
|
|
29
|
+
: null;
|
|
30
|
+
if (pl === 'darwin')
|
|
31
|
+
return get(spec.darwin);
|
|
32
|
+
if (pl === 'win32')
|
|
33
|
+
return get(spec.win32);
|
|
34
|
+
return get(spec.linux);
|
|
35
|
+
}
|
|
36
|
+
const TARGETS = [
|
|
37
|
+
// --------------------------------------------------------------------------
|
|
38
|
+
// Anthropic Claude Desktop
|
|
39
|
+
// ~/Library/Application Support/Claude/claude_desktop_config.json
|
|
40
|
+
// --------------------------------------------------------------------------
|
|
41
|
+
{
|
|
42
|
+
host: 'claude-desktop',
|
|
43
|
+
configPath: () => platformPath({
|
|
44
|
+
darwin: '~/Library/Application Support/Claude/claude_desktop_config.json',
|
|
45
|
+
win32: '%APPDATA%/Claude/claude_desktop_config.json',
|
|
46
|
+
linux: '~/.config/Claude/claude_desktop_config.json',
|
|
47
|
+
}),
|
|
48
|
+
schemaKey: 'mcpServers',
|
|
49
|
+
},
|
|
50
|
+
// --------------------------------------------------------------------------
|
|
51
|
+
// 5ire(cross-platform desktop AI assistant)
|
|
52
|
+
// ~/.5ire/mcp.json (schema 类似 Claude Desktop)
|
|
53
|
+
// --------------------------------------------------------------------------
|
|
54
|
+
{
|
|
55
|
+
host: '5ire',
|
|
56
|
+
configPath: () => platformPath({
|
|
57
|
+
darwin: '~/.5ire/mcp.json',
|
|
58
|
+
win32: '~/.5ire/mcp.json',
|
|
59
|
+
linux: '~/.5ire/mcp.json',
|
|
60
|
+
}),
|
|
61
|
+
schemaKey: 'mcpServers',
|
|
62
|
+
},
|
|
63
|
+
// --------------------------------------------------------------------------
|
|
64
|
+
// Tome(open-source desktop app + Ollama + MCP)
|
|
65
|
+
// ~/.config/tome/mcp.json
|
|
66
|
+
// --------------------------------------------------------------------------
|
|
67
|
+
{
|
|
68
|
+
host: 'tome',
|
|
69
|
+
configPath: () => platformPath({
|
|
70
|
+
darwin: '~/Library/Application Support/tome/mcp.json',
|
|
71
|
+
win32: '%APPDATA%/tome/mcp.json',
|
|
72
|
+
linux: '~/.config/tome/mcp.json',
|
|
73
|
+
}),
|
|
74
|
+
schemaKey: 'mcpServers',
|
|
75
|
+
},
|
|
76
|
+
// --------------------------------------------------------------------------
|
|
77
|
+
// Witsy(universal MCP client)
|
|
78
|
+
// ~/.config/witsy/mcp.json
|
|
79
|
+
// --------------------------------------------------------------------------
|
|
80
|
+
{
|
|
81
|
+
host: 'witsy',
|
|
82
|
+
configPath: () => platformPath({
|
|
83
|
+
darwin: '~/Library/Application Support/witsy/mcp.json',
|
|
84
|
+
win32: '%APPDATA%/witsy/mcp.json',
|
|
85
|
+
linux: '~/.config/witsy/mcp.json',
|
|
86
|
+
}),
|
|
87
|
+
schemaKey: 'mcpServers',
|
|
88
|
+
},
|
|
89
|
+
];
|
|
90
|
+
const SUPPORTED = ['claude-desktop', '5ire', 'tome', 'witsy'];
|
|
91
|
+
// ============================================================================
|
|
92
|
+
// MCP server 配置(统一)
|
|
93
|
+
// ============================================================================
|
|
94
|
+
const SKILLFM_MCP_BRIDGE_BIN = 'skillfm-mcp-bridge';
|
|
95
|
+
function buildMcpRegistrationPatch(filePath, schemaKey) {
|
|
96
|
+
return {
|
|
97
|
+
filePath,
|
|
98
|
+
emptyJson: () => ({}),
|
|
99
|
+
isAlreadyRegistered: (data) => {
|
|
100
|
+
const servers = data[schemaKey];
|
|
101
|
+
return Boolean(servers?.skillfm);
|
|
102
|
+
},
|
|
103
|
+
mergePatch: (data) => {
|
|
104
|
+
const servers = ensureObjectPath(data, schemaKey);
|
|
105
|
+
servers.skillfm = {
|
|
106
|
+
command: SKILLFM_MCP_BRIDGE_BIN,
|
|
107
|
+
args: [],
|
|
108
|
+
env: {},
|
|
109
|
+
};
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
// ============================================================================
|
|
114
|
+
// Adapter
|
|
115
|
+
// ============================================================================
|
|
116
|
+
export const mcpOnlyAdapter = {
|
|
117
|
+
kind: 'mcp-only',
|
|
118
|
+
supportedHosts: SUPPORTED,
|
|
119
|
+
matches(host) {
|
|
120
|
+
return SUPPORTED.includes(host.host);
|
|
121
|
+
},
|
|
122
|
+
async install(ctx) {
|
|
123
|
+
const tgt = TARGETS.find((t) => t.host === ctx.host.host);
|
|
124
|
+
if (!tgt) {
|
|
125
|
+
return {
|
|
126
|
+
kernel: 'mcp-only',
|
|
127
|
+
host: ctx.host.host,
|
|
128
|
+
files: [],
|
|
129
|
+
warnings: [`mcp-only: unsupported host ${ctx.host.host}`],
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
const configPath = tgt.configPath();
|
|
133
|
+
if (!configPath) {
|
|
134
|
+
return {
|
|
135
|
+
kernel: 'mcp-only',
|
|
136
|
+
host: ctx.host.host,
|
|
137
|
+
files: [],
|
|
138
|
+
warnings: [`mcp-only: 当前平台无 ${ctx.host.host} 配置路径`],
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
const installed = mergeJsonFile({
|
|
142
|
+
...buildMcpRegistrationPatch(configPath, tgt.schemaKey),
|
|
143
|
+
dryRun: !ctx.apply,
|
|
144
|
+
});
|
|
145
|
+
return {
|
|
146
|
+
kernel: 'mcp-only',
|
|
147
|
+
host: ctx.host.host,
|
|
148
|
+
files: [installed],
|
|
149
|
+
warnings: [
|
|
150
|
+
'强制力依赖 Layer 2 (MCP Protocol-Reject) — 确认 sidecar 输出层 ≥ v2 (URLElicitationRequiredError + isError 双发)',
|
|
151
|
+
],
|
|
152
|
+
};
|
|
153
|
+
},
|
|
154
|
+
async uninstall(ctx) {
|
|
155
|
+
return {
|
|
156
|
+
kernel: 'mcp-only',
|
|
157
|
+
host: ctx.host.host,
|
|
158
|
+
files: [],
|
|
159
|
+
warnings: ['完整 uninstall 未实现;从 ~/.skillfm/backups/<最近 ts>/ 恢复 host config'],
|
|
160
|
+
};
|
|
161
|
+
},
|
|
162
|
+
async diagnose(ctx) {
|
|
163
|
+
const tgt = TARGETS.find((t) => t.host === ctx.host.host);
|
|
164
|
+
if (!tgt) {
|
|
165
|
+
return {
|
|
166
|
+
kernel: 'mcp-only',
|
|
167
|
+
host: ctx.host.host,
|
|
168
|
+
level: 'absent',
|
|
169
|
+
checks: [{ name: 'host-supported', ok: false }],
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
const configPath = tgt.configPath();
|
|
173
|
+
if (!configPath || !existsSync(configPath)) {
|
|
174
|
+
return {
|
|
175
|
+
kernel: 'mcp-only',
|
|
176
|
+
host: ctx.host.host,
|
|
177
|
+
level: 'absent',
|
|
178
|
+
checks: [
|
|
179
|
+
{ name: 'config-file-exists', ok: false, detail: configPath || 'unknown' },
|
|
180
|
+
],
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
let registered = false;
|
|
184
|
+
try {
|
|
185
|
+
const raw = readFileSync(configPath, 'utf-8');
|
|
186
|
+
registered = raw.includes('skillfm');
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
// ignore
|
|
190
|
+
}
|
|
191
|
+
return {
|
|
192
|
+
kernel: 'mcp-only',
|
|
193
|
+
host: ctx.host.host,
|
|
194
|
+
level: registered ? 'protocol-fallback' : 'absent',
|
|
195
|
+
checks: [
|
|
196
|
+
{ name: 'config-file-exists', ok: true, detail: configPath },
|
|
197
|
+
{ name: 'skillfm-mcp-server-registered', ok: registered },
|
|
198
|
+
],
|
|
199
|
+
};
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
/**
|
|
203
|
+
* 全候选扫描:对所有 mcp-only 目标做存在性探测。
|
|
204
|
+
* `skillfm init` 默认走 detector 命中的 host;但用户 desktop 可能同时装 5ire+Witsy
|
|
205
|
+
* 等多个 client。提供本工具让 doctor / `skillfm init --scan-mcp-hosts` 用。
|
|
206
|
+
*/
|
|
207
|
+
export function scanMcpOnlyHosts() {
|
|
208
|
+
return TARGETS.flatMap((t) => {
|
|
209
|
+
const p = t.configPath();
|
|
210
|
+
if (!p || !existsSync(p))
|
|
211
|
+
return [];
|
|
212
|
+
return [{ host: t.host, source: 'scanned', reason: `config exists: ${p}` }];
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
//# sourceMappingURL=mcp-only.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-only.js","sourceRoot":"","sources":["../../../src/harness/kernels/mcp-only.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BSO M9 v0.3 — KernelD: protocol-reject (Layer 2 联动诊断占位)
|
|
3
|
+
*
|
|
4
|
+
* Refs:
|
|
5
|
+
* - docs/prd/PRD-BSO-M9-HARNESS-HOOKS.md §3.4.2 KernelD + §3.3
|
|
6
|
+
*
|
|
7
|
+
* 不是独立 install adapter — Layer 2 协议级 reject 在 sidecar 输出层实现,
|
|
8
|
+
* 不写任何 host 配置。本 adapter 只提供诊断接口让 doctor 单独检查
|
|
9
|
+
* "Layer 2 是否就绪"。
|
|
10
|
+
*
|
|
11
|
+
* 检查项:
|
|
12
|
+
* 1. sidecar 在跑 + /internal/mcp/probe 200
|
|
13
|
+
* 2. probe 响应版本 ≥ v2(URLElicitationRequiredError + isError 双发)
|
|
14
|
+
* 3. /deny-review/:task_id 端点可达(返回 200 或 404 都算可达;500 算挂)
|
|
15
|
+
*/
|
|
16
|
+
import type { KernelAdapter } from './types.js';
|
|
17
|
+
export declare const protocolRejectAdapter: KernelAdapter;
|
|
18
|
+
//# sourceMappingURL=protocol-reject.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol-reject.d.ts","sourceRoot":"","sources":["../../../src/harness/kernels/protocol-reject.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAIV,aAAa,EACd,MAAM,YAAY,CAAC;AAoEpB,eAAO,MAAM,qBAAqB,EAAE,aAuDnC,CAAC"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BSO M9 v0.3 — KernelD: protocol-reject (Layer 2 联动诊断占位)
|
|
3
|
+
*
|
|
4
|
+
* Refs:
|
|
5
|
+
* - docs/prd/PRD-BSO-M9-HARNESS-HOOKS.md §3.4.2 KernelD + §3.3
|
|
6
|
+
*
|
|
7
|
+
* 不是独立 install adapter — Layer 2 协议级 reject 在 sidecar 输出层实现,
|
|
8
|
+
* 不写任何 host 配置。本 adapter 只提供诊断接口让 doctor 单独检查
|
|
9
|
+
* "Layer 2 是否就绪"。
|
|
10
|
+
*
|
|
11
|
+
* 检查项:
|
|
12
|
+
* 1. sidecar 在跑 + /internal/mcp/probe 200
|
|
13
|
+
* 2. probe 响应版本 ≥ v2(URLElicitationRequiredError + isError 双发)
|
|
14
|
+
* 3. /deny-review/:task_id 端点可达(返回 200 或 404 都算可达;500 算挂)
|
|
15
|
+
*/
|
|
16
|
+
async function probeSidecarMcpOutput() {
|
|
17
|
+
const { readSidecarEndpoint } = await import('../../guard/sidecar-client.js');
|
|
18
|
+
const endpoint = readSidecarEndpoint();
|
|
19
|
+
if (!endpoint) {
|
|
20
|
+
return { ok: false, detail: 'sidecar 未运行' };
|
|
21
|
+
}
|
|
22
|
+
try {
|
|
23
|
+
const url = `${endpoint.url}/internal/mcp/probe`;
|
|
24
|
+
const ctrl = new AbortController();
|
|
25
|
+
const timer = setTimeout(() => ctrl.abort(), 1000);
|
|
26
|
+
const r = await fetch(url, { signal: ctrl.signal }).catch((err) => {
|
|
27
|
+
throw err;
|
|
28
|
+
});
|
|
29
|
+
clearTimeout(timer);
|
|
30
|
+
if (!r.ok) {
|
|
31
|
+
return { ok: false, detail: `probe 返回 ${r.status}` };
|
|
32
|
+
}
|
|
33
|
+
const body = (await r.json());
|
|
34
|
+
return {
|
|
35
|
+
ok: body.output_version !== undefined,
|
|
36
|
+
outputVersion: body.output_version,
|
|
37
|
+
features: body.features,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
return { ok: false, detail: `probe 失败: ${err.message}` };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
async function probeDenyReviewEndpoint() {
|
|
45
|
+
const { readSidecarEndpoint } = await import('../../guard/sidecar-client.js');
|
|
46
|
+
const endpoint = readSidecarEndpoint();
|
|
47
|
+
if (!endpoint)
|
|
48
|
+
return { ok: false, detail: 'sidecar 未运行' };
|
|
49
|
+
try {
|
|
50
|
+
const url = `${endpoint.url}/deny-review/__probe__`;
|
|
51
|
+
const ctrl = new AbortController();
|
|
52
|
+
const timer = setTimeout(() => ctrl.abort(), 1000);
|
|
53
|
+
const r = await fetch(url, { signal: ctrl.signal }).catch((err) => {
|
|
54
|
+
throw err;
|
|
55
|
+
});
|
|
56
|
+
clearTimeout(timer);
|
|
57
|
+
// 200 / 404 / 410 都算"端点存在";500 算挂
|
|
58
|
+
if (r.status >= 500)
|
|
59
|
+
return { ok: false, detail: `端点 5xx: ${r.status}` };
|
|
60
|
+
return { ok: true, detail: `${r.status}` };
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
return { ok: false, detail: `请求失败: ${err.message}` };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// ============================================================================
|
|
67
|
+
// Adapter
|
|
68
|
+
// ============================================================================
|
|
69
|
+
export const protocolRejectAdapter = {
|
|
70
|
+
kind: 'protocol-reject',
|
|
71
|
+
supportedHosts: [], // 无独立 host
|
|
72
|
+
matches() {
|
|
73
|
+
return false; // 不参与 install 装配,只走 diagnose
|
|
74
|
+
},
|
|
75
|
+
async install() {
|
|
76
|
+
return {
|
|
77
|
+
kernel: 'protocol-reject',
|
|
78
|
+
host: 'unknown',
|
|
79
|
+
files: [],
|
|
80
|
+
warnings: ['protocol-reject 不需要 install — 在 sidecar 输出层实现'],
|
|
81
|
+
};
|
|
82
|
+
},
|
|
83
|
+
async uninstall() {
|
|
84
|
+
return {
|
|
85
|
+
kernel: 'protocol-reject',
|
|
86
|
+
host: 'unknown',
|
|
87
|
+
files: [],
|
|
88
|
+
warnings: ['protocol-reject 无 uninstall'],
|
|
89
|
+
};
|
|
90
|
+
},
|
|
91
|
+
async diagnose(_ctx) {
|
|
92
|
+
const probe = await probeSidecarMcpOutput();
|
|
93
|
+
const review = await probeDenyReviewEndpoint();
|
|
94
|
+
const checks = [
|
|
95
|
+
{
|
|
96
|
+
name: 'sidecar-mcp-probe',
|
|
97
|
+
ok: probe.ok,
|
|
98
|
+
detail: probe.outputVersion
|
|
99
|
+
? `output_version=${probe.outputVersion} features=${(probe.features || []).join(',')}`
|
|
100
|
+
: probe.detail,
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: 'deny-review-endpoint',
|
|
104
|
+
ok: review.ok,
|
|
105
|
+
detail: review.detail,
|
|
106
|
+
},
|
|
107
|
+
];
|
|
108
|
+
const supportsV2 = probe.ok && (probe.outputVersion === 'v2' || (probe.features || []).includes('elicitation'));
|
|
109
|
+
return {
|
|
110
|
+
kernel: 'protocol-reject',
|
|
111
|
+
host: 'unknown',
|
|
112
|
+
level: supportsV2 ? 'strong' : probe.ok ? 'soft' : 'absent',
|
|
113
|
+
checks,
|
|
114
|
+
};
|
|
115
|
+
},
|
|
116
|
+
};
|
|
117
|
+
//# sourceMappingURL=protocol-reject.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol-reject.js","sourceRoot":"","sources":["../../../src/harness/kernels/protocol-reject.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BSO M9 v0.3 — Layer 3 KernelAdapter 注册表 + 装配
|
|
3
|
+
*
|
|
4
|
+
* Refs:
|
|
5
|
+
* - docs/prd/PRD-BSO-M9-HARNESS-HOOKS.md §3.4.3
|
|
6
|
+
*
|
|
7
|
+
* `installAll(host)`:根据 host 命中所有匹配的 adapter,并行 install。
|
|
8
|
+
* 多内核共存策略:M9 P0 取强制力最强的一类(hook-file > deny-pipeline > mcp-only)。
|
|
9
|
+
*
|
|
10
|
+
* 用法:
|
|
11
|
+
* ```ts
|
|
12
|
+
* const host = detectHostInfo();
|
|
13
|
+
* const report = await installAll({ host, cwd: process.cwd(), apply: true });
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
import { type Harness } from '../detector.js';
|
|
17
|
+
import type { DiagnoseResult, HostId, HostInfo, InstallResult, KernelAdapter, KernelType } from './types.js';
|
|
18
|
+
export declare const REGISTRY: KernelAdapter[];
|
|
19
|
+
export declare const ALL_ADAPTERS: KernelAdapter[];
|
|
20
|
+
export declare function getAdapter(kind: KernelType): KernelAdapter | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* detectHarness 只识别 v0.2 的 5 个 IDE/CLI host;v0.3 新增的 mcp-only host
|
|
23
|
+
* (Claude Desktop / 5ire / Tome / Witsy)需要走配置文件扫描。
|
|
24
|
+
*
|
|
25
|
+
* 策略:
|
|
26
|
+
* 1. detector 命中 → 返回该 host
|
|
27
|
+
* 2. detector unknown → 扫 mcp-only 候选;若有命中且唯一 → 返回该 host
|
|
28
|
+
* 3. 多个候选或无候选 → 返回 unknown
|
|
29
|
+
*/
|
|
30
|
+
export declare function detectPrimaryHost(): HostInfo;
|
|
31
|
+
export interface InstallAllOptions {
|
|
32
|
+
host: HostInfo;
|
|
33
|
+
cwd: string;
|
|
34
|
+
/** 真正落盘 */
|
|
35
|
+
apply: boolean;
|
|
36
|
+
/** 强制走某个 kernel(覆盖 matches 判断),用于测试 / 用户显式 --kernel=<type> */
|
|
37
|
+
forceKernel?: KernelType;
|
|
38
|
+
/** mcp-only 的额外 host 安装(让用户一次给 Claude Desktop + 5ire 同时装) */
|
|
39
|
+
alsoInstallMcpHosts?: HostId[];
|
|
40
|
+
}
|
|
41
|
+
export interface InstallAllReport {
|
|
42
|
+
host: HostInfo;
|
|
43
|
+
/** 命中的 adapter 顺序(强制力降序) */
|
|
44
|
+
matched: KernelType[];
|
|
45
|
+
results: InstallResult[];
|
|
46
|
+
warnings: string[];
|
|
47
|
+
}
|
|
48
|
+
export declare function installAll(opts: InstallAllOptions): Promise<InstallAllReport>;
|
|
49
|
+
export interface DiagnoseAllReport {
|
|
50
|
+
host: HostInfo;
|
|
51
|
+
layer3: DiagnoseResult[];
|
|
52
|
+
layer2: DiagnoseResult;
|
|
53
|
+
}
|
|
54
|
+
export declare function diagnoseAll(host: HostInfo, cwd: string): Promise<DiagnoseAllReport>;
|
|
55
|
+
export declare function harnessToHostId(h: Harness): HostId;
|
|
56
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/harness/kernels/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAiB,KAAK,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAK7D,OAAO,KAAK,EACV,cAAc,EACd,MAAM,EACN,QAAQ,EAER,aAAa,EACb,aAAa,EACb,UAAU,EACX,MAAM,YAAY,CAAC;AAMpB,eAAO,MAAM,QAAQ,EAAE,aAAa,EAKnC,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,aAAa,EAGvC,CAAC;AAEF,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,aAAa,GAAG,SAAS,CAEtE;AAMD;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,IAAI,QAAQ,CA0B5C;AAMD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,QAAQ,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW;IACX,KAAK,EAAE,OAAO,CAAC;IACf,8DAA8D;IAC9D,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB,6DAA6D;IAC7D,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,QAAQ,CAAC;IACf,4BAA4B;IAC5B,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAyDnF;AAMD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAOzF;AAMD,wBAAgB,eAAe,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAElD"}
|