@deerdesign/deertools 1.2.12 → 1.2.13

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deerdesign/deertools",
3
- "version": "1.2.12",
3
+ "version": "1.2.13",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "registry": "https://registry.npmjs.org/"
package/src/commands.js CHANGED
@@ -57,7 +57,14 @@ async function cmdLogin(pos, flags) {
57
57
  }
58
58
 
59
59
  const products = resolveProducts(pos[0]);
60
- const scope = flags.write ? 'read write' : normalizeScope(flags.scope || 'read');
60
+ const requestedScope = flags.admin
61
+ ? 'admin'
62
+ : (flags.ro || flags['read-only'])
63
+ ? 'read'
64
+ : (flags.rw || flags.write)
65
+ ? 'read write'
66
+ : (flags.scope || 'read');
67
+ const scope = normalizeScope(requestedScope);
61
68
  let failures = 0;
62
69
  for (const product of products) {
63
70
  out(`\n=== ${product.name} ===`);
@@ -514,7 +521,7 @@ DeerTools CLI — ekosystem narzędzi dla architektów i agentów AI Deer Design
514
521
  Produkty: ${ALL_IDS.join(', ')}
515
522
 
516
523
  Dostęp i autoryzacja:
517
- deertools login <produkt|all> [--write] [--no-open] Logowanie OAuth przez przeglądarkę.
524
+ deertools login <produkt|all> [--ro|--rw|--admin] Logowanie OAuth (RO: tylko odczyt, RW: zapis, Admin).
518
525
  deertools logout [produkt|all] Usuwa lokalny klucz.
519
526
  deertools whoami [produkt|all] [--json] Status logowania, zakres, ważność.
520
527
  deertools profile [list|use <nazwa>|current] Przełączanie profili poświadczeń.
package/src/login.js CHANGED
@@ -7,7 +7,7 @@ const credentials = require('./credentials');
7
7
 
8
8
  const CLIENT_ID = 'deertools-cli';
9
9
  const LOGIN_TIMEOUT_MS = 5 * 60 * 1000;
10
- const VALID_SCOPES = ['read', 'write'];
10
+ const VALID_SCOPES = ['read', 'write', 'admin'];
11
11
 
12
12
  const b64url = (buf) => Buffer.from(buf).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
13
13
 
@@ -21,14 +21,24 @@ function escapeHtml(s) {
21
21
  }
22
22
 
23
23
  function normalizeScope(input) {
24
- const list = String(input || 'read').split(/[\s,]+/).filter(Boolean);
24
+ if (!input) return 'read';
25
+ const raw = String(input).toLowerCase().trim();
26
+ if (raw === 'ro' || raw === 'read-only') return 'read';
27
+ if (raw === 'rw' || raw === 'read-write') return 'read write';
28
+ if (raw === 'admin') return 'read write admin';
29
+
30
+ const list = raw.split(/[\s,]+/).filter(Boolean);
25
31
  const bad = list.filter((s) => !VALID_SCOPES.includes(s));
26
32
  if (bad.length) {
27
- const err = new Error(`Nieznany zakres: ${bad.join(', ')}. Dozwolone: ${VALID_SCOPES.join(', ')}.`);
33
+ const err = new Error(`Nieznany zakres: ${bad.join(', ')}. Dozwolone: ${VALID_SCOPES.join(', ')} (lub aliasy: ro, rw, admin).`);
28
34
  err.exitCode = 2;
29
35
  throw err;
30
36
  }
31
37
  const set = new Set(list.length ? list : ['read']);
38
+ if (set.has('admin')) {
39
+ set.add('write');
40
+ set.add('read');
41
+ }
32
42
  if (set.has('write')) set.add('read'); // zapis zakłada odczyt
33
43
  return VALID_SCOPES.filter((s) => set.has(s)).join(' ');
34
44
  }
package/src/mcp-stdio.js CHANGED
@@ -103,12 +103,14 @@ async function cmdMcpServe(pos, flags) {
103
103
  },
104
104
  {
105
105
  name: 'deer_update_skills',
106
- description: 'Autonomiczna aktualizacja skilli Deer Design — pobiera najnowsze wersje paczek z DeerSkills Hub i odświeża plik blokady.',
106
+ description: 'Autonomiczna aktualizacja skilli Deer Design — pobiera najnowsze wersje paczek z DeerSkills Hub i odświeża plik blokady. WYMAGA POTWIERDZENIA CZŁOWIEKA (Human-in-the-Loop) — parametr confirmed=true po zatwierdzeniu przez użytkownika.',
107
107
  inputSchema: {
108
108
  type: 'object',
109
109
  properties: {
110
110
  slug: { type: 'string', description: 'Opcjonalny slug konkretnego skilla do zaktualizowania (np. deer-kosztorys). Domyślnie aktualizuje wszystkie przestarzałe skille.' },
111
+ confirmed: { type: 'boolean', description: 'Wymagany bezpiecznik HITL: true tylko po uprzednim zapytaniu człowieka o zgodę w ankiecie (ask_question).' },
111
112
  },
113
+ required: ['confirmed'],
112
114
  },
113
115
  },
114
116
  ];
@@ -227,6 +229,25 @@ async function cmdMcpServe(pos, flags) {
227
229
  }
228
230
 
229
231
  if (toolName === 'deer_update_skills') {
232
+ if (args.confirmed !== true) {
233
+ send({
234
+ jsonrpc: '2.0',
235
+ id,
236
+ result: {
237
+ content: [{
238
+ type: 'text',
239
+ text: JSON.stringify({
240
+ status: 'requires_human_confirmation',
241
+ message: 'BEZPIECZNIK HITL (Human-in-the-Loop): Operacja aktualizacji skilli modyfikuje pliki w środowisku użytkownika. Agent AI NIE MOŻE sam podjąć tej decyzji ani pominąć człowieka.',
242
+ instruction_for_agent: 'Wyświetl użytkownikowi interaktywną ankietę (np. narzędziem ask_question w Antigravity) pytając o zgodę na aktualizację: „Czy zatwierdzasz aktualizację skilli: ' + (args.slug || 'wszystkie przestarzałe skille') + '?”. Dopiero po kliknięciu potwierdzenia przez człowieka wywołaj deer_update_skills ponownie z argumentem confirmed: true.',
243
+ target_skills: args.slug || 'all',
244
+ }, null, 2),
245
+ }],
246
+ },
247
+ });
248
+ return;
249
+ }
250
+
230
251
  const res = await updateSkills(args.slug || null);
231
252
  send({
232
253
  jsonrpc: '2.0',