leerness 1.9.158 โ†’ 1.9.160

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/CHANGELOG.md CHANGED
@@ -1,5 +1,99 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.9.160 โ€” 2026-05-20
4
+
5
+ **๐ŸŽ‰ ์ž์œจ ๋ชจ๋“œ 90 ๋ผ์šด๋“œ ๋งˆ์ผ์Šคํ†ค + `provider sync` (์™ธ๋ถ€ catalog ์ž๋™ ๋™๊ธฐํ™”).**
6
+
7
+ ### Added โ€” `leerness provider sync <url>` (1.9.157 Provider Registry ํ™•์žฅ)
8
+ - ์™ธ๋ถ€ URL ์—์„œ provider catalog ์ž๋™ ๊ฐ€์ ธ์˜ค๊ธฐ โ€” OpenRouter llms.txt / GitHub raw JSON / ์ž์ฒด ํ˜ธ์ŠคํŠธ
9
+ - **์˜์กด์„ฑ 0 ์œ ์ง€** โ€” Node built-in `https.get` ์‚ฌ์šฉ
10
+ - 2๊ฐ€์ง€ ํ˜•์‹ ์ž๋™ ์ธ์‹:
11
+ 1. **JSON array** โ€” `[{ id, bin, envFlag?, desc?, ... }, ...]` ๋˜๋Š” `{ providers: [...] }`
12
+ 2. **llms.txt** โ€” ํ•œ ์ค„๋‹น `"id|bin|desc"` (`#` ์ฃผ์„ ๋ฌด์‹œ)
13
+ - `--dry-run` โ€” ํŒŒ์ผ ์“ฐ๊ธฐ ์Šคํ‚ตํ•˜๊ณ  ๊ฒฐ๊ณผ๋งŒ ๋ฏธ๋ฆฌ๋ณด๊ธฐ
14
+ - ๋ณด์•ˆ:
15
+ - `LEERNESS_OFFLINE=1` ์‹œ ๊ฑฐ๋ถ€
16
+ - http:// ๋˜๋Š” https:// ๊ฐ•์ œ
17
+ - response 1MB ์ œํ•œ
18
+ - timeout 15s
19
+ - 3xx redirect ์ž๋™ follow (1๋‹จ๊ณ„)
20
+ - id ์ •๊ทœ์‹ ๊ฒ€์ฆ (์˜๋ฌธ์ž/์ˆซ์ž/_- ๋งŒ โ€” sync ๋„ add ์™€ ๋™์ผ)
21
+ - ๊ฐ™์€ id ๋‘ ๋ฒˆ โ†’ ๊ฐฑ์‹  (๋ฎ์–ด์“ฐ๊ธฐ) / ์ž˜๋ชป๋œ id โ†’ skip
22
+
23
+ ### Use Case โ€” OpenRouter / Bedrock ์ผ๊ด„ ํก์ˆ˜
24
+ ```bash
25
+ # ๊ฐ€์ƒ์˜ leerness-providers catalog
26
+ leerness provider sync https://raw.githubusercontent.com/example/leerness-providers/main/openrouter.json
27
+
28
+ # ๋˜๋Š” llms.txt ํ˜•์‹
29
+ leerness provider sync https://example.com/providers.txt --dry-run
30
+ ```
31
+
32
+ ### Verified โ€” ๐ŸŽ‰ 90 ๋ผ์šด๋“œ ๋งˆ์ผ์Šคํ†ค ๋ณด๊ณ ์„œ
33
+ - `_reports/1.9.160-90-rounds-milestone.md` (๋น„๊ณต๊ฐœ)
34
+ - 1.9.140 ~ 1.9.160 โ€” 21 ๋ผ์šด๋“œ ์ง„ํ™” ํƒ€์ž„๋ผ์ธ (์‚ฌ์šฉ์ž ๋ช…์‹œ 11 / ์ž์œจ ํ›„์† 10)
35
+ - MCP ๋„๊ตฌ ์ง„ํ™”: 8 โ†’ 30 ๐ŸŽ‰ โ†’ 40 ๐ŸŽ‰ โ†’ 47 โ†’ 48 โ†’ **50 ๐ŸŽ‰**
36
+ - **21 ๋ผ์šด๋“œ ์—ฐ์† `main` ์ž๋™ sync** ์•ˆ์ •์„ฑ
37
+ - 5๋Šฅ๋ ฅ ๋งคํŠธ๋ฆญ์Šค ๊ฐฑ์‹ : 55% โ†’ **65%**
38
+
39
+ ### Pending โ€” ๋‹ค์Œ 10 ๋ผ์šด๋“œ ์ „๋ง (1.9.161 ~ 1.9.170)
40
+ 1. LSP ์–ด๋Œ‘ํ„ฐ MVP (TypeScript) โ€” 5๋Šฅ๋ ฅ #2
41
+ 2. playwright/computer-use bridge โ€” 5๋Šฅ๋ ฅ #4
42
+ 3. i18n + ์˜์–ด docs ํ† ๊ธ€
43
+ 4. REPL slash ์ถ”๊ฐ€ (`:lessons`, `:brainstorm`)
44
+
45
+ ### Verified
46
+ - e2e 217/217 โœ“
47
+ - stress-v105: 20/20 (provider sync 10์ข… + ๋งˆ์ผ์Šคํ†ค ๋ณด๊ณ ์„œ 3์ข… + ๋ˆ„์  ํšŒ๊ท€ 7์ข…) ๐ŸŽ‰ **90 ๋ผ์šด๋“œ ๋งˆ์ผ์Šคํ†ค**
48
+ - VERSION = 1.9.160 / autonomous-rounds = 90
49
+
50
+ ---
51
+
52
+ ## 1.9.159 โ€” 2026-05-20
53
+
54
+ **๐ŸŽ‰ MCP 50 ๋„๊ตฌ ๋งˆ์ผ์Šคํ†ค โ€” Provider Registry CRUD MCP ์™„์„ฑ (list/add/remove).**
55
+
56
+ ์ž์œจ ๋ชจ๋“œ 89 ๋ผ์šด๋“œ. 1.9.158 (list) ์˜ ์ž์—ฐ์Šค๋Ÿฌ์šด ํ›„์† โ€” add/remove ๊นŒ์ง€ MCP ๋กœ ๋…ธ์ถœ โ†’ ์™ธ๋ถ€ AI ๊ฐ€ ์ž๊ฐ€ ํ™•์žฅ ๊ฐ€๋Šฅ.
57
+
58
+ ### Added โ€” MCP `leerness_provider_add` (49๋ฒˆ์งธ ๋„๊ตฌ)
59
+ - ์™ธ๋ถ€ AI ๊ฐ€ ์ƒˆ provider ๋™์  ๋“ฑ๋ก โ€” OpenRouter / Bedrock / Groq / Hugging Face ๋“ฑ
60
+ - ์ธ์ž: `{ id (required), bin?, envFlag?, versionArgs?, desc?, installHint?, path? }`
61
+ - ๊ฐ™์€ id ๋‘ ๋ฒˆ โ†’ ๊ฐฑ์‹  / ๋นŒํŠธ์ธ id โ†’ user override
62
+ - id ์ •๊ทœ์‹ ๊ฒ€์ฆ (์˜๋ฌธ์ž/์ˆซ์ž/_- ๋งŒ)
63
+
64
+ ### Added โ€” MCP `leerness_provider_remove` (50๋ฒˆ์งธ ๋„๊ตฌ) ๐ŸŽ‰
65
+ - ์‚ฌ์šฉ์ž ์ •์˜ provider ๋งŒ ์ œ๊ฑฐ (๋นŒํŠธ์ธ 5์ข… โ†’ ๊ฑฐ๋ถ€)
66
+ - ์ธ์ž: `{ id (required), path? }`
67
+
68
+ ### Provider Registry CRUD MCP ์™„์„ฑ
69
+ | ์ž‘์—… | CLI | MCP | ๋งˆ์ผ์Šคํ†ค |
70
+ |---|---|---|---|
71
+ | Read | `leerness provider list` | `leerness_provider_list` | 1.9.158 (48๋ฒˆ์งธ) |
72
+ | Write | `leerness provider add` | `leerness_provider_add` | 1.9.159 (49๋ฒˆ์งธ) |
73
+ | Delete | `leerness provider remove` | `leerness_provider_remove` | 1.9.159 (50๋ฒˆ์งธ) ๐ŸŽ‰ |
74
+
75
+ ### Use Cases โ€” ์™ธ๋ถ€ AI ์ž๊ฐ€ ํ™•์žฅ
76
+ ```javascript
77
+ // ๋ฉ”์ธ ์—์ด์ „ํŠธ๊ฐ€ OpenRouter ๋ฐœ๊ฒฌ ์‹œ ์ž๊ฐ€ ๋“ฑ๋ก
78
+ await mcp.callTool('leerness_provider_add', {
79
+ id: 'openrouter', bin: 'openrouter-cli',
80
+ desc: 'OpenRouter 200+ models aggregator'
81
+ });
82
+
83
+ // ์ž˜๋ชป ๋“ฑ๋กํ•œ provider ์ž๊ฐ€ ์ •๋ฆฌ
84
+ await mcp.callTool('leerness_provider_remove', { id: 'broken-provider' });
85
+ ```
86
+
87
+ ### MCP ๋„๊ตฌ ์นด์šดํŠธ ์ง„ํ™”
88
+ - 1.9.43: 8 โ†’ 1.9.110: **30** ๐ŸŽ‰ โ†’ 1.9.128: **40** ๐ŸŽ‰ โ†’ 1.9.145: 47 โ†’ 1.9.158: 48 โ†’ **1.9.159: 50** ๐ŸŽ‰
89
+
90
+ ### Verified
91
+ - e2e 217/217 โœ“
92
+ - stress-v104: 16/16 (MCP tools/list 50๊ฐœ 3์ข… + provider_add 3์ข… + provider_remove 3์ข… + ๋ˆ„์  ํšŒ๊ท€ 7์ข…) ๐ŸŽ‰ **MCP 50 ๋„๊ตฌ ๋งˆ์ผ์Šคํ†ค**
93
+ - VERSION = 1.9.159 / autonomous-rounds = 89
94
+
95
+ ---
96
+
3
97
  ## 1.9.158 โ€” 2026-05-20
4
98
 
5
99
  **๐ŸŽ‰ MCP 48๋ฒˆ์งธ ๋„๊ตฌ `leerness_provider_list` โ€” Provider Registry ์™ธ๋ถ€ AI ๋…ธ์ถœ ๋งˆ์ผ์Šคํ†ค.**
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > **AI ์ฝ”๋”ฉ ์—์ด์ „ํŠธ์˜ ๊ฑฐ์ง“ ์™„๋ฃŒยท์ค‘๋ณตยท๋ง๊ฐยท์ถฉ๋Œ์„ ๋ง‰์•„์ฃผ๋Š” ๊ฒ€์ˆ˜ยท๊ธฐ์–ตยทํ˜‘์—… CLI ํ•˜๋„ค์Šค.**
4
4
 
5
- [![npm](https://img.shields.io/badge/npm-leerness-blue)](https://www.npmjs.com/package/leerness) [![version](https://img.shields.io/badge/version-1.9.158-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v103-12%2F12-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-48-blue)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-88-blueviolet)]() [![main-push](https://img.shields.io/badge/release--main--push-auto-success)]() [![provider-registry](https://img.shields.io/badge/provider_registry-CLI%2BMCP-success)]() [![multi-execute](https://img.shields.io/badge/agents_multi-real_spawn%2Bconsensus-success)]() [![sandbox](https://img.shields.io/badge/runCommandSafe-cwd_jail%2Benv_scrub-success)]() [![license](https://img.shields.io/badge/license-MIT-lightgrey)]()
5
+ [![npm](https://img.shields.io/badge/npm-leerness-blue)](https://www.npmjs.com/package/leerness) [![version](https://img.shields.io/badge/version-1.9.160-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v105-20%2F20-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-50-brightgreen)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-90%20%F0%9F%8E%89-brightgreen)]() [![main-push](https://img.shields.io/badge/release--main--push-21_rounds-success)]() [![provider-crud](https://img.shields.io/badge/provider_registry-CRUD%2Bsync-success)]() [![multi-execute](https://img.shields.io/badge/agents_multi-real_spawn%2Bconsensus-success)]() [![sandbox](https://img.shields.io/badge/runCommandSafe-cwd_jail%2Benv_scrub-success)]() [![license](https://img.shields.io/badge/license-MIT-lightgrey)]()
6
6
 
7
7
  ```
8
8
  โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•—
@@ -12,7 +12,7 @@
12
12
  โ•‘ โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ• โ–ˆโ–ˆโ•”โ•โ•โ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ•šโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•”โ•โ•โ• โ•šโ•โ•โ•โ•โ–ˆโ–ˆโ•‘ โ•‘
13
13
  โ•‘ โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ•‘ โ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ•‘ โ•šโ–ˆโ–ˆโ–ˆโ–ˆโ•‘โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•—โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ•‘ โ•‘
14
14
  โ•‘ โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ• โ•šโ•โ•โ•šโ•โ• โ•šโ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ•โ•šโ•โ•โ•โ•โ•โ•โ• โ•‘
15
- โ•‘ v1.9.158 AI Agent Reliability Harness + Sandbox โ•‘
15
+ โ•‘ v1.9.160 AI Agent Reliability Harness + Sandbox โ•‘
16
16
  โ•‘ verify ยท remember ยท orchestrate ยท audit ยท sandbox ยท drift โ•‘
17
17
  โ•šโ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•
18
18
  ```
package/bin/harness.js CHANGED
@@ -6,7 +6,7 @@ const path = require('path');
6
6
  const cp = require('child_process');
7
7
  const readline = require('readline');
8
8
 
9
- const VERSION = '1.9.158';
9
+ const VERSION = '1.9.160';
10
10
  const MARK = '<!-- leerness:managed -->';
11
11
  const README_START = '<!-- leerness:project-readme:start -->';
12
12
  const README_END = '<!-- leerness:project-readme:end -->';
@@ -4694,7 +4694,93 @@ function providerCmd(root, sub, ...args) {
4694
4694
  ok(`provider ์ œ๊ฑฐ: ${id}`);
4695
4695
  return;
4696
4696
  }
4697
- fail(`์•Œ ์ˆ˜ ์—†๋Š” sub: ${sub} (list / add / remove)`);
4697
+ if (sub === 'sync') {
4698
+ // 1.9.160: ์™ธ๋ถ€ catalog URL ์—์„œ provider ์ž๋™ ๋“ฑ๋ก (์˜์กด์„ฑ 0 โ€” Node built-in https)
4699
+ // ํ˜•์‹ 1: llms.txt โ€” ํ•œ ์ค„๋‹น "id|bin|desc" (์˜ˆ: "openrouter|openrouter-cli|OpenRouter 200+ models")
4700
+ // ํ˜•์‹ 2: JSON [{ id, bin, envFlag?, desc?, installHint? }, ...]
4701
+ // ๋ณด์•ˆ: LEERNESS_OFFLINE=1 ์‹œ ๊ฑฐ๋ถ€
4702
+ const url = (args[0] || arg('--url', '')).trim();
4703
+ if (!url) return fail('provider sync <url> ํ•„์š” (์˜ˆ: https://raw.githubusercontent.com/.../providers.json ๋˜๋Š” llms.txt)');
4704
+ if (process.env.LEERNESS_OFFLINE === '1') return fail('LEERNESS_OFFLINE=1 โ€” ์™ธ๋ถ€ fetch ๊ฑฐ๋ถ€ (๋ณด์•ˆ ์ •์ฑ…)');
4705
+ if (!/^https?:\/\//.test(url)) return fail(`URL ํ˜•์‹ ์˜ค๋ฅ˜: ${url} (http:// ๋˜๋Š” https://)`);
4706
+ const dryRun = has('--dry-run');
4707
+ return (async () => {
4708
+ const lib = url.startsWith('https:') ? require('https') : require('http');
4709
+ const fetchUrl = (u) => new Promise((resolve) => {
4710
+ try {
4711
+ const req = lib.get(u, { timeout: 15000, headers: { 'User-Agent': `leerness/${VERSION}` } }, (res) => {
4712
+ // redirect handling (3xx)
4713
+ if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
4714
+ return resolve(fetchUrl(res.headers.location));
4715
+ }
4716
+ if (res.statusCode !== 200) return resolve({ ok: false, error: `HTTP ${res.statusCode}` });
4717
+ let data = '';
4718
+ res.on('data', c => { data += c; if (data.length > 1024 * 1024) { req.destroy(); resolve({ ok: false, error: 'response > 1MB' }); } });
4719
+ res.on('end', () => resolve({ ok: true, body: data, contentType: res.headers['content-type'] || '' }));
4720
+ });
4721
+ req.on('error', e => resolve({ ok: false, error: e.message }));
4722
+ req.on('timeout', () => { req.destroy(); resolve({ ok: false, error: 'timeout' }); });
4723
+ } catch (e) { resolve({ ok: false, error: e.message }); }
4724
+ });
4725
+ log(`# leerness provider sync (1.9.160)`);
4726
+ log(`URL: ${url}`);
4727
+ const r = await fetchUrl(url);
4728
+ if (!r.ok) { fail(`fetch ์‹คํŒจ: ${r.error}`); process.exitCode = 1; return; }
4729
+ // ํŒŒ์‹ฑ: JSON ์šฐ์„  โ†’ llms.txt fallback
4730
+ let entries = null;
4731
+ try {
4732
+ const j = JSON.parse(r.body);
4733
+ if (Array.isArray(j)) entries = j;
4734
+ else if (Array.isArray(j.providers)) entries = j.providers;
4735
+ } catch {}
4736
+ if (!entries) {
4737
+ // llms.txt ํ˜•์‹ โ€” "id|bin|desc" ํ•œ ์ค„๋‹น
4738
+ entries = r.body.split('\n')
4739
+ .map(l => l.trim())
4740
+ .filter(l => l && !l.startsWith('#'))
4741
+ .map(l => {
4742
+ const parts = l.split('|').map(s => s.trim());
4743
+ if (parts.length < 2) return null;
4744
+ return { id: parts[0], bin: parts[1], desc: parts[2] || `(synced from ${url})` };
4745
+ })
4746
+ .filter(Boolean);
4747
+ }
4748
+ if (!entries.length) { fail(`URL ์‘๋‹ต์—์„œ provider ์ถ”์ถœ ์‹คํŒจ (JSON array ๋˜๋Š” llms.txt "id|bin|desc" ํ˜•์‹ ๊ธฐ๋Œ€)`); process.exitCode = 1; return; }
4749
+ log(`๋ฐœ๊ฒฌ ${entries.length}๊ฐœ ํ›„๋ณด`);
4750
+ log('');
4751
+ const userList = _readUserProviders(root);
4752
+ const existingIds = new Set(userList.map(u => u.id));
4753
+ const validIdRegex = /^[a-z][a-z0-9_-]*$/i;
4754
+ let added = 0, updated = 0, skipped = 0;
4755
+ for (const e of entries) {
4756
+ if (!e.id || !e.bin || !validIdRegex.test(e.id)) { skipped++; continue; }
4757
+ const entry = {
4758
+ id: e.id,
4759
+ bin: e.bin,
4760
+ envFlag: e.envFlag || `LEERNESS_ENABLE_${String(e.id).toUpperCase()}`,
4761
+ versionArgs: Array.isArray(e.versionArgs) ? e.versionArgs : (typeof e.versionArgs === 'string' ? e.versionArgs.split(/\s+/) : ['--version']),
4762
+ desc: e.desc || `(synced) ${e.id}`,
4763
+ installHint: e.installHint || ''
4764
+ };
4765
+ if (existingIds.has(e.id)) {
4766
+ const idx = userList.findIndex(u => u.id === e.id);
4767
+ if (!dryRun) userList[idx] = entry;
4768
+ updated++;
4769
+ log(` โ†บ ${e.id} (๊ฐฑ์‹ )`);
4770
+ } else {
4771
+ if (!dryRun) userList.push(entry);
4772
+ existingIds.add(e.id);
4773
+ added++;
4774
+ log(` + ${e.id} (์‹ ๊ทœ)`);
4775
+ }
4776
+ }
4777
+ if (!dryRun) _writeUserProviders(root, userList);
4778
+ log('');
4779
+ log(`โœ“ sync ์™„๋ฃŒ: ์‹ ๊ทœ ${added} ยท ๊ฐฑ์‹  ${updated} ยท ๋ฌด์‹œ ${skipped}${dryRun ? ' (--dry-run)' : ''}`);
4780
+ if (!dryRun) log(` .env ์— LEERNESS_ENABLE_<X>=1 ์„ค์ • ํ›„ \`leerness agents list\` ๋กœ ํ™•์ธ`);
4781
+ })();
4782
+ }
4783
+ fail(`์•Œ ์ˆ˜ ์—†๋Š” sub: ${sub} (list / add / remove / sync)`);
4698
4784
  }
4699
4785
 
4700
4786
  // 1.9.36: ์ž‘์—… ํ‚ค์›Œ๋“œ ๋ถ„์„์œผ๋กœ ์ตœ์  CLI ์ถ”์ฒœ
@@ -9742,7 +9828,9 @@ function mcpServeCmd(root) {
9742
9828
  { name: 'leerness_feature_add', description: '1.9.142 โ€” Feature Graph ์— ์ƒˆ ๋…ธ๋“œ ์ถ”๊ฐ€ (์™ธ๋ถ€ AI๊ฐ€ ์ฝ”๋“œ ์ž‘์„ฑ ์ค‘ ์ง์ ‘ feature ๋“ฑ๋ก). ์ธ์ž: { title (required), dependsOn?, affects?, coChangesWith?, files?, path? }. ์ž๋™ F-XXXX ID ๋ถ€์—ฌ. CRUD ์™„์„ฑ์— ๊ธฐ์—ฌ', inputSchema: { type: 'object', properties: { title: { type: 'string' }, dependsOn: { type: 'string' }, affects: { type: 'string' }, coChangesWith: { type: 'string' }, files: { type: 'string' }, path: { type: 'string' } }, required: ['title'] } },
9743
9829
  { name: 'leerness_feature_link', description: '1.9.142 โ€” ๊ธฐ์กด feature ๋…ธ๋“œ์— ์˜์กด/์˜ํ–ฅ/๊ณต๋ณ€๊ฒฝ ์—ฃ์ง€ ์ถ”๊ฐ€. ์ธ์ž: { id (required, F-XXXX), dependsOn?, affects?, coChangesWith?, path? }. ์™ธ๋ถ€ AI๊ฐ€ ์ฝ”๋“œ ๋ณ€๊ฒฝ ๋„์ค‘ ๋ฐœ๊ฒฌํ•œ ์ธ๊ณผ๊ด€๊ณ„๋ฅผ ์ฆ‰์‹œ ๊ทธ๋ž˜ํ”„์— ๋ฐ˜์˜', inputSchema: { type: 'object', properties: { id: { type: 'string' }, dependsOn: { type: 'string' }, affects: { type: 'string' }, coChangesWith: { type: 'string' }, path: { type: 'string' } }, required: ['id'] } },
9744
9830
  { name: 'leerness_env_detect', description: '1.9.145 โ€” ์‹คํ–‰ ํ™˜๊ฒฝ ์ž๋™ ๊ฐ์ง€ + ๋ณ€๋™ ์ถ”์  JSON ({ snapshot: { os, hardware, locale, shell, node, tools, scriptDependencies }, diff: { firstCapture, changes, missing }, persisted }). "X์€(๋Š”) ๋‚ด๋ถ€ ๋˜๋Š” ์™ธ๋ถ€ ๋ช…๋ น... ์•„๋‹™๋‹ˆ๋‹ค" ์‚ฌ์ „ ๋ฐฉ์ง€: package.json scripts ์˜์กด ๋„๊ตฌ๊ฐ€ PATH์— ์žˆ๋Š”์ง€ ๊ฒ€์ฆ + ๋จธ์‹ /Node/๋„๊ตฌ ๋ณ€๊ฒฝ ๊ฐ์ง€. ์ ˆ๋Œ€๊ฒฝ๋กœ ๋งˆ์Šคํ‚น (๋ณด์•ˆ). ์ธ์ž: { path? }', inputSchema: { type: 'object', properties: { path: { type: 'string' } } } },
9745
- { name: 'leerness_provider_list', description: '1.9.157/158 โ€” Provider Registry ์กฐํšŒ JSON ({ total, builtin, user, providers: [{ id, bin, envFlag, source, desc }] }). ๋นŒํŠธ์ธ 5์ข… (claude/codex/gemini/copilot/ollama) + .harness/providers.json ์‚ฌ์šฉ์ž ์ •์˜ ํ†ตํ•ฉ. ์™ธ๋ถ€ AI๊ฐ€ sub-agent ๋ถ„๋ฐฐ ๊ฐ€๋Šฅํ•œ provider ์ „์ฒด ํšŒ์ˆ˜ (OpenRouter/Bedrock ๋“ฑ ๋“ฑ๋ก๋˜์–ด ์žˆ์œผ๋ฉด ๊ฐ™์ด ๋…ธ์ถœ). ๐ŸŽ‰ MCP 48 ๋„๊ตฌ ๋งˆ์ผ์Šคํ†ค', inputSchema: { type: 'object', properties: { path: { type: 'string' } } } }
9831
+ { name: 'leerness_provider_list', description: '1.9.157/158 โ€” Provider Registry ์กฐํšŒ JSON ({ total, builtin, user, providers: [{ id, bin, envFlag, source, desc }] }). ๋นŒํŠธ์ธ 5์ข… (claude/codex/gemini/copilot/ollama) + .harness/providers.json ์‚ฌ์šฉ์ž ์ •์˜ ํ†ตํ•ฉ. ์™ธ๋ถ€ AI๊ฐ€ sub-agent ๋ถ„๋ฐฐ ๊ฐ€๋Šฅํ•œ provider ์ „์ฒด ํšŒ์ˆ˜ (OpenRouter/Bedrock ๋“ฑ ๋“ฑ๋ก๋˜์–ด ์žˆ์œผ๋ฉด ๊ฐ™์ด ๋…ธ์ถœ). ๐ŸŽ‰ MCP 48 ๋„๊ตฌ ๋งˆ์ผ์Šคํ†ค', inputSchema: { type: 'object', properties: { path: { type: 'string' } } } },
9832
+ { name: 'leerness_provider_add', description: '1.9.159 โ€” Provider Registry ์— ์ƒˆ provider ๋™์  ์ถ”๊ฐ€. ์ธ์ž: { id (required), bin?, envFlag?, versionArgs?, desc?, path? }. ์™ธ๋ถ€ AI๊ฐ€ ์ƒˆ CLI ๋ฐœ๊ฒฌ ์‹œ ์ž๊ฐ€ ํ™•์žฅ (OpenRouter / Bedrock / Groq / Hugging Face ๋“ฑ ๋“ฑ๋ก). ๊ฐ™์€ id ๋‘ ๋ฒˆ ํ˜ธ์ถœ โ†’ ๊ฐฑ์‹ . ๋นŒํŠธ์ธ id ํ˜ธ์ถœ โ†’ user override. id ๋Š” ์˜๋ฌธ์ž/์ˆซ์ž/_- ๋งŒ ํ—ˆ์šฉ.', inputSchema: { type: 'object', properties: { id: { type: 'string' }, bin: { type: 'string' }, envFlag: { type: 'string' }, versionArgs: { type: 'string' }, desc: { type: 'string' }, installHint: { type: 'string' }, path: { type: 'string' } }, required: ['id'] } },
9833
+ { name: 'leerness_provider_remove', description: '1.9.159 โ€” Provider Registry ์—์„œ ์‚ฌ์šฉ์ž ์ •์˜ provider ์ œ๊ฑฐ. ์ธ์ž: { id (required), path? }. ๋นŒํŠธ์ธ 5์ข… id ๋Š” ์ œ๊ฑฐ ๋ถˆ๊ฐ€ (override ๋งŒ ์ œ๊ฑฐ ๊ฐ€๋Šฅ). ๐ŸŽ‰ MCP 50 ๋„๊ตฌ ๋งˆ์ผ์Šคํ†ค โ€” Provider Registry CRUD MCP ์™„์„ฑ (list/add/remove)', inputSchema: { type: 'object', properties: { id: { type: 'string' }, path: { type: 'string' } }, required: ['id'] } }
9746
9834
  ];
9747
9835
 
9748
9836
  function send(obj) {
@@ -9837,6 +9925,18 @@ function mcpServeCmd(root) {
9837
9925
  case 'leerness_env_detect': cliArgs = ['env', 'detect', targetPath, '--json']; break;
9838
9926
  // 1.9.158: Provider Registry โ€” ์™ธ๋ถ€ AI ๊ฐ€ ๋“ฑ๋ก๋œ provider ํšŒ์ˆ˜
9839
9927
  case 'leerness_provider_list': cliArgs = ['provider', 'list', '--path', targetPath, '--json']; break;
9928
+ // 1.9.159: Provider Registry CRUD โ€” ์™ธ๋ถ€ AI ๊ฐ€ ์ž๊ฐ€ ํ™•์žฅ
9929
+ case 'leerness_provider_add':
9930
+ cliArgs = ['provider', 'add', String(args.id || ''), '--path', targetPath];
9931
+ if (args.bin) cliArgs.push('--bin', String(args.bin));
9932
+ if (args.envFlag) cliArgs.push('--env-flag', String(args.envFlag));
9933
+ if (args.versionArgs) cliArgs.push('--version-args', String(args.versionArgs));
9934
+ if (args.desc) cliArgs.push('--desc', String(args.desc));
9935
+ if (args.installHint) cliArgs.push('--install-hint', String(args.installHint));
9936
+ break;
9937
+ case 'leerness_provider_remove':
9938
+ cliArgs = ['provider', 'remove', String(args.id || ''), '--path', targetPath];
9939
+ break;
9840
9940
  default:
9841
9941
  return send({ jsonrpc: '2.0', id, error: { code: -32601, message: `Unknown tool: ${name}` } });
9842
9942
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "leerness",
3
- "version": "1.9.158",
3
+ "version": "1.9.160",
4
4
  "description": "Leerness: ๋น„ํŒŒ๊ดด ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜, ์ž๋™ ๋ฒ„์ „ ๊ฐ์ง€ยท์—…๋ฐ์ดํŠธ, ๊ณ„ํš/์ง„ํ–‰/ํ•ธ๋“œ์˜คํ”„ ์ž๋™ํ™”, ๊ฒŒ์œผ๋ฆ„ยท์‹œํฌ๋ฆฟยท์ธ์ฝ”๋”ฉ ์ž๋™ ๊ฐ€๋“œ, Claude Code ์Šฌ๋ž˜์‹œ ํ†ตํ•ฉ์„ ๊ฐ–์ถ˜ ํ•œ๊ตญ์–ด ์šฐ์„  AI ๊ฐœ๋ฐœ ํ•˜๋„ค์Šค.",
5
5
  "keywords": [
6
6
  "leerness",