leerness 1.9.179 β 1.9.180
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 +68 -0
- package/README.md +3 -3
- package/bin/harness.js +44 -11
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,73 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.9.180 β 2026-05-21
|
|
4
|
+
|
|
5
|
+
**π§ REPL Tab cycle ν΅μ¬ fix + μ±ν
μμ separator β μ¬μ©μ λͺ
μ (μ§μ ꡬλ ν
μ€νΈ κ²°κ³Ό).**
|
|
6
|
+
|
|
7
|
+
μμ¨ λͺ¨λ 110 λΌμ΄λ. μ¬μ©μ λͺ
μ: *"REPL agent λͺ¨λλ₯Ό λ€κ° μ§μ ꡬλν΄μ ν
μ€νΈν΄μ€ / REPL agent λͺ¨λλ κ³ μ λ ν€λμ μ±ν
νμμ΄μ΄μΌν΄ / κ·Έλ¦¬κ³ λͺ¨λΈμ΄λ νλ‘λ°μ΄λ μ νμ΄ μννμ§μμκ±°κ°μ"*.
|
|
8
|
+
|
|
9
|
+
### ν΅μ¬ fix β Tab cycle μ€ λμ 보μ₯
|
|
10
|
+
|
|
11
|
+
#### 1. readline `completer` no-op
|
|
12
|
+
```js
|
|
13
|
+
// 1.9.180: completer no-op β readlineμ μ체 Tab completionμ΄ keypress 리μ€λλ₯Ό κ°λ‘μ±λ λ¬Έμ μ°¨λ¨
|
|
14
|
+
const rl = readline.createInterface({
|
|
15
|
+
input: process.stdin,
|
|
16
|
+
output: process.stdout,
|
|
17
|
+
completer: (line) => [[], line]
|
|
18
|
+
});
|
|
19
|
+
```
|
|
20
|
+
μ΄μ : μ¬μ©μκ° Tabμ λλ₯΄λ©΄ readline κΈ°λ³Έ completerκ° λΉ κ²°κ³Όλ₯Ό νμνλ©° promptλ₯Ό μ¬μΆλ ₯ν΄ keypress 리μ€λκ° λμνμ§ μμ λκ° μμμ.
|
|
21
|
+
μ§κΈ: `completer: () => [[], line]` λͺ
μλ‘ readlineμ Tab κ°λ‘μ±κΈ° μ°¨λ¨ β keypress 리μ€λκ° νμ λ°λ.
|
|
22
|
+
|
|
23
|
+
#### 2. Shift+Tab β `cycleModel(false)` λ§€ν μμ (CRITICAL)
|
|
24
|
+
```js
|
|
25
|
+
process.stdin.on('keypress', (str, key) => {
|
|
26
|
+
if (!key) return;
|
|
27
|
+
if (key.name === 'tab') {
|
|
28
|
+
// 1.9.180 fix: Shift+Tab β cycleModel (μ΄μ cycleProvider μλͺ»)
|
|
29
|
+
if (key.shift === true) {
|
|
30
|
+
cycleModel(false); // Shift+Tab β νμ¬ providerμ λͺ¨λΈ cycle
|
|
31
|
+
} else {
|
|
32
|
+
cycleProvider(false); // Tab β λ€μ provider
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
μ΄μ (1.9.170): `cycleProvider(key.shift)` β Shift+Tabμ provider reverse μκ³ model cycle ν€κ° μμμ.
|
|
38
|
+
μ§κΈ: μ¬μ©μ μλλλ‘ `Tab=provider`, `Shift+Tab=model`.
|
|
39
|
+
|
|
40
|
+
### μκ° νΌλλ°± κ°ν (μ¬μ©μ λͺ
μ: "μννμ§ μμ")
|
|
41
|
+
```
|
|
42
|
+
β provider [3/5]: claude β ready
|
|
43
|
+
β 7κ° λͺ¨λΈ catalog Β· Shift+TabμΌλ‘ model cycle
|
|
44
|
+
|
|
45
|
+
β model [2/7]: claude-opus-4
|
|
46
|
+
β μ΅μ thinking λͺ¨λΈ
|
|
47
|
+
```
|
|
48
|
+
- bold green provider Β· bold magenta model
|
|
49
|
+
- `[idx/total]` μμΉ/μ΄μ νμ
|
|
50
|
+
- ready/β status νμ± μ¬λΆ νμ
|
|
51
|
+
- catalog λͺ¨λΈ μ λ
ΈμΆ
|
|
52
|
+
|
|
53
|
+
### μ±ν
μμ separator (μ¬μ©μ λͺ
μ: "κ³ μ λ ν€λμ μ±ν
νμ")
|
|
54
|
+
```
|
|
55
|
+
[... νμ νλ©΄ (ν€λ + Tips + What's new + Slash + ν€λ³΄λ + μνλ°) ...]
|
|
56
|
+
|
|
57
|
+
βββββββββββββββββββββββββββββ μ±ν
μμ βββββββββββββββββββββββββββββ
|
|
58
|
+
λ©μμ§ μ
λ ₯ ν Enter Β· :help μΌλ‘ λͺ
λ Ή λͺ©λ‘ Β· Ctrl+C λ‘ μ’
λ£
|
|
59
|
+
|
|
60
|
+
agent[ollama/actor/βΆ]> _
|
|
61
|
+
```
|
|
62
|
+
νμ νλ©΄ (κ³ μ ν€λ) κ³Ό μ
λ ₯ μμ (μ±ν
) μ μκ°μ ꡬλΆμ λͺ
ννκ².
|
|
63
|
+
|
|
64
|
+
### Verified
|
|
65
|
+
- e2e 217/217 baseline μ μ§
|
|
66
|
+
- stress-v125: **17/17** (Tab cycle fix 3 + μκ° νΌλλ°± 4 + μ±ν
μμ 3 + λμ νκ· 7)
|
|
67
|
+
- VERSION = 1.9.180 Β· autonomous-rounds = 110 Β· main μλ push 41 λΌμ΄λ μ°μ
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
3
71
|
## 1.9.179 β 2026-05-21
|
|
4
72
|
|
|
5
73
|
**π¨ REPL νμ νλ©΄ μ¬λμμΈ β Hermes/Claude/Codex/Gemini CLI μ€νμΌ (μ¬μ©μ λͺ
μ).**
|
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) []() []() []() []() []() []() []() []() []() []() []() []()
|
|
6
6
|
|
|
7
7
|
```
|
|
8
8
|
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
β βββ ββββββ ββββββ ββββββββββββββββββββββββ ββββββββ β
|
|
13
13
|
β βββββββββββββββββββββββββββ ββββββ ββββββββββββββββββββββ β
|
|
14
14
|
β βββββββββββββββββββββββββββ ββββββ βββββββββββββββββββββ β
|
|
15
|
-
β v1.9.
|
|
15
|
+
β v1.9.180 AI Agent Reliability Harness + Sandbox β
|
|
16
16
|
β verify Β· remember Β· orchestrate Β· audit Β· sandbox Β· drift β
|
|
17
|
-
β
|
|
17
|
+
β π§ REPL Tab cycle fix Β· μ±ν
μμ separator (κ³ μ ν€λ+μ±ν
) β
|
|
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.180';
|
|
11
11
|
const MARK = '<!-- leerness:managed -->';
|
|
12
12
|
const README_START = '<!-- leerness:project-readme:start -->';
|
|
13
13
|
const README_END = '<!-- leerness:project-readme:end -->';
|
|
@@ -11053,7 +11053,13 @@ async function _agentRepl(root, opts) {
|
|
|
11053
11053
|
// 1.9.153: .env μλ λ‘λ (REPL μ§μ
μ§μ ) β install μ§ν LEERNESS_ENABLE_* μ¦μ λ°μ
|
|
11054
11054
|
try { _loadEnvFile(root); } catch {}
|
|
11055
11055
|
const readline = require('readline');
|
|
11056
|
-
|
|
11056
|
+
// 1.9.180: completer no-op β readline μ Tab completion κ°λ‘μ±κΈ°λ₯Ό μ°¨λ¨ν΄ keypress 리μ€λκ° Tab cycleμ μ²λ¦¬.
|
|
11057
|
+
// (μ¬μ©μ λͺ
μ: "λͺ¨λΈ/νλ‘λ°μ΄λ μ νμ΄ μννμ§ μλ€" β readline Tab completionμ΄ cycle ν€λ₯Ό κ°λ‘μ±λ κ²½μ° fix)
|
|
11058
|
+
const rl = readline.createInterface({
|
|
11059
|
+
input: process.stdin,
|
|
11060
|
+
output: process.stdout,
|
|
11061
|
+
completer: (line) => [[], line] // λΉ completion + μλ³Έ line λ°ν β Tabμ keypress 리μ€λλ‘λ§ μ²λ¦¬
|
|
11062
|
+
});
|
|
11057
11063
|
const isTty = process.stdout.isTTY;
|
|
11058
11064
|
const C = isTty ? {
|
|
11059
11065
|
cy: s => `\x1b[36m${s}\x1b[0m`, dim: s => `\x1b[2m${s}\x1b[0m`,
|
|
@@ -11187,6 +11193,11 @@ async function _agentRepl(root, opts) {
|
|
|
11187
11193
|
+ C.green(`role=${state.role}`) + ' Β· '
|
|
11188
11194
|
+ C.yel(`perms=${permMode}`) + ' Β· '
|
|
11189
11195
|
+ (state.streamMode ? C.green('βΆ stream=on') : C.dim('β‘ stream=off')));
|
|
11196
|
+
// 1.9.180: μ±ν
μμ μ§μ
separator (μ¬μ©μ λͺ
μ β "κ³ μ ν€λ + μ±ν
νμ")
|
|
11197
|
+
// νμ νλ©΄ λμ λͺ
νν ꡬλΆμ + μλ΄ β μ±ν
μμ λͺ
ν.
|
|
11198
|
+
log('');
|
|
11199
|
+
log(C.dim(' βββββββββββββββββββββββββββββ μ±ν
μμ βββββββββββββββββββββββββββββ'));
|
|
11200
|
+
log(C.dim(' λ©μμ§ μ
λ ₯ ν Enter Β· :help μΌλ‘ λͺ
λ Ή λͺ©λ‘ Β· Ctrl+C λ‘ μ’
λ£'));
|
|
11190
11201
|
// 1.9.155: REPL μ§μ
μ handoff 컨ν
μ€νΈ μλ λ
ΈμΆ (UX κ°μ β μ¬μ©μκ° λ§€λ² :handoff μ ν΄λ 컨ν
μ€νΈ μΈμ§)
|
|
11191
11202
|
try {
|
|
11192
11203
|
const hf = cp.spawnSync(process.execPath, [__filename, 'handoff', root, '--compact', '--no-drift-check', '--no-headline'], {
|
|
@@ -11224,20 +11235,34 @@ async function _agentRepl(root, opts) {
|
|
|
11224
11235
|
} catch {}
|
|
11225
11236
|
return _PROVIDER_CYCLE_ORDER.slice();
|
|
11226
11237
|
};
|
|
11238
|
+
// 1.9.180: cycleProvider/cycleModel β μκ° νΌλλ°± κ°ν (μ¬μ©μ λͺ
μ "μννμ§ μλ€").
|
|
11239
|
+
// μ΄μ : ν μ€ β λ©μμ§λ§. 1.9.180: provider μμΉ νμ [1/5] + bold highlight + νμ± μ¬λΆ νμ.
|
|
11227
11240
|
const cycleProvider = (reverse) => {
|
|
11228
11241
|
const list = getProviders();
|
|
11229
11242
|
let idx = list.indexOf(state.provider);
|
|
11230
11243
|
if (idx < 0) idx = 0;
|
|
11231
11244
|
idx = reverse ? (idx - 1 + list.length) % list.length : (idx + 1) % list.length;
|
|
11232
11245
|
state.provider = list[idx];
|
|
11233
|
-
state.model = null;
|
|
11246
|
+
state.model = null;
|
|
11234
11247
|
const cat = _PROVIDER_MODEL_CATALOG[state.provider];
|
|
11235
|
-
|
|
11236
|
-
|
|
11248
|
+
// νμ± μ¬λΆ μ¬μ νμΈ (1.9.180 UX β μ¬μ©μκ° μ¦μ μΈμ§)
|
|
11249
|
+
let activeMark = '';
|
|
11250
|
+
try {
|
|
11251
|
+
if (state.provider !== 'ollama') {
|
|
11252
|
+
const agent = EXTERNAL_AGENTS.find(a => a.id === state.provider);
|
|
11253
|
+
if (agent) {
|
|
11254
|
+
const st = _checkAgent(agent);
|
|
11255
|
+
activeMark = st.status === 'ready' ? C.green(' β ready') : C.yel(` β ${st.status}`);
|
|
11256
|
+
}
|
|
11257
|
+
}
|
|
11258
|
+
} catch {}
|
|
11237
11259
|
process.stdout.write('\r\x1b[K');
|
|
11238
|
-
process.stdout.write(C.green(` β provider: ${state.provider}
|
|
11260
|
+
process.stdout.write(C.bold(C.green(` β provider [${idx + 1}/${list.length}]: ${state.provider}`)) + activeMark + '\n');
|
|
11261
|
+
if (cat?.length) {
|
|
11262
|
+
process.stdout.write(C.dim(` β ${cat.length}κ° λͺ¨λΈ catalog Β· Shift+TabμΌλ‘ model cycle\n`));
|
|
11263
|
+
}
|
|
11239
11264
|
rl.setPrompt(prompt());
|
|
11240
|
-
rl.prompt(true);
|
|
11265
|
+
rl.prompt(true);
|
|
11241
11266
|
};
|
|
11242
11267
|
const cycleModel = (reverse) => {
|
|
11243
11268
|
const cat = _PROVIDER_MODEL_CATALOG[state.provider] || [];
|
|
@@ -11252,17 +11277,25 @@ async function _agentRepl(root, opts) {
|
|
|
11252
11277
|
idx = reverse ? (idx - 1 + cat.length) % cat.length : (idx + 1) % cat.length;
|
|
11253
11278
|
state.model = cat[idx].id;
|
|
11254
11279
|
process.stdout.write('\r\x1b[K');
|
|
11255
|
-
process.stdout.write(C.
|
|
11280
|
+
process.stdout.write(C.bold(C.mag(` β model [${idx + 1}/${cat.length}]: ${state.model}`)) + '\n');
|
|
11281
|
+
if (cat[idx].note) {
|
|
11282
|
+
process.stdout.write(C.dim(` β ${cat[idx].note}\n`));
|
|
11283
|
+
}
|
|
11256
11284
|
rl.setPrompt(prompt());
|
|
11257
11285
|
rl.prompt(true);
|
|
11258
11286
|
};
|
|
11259
11287
|
process.stdin.on('keypress', (str, key) => {
|
|
11260
11288
|
if (!key) return;
|
|
11261
11289
|
if (key.name === 'tab') {
|
|
11262
|
-
|
|
11290
|
+
// 1.9.180 fix: Shift+Tab β cycleModel (μ¬μ©μ λͺ
μ μλ).
|
|
11291
|
+
// μ΄μ (1.9.170): cycleProvider(key.shift) β Shift+Tab μ provider reverse cycleλ§ λμ΄ model μ νμ΄ λΆκ°λ₯νμ.
|
|
11292
|
+
// μ¬μ©μ λͺ
μ: "Tab=provider, Shift+Tab=model μ νκ³Ό μ νμ΄ κ°νΈνκ²".
|
|
11293
|
+
if (key.shift === true) {
|
|
11294
|
+
cycleModel(false); // Shift+Tab β νμ¬ providerμ λ€μ model
|
|
11295
|
+
} else {
|
|
11296
|
+
cycleProvider(false); // Tab β λ€μ provider
|
|
11297
|
+
}
|
|
11263
11298
|
}
|
|
11264
|
-
// Shift+\ λλ λ€λ₯Έ λͺ¨λΈ cycle alias β μΌλΆ ν°λ―Έλμμ Shift+Tab μ²λ¦¬ μ΄λ €μ λλΉ
|
|
11265
|
-
// (Shift+Tabμ key.name='tab' + key.shift=true λ‘ μμμ μ²λ¦¬λ¨)
|
|
11266
11299
|
});
|
|
11267
11300
|
} catch (e) {
|
|
11268
11301
|
log(C.dim(` (Tab cycle λΉνμ±: ${e.message})`));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "leerness",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.180",
|
|
4
4
|
"description": "Leerness: λΉνκ΄΄ λ§μ΄κ·Έλ μ΄μ
, μλ λ²μ κ°μ§Β·μ
λ°μ΄νΈ, κ³ν/μ§ν/νΈλμ€ν μλν, κ²μΌλ¦Β·μν¬λ¦ΏΒ·μΈμ½λ© μλ κ°λ, Claude Code μ¬λμ ν΅ν©μ κ°μΆ νκ΅μ΄ μ°μ AI κ°λ° νλ€μ€.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"leerness",
|