leerness 1.9.159 โ†’ 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,54 @@
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
+
3
52
  ## 1.9.159 โ€” 2026-05-20
4
53
 
5
54
  **๐ŸŽ‰ MCP 50 ๋„๊ตฌ ๋งˆ์ผ์Šคํ†ค โ€” Provider Registry CRUD MCP ์™„์„ฑ (list/add/remove).**
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.159-green)]() [![tests](https://img.shields.io/badge/e2e-217%2F217-success)]() [![stress](https://img.shields.io/badge/stress--v104-16%2F16-success)]() [![mcp](https://img.shields.io/badge/MCP--tools-50%20%F0%9F%8E%89-brightgreen)]() [![rounds](https://img.shields.io/badge/autonomous--rounds-89-blueviolet)]() [![main-push](https://img.shields.io/badge/release--main--push-auto-success)]() [![provider-crud](https://img.shields.io/badge/provider_registry-CRUD_MCP_complete-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.159 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.159';
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 ์ถ”์ฒœ
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "leerness",
3
- "version": "1.9.159",
3
+ "version": "1.9.160",
4
4
  "description": "Leerness: ๋น„ํŒŒ๊ดด ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜, ์ž๋™ ๋ฒ„์ „ ๊ฐ์ง€ยท์—…๋ฐ์ดํŠธ, ๊ณ„ํš/์ง„ํ–‰/ํ•ธ๋“œ์˜คํ”„ ์ž๋™ํ™”, ๊ฒŒ์œผ๋ฆ„ยท์‹œํฌ๋ฆฟยท์ธ์ฝ”๋”ฉ ์ž๋™ ๊ฐ€๋“œ, Claude Code ์Šฌ๋ž˜์‹œ ํ†ตํ•ฉ์„ ๊ฐ–์ถ˜ ํ•œ๊ตญ์–ด ์šฐ์„  AI ๊ฐœ๋ฐœ ํ•˜๋„ค์Šค.",
5
5
  "keywords": [
6
6
  "leerness",