@harness-nexus/cli 0.1.0-alpha.1
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/LICENSE +21 -0
- package/README.md +59 -0
- package/dist/config.d.ts +24 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +38 -0
- package/dist/config.js.map +1 -0
- package/dist/daemon/acp/adapters.d.ts +7 -0
- package/dist/daemon/acp/adapters.d.ts.map +1 -0
- package/dist/daemon/acp/adapters.js +34 -0
- package/dist/daemon/acp/adapters.js.map +1 -0
- package/dist/daemon/acp/agent-connection.d.ts +45 -0
- package/dist/daemon/acp/agent-connection.d.ts.map +1 -0
- package/dist/daemon/acp/agent-connection.js +158 -0
- package/dist/daemon/acp/agent-connection.js.map +1 -0
- package/dist/daemon/chat.d.ts +22 -0
- package/dist/daemon/chat.d.ts.map +1 -0
- package/dist/daemon/chat.js +280 -0
- package/dist/daemon/chat.js.map +1 -0
- package/dist/daemon/client.d.ts +23 -0
- package/dist/daemon/client.d.ts.map +1 -0
- package/dist/daemon/client.js +117 -0
- package/dist/daemon/client.js.map +1 -0
- package/dist/daemon/jobs.d.ts +19 -0
- package/dist/daemon/jobs.d.ts.map +1 -0
- package/dist/daemon/jobs.js +65 -0
- package/dist/daemon/jobs.js.map +1 -0
- package/dist/errors.d.ts +11 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +11 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +481 -0
- package/dist/index.js.map +1 -0
- package/dist/install/adapter-factory.d.ts +24 -0
- package/dist/install/adapter-factory.d.ts.map +1 -0
- package/dist/install/adapter-factory.js +80 -0
- package/dist/install/adapter-factory.js.map +1 -0
- package/dist/install/adapters/codex.d.ts +16 -0
- package/dist/install/adapters/codex.d.ts.map +1 -0
- package/dist/install/adapters/codex.js +172 -0
- package/dist/install/adapters/codex.js.map +1 -0
- package/dist/install/adapters/deepseek.d.ts +26 -0
- package/dist/install/adapters/deepseek.d.ts.map +1 -0
- package/dist/install/adapters/deepseek.js +246 -0
- package/dist/install/adapters/deepseek.js.map +1 -0
- package/dist/install/adapters/hermes.d.ts +16 -0
- package/dist/install/adapters/hermes.d.ts.map +1 -0
- package/dist/install/adapters/hermes.js +267 -0
- package/dist/install/adapters/hermes.js.map +1 -0
- package/dist/install/adapters/stub.d.ts +2 -0
- package/dist/install/adapters/stub.d.ts.map +1 -0
- package/dist/install/adapters/stub.js +22 -0
- package/dist/install/adapters/stub.js.map +1 -0
- package/dist/install/install-state.d.ts +31 -0
- package/dist/install/install-state.d.ts.map +1 -0
- package/dist/install/install-state.js +29 -0
- package/dist/install/install-state.js.map +1 -0
- package/dist/install/installer.d.ts +16 -0
- package/dist/install/installer.d.ts.map +1 -0
- package/dist/install/installer.js +96 -0
- package/dist/install/installer.js.map +1 -0
- package/dist/install/planner.d.ts +26 -0
- package/dist/install/planner.d.ts.map +1 -0
- package/dist/install/planner.js +25 -0
- package/dist/install/planner.js.map +1 -0
- package/dist/install/registry.d.ts +21 -0
- package/dist/install/registry.d.ts.map +1 -0
- package/dist/install/registry.js +31 -0
- package/dist/install/registry.js.map +1 -0
- package/dist/install/resolver.d.ts +15 -0
- package/dist/install/resolver.d.ts.map +1 -0
- package/dist/install/resolver.js +57 -0
- package/dist/install/resolver.js.map +1 -0
- package/dist/install/types.d.ts +93 -0
- package/dist/install/types.d.ts.map +1 -0
- package/dist/install/types.js +2 -0
- package/dist/install/types.js.map +1 -0
- package/dist/install/uninstaller.d.ts +29 -0
- package/dist/install/uninstaller.d.ts.map +1 -0
- package/dist/install/uninstaller.js +107 -0
- package/dist/install/uninstaller.js.map +1 -0
- package/dist/inventory/common.d.ts +86 -0
- package/dist/inventory/common.d.ts.map +1 -0
- package/dist/inventory/common.js +137 -0
- package/dist/inventory/common.js.map +1 -0
- package/dist/inventory/scan.d.ts +23 -0
- package/dist/inventory/scan.d.ts.map +1 -0
- package/dist/inventory/scan.js +117 -0
- package/dist/inventory/scan.js.map +1 -0
- package/dist/inventory/scanners/claude-code.d.ts +3 -0
- package/dist/inventory/scanners/claude-code.d.ts.map +1 -0
- package/dist/inventory/scanners/claude-code.js +191 -0
- package/dist/inventory/scanners/claude-code.js.map +1 -0
- package/dist/inventory/scanners/codex.d.ts +14 -0
- package/dist/inventory/scanners/codex.d.ts.map +1 -0
- package/dist/inventory/scanners/codex.js +201 -0
- package/dist/inventory/scanners/codex.js.map +1 -0
- package/dist/inventory/scanners/deepseek.d.ts +9 -0
- package/dist/inventory/scanners/deepseek.d.ts.map +1 -0
- package/dist/inventory/scanners/deepseek.js +200 -0
- package/dist/inventory/scanners/deepseek.js.map +1 -0
- package/dist/inventory/scanners/hermes.d.ts +3 -0
- package/dist/inventory/scanners/hermes.d.ts.map +1 -0
- package/dist/inventory/scanners/hermes.js +194 -0
- package/dist/inventory/scanners/hermes.js.map +1 -0
- package/dist/inventory/types.d.ts +33 -0
- package/dist/inventory/types.d.ts.map +1 -0
- package/dist/inventory/types.js +2 -0
- package/dist/inventory/types.js.map +1 -0
- package/dist/mcp/serve.d.ts +8 -0
- package/dist/mcp/serve.d.ts.map +1 -0
- package/dist/mcp/serve.js +118 -0
- package/dist/mcp/serve.js.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { MAX_ITEM_BYTES, isPlatformMcpName, mcpMeta, previewOf, readTextBounded, skillDirFiles, summarize, } from '../common.js';
|
|
4
|
+
/**
|
|
5
|
+
* DeepSeek Harness (dsh) scanner (Phase 8 T1). Ground truth mirrors the T1
|
|
6
|
+
* adapter:
|
|
7
|
+
* skills → ~/.dsh/skills/<name>/SKILL.md (+ bundle files)
|
|
8
|
+
* commands → flat ~/.dsh/skills/<name>.md (the /name invocation surface)
|
|
9
|
+
* mcp → `- insert:` rows mounting '@deepseek-ai/dsh-mcp-client' in the
|
|
10
|
+
* home ~/.dsh/cordis.patch.yml (applies to every profile)
|
|
11
|
+
* Rules (persona is a config row), sub-agents (programmatic providers) and
|
|
12
|
+
* hooks (opt-in bridge packages) have no declarative home shape — not scanned.
|
|
13
|
+
*
|
|
14
|
+
* The patch parse is tolerant text surgery over the README field spellings,
|
|
15
|
+
* not a YAML parser — same tradeoff as the Codex TOML parser.
|
|
16
|
+
*/
|
|
17
|
+
const MCP_BRIDGE = '@deepseek-ai/dsh-mcp-client';
|
|
18
|
+
/**
|
|
19
|
+
* Extract dsh-mcp-client mount rows from a cordis patch document, keyed by
|
|
20
|
+
* `serverName` (the user-meaningful server name; tools surface as
|
|
21
|
+
* `mcp__<serverName>__<tool>`).
|
|
22
|
+
*/
|
|
23
|
+
export function parseDeepseekMcpServers(patch) {
|
|
24
|
+
const out = {};
|
|
25
|
+
// Segment into items at every `- key:` list line; MCP mounts are the items
|
|
26
|
+
// whose `name` key is the bridge package.
|
|
27
|
+
const items = [];
|
|
28
|
+
let current = null;
|
|
29
|
+
for (const line of patch.split('\n')) {
|
|
30
|
+
if (/^\s*-\s+\w+:/.test(line)) {
|
|
31
|
+
current = [];
|
|
32
|
+
items.push(current);
|
|
33
|
+
}
|
|
34
|
+
if (current !== null && !/^\s*#/.test(line))
|
|
35
|
+
current.push(line);
|
|
36
|
+
}
|
|
37
|
+
for (const item of items) {
|
|
38
|
+
const text = item.join('\n');
|
|
39
|
+
const name = /(?:^|\n)\s*(?:-\s+)?name:\s*['"]?([^'"\n]+?)['"]?\s*$/m.exec(text)?.[1];
|
|
40
|
+
if (name !== MCP_BRIDGE)
|
|
41
|
+
continue;
|
|
42
|
+
const serverName = /serverName:\s*['"]?([^'"\n]+?)['"]?\s*$/m.exec(text)?.[1];
|
|
43
|
+
if (serverName === undefined || serverName === '')
|
|
44
|
+
continue;
|
|
45
|
+
const entry = {};
|
|
46
|
+
const command = /command:\s*['"]?([^'"\n]+?)['"]?\s*$/m.exec(text)?.[1];
|
|
47
|
+
if (command !== undefined)
|
|
48
|
+
entry.command = command;
|
|
49
|
+
const url = /url:\s*['"]?([^'"\n]+?)['"]?\s*$/m.exec(text)?.[1];
|
|
50
|
+
if (url !== undefined)
|
|
51
|
+
entry.url = url;
|
|
52
|
+
const argsLine = /args:\s*\[(.*)\]/.exec(text)?.[1];
|
|
53
|
+
if (argsLine !== undefined) {
|
|
54
|
+
const args = [...argsLine.matchAll(/'([^']*)'|"((?:[^"\\]|\\.)*)"/g)].map((m) => m[1] ?? m[2].replace(/\\"/g, '"'));
|
|
55
|
+
if (args.length > 0)
|
|
56
|
+
entry.args = args;
|
|
57
|
+
}
|
|
58
|
+
out[serverName] = entry;
|
|
59
|
+
}
|
|
60
|
+
return out;
|
|
61
|
+
}
|
|
62
|
+
function readPatch(home) {
|
|
63
|
+
try {
|
|
64
|
+
return fs.readFileSync(path.join(home, 'cordis.patch.yml'), 'utf8');
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return '';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export const deepseekScanner = {
|
|
71
|
+
target: 'deepseek',
|
|
72
|
+
homeOf: (homeDir) => path.join(homeDir, '.dsh'),
|
|
73
|
+
discover(home) {
|
|
74
|
+
if (!fs.existsSync(home))
|
|
75
|
+
return null;
|
|
76
|
+
const items = [];
|
|
77
|
+
const skillsDir = path.join(home, 'skills');
|
|
78
|
+
if (fs.existsSync(skillsDir)) {
|
|
79
|
+
for (const entry of fs
|
|
80
|
+
.readdirSync(skillsDir, { withFileTypes: true })
|
|
81
|
+
.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
82
|
+
// Bundles (<name>/SKILL.md) are skills; flat <name>.md files are the
|
|
83
|
+
// /name command surface — the split our adapter emits, preserved on
|
|
84
|
+
// the round trip.
|
|
85
|
+
if (entry.isDirectory()) {
|
|
86
|
+
const dir = path.join(skillsDir, entry.name);
|
|
87
|
+
const files = skillDirFiles(dir);
|
|
88
|
+
const skillMd = readTextBounded(path.join(dir, 'SKILL.md'));
|
|
89
|
+
if (!skillMd.ok) {
|
|
90
|
+
items.push({
|
|
91
|
+
kind: 'skill',
|
|
92
|
+
name: entry.name,
|
|
93
|
+
absPath: dir,
|
|
94
|
+
relPath: `skills/${entry.name}`,
|
|
95
|
+
importable: false,
|
|
96
|
+
note: files.length === 0 ? 'empty' : `SKILL.md ${skillMd.error}`,
|
|
97
|
+
});
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
const totalBytes = files.reduce((sum, f) => sum + fs.statSync(path.join(dir, f)).size, 0);
|
|
101
|
+
items.push({
|
|
102
|
+
kind: 'skill',
|
|
103
|
+
name: entry.name,
|
|
104
|
+
absPath: dir,
|
|
105
|
+
relPath: `skills/${entry.name}`,
|
|
106
|
+
importable: totalBytes <= MAX_ITEM_BYTES,
|
|
107
|
+
...(totalBytes > MAX_ITEM_BYTES ? { note: 'too-large' } : {}),
|
|
108
|
+
summary: summarize(skillMd.content),
|
|
109
|
+
preview: previewOf(skillMd.content),
|
|
110
|
+
meta: { multi: files.length > 1 },
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
else if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
114
|
+
const name = entry.name.slice(0, -3);
|
|
115
|
+
const abs = path.join(skillsDir, entry.name);
|
|
116
|
+
const text = readTextBounded(abs);
|
|
117
|
+
items.push({
|
|
118
|
+
kind: 'command',
|
|
119
|
+
name,
|
|
120
|
+
absPath: abs,
|
|
121
|
+
relPath: `skills/${entry.name}`,
|
|
122
|
+
importable: text.ok,
|
|
123
|
+
...(text.ok ? { summary: summarize(text.content) } : { note: text.error }),
|
|
124
|
+
...(text.ok ? { preview: previewOf(text.content) } : {}),
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
for (const [serverName, entry] of Object.entries(parseDeepseekMcpServers(readPatch(home)))) {
|
|
130
|
+
items.push({
|
|
131
|
+
kind: 'mcp',
|
|
132
|
+
name: serverName,
|
|
133
|
+
absPath: path.join(home, 'cordis.patch.yml'),
|
|
134
|
+
relPath: 'cordis.patch.yml#insert',
|
|
135
|
+
importable: Boolean(entry.command ?? entry.url),
|
|
136
|
+
...((entry.command ?? entry.url) ? {} : { note: 'unsupported shape' }),
|
|
137
|
+
meta: mcpMeta(entry),
|
|
138
|
+
...(isPlatformMcpName(serverName) ? { platform: true } : {}),
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
return items;
|
|
142
|
+
},
|
|
143
|
+
platformMarkers(home) {
|
|
144
|
+
return Object.keys(parseDeepseekMcpServers(readPatch(home))).filter(isPlatformMcpName);
|
|
145
|
+
},
|
|
146
|
+
async collect(home, item) {
|
|
147
|
+
if (item.kind === 'skill') {
|
|
148
|
+
const files = {};
|
|
149
|
+
for (const rel of skillDirFiles(item.absPath)) {
|
|
150
|
+
const text = readTextBounded(path.join(item.absPath, rel));
|
|
151
|
+
if (!text.ok)
|
|
152
|
+
return { kind: 'skill', name: item.name, ok: false, error: `${rel}: ${text.error}` };
|
|
153
|
+
files[rel] = text.content;
|
|
154
|
+
}
|
|
155
|
+
if (!('SKILL.md' in files)) {
|
|
156
|
+
return { kind: 'skill', name: item.name, ok: false, error: 'SKILL.md missing' };
|
|
157
|
+
}
|
|
158
|
+
return { kind: 'skill', name: item.name, ok: true, artifact: { kind: 'skill', files } };
|
|
159
|
+
}
|
|
160
|
+
if (item.kind === 'command') {
|
|
161
|
+
const text = readTextBounded(item.absPath);
|
|
162
|
+
if (!text.ok)
|
|
163
|
+
return { kind: 'command', name: item.name, ok: false, error: text.error };
|
|
164
|
+
return {
|
|
165
|
+
kind: 'command',
|
|
166
|
+
name: item.name,
|
|
167
|
+
ok: true,
|
|
168
|
+
artifact: { kind: 'command', content: text.content },
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
const entry = parseDeepseekMcpServers(readPatch(home))[item.name];
|
|
172
|
+
if (!entry)
|
|
173
|
+
return { kind: 'mcp', name: item.name, ok: false, error: 'entry missing' };
|
|
174
|
+
if (entry.command) {
|
|
175
|
+
return {
|
|
176
|
+
kind: 'mcp',
|
|
177
|
+
name: item.name,
|
|
178
|
+
ok: true,
|
|
179
|
+
artifact: {
|
|
180
|
+
kind: 'mcp',
|
|
181
|
+
transport: {
|
|
182
|
+
type: 'stdio',
|
|
183
|
+
command: entry.command,
|
|
184
|
+
...(entry.args ? { args: entry.args } : {}),
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
if (entry.url) {
|
|
190
|
+
return {
|
|
191
|
+
kind: 'mcp',
|
|
192
|
+
name: item.name,
|
|
193
|
+
ok: true,
|
|
194
|
+
artifact: { kind: 'mcp', transport: { type: 'streamable-http', url: entry.url } },
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
return { kind: 'mcp', name: item.name, ok: false, error: 'unsupported shape' };
|
|
198
|
+
},
|
|
199
|
+
};
|
|
200
|
+
//# sourceMappingURL=deepseek.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deepseek.js","sourceRoot":"","sources":["../../../src/inventory/scanners/deepseek.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hermes.d.ts","sourceRoot":"","sources":["../../../src/inventory/scanners/hermes.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAe,aAAa,EAAE,MAAM,aAAa,CAAC;AA8D9D,eAAO,MAAM,aAAa,EAAE,aA6I3B,CAAC"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import yaml from 'js-yaml';
|
|
4
|
+
import { MAX_ITEM_BYTES, isPlatformMcpName, mcpMeta, previewOf, readTextBounded, redactSecretMap, skillDirFiles, summarize, } from '../common.js';
|
|
5
|
+
/**
|
|
6
|
+
* Hermes scanner (Phase 8 C3). Ground truth mirrors the 3.4 adapter:
|
|
7
|
+
* skills → ~/.hermes/plugins/<slug>/skills/<name>/SKILL.md — BOTH ours
|
|
8
|
+
* (plugin.yaml author 'Harness Nexus') and third-party plugins
|
|
9
|
+
* mcp → `mcp_servers:` map in ~/.hermes/config.yaml (YAML)
|
|
10
|
+
* rules → ~/.hermes/AGENTS.md (Hermes auto-loads it; the adapter writes it)
|
|
11
|
+
* sub_agents/hooks have no file format — not scanned.
|
|
12
|
+
*/
|
|
13
|
+
/** Read config.yaml's mcp_servers map, tolerating absence/garbage. */
|
|
14
|
+
function parseHermesMcpServers(home) {
|
|
15
|
+
try {
|
|
16
|
+
const parsed = yaml.load(fs.readFileSync(path.join(home, 'config.yaml'), 'utf8'));
|
|
17
|
+
return parsed?.mcp_servers ?? {};
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return {};
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/** True iff the plugin bundle is ours (plugin.yaml author). */
|
|
24
|
+
function isHarnessPlugin(pluginDir) {
|
|
25
|
+
try {
|
|
26
|
+
const manifest = yaml.load(fs.readFileSync(path.join(pluginDir, 'plugin.yaml'), 'utf8'));
|
|
27
|
+
return manifest?.author === 'Harness Nexus';
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function scanSkillDir(dir, relPath, platform) {
|
|
34
|
+
const files = skillDirFiles(dir);
|
|
35
|
+
const skillMd = readTextBounded(path.join(dir, 'SKILL.md'));
|
|
36
|
+
if (!skillMd.ok) {
|
|
37
|
+
return {
|
|
38
|
+
error: files.length === 0 ? 'empty' : `SKILL.md ${skillMd.error}`,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
const totalBytes = files.reduce((sum, f) => sum + fs.statSync(path.join(dir, f)).size, 0);
|
|
42
|
+
return {
|
|
43
|
+
kind: 'skill',
|
|
44
|
+
name: path.basename(dir),
|
|
45
|
+
absPath: dir,
|
|
46
|
+
relPath,
|
|
47
|
+
importable: totalBytes <= MAX_ITEM_BYTES,
|
|
48
|
+
...(totalBytes > MAX_ITEM_BYTES ? { note: 'too-large' } : {}),
|
|
49
|
+
summary: summarize(skillMd.content) ?? '(no description)',
|
|
50
|
+
preview: previewOf(skillMd.content) ?? '',
|
|
51
|
+
meta: { multi: files.length > 1 },
|
|
52
|
+
...(platform ? { platform: true } : {}),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export const hermesScanner = {
|
|
56
|
+
target: 'hermes',
|
|
57
|
+
homeOf: (homeDir) => path.join(homeDir, '.hermes'),
|
|
58
|
+
discover(home) {
|
|
59
|
+
if (!fs.existsSync(home))
|
|
60
|
+
return null;
|
|
61
|
+
const items = [];
|
|
62
|
+
const pluginsDir = path.join(home, 'plugins');
|
|
63
|
+
if (fs.existsSync(pluginsDir)) {
|
|
64
|
+
for (const entry of fs
|
|
65
|
+
.readdirSync(pluginsDir, { withFileTypes: true })
|
|
66
|
+
.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
67
|
+
if (!entry.isDirectory())
|
|
68
|
+
continue;
|
|
69
|
+
const pluginDir = path.join(pluginsDir, entry.name);
|
|
70
|
+
const ours = isHarnessPlugin(pluginDir);
|
|
71
|
+
const skillsDir = path.join(pluginDir, 'skills');
|
|
72
|
+
if (!fs.existsSync(skillsDir))
|
|
73
|
+
continue;
|
|
74
|
+
for (const skill of fs
|
|
75
|
+
.readdirSync(skillsDir, { withFileTypes: true })
|
|
76
|
+
.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
77
|
+
if (!skill.isDirectory())
|
|
78
|
+
continue;
|
|
79
|
+
const found = scanSkillDir(path.join(skillsDir, skill.name), `plugins/${entry.name}/skills/${skill.name}`, ours);
|
|
80
|
+
if ('error' in found) {
|
|
81
|
+
items.push({
|
|
82
|
+
kind: 'skill',
|
|
83
|
+
name: skill.name,
|
|
84
|
+
absPath: path.join(skillsDir, skill.name),
|
|
85
|
+
relPath: `plugins/${entry.name}/skills/${skill.name}`,
|
|
86
|
+
importable: false,
|
|
87
|
+
note: found.error,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
items.push(found);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
for (const [key, entry] of Object.entries(parseHermesMcpServers(home))) {
|
|
97
|
+
if (!entry || typeof entry !== 'object')
|
|
98
|
+
continue;
|
|
99
|
+
items.push({
|
|
100
|
+
kind: 'mcp',
|
|
101
|
+
name: key,
|
|
102
|
+
absPath: path.join(home, 'config.yaml'),
|
|
103
|
+
relPath: 'config.yaml#mcp_servers',
|
|
104
|
+
importable: Boolean(entry.command ?? entry.url),
|
|
105
|
+
...((entry.command ?? entry.url) ? {} : { note: 'unsupported shape' }),
|
|
106
|
+
meta: mcpMeta(entry),
|
|
107
|
+
...(isPlatformMcpName(key) ? { platform: true } : {}),
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
const agentsMd = path.join(home, 'AGENTS.md');
|
|
111
|
+
if (fs.existsSync(agentsMd)) {
|
|
112
|
+
const text = readTextBounded(agentsMd);
|
|
113
|
+
items.push({
|
|
114
|
+
kind: 'rule',
|
|
115
|
+
name: 'AGENTS',
|
|
116
|
+
absPath: agentsMd,
|
|
117
|
+
relPath: 'AGENTS.md',
|
|
118
|
+
importable: text.ok,
|
|
119
|
+
...(text.ok
|
|
120
|
+
? {
|
|
121
|
+
summary: summarize(text.content) ?? '(empty)',
|
|
122
|
+
preview: previewOf(text.content) ?? '',
|
|
123
|
+
}
|
|
124
|
+
: { note: text.error }),
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return items;
|
|
128
|
+
},
|
|
129
|
+
platformMarkers(home) {
|
|
130
|
+
return Object.keys(parseHermesMcpServers(home)).filter(isPlatformMcpName);
|
|
131
|
+
},
|
|
132
|
+
async collect(home, item) {
|
|
133
|
+
if (item.kind === 'skill') {
|
|
134
|
+
const files = {};
|
|
135
|
+
for (const rel of skillDirFiles(item.absPath)) {
|
|
136
|
+
const text = readTextBounded(path.join(item.absPath, rel));
|
|
137
|
+
if (!text.ok)
|
|
138
|
+
return { kind: 'skill', name: item.name, ok: false, error: `${rel}: ${text.error}` };
|
|
139
|
+
files[rel] = text.content;
|
|
140
|
+
}
|
|
141
|
+
if (!('SKILL.md' in files)) {
|
|
142
|
+
return { kind: 'skill', name: item.name, ok: false, error: 'SKILL.md missing' };
|
|
143
|
+
}
|
|
144
|
+
return { kind: 'skill', name: item.name, ok: true, artifact: { kind: 'skill', files } };
|
|
145
|
+
}
|
|
146
|
+
if (item.kind === 'rule') {
|
|
147
|
+
const text = readTextBounded(item.absPath);
|
|
148
|
+
if (!text.ok)
|
|
149
|
+
return { kind: 'rule', name: item.name, ok: false, error: text.error };
|
|
150
|
+
return {
|
|
151
|
+
kind: 'rule',
|
|
152
|
+
name: item.name,
|
|
153
|
+
ok: true,
|
|
154
|
+
artifact: { kind: 'rule', content: text.content },
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
const entry = parseHermesMcpServers(home)[item.name];
|
|
158
|
+
if (!entry)
|
|
159
|
+
return { kind: 'mcp', name: item.name, ok: false, error: 'entry missing' };
|
|
160
|
+
if (entry.command) {
|
|
161
|
+
return {
|
|
162
|
+
kind: 'mcp',
|
|
163
|
+
name: item.name,
|
|
164
|
+
ok: true,
|
|
165
|
+
artifact: {
|
|
166
|
+
kind: 'mcp',
|
|
167
|
+
transport: {
|
|
168
|
+
type: 'stdio',
|
|
169
|
+
command: entry.command,
|
|
170
|
+
...(entry.args ? { args: entry.args } : {}),
|
|
171
|
+
...(entry.env ? { env: redactSecretMap(entry.env) } : {}),
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
if (entry.url) {
|
|
177
|
+
return {
|
|
178
|
+
kind: 'mcp',
|
|
179
|
+
name: item.name,
|
|
180
|
+
ok: true,
|
|
181
|
+
artifact: {
|
|
182
|
+
kind: 'mcp',
|
|
183
|
+
transport: {
|
|
184
|
+
type: entry.type === 'sse' ? 'sse' : 'streamable-http',
|
|
185
|
+
url: entry.url,
|
|
186
|
+
...(entry.headers ? { headers: redactSecretMap(entry.headers) } : {}),
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
return { kind: 'mcp', name: item.name, ok: false, error: 'unsupported shape' };
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
//# sourceMappingURL=hermes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hermes.js","sourceRoot":"","sources":["../../../src/inventory/scanners/hermes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,IAAI,MAAM,SAAS,CAAC;AAC3B,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,OAAO,EACP,SAAS,EACT,eAAe,EACf,eAAe,EACf,aAAa,EACb,SAAS,GAEV,MAAM,cAAc,CAAC;AAGtB;;;;;;;GAOG;AAEH,sEAAsE;AACtE,SAAS,qBAAqB,CAAC,IAAY;IACzC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAExE,CAAC;QACT,OAAO,MAAM,EAAE,WAAW,IAAI,EAAE,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,+DAA+D;AAC/D,SAAS,eAAe,CAAC,SAAiB;IACxC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC,CAE/E,CAAC;QACT,OAAO,QAAQ,EAAE,MAAM,KAAK,eAAe,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CACnB,GAAW,EACX,OAAe,EACf,QAAiB;IAEjB,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IACjC,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC;IAC5D,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QAChB,OAAO;YACL,KAAK,EAAE,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,OAAO,CAAC,KAAK,EAAE;SAClE,CAAC;IACJ,CAAC;IACD,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC1F,OAAO;QACL,IAAI,EAAE,OAAO;QACb,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QACxB,OAAO,EAAE,GAAG;QACZ,OAAO;QACP,UAAU,EAAE,UAAU,IAAI,cAAc;QACxC,GAAG,CAAC,UAAU,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7D,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,kBAAkB;QACzD,OAAO,EAAE,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE;QACzC,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;QACjC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACxC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAkB;IAC1C,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC;IAElD,QAAQ,CAAC,IAAI;QACX,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QACtC,MAAM,KAAK,GAAqB,EAAE,CAAC;QAEnC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QAC9C,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9B,KAAK,MAAM,KAAK,IAAI,EAAE;iBACnB,WAAW,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;iBAChD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;gBAChD,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;oBAAE,SAAS;gBACnC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBACpD,MAAM,IAAI,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;gBACxC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;gBACjD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;oBAAE,SAAS;gBACxC,KAAK,MAAM,KAAK,IAAI,EAAE;qBACnB,WAAW,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;qBAC/C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;oBAChD,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;wBAAE,SAAS;oBACnC,MAAM,KAAK,GAAG,YAAY,CACxB,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,EAChC,WAAW,KAAK,CAAC,IAAI,WAAW,KAAK,CAAC,IAAI,EAAE,EAC5C,IAAI,CACL,CAAC;oBACF,IAAI,OAAO,IAAI,KAAK,EAAE,CAAC;wBACrB,KAAK,CAAC,IAAI,CAAC;4BACT,IAAI,EAAE,OAAO;4BACb,IAAI,EAAE,KAAK,CAAC,IAAI;4BAChB,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC;4BACzC,OAAO,EAAE,WAAW,KAAK,CAAC,IAAI,WAAW,KAAK,CAAC,IAAI,EAAE;4BACrD,UAAU,EAAE,KAAK;4BACjB,IAAI,EAAE,KAAK,CAAC,KAAK;yBAClB,CAAC,CAAC;oBACL,CAAC;yBAAM,CAAC;wBACN,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;oBACpB,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YACvE,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;gBAAE,SAAS;YAClD,KAAK,CAAC,IAAI,CAAC;gBACT,IAAI,EAAE,KAAK;gBACX,IAAI,EAAE,GAAG;gBACT,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC;gBACvC,OAAO,EAAE,yBAAyB;gBAClC,UAAU,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC;gBAC/C,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,CAAC;gBACtE,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC;gBACpB,GAAG,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACtD,CAAC,CAAC;QACL,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAC9C,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC;gBACT,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,QAAQ;gBACjB,OAAO,EAAE,WAAW;gBACpB,UAAU,EAAE,IAAI,CAAC,EAAE;gBACnB,GAAG,CAAC,IAAI,CAAC,EAAE;oBACT,CAAC,CAAC;wBACE,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,SAAS;wBAC7C,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE;qBACvC;oBACH,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;aAC1B,CAAC,CAAC;QACL,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED,eAAe,CAAC,IAAI;QAClB,OAAO,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAC5E,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI;QACtB,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC1B,MAAM,KAAK,GAA2B,EAAE,CAAC;YACzC,KAAK,MAAM,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC9C,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;gBAC3D,IAAI,CAAC,IAAI,CAAC,EAAE;oBACV,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,GAAG,KAAK,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;gBACvF,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC;YAC5B,CAAC;YACD,IAAI,CAAC,CAAC,UAAU,IAAI,KAAK,CAAC,EAAE,CAAC;gBAC3B,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC;YAClF,CAAC;YACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC;QAC1F,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC3C,IAAI,CAAC,IAAI,CAAC,EAAE;gBAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;YACrF,OAAO;gBACL,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,EAAE,EAAE,IAAI;gBACR,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE;aAClD,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrD,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC;QACvF,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAClB,OAAO;gBACL,IAAI,EAAE,KAAK;gBACX,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,EAAE,EAAE,IAAI;gBACR,QAAQ,EAAE;oBACR,IAAI,EAAE,KAAK;oBACX,SAAS,EAAE;wBACT,IAAI,EAAE,OAAO;wBACb,OAAO,EAAE,KAAK,CAAC,OAAO;wBACtB,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;wBAC3C,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;qBAC1D;iBACF;aACF,CAAC;QACJ,CAAC;QACD,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC;YACd,OAAO;gBACL,IAAI,EAAE,KAAK;gBACX,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,EAAE,EAAE,IAAI;gBACR,QAAQ,EAAE;oBACR,IAAI,EAAE,KAAK;oBACX,SAAS,EAAE;wBACT,IAAI,EAAE,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,iBAAiB;wBACtD,GAAG,EAAE,KAAK,CAAC,GAAG;wBACd,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,eAAe,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;qBACtE;iBACF;aACF,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC;IACjF,CAAC;CACF,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { AgentTarget, InventoryArtifact, InventoryItemKind } from '@harness-nexus/shared';
|
|
2
|
+
import type { DiscoveredItem } from './common.js';
|
|
3
|
+
/** One row of an `inventory:payload` event (success or per-item error). */
|
|
4
|
+
export interface PayloadItem {
|
|
5
|
+
kind: InventoryItemKind;
|
|
6
|
+
name: string;
|
|
7
|
+
ok: boolean;
|
|
8
|
+
error?: string;
|
|
9
|
+
artifact?: InventoryArtifact;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* A per-target scanner. `discover` re-runs on every collect — the daemon never
|
|
13
|
+
* trusts server-supplied paths.
|
|
14
|
+
*/
|
|
15
|
+
export interface TargetScanner {
|
|
16
|
+
target: AgentTarget;
|
|
17
|
+
/** The agent's home dir (may not exist — discover then returns null). */
|
|
18
|
+
homeOf(homeDir: string): string;
|
|
19
|
+
discover(home: string): DiscoveredItem[] | null;
|
|
20
|
+
/** Whole-home platform markers beyond the ledger (e.g. shim MCP names). */
|
|
21
|
+
platformMarkers(home: string): string[];
|
|
22
|
+
collect(home: string, item: DiscoveredItem): Promise<PayloadItem>;
|
|
23
|
+
}
|
|
24
|
+
/** The config-file MCP entry shape all three parsers normalize to. */
|
|
25
|
+
export interface RawMcpEntry {
|
|
26
|
+
type?: string;
|
|
27
|
+
command?: string;
|
|
28
|
+
args?: string[];
|
|
29
|
+
env?: Record<string, string>;
|
|
30
|
+
url?: string;
|
|
31
|
+
headers?: Record<string, string>;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/inventory/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC/F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,2EAA2E;AAC3E,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,iBAAiB,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,iBAAiB,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,WAAW,CAAC;IACpB,yEAAyE;IACzE,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE,GAAG,IAAI,CAAC;IAChD,2EAA2E;IAC3E,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACxC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CACnE;AAED,sEAAsE;AACtE,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/inventory/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../src/mcp/serve.ts"],"names":[],"mappings":"AAqDA,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAyFtE"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `hnx mcp serve` — the client MCP shim (Phase 8 C2).
|
|
3
|
+
*
|
|
4
|
+
* Spawned BY an Agent tool as a per-session stdio MCP server (the tool's MCP
|
|
5
|
+
* config carries one stdio entry per profile). The shim:
|
|
6
|
+
* 1. fetches its resolved config from the platform
|
|
7
|
+
* (`GET /api/client/mcp-config?profile=<id>` — machine PAT or user PAT);
|
|
8
|
+
* 2. dials every CLIENT-dialed upstream locally via `mcp-runtime` (stdio /
|
|
9
|
+
* SSE / HTTP; credential plaintext lives in this process's memory only);
|
|
10
|
+
* 3. dials the platform `/mcp?profile=<id>` outlet as one PASSTHROUGH
|
|
11
|
+
* upstream when the profile has server-dialed entries (their tools are
|
|
12
|
+
* already namespaced server-side);
|
|
13
|
+
* 4. serves the merged, namespaced tool set over stdio until the tool
|
|
14
|
+
* closes our stdin.
|
|
15
|
+
*
|
|
16
|
+
* Config applies at process start — changes take effect next agent session.
|
|
17
|
+
* NEVER write to stdout (it carries the MCP protocol); all logs go to stderr.
|
|
18
|
+
* Uses the low-level `Server` (not `McpServer`) so upstream tools' raw JSON
|
|
19
|
+
* inputSchemas pass through verbatim — no zod round-trip, no schema drift.
|
|
20
|
+
*/
|
|
21
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
22
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
23
|
+
import { ListToolsRequestSchema, CallToolRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
24
|
+
import { UpstreamPool, } from '@harness-nexus/mcp-runtime';
|
|
25
|
+
import { HarnessNexusClient, HarnessNexusError } from '@harness-nexus/sdk';
|
|
26
|
+
import { InstallError } from '../errors.js';
|
|
27
|
+
import { DAEMON_VERSION } from '../daemon/client.js';
|
|
28
|
+
/** stderr-only logger for the pool (stdout belongs to the MCP protocol). */
|
|
29
|
+
const stderrLog = {
|
|
30
|
+
info(_obj, msg) {
|
|
31
|
+
// eslint-disable-next-line no-console
|
|
32
|
+
console.error(`[hnx-mcp] ${msg}`);
|
|
33
|
+
},
|
|
34
|
+
warn(obj, msg) {
|
|
35
|
+
const detail = 'err' in obj && obj.err instanceof Error ? `: ${obj.err.message}` : '';
|
|
36
|
+
// eslint-disable-next-line no-console
|
|
37
|
+
console.error(`[hnx-mcp] WARN ${msg}${detail}`);
|
|
38
|
+
},
|
|
39
|
+
debug() {
|
|
40
|
+
/* quiet by default */
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
export async function runMcpServe(opts) {
|
|
44
|
+
const client = new HarnessNexusClient({ baseUrl: opts.server, token: opts.token });
|
|
45
|
+
let config;
|
|
46
|
+
try {
|
|
47
|
+
config = await client.getClientMcpConfig(opts.profileId);
|
|
48
|
+
}
|
|
49
|
+
catch (e) {
|
|
50
|
+
throw new InstallError(`Failed to fetch MCP config for profile '${opts.profileId}': ${e instanceof HarnessNexusError
|
|
51
|
+
? `${e.code}: ${e.message}`
|
|
52
|
+
: e instanceof Error
|
|
53
|
+
? e.message
|
|
54
|
+
: String(e)}`, 'RESOLVE_FAILED', e);
|
|
55
|
+
}
|
|
56
|
+
// Client-dialed upstreams (transports arrive resolved — memory-only secrets).
|
|
57
|
+
// Cast: zod-inferred optionals (`| undefined`) vs the runtime's exact-optional
|
|
58
|
+
// shape — identical at runtime, validated at the API boundary.
|
|
59
|
+
const defs = [];
|
|
60
|
+
for (const s of config.servers) {
|
|
61
|
+
if (s.dialSite !== 'client')
|
|
62
|
+
continue;
|
|
63
|
+
defs.push({ id: s.id, name: s.name, transport: s.transport });
|
|
64
|
+
}
|
|
65
|
+
// The platform outlet as ONE passthrough upstream (tools already namespaced).
|
|
66
|
+
if (config.platform !== null) {
|
|
67
|
+
defs.push({
|
|
68
|
+
id: '__outlet__',
|
|
69
|
+
name: 'harness-nexus',
|
|
70
|
+
transport: {
|
|
71
|
+
type: 'streamable-http',
|
|
72
|
+
url: `${config.platform.baseUrl.replace(/\/$/, '')}/mcp?profile=${encodeURIComponent(config.profileId)}`,
|
|
73
|
+
headers: { Authorization: `Bearer ${opts.token}` },
|
|
74
|
+
},
|
|
75
|
+
namespaced: true,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
const pool = new UpstreamPool({
|
|
79
|
+
logger: stderrLog,
|
|
80
|
+
clientName: 'hnx-mcp-serve',
|
|
81
|
+
clientVersion: DAEMON_VERSION,
|
|
82
|
+
});
|
|
83
|
+
await pool.sync(defs);
|
|
84
|
+
await pool.settle();
|
|
85
|
+
for (const s of pool.statuses()) {
|
|
86
|
+
if (s.status === 'error') {
|
|
87
|
+
stderrLog.warn({}, `upstream "${s.name}" failed: ${s.detail ?? 'unknown error'} (skipped)`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const server = new Server({ name: 'hnx-mcp-serve', version: DAEMON_VERSION }, { capabilities: { tools: {} } });
|
|
91
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
92
|
+
tools: pool.listTools().map((t) => ({
|
|
93
|
+
name: t.name,
|
|
94
|
+
...(t.description !== undefined ? { description: t.description } : {}),
|
|
95
|
+
inputSchema: t.inputSchema,
|
|
96
|
+
})),
|
|
97
|
+
}));
|
|
98
|
+
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
99
|
+
const { name, arguments: args } = req.params;
|
|
100
|
+
try {
|
|
101
|
+
const result = await pool.callTool(name, args);
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
catch (e) {
|
|
105
|
+
const text = e instanceof Error ? e.message : String(e);
|
|
106
|
+
return { content: [{ type: 'text', text }], isError: true };
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
const transport = new StdioServerTransport();
|
|
110
|
+
await server.connect(transport);
|
|
111
|
+
stderrLog.info({}, `serving profile ${config.profileId} (${pool.listTools().length} tools)`);
|
|
112
|
+
await new Promise((resolve) => {
|
|
113
|
+
server.onclose = () => {
|
|
114
|
+
void pool.shutdown().finally(resolve);
|
|
115
|
+
};
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=serve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../src/mcp/serve.ts"],"names":[],"mappings":"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"}
|