leerness 1.9.194 β 1.9.196
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 +129 -0
- package/README.md +3 -3
- package/bin/harness.js +176 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,134 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.9.196 β 2026-05-21
|
|
4
|
+
|
|
5
|
+
**π DμΆ (μ₯κΈ° λ§₯λ½ μ μ§) λ³΄κ° β 7μΌ+ μ₯κΈ° μ 체 + 30μΌ+ lessons νκ³ + ScheduleWakeup miss detector.**
|
|
6
|
+
|
|
7
|
+
μμ¨ λͺ¨λ 126 λΌμ΄λ. μ¬μ©μ λͺ
μ:
|
|
8
|
+
> *"λ€μ λΌμ΄λ μ§ννκ³ , ScheduleWakeup κ° μ μμ μΌλ‘ μλνλλ‘ μ‘°μ·¨λ₯Ό μ·¨ν΄μ€"*
|
|
9
|
+
|
|
10
|
+
5μΆ λ§€νΈλ¦μ€ λ§μ§λ§ λ―Έλ³΄κ° μΆμΈ **DμΆ (9.5/10 β λͺ©ν 10/10)** + μ¬μ©μ λͺ
μ ScheduleWakeup μμ ν.
|
|
11
|
+
|
|
12
|
+
### 1. DμΆ ν΅μ¬ β μ₯κΈ° μ 체 + 30μΌ+ νκ³ (handoff μλ)
|
|
13
|
+
**7μΌ+ critical λ¨κ³** (24h+ lazy λ€μ λ¨κ³):
|
|
14
|
+
```
|
|
15
|
+
## β μ§μ² μ 체 κ°μ§ (1.9.194 EμΆ) β progress-tracker λ§μ§λ§ λ³λ 8d μ
|
|
16
|
+
...
|
|
17
|
+
π΄ 7μΌ+ μ₯κΈ° μ 체 (8d) β μ₯κΈ° λ§₯λ½ μμ€ μν (1.9.196 DμΆ)
|
|
18
|
+
β μ¦μ νκ³ : leerness retro . --since 8d
|
|
19
|
+
β λλ archive: leerness task drop T-XXXX
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**30μΌ+ μ₯κΈ° lessons νκ³ ** (long-term memory recall):
|
|
23
|
+
- handoff keyword λ§€μΉ + lessons.md 30μΌ+ μ λΈλ‘
|
|
24
|
+
- μ μΉμ
: `## π μ₯κΈ° lessons νκ³ (1.9.196 DμΆ) β ν€μλ "X" κ΄λ ¨ 30μΌ+ N건`
|
|
25
|
+
- μνμ§ κ³Όκ±° κ΅ν μλ μ¬μκΈ° β κ°μ μ€μ λ°λ³΅ λ°©μ§
|
|
26
|
+
- λκΈ°: `--no-longterm-recall` / `LEERNESS_NO_LONGTERM_RECALL=1`
|
|
27
|
+
|
|
28
|
+
### 2. ScheduleWakeup μμ ν (μ¬μ©μ λͺ
μ) β λ€μΈ΅ redundancy
|
|
29
|
+
**Layer 1**: λ μ§§μ ScheduleWakeup (1.9.193λΆν° 900s β **270s** β 5λΆ cache μμ μ μ§)
|
|
30
|
+
**Layer 2**: CronCreate every 13min (durable: false) β primary λλ½ μ backup
|
|
31
|
+
**Layer 3**: handoffμ wakeup miss detector β 60λΆ+ 무 νλ μ μλ¦Ό
|
|
32
|
+
```
|
|
33
|
+
## β° ScheduleWakeup miss μμ¬ (1.9.196) β λ§μ§λ§ νλ 90λΆ μ
|
|
34
|
+
μμ¨ λͺ¨λ μ μ cycle: ~15λΆ. 60λΆ μ΄μ 무 νλ β μμ€ν
sleep λλ wakeup λλ½
|
|
35
|
+
β μ¬κ°: μ¬μ©μκ° "λ€μ λΌμ΄λ" λλ "/loop" μ
λ ₯
|
|
36
|
+
```
|
|
37
|
+
λκΈ°: `LEERNESS_NO_WAKEUP_MISS=1`
|
|
38
|
+
|
|
39
|
+
### 3. λμ νκ· (1.9.190~195) β λͺ¨λ μ μ§
|
|
40
|
+
- [1.9.195] _probeProviderEndpoints (provider universal probe)
|
|
41
|
+
- [1.9.194] _suggestNextActions (handoff next-actions)
|
|
42
|
+
- [1.9.193] agents multi consensus β lessons.md
|
|
43
|
+
- [1.9.192] _loadOfficialSkillCache + 24h μΊμ
|
|
44
|
+
- [1.9.191] ꡬ쑰 μ΅μ ν λ³΄κ³ μ 88/100
|
|
45
|
+
- [1.9.190] _selectOne/_selectMany Ctrl+C μ¦μ μ’
λ£
|
|
46
|
+
|
|
47
|
+
### 4. stress-v141 β 15/15 PASS
|
|
48
|
+
- DμΆ λ³΄κ° (6: ν¨μ + 7μΌ+ + 30μΌ+ + miss detector + μμ μν¬μ€νμ΄μ€ ν΅ν©) + μ±λ₯ (2) + λμ νκ· (7)
|
|
49
|
+
- μ±λ₯: --version cold start avg **709 ms** Β· MCP 54 λꡬ **534 ms**
|
|
50
|
+
|
|
51
|
+
### 5. 5μΆ λ§€νΈλ¦μ€ λ³λ
|
|
52
|
+
| μΆ | 1.9.195 | 1.9.196 | Ξ |
|
|
53
|
+
|---|---|---|---|
|
|
54
|
+
| D. μ₯κΈ° λ§₯λ½ μ μ§ | 9.5/10 | **10/10** | +0.5 (7μΌ+ critical + 30μΌ+ recall + miss detector) |
|
|
55
|
+
| μ’
ν© | 46.5/50 (93%) | **47/50 (94%)** | +1% |
|
|
56
|
+
|
|
57
|
+
### 6. 5μΆ λͺ¨λ λ³΄κ° μλ£
|
|
58
|
+
| μΆ | μμ | νμ¬ | Ξ |
|
|
59
|
+
|---|---|---|---|
|
|
60
|
+
| A. λ²μ© AI νλ€μ€ | 9 | **9.5** | +0.5 (1.9.195 probe) |
|
|
61
|
+
| B. λ©ν° Sub-Agent | 8.5 | **9** | +0.5 (1.9.193 consensus lessons) |
|
|
62
|
+
| C. 곡μ μ€ν¬ μλ | 8 | **9** | +1 (1.9.192 official catalog) |
|
|
63
|
+
| D. μ₯κΈ° λ§₯λ½ μ μ§ | 9.5 | **10** | +0.5 (1.9.196 7μΌ+/30μΌ+ recall) |
|
|
64
|
+
| E. κ²μΌλ¦ λ°©μ§ | 9 | **9.5** | +0.5 (1.9.194 next-actions) |
|
|
65
|
+
| **μ’
ν©** | 44/50 (88%) | **47/50 (94%)** | **+6%** |
|
|
66
|
+
|
|
67
|
+
### 7. μλ release νλ¦
|
|
68
|
+
- main μλ push **58 λΌμ΄λ μ°μ** (1.9.140~196)
|
|
69
|
+
- npm publish μλ (1.9.178~)
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## 1.9.195 β 2026-05-21
|
|
74
|
+
|
|
75
|
+
**π AμΆ (λ²μ© AI νλ€μ€) λ³΄κ° β `leerness provider probe` μ κ· λͺ
λ Ή (CLI/endpoint/API ν€ 3μ’
μλ κ°μ§).**
|
|
76
|
+
|
|
77
|
+
μμ¨ λͺ¨λ 125 λΌμ΄λ. 1.9.192 C / 193 B / 194 E 보κ°μ μ΄μ΄ **AμΆ (9/10 β λͺ©ν 9.5/10)** 보κ°.
|
|
78
|
+
|
|
79
|
+
### μ¬μ©μ μλ μ λ ¬ (1.9.191 verbatim)
|
|
80
|
+
> *"λ²μ© AI νλ€μ€ ... μ΅κ³ μ λꡬ"*
|
|
81
|
+
|
|
82
|
+
### 1. `leerness provider probe` μ κ· λͺ
λ Ή (AμΆ ν΅μ¬)
|
|
83
|
+
- **3μ’
μλ κ°μ§** (μμ‘΄μ± 0 β Node built-in cp + http):
|
|
84
|
+
1. **CLI binaries**: claude / codex / gemini / copilot / ollama (PATH + `--version`)
|
|
85
|
+
2. **Local endpoint**: Ollama (11434) / LM Studio (1234) / llama.cpp (8080)
|
|
86
|
+
3. **Cloud API key**: OPENROUTER / GROQ / TOGETHER / ANTHROPIC / OPENAI
|
|
87
|
+
|
|
88
|
+
- **μΆλ ₯ μ΅μ
**: `--json` (μλν/CI) Β· ν
μ€νΈ λ§ν¬λ€μ΄ (μ¬λ μ½κΈ°)
|
|
89
|
+
- **νμμμ**: `--timeout 1500` (κΈ°λ³Έ, ms)
|
|
90
|
+
- **νκ²½λ³μ override**: `OLLAMA_HOST` / `LMSTUDIO_HOST` / `LLAMACPP_HOST`
|
|
91
|
+
|
|
92
|
+
### 2. μ€ μΈ‘μ (κ°λ° PC)
|
|
93
|
+
```
|
|
94
|
+
| id | bin | found | version |
|
|
95
|
+
| claude | claude | β | 2.1.146 (Claude Code) |
|
|
96
|
+
| codex | codex | β | codex-cli 0.132.0 |
|
|
97
|
+
| gemini | gemini | β | - |
|
|
98
|
+
| copilot | copilot | β | - |
|
|
99
|
+
| ollama | ollama | β | (installed) |
|
|
100
|
+
|
|
101
|
+
β μ¬μ© κ°λ₯ ν보 3건
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### 3. μ κ· ν¨μ
|
|
105
|
+
- `_probeProviderEndpoints(root, timeoutMs)` β 3μ’
ν΅ν© κ°μ§
|
|
106
|
+
- `_probeHttpEndpoint(url, timeoutMs)` β Promise κΈ°λ° HTTP reachability check
|
|
107
|
+
|
|
108
|
+
### 4. λμ νκ· (1.9.189~194) β λͺ¨λ μ μ§
|
|
109
|
+
- [1.9.194] _suggestNextActions + lazy κ°μ§
|
|
110
|
+
- [1.9.193] agents multi consensus β lessons.md
|
|
111
|
+
- [1.9.192] _loadOfficialSkillCache + 24h μΊμ
|
|
112
|
+
- [1.9.191] ꡬ쑰 μ΅μ ν λ³΄κ³ μ 88/100
|
|
113
|
+
- [1.9.190] _selectOne/_selectMany Ctrl+C μ¦μ μ’
λ£
|
|
114
|
+
- [1.9.189] _showSlashCommandList + Tab cycle ν μ€ κ°±μ
|
|
115
|
+
|
|
116
|
+
### 5. stress-v140 β 15/15 PASS
|
|
117
|
+
- provider probe (6: ν¨μ + 3μ’
λμ + --json + ν
μ€νΈ) + μ±λ₯ (2) + λμ νκ· (7)
|
|
118
|
+
- μ±λ₯: --version cold start avg **442 ms** Β· MCP 54 λꡬ **514 ms**
|
|
119
|
+
|
|
120
|
+
### 6. 5μΆ λ§€νΈλ¦μ€ λ³λ
|
|
121
|
+
| μΆ | 1.9.194 | 1.9.195 | Ξ |
|
|
122
|
+
|---|---|---|---|
|
|
123
|
+
| A. λ²μ© AI νλ€μ€ | 9/10 | **9.5/10** | +0.5 (universal probe β 11 backend ν보 μλ κ°μ§) |
|
|
124
|
+
| μ’
ν© | 46/50 (92%) | **46.5/50 (93%)** | +1% |
|
|
125
|
+
|
|
126
|
+
### 7. μλ release νλ¦
|
|
127
|
+
- main μλ push **57 λΌμ΄λ μ°μ** (1.9.140~195)
|
|
128
|
+
- npm publish μλ (1.9.178~)
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
3
132
|
## 1.9.194 β 2026-05-21
|
|
4
133
|
|
|
5
134
|
**π― EμΆ (κ²μΌλ¦ λ°©μ§) λ³΄κ° β handoff λ€μ λ¨κ³ μλ μ μ + 24h+ 무μ§μ² lazy κ°μ§.**
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> **AI μ½λ© μμ΄μ νΈμ κ±°μ§ μλ£Β·μ€λ³΅Β·λ§κ°Β·μΆ©λμ λ§μμ£Όλ κ²μΒ·κΈ°μ΅Β·νμ
CLI νλ€μ€.**
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/leerness) [](https://www.npmjs.com/package/leerness) []() []() []() []() []() []() [-brightgreen)]() []() []() []() []() []()
|
|
6
6
|
|
|
7
7
|
```
|
|
8
8
|
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
β βββ ββββββ ββββββ ββββββββββββββββββββββββ ββββββββ β
|
|
13
13
|
β βββββββββββββββββββββββββββ ββββββ ββββββββββββββββββββββ β
|
|
14
14
|
β βββββββββββββββββββββββββββ ββββββ βββββββββββββββββββββ β
|
|
15
|
-
β v1.9.
|
|
15
|
+
β v1.9.196 AI Agent Reliability Harness + Sandbox β
|
|
16
16
|
β verify Β· remember Β· orchestrate Β· audit Β· sandbox Β· drift β
|
|
17
|
-
β
|
|
17
|
+
β π 5μΆ λ³΄κ° μλ£ (94/100) Β· 30μΌ+ recall Β· 126 λΌμ΄λ β
|
|
18
18
|
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
19
19
|
```
|
|
20
20
|
|
package/bin/harness.js
CHANGED
|
@@ -7,7 +7,7 @@ const cp = require('child_process');
|
|
|
7
7
|
const os = require('os'); // 1.9.178: _publishToNpm μμ os.tmpdir() μ¬μ© (μ μ import)
|
|
8
8
|
const readline = require('readline');
|
|
9
9
|
|
|
10
|
-
const VERSION = '1.9.
|
|
10
|
+
const VERSION = '1.9.196';
|
|
11
11
|
|
|
12
12
|
// 1.9.184: DEP0190 (child_process shell: true) deprecation warning μ΅μ (μ¬μ©μ λͺ
μ).
|
|
13
13
|
// leerness λ cross-platform PATH resolution μ μν΄ shell: true λ₯Ό μλμ μΌλ‘ μ¬μ© (claude.cmd / ollama.cmd λ± Windows .cmd μ²λ¦¬).
|
|
@@ -3704,6 +3704,51 @@ function handoff(root) {
|
|
|
3704
3704
|
log(dim(` β λ³κ²½: leerness task update ${latestRow.id} --status in-progress λλ --status completed`));
|
|
3705
3705
|
log(dim(` β νκ³ : leerness lazy detect --json`));
|
|
3706
3706
|
log('');
|
|
3707
|
+
// 1.9.196: DμΆ (μ₯κΈ° λ§₯λ½) λ³΄κ° β 7μΌ+ critical λ¨κ³ μλ¦Ό + μλ νκ³ κΆμ₯
|
|
3708
|
+
if (ageHours >= 24 * 7) {
|
|
3709
|
+
const days = Math.floor(ageHours / 24);
|
|
3710
|
+
log(yel(` π΄ 7μΌ+ μ₯κΈ° μ 체 (${days}d) β μ₯κΈ° λ§₯λ½ μμ€ μν (1.9.196 DμΆ)`));
|
|
3711
|
+
log(dim(` β μ¦μ νκ³ : leerness retro . --since ${days}d`));
|
|
3712
|
+
log(dim(` β λλ archive: leerness task drop ${latestRow.id}`));
|
|
3713
|
+
log('');
|
|
3714
|
+
}
|
|
3715
|
+
}
|
|
3716
|
+
}
|
|
3717
|
+
} catch {}
|
|
3718
|
+
}
|
|
3719
|
+
// 1.9.196: DμΆ (μ₯κΈ° λ§₯λ½ μ μ§) λ³΄κ° β 30μΌ+ μ lessons μλ νκ³ (long-term memory recall)
|
|
3720
|
+
// keyword μ λ§€μΉλλ 30μΌ+ μ€λλ lessons 1건 λ
ΈμΆ β μνμ§ κ³Όκ±° κ΅ν μ¬μκΈ°
|
|
3721
|
+
// λκΈ°: --no-longterm-recall λλ LEERNESS_NO_LONGTERM_RECALL=1
|
|
3722
|
+
if (!has('--no-longterm-recall') && !has('--quiet') && process.env.LEERNESS_NO_LONGTERM_RECALL !== '1') {
|
|
3723
|
+
try {
|
|
3724
|
+
const lp = lessonsPath(root);
|
|
3725
|
+
if (exists(lp)) {
|
|
3726
|
+
const lt = read(lp);
|
|
3727
|
+
const cutoff = Date.now() - 30 * 24 * 3600 * 1000;
|
|
3728
|
+
const fuzzyRe = new RegExp(escapeRegex(keyword.slice(0, Math.max(4, Math.floor(keyword.length * 0.7)))), 'i');
|
|
3729
|
+
// ### YYYY-MM-DD λΈλ‘ λΆλ¦¬ β 30μΌ+ μ΄μ + keyword λ§€μΉ
|
|
3730
|
+
const blocks = lt.split(/\n### /).slice(1).map(b => '### ' + b);
|
|
3731
|
+
const matches = [];
|
|
3732
|
+
for (const b of blocks) {
|
|
3733
|
+
const m = b.match(/^### (\d{4}-\d{2}-\d{2})/);
|
|
3734
|
+
if (!m) continue;
|
|
3735
|
+
const blockDate = new Date(m[1]).getTime();
|
|
3736
|
+
if (isNaN(blockDate) || blockDate > cutoff) continue;
|
|
3737
|
+
if (fuzzyRe.test(b)) matches.push({ date: m[1], title: (b.split('\n')[0] || '').slice(0, 80) });
|
|
3738
|
+
}
|
|
3739
|
+
if (matches.length > 0) {
|
|
3740
|
+
const isTty = process.stdout && process.stdout.isTTY;
|
|
3741
|
+
const blu = s => isTty ? `\x1b[34m${s}\x1b[0m` : s;
|
|
3742
|
+
const dim = s => isTty ? `\x1b[2m${s}\x1b[0m` : s;
|
|
3743
|
+
const oldest = matches[matches.length - 1];
|
|
3744
|
+
const ageDays = Math.floor((Date.now() - new Date(oldest.date).getTime()) / (24 * 3600 * 1000));
|
|
3745
|
+
log(blu(`## π μ₯κΈ° lessons νκ³ (1.9.196 DμΆ) β ν€μλ "${keyword}" κ΄λ ¨ 30μΌ+ ${matches.length}건`));
|
|
3746
|
+
log(dim(` μ΅μ€λλ: ${oldest.date} (${ageDays}μΌ μ ) β ${oldest.title}`));
|
|
3747
|
+
if (matches.length > 1) {
|
|
3748
|
+
log(dim(` μ΅κ·Ό30μΌ+: ${matches[0].date} β ${matches[0].title}`));
|
|
3749
|
+
}
|
|
3750
|
+
log(dim(` β μ 체 νκ³ : cat .harness/lessons.md`));
|
|
3751
|
+
log('');
|
|
3707
3752
|
}
|
|
3708
3753
|
}
|
|
3709
3754
|
} catch {}
|
|
@@ -3712,6 +3757,29 @@ function handoff(root) {
|
|
|
3712
3757
|
}
|
|
3713
3758
|
} catch {}
|
|
3714
3759
|
}
|
|
3760
|
+
// 1.9.196: ScheduleWakeup miss detector β μμ¨ λͺ¨λ μ¬μ©μ λͺ
μ "λͺ»μΌμ΄λλ κ²½μ° μ’
μ’
μμ" (1.9.191) νμ
|
|
3761
|
+
// λ§μ§λ§ session μκ° (handoff mtime λλ task-log λ§μ§λ§ entry) > 2h ago μ μλ¦Ό
|
|
3762
|
+
// λκΈ°: LEERNESS_NO_WAKEUP_MISS=1
|
|
3763
|
+
if (process.env.LEERNESS_NO_WAKEUP_MISS !== '1' && !has('--quiet') && !has('--no-wakeup-miss')) {
|
|
3764
|
+
try {
|
|
3765
|
+
const tlp = taskLogPath(root);
|
|
3766
|
+
if (exists(tlp)) {
|
|
3767
|
+
const ageMs = Date.now() - fs.statSync(tlp).mtimeMs;
|
|
3768
|
+
const ageMin = Math.floor(ageMs / 60000);
|
|
3769
|
+
// μμ¨ λͺ¨λλ ~15λΆ cycle. 60λΆ μ΄μ 무 νλμ΄λ©΄ wakeup miss μμ¬ (CronCreate 13min λ°±μ
κ³Ό ν¨κ»)
|
|
3770
|
+
if (ageMin >= 60) {
|
|
3771
|
+
const isTty = process.stdout && process.stdout.isTTY;
|
|
3772
|
+
const yel = s => isTty ? `\x1b[33m${s}\x1b[0m` : s;
|
|
3773
|
+
const dim = s => isTty ? `\x1b[2m${s}\x1b[0m` : s;
|
|
3774
|
+
const label = ageMin < 120 ? `${ageMin}λΆ` : (ageMin < 1440 ? `${Math.floor(ageMin/60)}μκ°` : `${Math.floor(ageMin/1440)}μΌ`);
|
|
3775
|
+
log(yel(`## β° ScheduleWakeup miss μμ¬ (1.9.196) β λ§μ§λ§ νλ ${label} μ `));
|
|
3776
|
+
log(dim(` μμ¨ λͺ¨λ μ μ cycle: ~15λΆ. 60λΆ μ΄μ 무 νλ β μμ€ν
sleep λλ wakeup λλ½ κ°λ₯μ±`));
|
|
3777
|
+
log(dim(` β μ¬κ°: μ¬μ©μκ° "λ€μ λΌμ΄λ" λλ "/loop" μ
λ ₯`));
|
|
3778
|
+
log('');
|
|
3779
|
+
}
|
|
3780
|
+
}
|
|
3781
|
+
} catch {}
|
|
3782
|
+
}
|
|
3715
3783
|
// 1.9.121: μ΅κ·Ό λ©λͺ¨λ¦¬ λ³λ μλ¦Ό β 24h λ΄ μΆκ°λ 5μ’
surface νλͺ© μΉ΄μ΄νΈ
|
|
3716
3784
|
// AI μμ΄μ νΈκ° μ΄μ μΈμ
μ’
λ£ ν μ΄λ€ λ©λͺ¨λ¦¬κ° μΆκ°λλμ§ μ¦μ μΈμ§.
|
|
3717
3785
|
// λκΈ°: --no-mem-delta λλ LEERNESS_NO_MEM_DELTA=1
|
|
@@ -5506,7 +5574,113 @@ function providerCmd(root, sub, ...args) {
|
|
|
5506
5574
|
if (!dryRun) log(` .env μ LEERNESS_ENABLE_<X>=1 μ€μ ν \`leerness agents list\` λ‘ νμΈ`);
|
|
5507
5575
|
})();
|
|
5508
5576
|
}
|
|
5509
|
-
|
|
5577
|
+
// 1.9.195: provider probe β AμΆ (λ²μ© AI νλ€μ€) 보κ°. μ¬μ©μ μλ: "λ²μ© AI νλ€μ€ ... μ΅κ³ μ λꡬ"
|
|
5578
|
+
// μμ€ν
μ μ¬μ© κ°λ₯ν provider μλ κ°μ§ (PATH λͺ
λ Ή + λ‘컬 endpoint + API ν€ νκ²½λ³μ)
|
|
5579
|
+
// κ°μ§ λμ:
|
|
5580
|
+
// - CLI: claude / codex / gemini / copilot / ollama (PATH check)
|
|
5581
|
+
// - Local endpoint: Ollama (11434) / LM Studio (1234) / llama.cpp server (8080)
|
|
5582
|
+
// - Cloud API key: OPENROUTER_API_KEY / GROQ_API_KEY / TOGETHER_API_KEY / ANTHROPIC_API_KEY / OPENAI_API_KEY
|
|
5583
|
+
// κ²°κ³Ό β table + LEERNESS_ENABLE_* μ€μ κΆμ₯
|
|
5584
|
+
if (sub === 'probe') {
|
|
5585
|
+
return (async () => {
|
|
5586
|
+
const json = has('--json');
|
|
5587
|
+
const timeoutMs = Number(arg('--timeout', '1500'));
|
|
5588
|
+
const results = await _probeProviderEndpoints(root, timeoutMs);
|
|
5589
|
+
if (json) { log(JSON.stringify(results, null, 2)); return; }
|
|
5590
|
+
log(`# leerness provider probe (1.9.195 β AμΆ λ²μ© AI νλ€μ€ 보κ°)`);
|
|
5591
|
+
log(`νμμμ: ${timeoutMs}ms`);
|
|
5592
|
+
log('');
|
|
5593
|
+
log('## CLI binaries (PATH)');
|
|
5594
|
+
log('| id | bin | found | version |');
|
|
5595
|
+
log('|---|---|---|---|');
|
|
5596
|
+
for (const r of results.cli) {
|
|
5597
|
+
log(`| ${r.id} | ${r.bin} | ${r.found ? 'β' : 'β'} | ${r.version || '-'} |`);
|
|
5598
|
+
}
|
|
5599
|
+
log('');
|
|
5600
|
+
log('## Local endpoint (HTTP)');
|
|
5601
|
+
log('| name | url | reachable | latency |');
|
|
5602
|
+
log('|---|---|---|---|');
|
|
5603
|
+
for (const r of results.endpoints) {
|
|
5604
|
+
log(`| ${r.name} | ${r.url} | ${r.reachable ? 'β' : 'β'} | ${r.latencyMs != null ? r.latencyMs + 'ms' : '-'} |`);
|
|
5605
|
+
}
|
|
5606
|
+
log('');
|
|
5607
|
+
log('## Cloud API keys (.env)');
|
|
5608
|
+
log('| key | present | mask |');
|
|
5609
|
+
log('|---|---|---|');
|
|
5610
|
+
for (const r of results.cloudKeys) {
|
|
5611
|
+
log(`| ${r.key} | ${r.present ? 'β' : 'β'} | ${r.mask || '-'} |`);
|
|
5612
|
+
}
|
|
5613
|
+
log('');
|
|
5614
|
+
const total = results.cli.filter(x => x.found).length + results.endpoints.filter(x => x.reachable).length + results.cloudKeys.filter(x => x.present).length;
|
|
5615
|
+
log(`β μ¬μ© κ°λ₯ ν보 ${total}건`);
|
|
5616
|
+
log(' β νμ±ν: .env μ LEERNESS_ENABLE_<ID>=1 + ENDPOINT/API ν€ μ€μ ');
|
|
5617
|
+
log(' β νμΈ: leerness agents list');
|
|
5618
|
+
})();
|
|
5619
|
+
}
|
|
5620
|
+
fail(`μ μ μλ sub: ${sub} (list / add / remove / sync / probe)`);
|
|
5621
|
+
}
|
|
5622
|
+
|
|
5623
|
+
// 1.9.195: provider probe ν΅μ¬ β CLI/endpoint/API ν€ 3μ’
κ°μ§
|
|
5624
|
+
// μμ‘΄μ± 0 β Node built-in cp.spawnSync (CLI version) + http.get (endpoint) + process.env (API key)
|
|
5625
|
+
async function _probeProviderEndpoints(root, timeoutMs) {
|
|
5626
|
+
const result = { cli: [], endpoints: [], cloudKeys: [], at: new Date().toISOString() };
|
|
5627
|
+
// 1) CLI binaries β PATH + --version
|
|
5628
|
+
const cliTargets = [
|
|
5629
|
+
{ id: 'claude', bin: 'claude' },
|
|
5630
|
+
{ id: 'codex', bin: 'codex' },
|
|
5631
|
+
{ id: 'gemini', bin: 'gemini' },
|
|
5632
|
+
{ id: 'copilot', bin: 'copilot' },
|
|
5633
|
+
{ id: 'ollama', bin: 'ollama' }
|
|
5634
|
+
];
|
|
5635
|
+
for (const t of cliTargets) {
|
|
5636
|
+
try {
|
|
5637
|
+
const r = cp.spawnSync(t.bin, ['--version'], { encoding: 'utf8', timeout: timeoutMs, shell: true });
|
|
5638
|
+
// exit 0 λλ stdout μ "vX.Y.Z" λΉμ·ν ννκ° μμΌλ©΄ found μ²λ¦¬
|
|
5639
|
+
const out = (r.stdout || '').trim();
|
|
5640
|
+
const errOut = (r.stderr || '').trim();
|
|
5641
|
+
const looksLikeVersion = /\d+\.\d+\.\d+|\bversion\b/i.test(out);
|
|
5642
|
+
const found = r.status === 0 || looksLikeVersion;
|
|
5643
|
+
result.cli.push({ id: t.id, bin: t.bin, found, version: found ? (out.split('\n')[0].slice(0, 40) || null) : null });
|
|
5644
|
+
} catch (e) {
|
|
5645
|
+
result.cli.push({ id: t.id, bin: t.bin, found: false, version: null });
|
|
5646
|
+
}
|
|
5647
|
+
}
|
|
5648
|
+
// 2) Local endpoints β http GET (μμ‘΄μ± 0)
|
|
5649
|
+
const endpointTargets = [
|
|
5650
|
+
{ name: 'ollama', url: process.env.OLLAMA_HOST || 'http://localhost:11434', path: '/api/tags' },
|
|
5651
|
+
{ name: 'lmstudio', url: process.env.LMSTUDIO_HOST || 'http://localhost:1234', path: '/v1/models' },
|
|
5652
|
+
{ name: 'llama.cpp', url: process.env.LLAMACPP_HOST || 'http://localhost:8080', path: '/health' }
|
|
5653
|
+
];
|
|
5654
|
+
for (const t of endpointTargets) {
|
|
5655
|
+
const reach = await _probeHttpEndpoint(t.url + t.path, timeoutMs);
|
|
5656
|
+
result.endpoints.push({ name: t.name, url: t.url + t.path, reachable: reach.ok, latencyMs: reach.latencyMs, status: reach.status });
|
|
5657
|
+
}
|
|
5658
|
+
// 3) Cloud API keys β .env
|
|
5659
|
+
const cloudKeys = ['OPENROUTER_API_KEY', 'GROQ_API_KEY', 'TOGETHER_API_KEY', 'ANTHROPIC_API_KEY', 'OPENAI_API_KEY'];
|
|
5660
|
+
for (const k of cloudKeys) {
|
|
5661
|
+
const val = process.env[k] || '';
|
|
5662
|
+
const present = val.length >= 10;
|
|
5663
|
+
result.cloudKeys.push({ key: k, present, mask: present ? `${val.slice(0, 4)}...${val.slice(-2)}` : null });
|
|
5664
|
+
}
|
|
5665
|
+
return result;
|
|
5666
|
+
}
|
|
5667
|
+
|
|
5668
|
+
// 1.9.195: HTTP endpoint reachability check (μμ‘΄μ± 0)
|
|
5669
|
+
function _probeHttpEndpoint(url, timeoutMs) {
|
|
5670
|
+
return new Promise((resolve) => {
|
|
5671
|
+
try {
|
|
5672
|
+
const lib = url.startsWith('https:') ? require('https') : require('http');
|
|
5673
|
+
const t0 = Date.now();
|
|
5674
|
+
const req = lib.get(url, { timeout: timeoutMs }, (res) => {
|
|
5675
|
+
res.on('data', () => {});
|
|
5676
|
+
res.on('end', () => resolve({ ok: res.statusCode < 500, status: res.statusCode, latencyMs: Date.now() - t0 }));
|
|
5677
|
+
});
|
|
5678
|
+
req.on('timeout', () => { req.destroy(); resolve({ ok: false, latencyMs: null, status: null }); });
|
|
5679
|
+
req.on('error', () => resolve({ ok: false, latencyMs: null, status: null }));
|
|
5680
|
+
} catch {
|
|
5681
|
+
resolve({ ok: false, latencyMs: null, status: null });
|
|
5682
|
+
}
|
|
5683
|
+
});
|
|
5510
5684
|
}
|
|
5511
5685
|
|
|
5512
5686
|
// 1.9.36: μμ
ν€μλ λΆμμΌλ‘ μ΅μ CLI μΆμ²
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "leerness",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.196",
|
|
4
4
|
"description": "Leerness: λΉνκ΄΄ λ§μ΄κ·Έλ μ΄μ
, μλ λ²μ κ°μ§Β·μ
λ°μ΄νΈ, κ³ν/μ§ν/νΈλμ€ν μλν, κ²μΌλ¦Β·μν¬λ¦ΏΒ·μΈμ½λ© μλ κ°λ, Claude Code μ¬λμ ν΅ν©μ κ°μΆ νκ΅μ΄ μ°μ AI κ°λ° νλ€μ€.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"leerness",
|