@deerdesign/deertools 1.2.13 → 1.2.21
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/README.md +22 -10
- package/package.json +1 -1
- package/src/agent-detector.js +127 -15
- package/src/cli.js +3 -0
- package/src/commands.js +128 -7
- package/src/mcp-stdio.js +106 -0
- package/src/skill-commands.js +547 -49
- package/src/skills-hub.js +159 -2
- package/src/team-commands.js +151 -0
package/README.md
CHANGED
|
@@ -185,18 +185,30 @@ deertools profile list
|
|
|
185
185
|
deertools profile use staging
|
|
186
186
|
|
|
187
187
|
# 12. AI Agent Skills (DeerSkills Hub):
|
|
188
|
-
deertools skill list # Wyświetl
|
|
189
|
-
deertools skill
|
|
190
|
-
deertools skill install
|
|
188
|
+
deertools skill list # Wyświetl listę skilli ze statusem zainstalowania w projekcie
|
|
189
|
+
deertools skill sync # Jedna komenda: instaluje brakujące i aktualizuje obecne skille zespołu
|
|
190
|
+
deertools skill install --all # To samo co skill sync (pełna synchronizacja zespołu)
|
|
191
|
+
deertools skill install deer-kosztorys # Zainstaluj konkretny skill w ~/.gemini/antigravity/skills lub .agents
|
|
191
192
|
deertools skill install deer-kosztorys --version 1.0.0
|
|
192
|
-
deertools skill
|
|
193
|
+
deertools skill search "kosztorys" # Wyszukaj skille po nazwie, tagu lub opisie
|
|
193
194
|
deertools skill push ./my-skill # Opublikuj nową wersję z automatycznym skanerem sekretów
|
|
194
|
-
deertools skill push ./my-skill --
|
|
195
|
+
deertools skill push ./my-skill --tags "wycena, kosztorys, marże" # Dodaj tagi przy publikacji
|
|
196
|
+
deertools skill push ./my-skill --team architekci # Publikacja bezpośrednio do zespołu
|
|
197
|
+
deertools skill share my-skill --team architekci # Udostępnij skill dla wskazanego zespołu
|
|
198
|
+
deertools skill share my-skill --private # Cofnij udostępnienie (tylko dla autora)
|
|
195
199
|
deertools skill update deer-kosztorys # Zaktualizuj zainstalowany skill do najnowszej wersji
|
|
196
200
|
deertools skill update # Zaktualizuj wszystkie zainstalowane skille
|
|
197
201
|
deertools skill promote my-skill # Zgłoś wniosek do admina o nominację do globalnego katalogu
|
|
198
202
|
|
|
199
|
-
# 13.
|
|
203
|
+
# 13. Team Management (Konfiguracja Zespołów):
|
|
204
|
+
deertools team list # Lista zespołów, liczba członków i skilli
|
|
205
|
+
deertools team members architekci # Członkowie i role w zespole architekci
|
|
206
|
+
deertools team add architekci jan@deer.pl # Dodaj członka do zespołu (rola member)
|
|
207
|
+
deertools team add architekci ewa@deer.pl --role lead # Dodaj lidera zespołu
|
|
208
|
+
deertools team remove architekci jan@deer.pl # Usuń członka z zespołu
|
|
209
|
+
deertools team create "Projektanci Wnętrz" --slug projektanci # Utwórz nowy zespół
|
|
210
|
+
|
|
211
|
+
# 14. AI Agent MCP Registry & Configuration:
|
|
200
212
|
deertools mcp list # Lista dostępnych serwerów MCP w ekosystemie
|
|
201
213
|
deertools mcp config # Wygeneruj konfigurację JSON dla Cursor, Claude, Antigravity
|
|
202
214
|
deertools mcp install # Automatycznie dopisz konfigurację do narzędzi AI
|
|
@@ -233,10 +245,10 @@ deertools mcp install # Automatycznie dopisz konfiguracj
|
|
|
233
245
|
|
|
234
246
|
**DeerSkills Hub** (`https://skills.deergroup.pl`) to centralna platforma dystrybucji, wersjonowania i zarządzania umiejętnościami agentów AI (Skills) oraz serwerami MCP w ekosystemie Deer Design:
|
|
235
247
|
|
|
236
|
-
1. **Struktura i
|
|
237
|
-
- **Oficjalne Skille (`global`)**: Zweryfikowane,
|
|
238
|
-
- **Skille
|
|
239
|
-
- **
|
|
248
|
+
1. **Trzypoziomowa Struktura Uprawnień i Widoczności**:
|
|
249
|
+
- **Oficjalne Skille Firmowe (`global`)**: Zweryfikowane narzędzia firmowe, widoczne dla wszystkich pracowników w organizacji, instalowane domyślnie.
|
|
250
|
+
- **Skille Zespołowe (`team`)**: Dedykowane dla konkretnego zespołu (np. Architekci, Doradcy Klienta, Kosztorysy, Logistyka, IT-Dev). Widoczne i instalowalne **wyłącznie** przez członków danego zespołu. Zespoły i role są w pełni konfigurowalne przez `deertools team` oraz portal Web.
|
|
251
|
+
- **Prywatne Skille Użytkownika (`user`)**: Każdy pracownik publikuje pod własną przestrzenią `@uzytkownik/nazwa-skilla`. Są w 100% prywatne (niewidoczne dla innych), dopóki autor nie zdecyduje się ich udostępnić swojemu zespołowi (`deertools skill share --team <slug>`) lub zgłosić do publikacji globalnej (`deertools skill promote`).
|
|
240
252
|
2. **Automatyczny Skaner Sekretów**:
|
|
241
253
|
- Każde wywołanie `deertools skill push` automatycznie skanuje pliki skilla w poszukiwaniu niebezpiecznych tokenów (`deer_*_live_`, `ghp_`, `sk-`, `X-BLToken`, haseł).
|
|
242
254
|
- Próba wysłania niezanominizowanych kluczy kończy się natychmiastową blokadą z kodem błędu i listą wykrytych linii.
|
package/package.json
CHANGED
package/src/agent-detector.js
CHANGED
|
@@ -3,6 +3,27 @@ const fs = require('fs');
|
|
|
3
3
|
const os = require('os');
|
|
4
4
|
const path = require('path');
|
|
5
5
|
|
|
6
|
+
const { execSync } = require('child_process');
|
|
7
|
+
const readline = require('readline');
|
|
8
|
+
const { readConfig, writeConfig } = require('./profiles');
|
|
9
|
+
|
|
10
|
+
function isBinaryInPath(cmd) {
|
|
11
|
+
try {
|
|
12
|
+
const check = process.platform === 'win32' ? `where ${cmd} 2>nul` : `which ${cmd} 2>/dev/null`;
|
|
13
|
+
execSync(check, { stdio: 'ignore', timeout: 800 });
|
|
14
|
+
return true;
|
|
15
|
+
} catch (_) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function isAppInstalled(appName) {
|
|
21
|
+
if (process.platform === 'darwin') {
|
|
22
|
+
return fs.existsSync(`/Applications/${appName}.app`) || fs.existsSync(path.join(os.homedir(), `Applications/${appName}.app`));
|
|
23
|
+
}
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
|
|
6
27
|
/**
|
|
7
28
|
* Rejestr obsługiwanych platform agentów AI.
|
|
8
29
|
* Obsługuje: Google Antigravity / Gemini, Claude Code, OpenAI Codex, Hermes AI,
|
|
@@ -19,35 +40,35 @@ const KNOWN_AGENTS = [
|
|
|
19
40
|
{
|
|
20
41
|
id: 'claude',
|
|
21
42
|
name: 'Claude Code',
|
|
22
|
-
detect: (home) => fs.existsSync(path.join(home, '.claude')),
|
|
43
|
+
detect: (home) => fs.existsSync(path.join(home, '.claude')) || isBinaryInPath('claude'),
|
|
23
44
|
getTarget: (home) => path.join(home, '.claude', 'skills'),
|
|
24
45
|
format: 'skill_md',
|
|
25
46
|
},
|
|
26
47
|
{
|
|
27
48
|
id: 'codex',
|
|
28
49
|
name: 'OpenAI Codex',
|
|
29
|
-
detect: (home) => fs.existsSync(path.join(home, '.codex')),
|
|
50
|
+
detect: (home) => fs.existsSync(path.join(home, '.codex')) || isBinaryInPath('codex'),
|
|
30
51
|
getTarget: (home) => path.join(home, '.codex', 'skills'),
|
|
31
52
|
format: 'skill_md',
|
|
32
53
|
},
|
|
33
54
|
{
|
|
34
55
|
id: 'hermes',
|
|
35
56
|
name: 'Hermes AI',
|
|
36
|
-
detect: (home) => fs.existsSync(path.join(home, '.hermes')) || fs.existsSync(path.join(home, '.config', 'hermes')) || Boolean(process.env.HERMES_HOME),
|
|
57
|
+
detect: (home) => fs.existsSync(path.join(home, '.hermes')) || fs.existsSync(path.join(home, '.config', 'hermes')) || Boolean(process.env.HERMES_HOME) || isBinaryInPath('hermes'),
|
|
37
58
|
getTarget: (home) => process.env.HERMES_SKILLS_DIR || path.join(home, '.hermes', 'skills'),
|
|
38
59
|
format: 'skill_md',
|
|
39
60
|
},
|
|
40
61
|
{
|
|
41
62
|
id: 'cursor',
|
|
42
63
|
name: 'Cursor IDE',
|
|
43
|
-
detect: (home, cwd) => fs.existsSync(path.join(cwd, '.cursor')) || fs.existsSync(path.join(home, '.cursor')),
|
|
64
|
+
detect: (home, cwd) => fs.existsSync(path.join(cwd, '.cursor')) || fs.existsSync(path.join(home, '.cursor')) || isAppInstalled('Cursor'),
|
|
44
65
|
getTarget: (home, cwd) => fs.existsSync(path.join(cwd, '.cursor')) ? path.join(cwd, '.cursor', 'rules') : path.join(home, '.cursor', 'rules'),
|
|
45
66
|
format: 'cursor_mdc',
|
|
46
67
|
},
|
|
47
68
|
{
|
|
48
69
|
id: 'windsurf',
|
|
49
70
|
name: 'Windsurf / Codeium',
|
|
50
|
-
detect: (home, cwd) => fs.existsSync(path.join(cwd, '.windsurfrules')) || fs.existsSync(path.join(cwd, '.windsurf')) || fs.existsSync(path.join(home, '.codeium')),
|
|
71
|
+
detect: (home, cwd) => fs.existsSync(path.join(cwd, '.windsurfrules')) || fs.existsSync(path.join(cwd, '.windsurf')) || fs.existsSync(path.join(home, '.codeium')) || isAppInstalled('Windsurf'),
|
|
51
72
|
getTarget: (home, cwd) => path.join(cwd, '.windsurf', 'rules'),
|
|
52
73
|
format: 'skill_md',
|
|
53
74
|
},
|
|
@@ -61,7 +82,40 @@ const KNOWN_AGENTS = [
|
|
|
61
82
|
];
|
|
62
83
|
|
|
63
84
|
/**
|
|
64
|
-
*
|
|
85
|
+
* Zwraca listę skonfigurowanych agentów użytkownika na tym PC.
|
|
86
|
+
*/
|
|
87
|
+
function getSelectedAgents() {
|
|
88
|
+
if (process.env.DEERTOOLS_AGENTS) {
|
|
89
|
+
const fromEnv = process.env.DEERTOOLS_AGENTS.split(',').map((s) => s.trim().toLowerCase()).filter(Boolean);
|
|
90
|
+
if (fromEnv.length > 0) return fromEnv;
|
|
91
|
+
}
|
|
92
|
+
const cfg = readConfig();
|
|
93
|
+
if (cfg.selectedAgents && Array.isArray(cfg.selectedAgents) && cfg.selectedAgents.length > 0) {
|
|
94
|
+
return cfg.selectedAgents.map((s) => String(s).trim().toLowerCase());
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Zapisuje listę wybranych agentów użytkownika w konfiguracji ~/.deertools/config.json.
|
|
101
|
+
*/
|
|
102
|
+
function setSelectedAgents(agentIds) {
|
|
103
|
+
const cfg = readConfig();
|
|
104
|
+
cfg.selectedAgents = agentIds.map((s) => String(s).trim().toLowerCase());
|
|
105
|
+
writeConfig(cfg);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Czyści zapisaną listę agentów (przywraca auto-detekcję wszystkich obecnych na PC).
|
|
110
|
+
*/
|
|
111
|
+
function clearSelectedAgents() {
|
|
112
|
+
const cfg = readConfig();
|
|
113
|
+
delete cfg.selectedAgents;
|
|
114
|
+
writeConfig(cfg);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Wykrywa zainstalowane środowiska agentów lub filtruje według flagi --agent / konfiguracji.
|
|
65
119
|
*/
|
|
66
120
|
function detectAgents(options = {}) {
|
|
67
121
|
const home = os.homedir();
|
|
@@ -77,7 +131,7 @@ function detectAgents(options = {}) {
|
|
|
77
131
|
}];
|
|
78
132
|
}
|
|
79
133
|
|
|
80
|
-
// Wymuszenie instalacji do WSZYSTKICH
|
|
134
|
+
// Wymuszenie instalacji do WSZYSTKICH znanych platform (--all-agents)
|
|
81
135
|
if (options['all-agents']) {
|
|
82
136
|
return KNOWN_AGENTS.map((spec) => ({
|
|
83
137
|
id: spec.id,
|
|
@@ -87,21 +141,35 @@ function detectAgents(options = {}) {
|
|
|
87
141
|
}));
|
|
88
142
|
}
|
|
89
143
|
|
|
90
|
-
// Wskazanie konkretnego agenta
|
|
144
|
+
// Wskazanie konkretnego agenta lub listy po przecinku (--agent claude,antigravity)
|
|
91
145
|
if (options.agent && options.agent !== 'all' && options.agent !== 'auto') {
|
|
92
|
-
const requested = options.agent.
|
|
93
|
-
const
|
|
94
|
-
if (
|
|
95
|
-
return
|
|
146
|
+
const requested = options.agent.split(',').map((s) => s.trim().toLowerCase()).filter(Boolean);
|
|
147
|
+
const matched = KNOWN_AGENTS.filter((spec) => requested.includes(spec.id));
|
|
148
|
+
if (matched.length > 0) {
|
|
149
|
+
return matched.map((spec) => ({
|
|
150
|
+
id: spec.id,
|
|
151
|
+
name: spec.name,
|
|
152
|
+
targetDir: spec.getTarget(home, cwd),
|
|
153
|
+
format: spec.format,
|
|
154
|
+
}));
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// Jeśli użytkownik ma zapisaną konfigurację wybranych agentów na tym PC:
|
|
159
|
+
const configured = getSelectedAgents();
|
|
160
|
+
if (configured && configured.length > 0 && !options['ignore-selected']) {
|
|
161
|
+
const matched = KNOWN_AGENTS.filter((spec) => configured.includes(spec.id));
|
|
162
|
+
if (matched.length > 0) {
|
|
163
|
+
return matched.map((spec) => ({
|
|
96
164
|
id: spec.id,
|
|
97
165
|
name: spec.name,
|
|
98
166
|
targetDir: spec.getTarget(home, cwd),
|
|
99
167
|
format: spec.format,
|
|
100
|
-
}
|
|
168
|
+
}));
|
|
101
169
|
}
|
|
102
170
|
}
|
|
103
171
|
|
|
104
|
-
// Automatyczne wykrywanie obecnych agentów
|
|
172
|
+
// Automatyczne wykrywanie obecnych agentów na PC
|
|
105
173
|
const matched = [];
|
|
106
174
|
for (const spec of KNOWN_AGENTS) {
|
|
107
175
|
try {
|
|
@@ -157,4 +225,48 @@ function installSkillContent(agent, skillName, rawMarkdown) {
|
|
|
157
225
|
return filePath;
|
|
158
226
|
}
|
|
159
227
|
|
|
160
|
-
|
|
228
|
+
/**
|
|
229
|
+
* Interaktywny prompt pytający użytkownika o wybór platform agentów w terminalu.
|
|
230
|
+
*/
|
|
231
|
+
async function promptSelectAgents(availableAgents) {
|
|
232
|
+
if (!process.stdin.isTTY) return availableAgents;
|
|
233
|
+
return new Promise((resolve) => {
|
|
234
|
+
const rl = readline.createInterface({
|
|
235
|
+
input: process.stdin,
|
|
236
|
+
output: process.stdout,
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
process.stdout.write(`\nWykryto platformy agentów AI na tym komputerze:\n`);
|
|
240
|
+
availableAgents.forEach((a, i) => {
|
|
241
|
+
process.stdout.write(` [${i + 1}] ${a.name} (${a.id})\n`);
|
|
242
|
+
});
|
|
243
|
+
process.stdout.write(`\nWybierz platformy (np. 1, 3 lub 'all') [domyślnie: wszystkie wykryte]: `);
|
|
244
|
+
|
|
245
|
+
rl.question('', (answer) => {
|
|
246
|
+
rl.close();
|
|
247
|
+
const trimmed = (answer || '').trim().toLowerCase();
|
|
248
|
+
if (!trimmed || trimmed === 'all') {
|
|
249
|
+
resolve(availableAgents);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
const parts = trimmed.split(/[\s,]+/).map((p) => parseInt(p, 10)).filter((n) => !isNaN(n) && n >= 1 && n <= availableAgents.length);
|
|
253
|
+
if (parts.length === 0) {
|
|
254
|
+
resolve(availableAgents);
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const selected = parts.map((n) => availableAgents[n - 1]);
|
|
258
|
+
resolve(selected);
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
module.exports = {
|
|
264
|
+
KNOWN_AGENTS,
|
|
265
|
+
detectAgents,
|
|
266
|
+
installSkillContent,
|
|
267
|
+
getSelectedAgents,
|
|
268
|
+
setSelectedAgents,
|
|
269
|
+
clearSelectedAgents,
|
|
270
|
+
promptSelectAgents,
|
|
271
|
+
isBinaryInPath,
|
|
272
|
+
};
|
package/src/cli.js
CHANGED
|
@@ -32,6 +32,9 @@ async function main(argv) {
|
|
|
32
32
|
const table = {
|
|
33
33
|
login: c.cmdLogin, logout: c.cmdLogout, whoami: c.cmdWhoami, docs: c.cmdDocs,
|
|
34
34
|
endpoints: c.cmdEndpoints, api: c.cmdApi, estimate: c.cmdEstimate, skill: c.cmdSkill,
|
|
35
|
+
sync: (pos, flags) => c.cmdSkill(['sync', ...pos], flags),
|
|
36
|
+
agent: c.cmdAgent, agents: c.cmdAgent,
|
|
37
|
+
team: c.cmdTeam, teams: c.cmdTeam,
|
|
35
38
|
mcp: c.cmdMcp, doctor: c.cmdDoctor, audit: c.cmdAudit, profile: c.cmdProfile,
|
|
36
39
|
completion: c.cmdCompletion, catalog: c.cmdCatalog, deliveries: c.cmdDeliveries,
|
|
37
40
|
supplier: c.cmdSupplier, rendermind: c.cmdRendermind, baselinker: c.cmdBaseLinker,
|
package/src/commands.js
CHANGED
|
@@ -379,6 +379,9 @@ async function cmdSkill(pos, flags) {
|
|
|
379
379
|
if (sub === 'bundle') {
|
|
380
380
|
return cmdSkillBundle(pos[1], flags);
|
|
381
381
|
}
|
|
382
|
+
if (sub === 'sync') {
|
|
383
|
+
return skillCommands.cmdSkillSync(flags, out, err);
|
|
384
|
+
}
|
|
382
385
|
if (sub === 'list') {
|
|
383
386
|
return skillCommands.cmdSkillList(flags, out, err);
|
|
384
387
|
}
|
|
@@ -403,10 +406,27 @@ async function cmdSkill(pos, flags) {
|
|
|
403
406
|
if (sub === 'promote') {
|
|
404
407
|
return skillCommands.cmdSkillPromote(pos[1], flags, out, err);
|
|
405
408
|
}
|
|
409
|
+
if (sub === 'review' || sub === 'reviews') {
|
|
410
|
+
return skillCommands.cmdSkillReview(pos.slice(1), flags, out, err);
|
|
411
|
+
}
|
|
412
|
+
if (sub === 'approve') {
|
|
413
|
+
return skillCommands.cmdSkillReview(['approve', ...pos.slice(1)], flags, out, err);
|
|
414
|
+
}
|
|
415
|
+
if (sub === 'reject') {
|
|
416
|
+
return skillCommands.cmdSkillReview(['reject', ...pos.slice(1)], flags, out, err);
|
|
417
|
+
}
|
|
418
|
+
if (sub === 'share') {
|
|
419
|
+
return skillCommands.cmdSkillShare(pos[1], flags, out, err);
|
|
420
|
+
}
|
|
421
|
+
if (sub === 'team' || sub === 'teams') {
|
|
422
|
+
const { cmdTeam: runTeam } = require('./team-commands');
|
|
423
|
+
return runTeam(pos.slice(1), flags, out, err);
|
|
424
|
+
}
|
|
406
425
|
if (sub === 'install') {
|
|
407
|
-
|
|
426
|
+
const target = pos[1] || (flags.all ? '--all' : null);
|
|
427
|
+
return skillCommands.cmdSkillInstall(target, flags, out, err);
|
|
408
428
|
}
|
|
409
|
-
fail('Użycie:\n deertools skill login [token]\n deertools skill bundle <architekci|kosztorysy|logistyka|sprzedaz|it>\n deertools skill list [--tag <tag>]\n deertools skill search <fraza>\n deertools skill install
|
|
429
|
+
fail('Użycie:\n deertools skill login [token]\n deertools skill sync [--force]\n deertools skill bundle <architekci|kosztorysy|logistyka|sprzedaz|it>\n deertools skill list [--tag <tag>]\n deertools skill search <fraza>\n deertools skill install [--all|<slug[@version]>]\n deertools skill check\n deertools skill update [slug]\n deertools skill versions <slug>\n deertools skill diff <slug> [wersjaA] [wersjaB]\n deertools skill push [katalog] [--team <zespół>] [--own|--global] [--bump patch|minor|major]\n deertools skill share <slug> --team <zespół>\n deertools skill review [list|approve|reject|submit]\n deertools skill promote <slug>', 2);
|
|
410
430
|
}
|
|
411
431
|
|
|
412
432
|
|
|
@@ -508,6 +528,96 @@ async function cmdMcp(pos, flags) {
|
|
|
508
528
|
fail('Użycie: deertools mcp [config|install|serve] [produkt|all] [--json]', 2);
|
|
509
529
|
}
|
|
510
530
|
|
|
531
|
+
async function cmdAgent(pos, flags) {
|
|
532
|
+
const {
|
|
533
|
+
KNOWN_AGENTS,
|
|
534
|
+
detectAgents,
|
|
535
|
+
getSelectedAgents,
|
|
536
|
+
setSelectedAgents,
|
|
537
|
+
clearSelectedAgents,
|
|
538
|
+
promptSelectAgents,
|
|
539
|
+
} = require('./agent-detector');
|
|
540
|
+
const action = pos[0] || 'list';
|
|
541
|
+
|
|
542
|
+
if (action === 'list') {
|
|
543
|
+
const selected = getSelectedAgents();
|
|
544
|
+
const detected = detectAgents({ 'ignore-selected': true });
|
|
545
|
+
const detectedIds = new Set(detected.map((a) => a.id));
|
|
546
|
+
|
|
547
|
+
out(`\n=== Platformy Agentów AI (DeerTools) ===\n`);
|
|
548
|
+
for (const a of KNOWN_AGENTS) {
|
|
549
|
+
const isDetected = detectedIds.has(a.id);
|
|
550
|
+
const isActive = selected ? selected.includes(a.id) : isDetected;
|
|
551
|
+
|
|
552
|
+
let statusBadge = '\x1b[90m[○ Niewykryty na PC]\x1b[0m';
|
|
553
|
+
if (isDetected) statusBadge = '\x1b[32m[✓ Wykryty na PC]\x1b[0m';
|
|
554
|
+
|
|
555
|
+
let activeBadge = '';
|
|
556
|
+
if (isActive) {
|
|
557
|
+
activeBadge = ' \x1b[36m(AKTYWNY DLA SKILLI)\x1b[0m';
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
out(` • ${a.id.padEnd(16)} ${(a.name).padEnd(32)} ${statusBadge}${activeBadge}`);
|
|
561
|
+
out(` Ścieżka: ${a.getTarget(os.homedir(), process.cwd())}`);
|
|
562
|
+
out('');
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
out('─'.repeat(72));
|
|
566
|
+
if (selected && selected.length > 0) {
|
|
567
|
+
out(`📌 Wybrane platformy na tym PC: \x1b[36m${selected.join(', ')}\x1b[0m (zapisane w ~/.deertools/config.json)`);
|
|
568
|
+
out(` Skille instalują się tylko u wybranych agentów.`);
|
|
569
|
+
out(` Aby przywrócić auto-wykrywanie wszystkich: \x1b[33mdeertools agent reset\x1b[0m`);
|
|
570
|
+
} else {
|
|
571
|
+
out(`⚡ Tryb: \x1b[32mAutomatyczne wykrywanie wszystkich platform obecnych na komputerze\x1b[0m`);
|
|
572
|
+
out(` Aby ograniczyć synchronizację do wybranych agentów:`);
|
|
573
|
+
out(` \x1b[36mdeertools agent select antigravity,cursor\x1b[0m`);
|
|
574
|
+
}
|
|
575
|
+
out('─'.repeat(72) + '\n');
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
if (action === 'select' || action === 'set') {
|
|
580
|
+
let targets = pos.slice(1).join(',').split(',').map((s) => s.trim().toLowerCase()).filter(Boolean);
|
|
581
|
+
if (targets.length === 0) {
|
|
582
|
+
const detected = detectAgents({ 'ignore-selected': true });
|
|
583
|
+
const picked = await promptSelectAgents(detected);
|
|
584
|
+
targets = picked.map((a) => a.id);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
const validIds = KNOWN_AGENTS.map((a) => a.id);
|
|
588
|
+
const validTargets = targets.filter((id) => validIds.includes(id));
|
|
589
|
+
|
|
590
|
+
if (validTargets.length === 0) {
|
|
591
|
+
fail(`Błąd: Podaj poprawne identyfikatory agentów: ${validIds.join(', ')}`, 2);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
setSelectedAgents(validTargets);
|
|
595
|
+
out(`✓ Zapisano aktywnych agentów na tym komputerze: \x1b[36m${validTargets.join(', ')}\x1b[0m`);
|
|
596
|
+
out(`Od teraz deertools skill sync i skill install instalują skille tylko dla tych platform.`);
|
|
597
|
+
out(`Aby przywrócić instalację u wszystkich wykrytych: deertools agent reset\n`);
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
if (action === 'reset' || action === 'clear') {
|
|
602
|
+
clearSelectedAgents();
|
|
603
|
+
out(`✓ Zresetowano konfigurację agentów. Przywrócono automatyczne wykrywanie obecnych na PC.\n`);
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
if (action === 'current') {
|
|
608
|
+
const active = detectAgents({});
|
|
609
|
+
out(active.map((a) => a.id).join(','));
|
|
610
|
+
return;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
fail(`Nieznana podkomenda „agent ${action}”. Użyj: deertools agent [list|select <agenty>|reset|current]`, 2);
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
async function cmdTeam(pos, flags) {
|
|
617
|
+
const { cmdTeam: runTeam } = require('./team-commands');
|
|
618
|
+
return runTeam(pos, flags, out, err);
|
|
619
|
+
}
|
|
620
|
+
|
|
511
621
|
const { cmdDoctor } = require('./doctor');
|
|
512
622
|
const { cmdAudit } = require('./audit');
|
|
513
623
|
const { cmdProfile } = require('./profiles');
|
|
@@ -544,12 +654,16 @@ BaseLinker MCP Proxy & Hub:
|
|
|
544
654
|
deertools baselinker catalog <search|get> Operacje katalogowe z poziomu terminala.
|
|
545
655
|
|
|
546
656
|
Integracje MCP i Agenci AI (DeerSkills Hub):
|
|
547
|
-
deertools
|
|
657
|
+
deertools agent [list|select <agenty>|reset] Wykrywanie i konfiguracja platform agentów AI na PC.
|
|
658
|
+
deertools skill list [--tag <tag>] Przegląda skille w Hubie wraz ze statusem zainstalowania.
|
|
659
|
+
deertools skill sync [--agent <id>|-i|--force] Instaluje brakujące i aktualizuje obecne skille zespołu.
|
|
660
|
+
deertools skill install [--all|<slug[@wersja]>] Instaluje wszystkie skille (--all) lub wskazany skill.
|
|
548
661
|
deertools skill search <fraza> Wyszukuje umiejętności po słowach kluczowych.
|
|
549
|
-
deertools skill install <slug[@wersja]> Instaluje skill w ~/.gemini/antigravity/skills lub .agents.
|
|
550
662
|
deertools skill versions <slug> Historia wydań z changelogami z commitów i datami.
|
|
551
663
|
deertools skill diff <slug> [wersjaA] [wersjaB] Porównanie zmian w plikach paczki i treści SKILL.md.
|
|
552
|
-
deertools skill push [katalog] [--
|
|
664
|
+
deertools skill push [katalog] [--team <zespół>] Publikuje do własnej przestrzeni, zespołu lub globalnie.
|
|
665
|
+
deertools skill share <slug> --team <zespół> Udostępnia skill prywatny wskazanemu zespołowi.
|
|
666
|
+
deertools skill review [list|approve|reject|submit] Zarządzanie procesem Peer Review i weryfikacją skilli zespołu.
|
|
553
667
|
deertools skill update [slug] Aktualizuje zainstalowane skille do najnowszej wersji.
|
|
554
668
|
deertools skill promote <slug> Zgłasza nominację skilla do oficjalnego katalogu globalnego.
|
|
555
669
|
deertools mcp list Lista dostępnych serwerów MCP w chmurze.
|
|
@@ -560,19 +674,26 @@ Integracje MCP i Agenci AI (DeerSkills Hub):
|
|
|
560
674
|
deertools endpoints <produkt> [--json] Lista endpointów REST z openapi.json.
|
|
561
675
|
deertools api <produkt> <METODA> </ścieżka> Wywołuje bezpośrednio API produktu.
|
|
562
676
|
|
|
677
|
+
Zarządzanie zespołami (DeerSkills Hub Teams):
|
|
678
|
+
deertools team [list] Przegląda listę zespołów, liczbę członków i przypisanych skilli.
|
|
679
|
+
deertools team members [zespół] Lista członków zespołów i ich ról (Lider / Członek).
|
|
680
|
+
deertools team add <zespół> <email> [--role lead] Dodaje lub aktualizuje rolę pracownika w zespole.
|
|
681
|
+
deertools team remove <zespół> <email> Usuwa pracownika ze wskazanego zespołu.
|
|
682
|
+
deertools team create <nazwa> [--slug <s>] [--desc] Tworzy nowy zespół w organizacji Deer Design.
|
|
683
|
+
|
|
563
684
|
Narzędzia systemowe:
|
|
564
685
|
deertools update Sprawdza i podpowiada aktualizację CLI.
|
|
565
686
|
deertools doctor [--json] Pełna diagnostyka połączeń, portów i kluczy.
|
|
566
687
|
deertools audit [--limit 25] [--clear] [--json] Historia operacji i wywołań API.
|
|
567
688
|
deertools completion [install|zsh|bash] Autouzupełnianie w powłoce po wciśnięciu Tab.
|
|
568
689
|
|
|
569
|
-
Zmienne środowiskowe: DEERTOOLS_<PRODUKT>_KEY, BASELINKER_TOKEN, DEERTOOLS_HOME, DEERTOOLS_PROFILE.
|
|
690
|
+
Zmienne środowiskowe: DEERTOOLS_<PRODUKT>_KEY, BASELINKER_TOKEN, DEERTOOLS_HOME, DEERTOOLS_PROFILE, DEERTOOLS_AGENTS.
|
|
570
691
|
`;
|
|
571
692
|
|
|
572
693
|
module.exports = {
|
|
573
694
|
cmdLogin, cmdLogout, cmdWhoami, cmdDocs, cmdEndpoints, cmdApi, cmdEstimate, cmdSkill, cmdMcp,
|
|
574
695
|
cmdDoctor, cmdAudit, cmdProfile, cmdCompletion, cmdCatalog, cmdDeliveries, cmdSupplier, cmdRendermind,
|
|
575
|
-
cmdBaseLinker,
|
|
696
|
+
cmdBaseLinker, cmdAgent, cmdTeam,
|
|
576
697
|
HELP, parseQuery,
|
|
577
698
|
};
|
|
578
699
|
|
package/src/mcp-stdio.js
CHANGED
|
@@ -4,6 +4,7 @@ const credentials = require('./credentials');
|
|
|
4
4
|
const { ALL_PRODUCTS, getProduct } = require('./registry');
|
|
5
5
|
const { apiRequest } = require('./http');
|
|
6
6
|
const { checkSkillUpdates, updateSkills } = require('./skill-commands');
|
|
7
|
+
const skillsHub = require('./skills-hub');
|
|
7
8
|
|
|
8
9
|
const PROTOCOL_VERSION = '2024-11-05';
|
|
9
10
|
const SERVER_INFO = { name: 'deertools-stdio-bridge', version: '1.0.5' };
|
|
@@ -113,6 +114,40 @@ async function cmdMcpServe(pos, flags) {
|
|
|
113
114
|
required: ['confirmed'],
|
|
114
115
|
},
|
|
115
116
|
},
|
|
117
|
+
{
|
|
118
|
+
name: 'deer_list_skill_reviews',
|
|
119
|
+
description: 'Pobiera kolejkę zgłoszeń skilli do Peer Review z DeerSkills Hub (zgłoszenia oczekujące, zatwierdzone lub odesłane do poprawek).',
|
|
120
|
+
inputSchema: {
|
|
121
|
+
type: 'object',
|
|
122
|
+
properties: {
|
|
123
|
+
status: { type: 'string', enum: ['pending', 'approved', 'changes_requested', 'all'], description: 'Status zgłoszenia (domyślnie pending - oczekujące)' },
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
name: 'deer_decide_skill_review',
|
|
129
|
+
description: 'Rozpatrzenie zgłoszonego skilla w Peer Review (zatwierdzenie do katalogu globalnego lub odesłanie do poprawek z uwagami) przez leada/admina.',
|
|
130
|
+
inputSchema: {
|
|
131
|
+
type: 'object',
|
|
132
|
+
properties: {
|
|
133
|
+
slug: { type: 'string', description: 'Identyfikator (slug) zgłoszonego skilla, np. deer-technical-documentation' },
|
|
134
|
+
approve: { type: 'boolean', description: 'true = zatwierdź (Approve) i przenieś do katalogu globalnego, false = odeślij do poprawek (Request Changes)' },
|
|
135
|
+
notes: { type: 'string', description: 'Uwagi i wytyczne dla autora (obowiązkowe przy odrzuceniu/poprawkach)' },
|
|
136
|
+
},
|
|
137
|
+
required: ['slug', 'approve'],
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
name: 'deer_submit_skill_review',
|
|
142
|
+
description: 'Zgłoszenie własnego opublikowanego skilla do weryfikacji zespołu / Peer Review w DeerSkills Hub.',
|
|
143
|
+
inputSchema: {
|
|
144
|
+
type: 'object',
|
|
145
|
+
properties: {
|
|
146
|
+
slug: { type: 'string', description: 'Identyfikator (slug) skilla do zgłoszenia, np. @mariusz.szostak/moj-skill' },
|
|
147
|
+
},
|
|
148
|
+
required: ['slug'],
|
|
149
|
+
},
|
|
150
|
+
},
|
|
116
151
|
];
|
|
117
152
|
|
|
118
153
|
send({ jsonrpc: '2.0', id, result: { tools } });
|
|
@@ -269,6 +304,77 @@ async function cmdMcpServe(pos, flags) {
|
|
|
269
304
|
return;
|
|
270
305
|
}
|
|
271
306
|
|
|
307
|
+
if (toolName === 'deer_list_skill_reviews') {
|
|
308
|
+
const res = await skillsHub.listReviews({ status: args.status || 'pending' });
|
|
309
|
+
if (!res.ok) {
|
|
310
|
+
send({ jsonrpc: '2.0', id, error: { code: -32000, message: res.data?.error || `Błąd pobierania (${res.status})` } });
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
send({
|
|
314
|
+
jsonrpc: '2.0',
|
|
315
|
+
id,
|
|
316
|
+
result: { content: [{ type: 'text', text: JSON.stringify(res.data, null, 2) }] },
|
|
317
|
+
});
|
|
318
|
+
return;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if (toolName === 'deer_decide_skill_review') {
|
|
322
|
+
const isUuid = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(args.slug);
|
|
323
|
+
const res = await skillsHub.decideReview({
|
|
324
|
+
slug: isUuid ? null : args.slug,
|
|
325
|
+
reviewId: isUuid ? args.slug : null,
|
|
326
|
+
approve: Boolean(args.approve),
|
|
327
|
+
notes: args.notes || '',
|
|
328
|
+
});
|
|
329
|
+
if (!res.ok) {
|
|
330
|
+
send({ jsonrpc: '2.0', id, error: { code: -32000, message: res.data?.error || `Błąd rozpatrywania (${res.status})` } });
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
send({
|
|
334
|
+
jsonrpc: '2.0',
|
|
335
|
+
id,
|
|
336
|
+
result: {
|
|
337
|
+
content: [{
|
|
338
|
+
type: 'text',
|
|
339
|
+
text: JSON.stringify({
|
|
340
|
+
success: true,
|
|
341
|
+
decision: args.approve ? 'approved' : 'changes_requested',
|
|
342
|
+
skill: res.data?.skill || res.data,
|
|
343
|
+
notes: args.notes || null,
|
|
344
|
+
message: args.approve
|
|
345
|
+
? `Skill został pomyślnie zatwierdzony i opublikowany w katalogu globalnym zespołu.`
|
|
346
|
+
: `Zgłoszenie zostało odesłane do poprawek z uwagami dla autora.`,
|
|
347
|
+
}, null, 2),
|
|
348
|
+
}],
|
|
349
|
+
},
|
|
350
|
+
});
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
if (toolName === 'deer_submit_skill_review') {
|
|
355
|
+
const res = await skillsHub.submitReview(args.slug);
|
|
356
|
+
if (!res.ok) {
|
|
357
|
+
send({ jsonrpc: '2.0', id, error: { code: -32000, message: res.data?.error || `Błąd zgłaszania (${res.status})` } });
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
send({
|
|
361
|
+
jsonrpc: '2.0',
|
|
362
|
+
id,
|
|
363
|
+
result: {
|
|
364
|
+
content: [{
|
|
365
|
+
type: 'text',
|
|
366
|
+
text: JSON.stringify({
|
|
367
|
+
success: true,
|
|
368
|
+
status: 'in_review',
|
|
369
|
+
skill: args.slug,
|
|
370
|
+
message: `Skill ${args.slug} został pomyślnie zgłoszony do Peer Review zespołu.`,
|
|
371
|
+
}, null, 2),
|
|
372
|
+
}],
|
|
373
|
+
},
|
|
374
|
+
});
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
|
|
272
378
|
send({ jsonrpc: '2.0', id, error: { code: -32601, message: `Tool not found: ${toolName}` } });
|
|
273
379
|
} catch (e) {
|
|
274
380
|
send({ jsonrpc: '2.0', id, error: { code: -32000, message: e.message } });
|