leerness 1.9.178 โ 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 +135 -0
- package/README.md +3 -3
- package/bin/harness.js +110 -28
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,140 @@
|
|
|
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
|
+
|
|
71
|
+
## 1.9.179 โ 2026-05-21
|
|
72
|
+
|
|
73
|
+
**๐จ REPL ํ์ ํ๋ฉด ์ฌ๋์์ธ โ Hermes/Claude/Codex/Gemini CLI ์คํ์ผ (์ฌ์ฉ์ ๋ช
์).**
|
|
74
|
+
|
|
75
|
+
์์จ ๋ชจ๋ 109 ๋ผ์ด๋. ์ฌ์ฉ์ ๋ช
์: ์ฒจ๋ถ ์ด๋ฏธ์ง (Hermes Agent v0.7.0 / Claude Code v2.1.126 / OpenAI Codex v0.132.0 / Gemini CLI v0.42.0) ์ฒ๋ผ ๊ตฌ์กฐํ๋ ํ์ ํ๋ฉด.
|
|
76
|
+
|
|
77
|
+
### ๋์์ธ ๊ตฌ์ฑ โ 5 ์น์
|
|
78
|
+
```
|
|
79
|
+
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
|
|
80
|
+
โ Leerness Agent v1.9.179 (2026-05-21) ยท ๊ฒ์ยท๊ธฐ์ตยท์๋๋ฐ์ค ํตํฉ AI โ
|
|
81
|
+
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
|
|
82
|
+
|
|
83
|
+
โธ Welcome back ยท leerness (.)
|
|
84
|
+
โธ Session: sess-2026-05-21T13-41-23
|
|
85
|
+
|
|
86
|
+
โโ Tips for getting started โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
87
|
+
โ Tab / Shift+Tab โ provider / model ์ ํ (1.9.170) โ
|
|
88
|
+
โ :review "<req>" โ ๋ฌด์กฐ๊ฑด ๊ตฌํ ์ ์ฌ์ ๊ฒํ (1.9.176) โ
|
|
89
|
+
โ :permissions <m> โ ์ฆ์ ๊ถํ ๋ณ๊ฒฝ basic|extended|full (1.9.174) โ
|
|
90
|
+
โ :stream on|off โ ์ค์๊ฐ ์คํธ๋ฆฌ๋ฐ ํ ๊ธ (default ON, 1.9.170/172) โ
|
|
91
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
92
|
+
|
|
93
|
+
โโ What's new (1.9.170~178) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
94
|
+
โ โข REPL Tab cycle + ์ค์๊ฐ ์คํธ๋ฆฌ๋ฐ (spinner / tool_use / diff ์๊น) โ
|
|
95
|
+
โ โข Bridge slash :web/:pc/:lsp REPL ์ฆ์ ํธ์ถ + LSP ๋ค๊ตญ์ด 5์ข
โ
|
|
96
|
+
โ โข review-request ์ฌ์ ๊ฒํ + task add ์๋ trigger โ
|
|
97
|
+
โ โข release sync-main ์๋ npm publish (.env NPM_TOKEN) โ
|
|
98
|
+
โ โข 6 ๋ฅ๋ ฅ ๋งคํธ๋ฆญ์ค 72% production-ready ยท MCP 54 ๋๊ตฌ โ
|
|
99
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
100
|
+
|
|
101
|
+
Available Slash (5 ๊ทธ๋ฃน)
|
|
102
|
+
โข meta: :help :model :role :provider :status :stream :clear :quit
|
|
103
|
+
โข internal: :verify :audit :handoff :health
|
|
104
|
+
โข memory: :lessons :brainstorm :tasks :plan
|
|
105
|
+
โข bridge: :web :pc :lsp (๊ฐ sub: check/symbols/click/screenshot/...)
|
|
106
|
+
โข review: :review "<request>" ยท :permissions [basic|extended|full]
|
|
107
|
+
|
|
108
|
+
โจ Tab=provider cycle ยท Shift+Tab=model ยท Ctrl+C=quit
|
|
109
|
+
|
|
110
|
+
โก provider=ollama ยท model=llama3 ยท role=actor ยท perms=basic ยท โถ stream=on
|
|
111
|
+
|
|
112
|
+
agent[ollama/actor/โถ]> _
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### ๋์์ธ ๊ฒฐ์
|
|
116
|
+
- **๋ฅ๊ทผ ๋ชจ์๋ฆฌ** (`โญ โฐ`) ํค๋ ๋ฐ์ค โ ์น๊ทผํ ์ธ์
|
|
117
|
+
- **์ฌ๊ฐ ๋ชจ์๋ฆฌ** (`โ โ`) Tips/What's new ๋ฐ์ค โ ์ ๋ณด ๋ฐ์ค ๊ตฌ๋ถ
|
|
118
|
+
- **์๊น ํ ํฐ**: cy(ํค๋), yel(Tips), green(What's new), mag(model), bold(์ค์ ๋ผ๋ฒจ)
|
|
119
|
+
- **5 ๊ทธ๋ฃน Slash ์นดํ๋ก๊ทธ**: Hermes-style "Available Tools / Skills" ์๊ฐ
|
|
120
|
+
- **์ํ๋ฐ โก**: provider/model/role/perms/stream 5์์ + ์๊น ๊ตฌ๋ถ
|
|
121
|
+
- **ํค๋ณด๋ ๋จ์ถํค โจ**: Tab/Shift+Tab/Ctrl+C ๋ช
์
|
|
122
|
+
|
|
123
|
+
### ์ฒจ๋ถ ์ด๋ฏธ์ง ์ฐธ๊ณ spirit (์ ํํ ๋ณต์ X)
|
|
124
|
+
| ์ด๋ฏธ์ง | ์ ์ฉ๋ ์์ |
|
|
125
|
+
|---|---|
|
|
126
|
+
| Hermes Agent v0.7.0 | "Available ..." ์นดํ๋ก๊ทธ 5 ๊ทธ๋ฃน |
|
|
127
|
+
| Claude Code v2.1.126 | "Welcome back" + "Tips/What's new" ๋ฐ์ค |
|
|
128
|
+
| OpenAI Codex v0.132.0 | ๋ชจ๋ธ/๋๋ ํ ๋ฆฌ ๋ฐ์ค + Tips |
|
|
129
|
+
| Gemini CLI v0.42.0 | ์ํ๋ฐ (sandbox/model/quota โ provider/model/perms/stream) |
|
|
130
|
+
|
|
131
|
+
### Verified
|
|
132
|
+
- e2e 217/217 baseline ์ ์ง
|
|
133
|
+
- stress-v124: **19/19** (ํค๋ ๋ฐ์ค 4 + Slash 5๊ทธ๋ฃน 3 + ์ํ๋ฐ 3 + 1.9.179 ์ฃผ์ 2 + ๋์ ํ๊ท 7)
|
|
134
|
+
- VERSION = 1.9.179 ยท autonomous-rounds = 109 ยท main ์๋ push 40 ๋ผ์ด๋ ์ฐ์
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
3
138
|
## 1.9.178 โ 2026-05-21
|
|
4
139
|
|
|
5
140
|
**๐ฆ ์ฌ์ฉ์ ๋ช
์: `release sync-main` ์๋ npm publish โ .env NPM_TOKEN ์ฌ์ฉ.**
|
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
|
@@ -4,9 +4,10 @@
|
|
|
4
4
|
const fs = require('fs');
|
|
5
5
|
const path = require('path');
|
|
6
6
|
const cp = require('child_process');
|
|
7
|
+
const os = require('os'); // 1.9.178: _publishToNpm ์์ os.tmpdir() ์ฌ์ฉ (์ ์ญ import)
|
|
7
8
|
const readline = require('readline');
|
|
8
9
|
|
|
9
|
-
const VERSION = '1.9.
|
|
10
|
+
const VERSION = '1.9.180';
|
|
10
11
|
const MARK = '<!-- leerness:managed -->';
|
|
11
12
|
const README_START = '<!-- leerness:project-readme:start -->';
|
|
12
13
|
const README_END = '<!-- leerness:project-readme:end -->';
|
|
@@ -7822,8 +7823,18 @@ function releaseSyncMainCmd(root) {
|
|
|
7822
7823
|
// - ์ด๋ฏธ publish๋ ๋ฒ์ ์๋ detect โ skip (์ค๋ณต publish ์ฐจ๋จ)
|
|
7823
7824
|
function _publishToNpm(root, opts = {}) {
|
|
7824
7825
|
root = absRoot(root || process.cwd());
|
|
7825
|
-
// .env ์๋ ๋ก๋ (
|
|
7826
|
-
|
|
7826
|
+
// .env ์๋ ๋ก๋ โ root + ์์ 3๋จ๊ณ๊น์ง ํ์ (์ํฌ์คํ์ด์ค root ์ .env ๋ ์ธ์).
|
|
7827
|
+
// ์: leerness-pkg/ ์์ sync-main ํธ์ถ ์ ../leerness/.env ๋ ์๋ ํ์.
|
|
7828
|
+
{
|
|
7829
|
+
let dir = root;
|
|
7830
|
+
for (let i = 0; i < 4; i++) {
|
|
7831
|
+
try { _loadEnvFile(dir); } catch {}
|
|
7832
|
+
if (process.env.LEERNESS_NPM_TOKEN || process.env.NPM_TOKEN) break;
|
|
7833
|
+
const parent = path.resolve(dir, '..');
|
|
7834
|
+
if (parent === dir) break; // ๋ฃจํธ ๋๋ฌ
|
|
7835
|
+
dir = parent;
|
|
7836
|
+
}
|
|
7837
|
+
}
|
|
7827
7838
|
const token = process.env.LEERNESS_NPM_TOKEN || process.env.NPM_TOKEN;
|
|
7828
7839
|
if (!token) {
|
|
7829
7840
|
log(` โ npm ์๋ ๋ฐฐํฌ ์คํต: NPM_TOKEN ๋ฏธ์ค์ (.env ์ NPM_TOKEN=npm_xxxxx ์ถ๊ฐ)`);
|
|
@@ -7865,8 +7876,11 @@ function _publishToNpm(root, opts = {}) {
|
|
|
7865
7876
|
const tmpNpmrc = path.join(tmpDir, '.npmrc');
|
|
7866
7877
|
fs.writeFileSync(tmpNpmrc, `//registry.npmjs.org/:_authToken=${token}\n`, { mode: 0o600 });
|
|
7867
7878
|
// 3) npm publish (--userconfig ๋ก ์์ .npmrc ์ฌ์ฉ, --access public)
|
|
7868
|
-
|
|
7869
|
-
|
|
7879
|
+
// 1.9.178+: 2FA OTP ์ง์ โ LEERNESS_NPM_OTP ํ๊ฒฝ๋ณ์ ๋๋ --npm-otp ์ธ์
|
|
7880
|
+
const otp = process.env.LEERNESS_NPM_OTP || arg('--npm-otp', null) || opts.otp;
|
|
7881
|
+
const baseArgs = ['publish', '--userconfig', tmpNpmrc, '--access', 'public'];
|
|
7882
|
+
if (otp) baseArgs.push(`--otp=${otp}`);
|
|
7883
|
+
const args = opts.dryRun ? [...baseArgs, '--dry-run'] : baseArgs;
|
|
7870
7884
|
log(` ${opts.dryRun ? '(dry-run) ' : ''}npm publish ์๋ ์ค...`);
|
|
7871
7885
|
const pubR = cp.spawnSync('npm', args, {
|
|
7872
7886
|
cwd: root, encoding: 'utf8', shell: true, timeout: 60000,
|
|
@@ -7879,6 +7893,12 @@ function _publishToNpm(root, opts = {}) {
|
|
|
7879
7893
|
const errOut = (pubR.stderr || pubR.stdout || '').slice(-400);
|
|
7880
7894
|
if (/EPUBLISHCONFLICT|already exists|cannot publish over/i.test(errOut)) {
|
|
7881
7895
|
log(` โ ์ด๋ฏธ publish๋จ (race condition) โ skip`);
|
|
7896
|
+
} else if (/EOTP|one-time password|--otp=/i.test(errOut)) {
|
|
7897
|
+
// 1.9.178+: 2FA ํ์ฑํ๋ ๊ณ์ โ Automation ํ ํฐ ๋๋ OTP ํ์
|
|
7898
|
+
warn(`npm publish ์คํจ: 2FA OTP ํ์ (NPM ๊ณ์ ์ 2FA ํ์ฑํ๋จ).`);
|
|
7899
|
+
log(` ํด๊ฒฐ 1: LEERNESS_NPM_OTP=<6์๋ฆฌ์ฝ๋> ๋๋ --npm-otp <code> ์ต์
์ฌ์ฉ`);
|
|
7900
|
+
log(` ํด๊ฒฐ 2: Automation ํ ํฐ ๋ฐ๊ธ โ npm token create --read-only=false (2FA bypass)`);
|
|
7901
|
+
log(` ๋ฐ๊ธ ํ .env ์ NPM_TOKEN ์ ์ ํ ํฐ์ผ๋ก ๊ต์ฒด`);
|
|
7882
7902
|
} else if (/EAUTH|forbidden|401|403/i.test(errOut)) {
|
|
7883
7903
|
warn(`npm publish ์คํจ: ํ ํฐ ๊ถํ ๋ถ์กฑ ๋๋ ๋ง๋ฃ โ .env NPM_TOKEN ์ฌ๋ฐ๊ธ ํ์`);
|
|
7884
7904
|
} else if (/ENEEDAUTH/i.test(errOut)) {
|
|
@@ -11033,7 +11053,13 @@ async function _agentRepl(root, opts) {
|
|
|
11033
11053
|
// 1.9.153: .env ์๋ ๋ก๋ (REPL ์ง์
์ง์ ) โ install ์งํ LEERNESS_ENABLE_* ์ฆ์ ๋ฐ์
|
|
11034
11054
|
try { _loadEnvFile(root); } catch {}
|
|
11035
11055
|
const readline = require('readline');
|
|
11036
|
-
|
|
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
|
+
});
|
|
11037
11063
|
const isTty = process.stdout.isTTY;
|
|
11038
11064
|
const C = isTty ? {
|
|
11039
11065
|
cy: s => `\x1b[36m${s}\x1b[0m`, dim: s => `\x1b[2m${s}\x1b[0m`,
|
|
@@ -11079,12 +11105,17 @@ async function _agentRepl(root, opts) {
|
|
|
11079
11105
|
writeUtf8(sessionPath(), lines + '\n');
|
|
11080
11106
|
} catch {}
|
|
11081
11107
|
};
|
|
11082
|
-
// ํ์
|
|
11108
|
+
// 1.9.179: ํ์ ํ๋ฉด ์ฌ๋์์ธ (์ฌ์ฉ์ ๋ช
์ โ Hermes/Claude/Codex/Gemini ์คํ์ผ).
|
|
11109
|
+
// ๊ธฐ์กด ๋จ์ ๋ฐ์ค โ ํค๋ ๋ฐ์ค + Tips / What's new ๋ฐ์ค + Slash ์นดํ๋ก๊ทธ 5 ๊ทธ๋ฃน.
|
|
11110
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
11111
|
+
const wsName = path.basename(absRoot(root));
|
|
11112
|
+
log('');
|
|
11113
|
+
log(C.bold(C.cy(' โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ')));
|
|
11114
|
+
log(C.bold(C.cy(` โ Leerness Agent v${VERSION} (${today}) ยท ๊ฒ์ยท๊ธฐ์ตยท์๋๋ฐ์ค ํตํฉ AI โ`)));
|
|
11115
|
+
log(C.bold(C.cy(' โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ')));
|
|
11083
11116
|
log('');
|
|
11084
|
-
log(C.
|
|
11085
|
-
log(C.
|
|
11086
|
-
log(C.bold(C.cy(' โ ๊ฒ์ยท๊ธฐ์ตยท์๋๋ฐ์ค ํตํฉ ์์จ AI ์์ด์ ํธ โ')));
|
|
11087
|
-
log(C.bold(C.cy(' โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ')));
|
|
11117
|
+
log(C.dim(` โธ Welcome back ยท ${wsName} (${rel(process.cwd(), absRoot(root))})`));
|
|
11118
|
+
log(C.dim(` โธ Session: ${state.sessionId}`));
|
|
11088
11119
|
log('');
|
|
11089
11120
|
// Ollama ๋ชจ๋ธ ์๋ ๊ฐ์ง โ model์ด ๋ช
์๋์ง ์์์ผ๋ฉด ์ฌ์ฉ์์๊ฒ ์ ํ์ง ์ ๊ณต
|
|
11090
11121
|
if (state.provider === 'ollama' && !state.model) {
|
|
@@ -11129,15 +11160,44 @@ async function _agentRepl(root, opts) {
|
|
|
11129
11160
|
}
|
|
11130
11161
|
}
|
|
11131
11162
|
}
|
|
11163
|
+
// 1.9.179: Tips + What's new ๋ฐ์ค (์ฌ์ฉ์ ๋ช
์ โ ์ฒจ๋ถ ์ด๋ฏธ์ง spirit ๋ฐ์)
|
|
11164
|
+
log('');
|
|
11165
|
+
log(C.bold(C.yel(' โโ Tips for getting started โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ')));
|
|
11166
|
+
log(C.yel(' โ ') + C.dim('Tab / Shift+Tab') + ' ' + C.dim('โ provider / model ์ ํ (1.9.170)') + C.yel(' '.repeat(Math.max(1, 17)) + 'โ'));
|
|
11167
|
+
log(C.yel(' โ ') + C.dim(':review "<req>"') + ' ' + C.dim('โ ๋ฌด์กฐ๊ฑด ๊ตฌํ ์ ์ฌ์ ๊ฒํ (1.9.176)') + C.yel(' '.repeat(Math.max(1, 13)) + 'โ'));
|
|
11168
|
+
log(C.yel(' โ ') + C.dim(':permissions <m>') + ' ' + C.dim('โ ์ฆ์ ๊ถํ ๋ณ๊ฒฝ basic|extended|full (1.9.174)') + C.yel(' โ'));
|
|
11169
|
+
log(C.yel(' โ ') + C.dim(':stream on|off') + ' ' + C.dim('โ ์ค์๊ฐ ์คํธ๋ฆฌ๋ฐ ํ ๊ธ (default ON, 1.9.170/172)') + C.yel(' โ'));
|
|
11170
|
+
log(C.bold(C.yel(' โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ')));
|
|
11171
|
+
log('');
|
|
11172
|
+
log(C.bold(C.green(' โโ What\'s new (1.9.170~178) โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ')));
|
|
11173
|
+
log(C.green(' โ ') + C.dim('โข REPL Tab cycle + ์ค์๊ฐ ์คํธ๋ฆฌ๋ฐ (spinner / tool_use / diff ์๊น)') + C.green(' โ'));
|
|
11174
|
+
log(C.green(' โ ') + C.dim('โข Bridge slash :web/:pc/:lsp REPL ์ฆ์ ํธ์ถ + LSP ๋ค๊ตญ์ด 5์ข
') + C.green(' โ'));
|
|
11175
|
+
log(C.green(' โ ') + C.dim('โข review-request ์ฌ์ ๊ฒํ + task add ์๋ trigger') + C.green(' โ'));
|
|
11176
|
+
log(C.green(' โ ') + C.dim('โข release sync-main ์๋ npm publish (.env NPM_TOKEN)') + C.green(' โ'));
|
|
11177
|
+
log(C.green(' โ ') + C.dim('โข 6 ๋ฅ๋ ฅ ๋งคํธ๋ฆญ์ค 72% production-ready ยท MCP 54 ๋๊ตฌ') + C.green(' โ'));
|
|
11178
|
+
log(C.bold(C.green(' โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ')));
|
|
11179
|
+
log('');
|
|
11180
|
+
log(C.bold(' Available Slash (5 ๊ทธ๋ฃน)'));
|
|
11181
|
+
log(C.dim(' โข meta: ') + ':help :model :role :provider :status :stream :clear :quit');
|
|
11182
|
+
log(C.dim(' โข internal: ') + ':verify :audit :handoff :health');
|
|
11183
|
+
log(C.dim(' โข memory: ') + ':lessons :brainstorm :tasks :plan');
|
|
11184
|
+
log(C.dim(' โข bridge: ') + ':web :pc :lsp ' + C.dim('(๊ฐ sub: check/symbols/click/screenshot/...)'));
|
|
11185
|
+
log(C.dim(' โข review: ') + ':review "<request>" ยท :permissions [basic|extended|full]');
|
|
11186
|
+
log('');
|
|
11187
|
+
log(C.dim(' โจ Tab=provider cycle ยท Shift+Tab=model ยท Ctrl+C=quit'));
|
|
11188
|
+
log('');
|
|
11189
|
+
// 1.9.179: ์ํ๋ฐ ํ ์ค โ ์๊น/๊ตฌ๋ถ์ ๊ฐํ
|
|
11190
|
+
const permMode = _readPermissions(root).mode || 'basic';
|
|
11191
|
+
log(' ' + C.bold('โก ') + C.cy(`provider=${state.provider}`) + ' ยท '
|
|
11192
|
+
+ C.mag(`model=${state.model || '(๊ธฐ๋ณธ)'}`) + ' ยท '
|
|
11193
|
+
+ C.green(`role=${state.role}`) + ' ยท '
|
|
11194
|
+
+ C.yel(`perms=${permMode}`) + ' ยท '
|
|
11195
|
+
+ (state.streamMode ? C.green('โถ stream=on') : C.dim('โก stream=off')));
|
|
11196
|
+
// 1.9.180: ์ฑํ
์์ญ ์ง์
separator (์ฌ์ฉ์ ๋ช
์ โ "๊ณ ์ ํค๋ + ์ฑํ
ํ์")
|
|
11197
|
+
// ํ์ ํ๋ฉด ๋์ ๋ช
ํํ ๊ตฌ๋ถ์ + ์๋ด โ ์ฑํ
์์ ๋ช
ํ.
|
|
11132
11198
|
log('');
|
|
11133
|
-
log(C.dim('
|
|
11134
|
-
log(C.dim('
|
|
11135
|
-
log(C.dim(' Memory Slash (1.9.161): :lessons | :brainstorm <topic> | :tasks | :plan'));
|
|
11136
|
-
log(C.dim(' ๐ 1.9.170 โ Tab=provider cycle, Shift+Tab=model cycle, :stream on|off (์ค์๊ฐ ์ถ๋ ฅ)'));
|
|
11137
|
-
log(C.dim(' ๐ 1.9.174 โ :permissions [basic|extended|full] ๋ก ์ฆ์ ๊ถํ ๋ณ๊ฒฝ (default: basic ์์ )'));
|
|
11138
|
-
log(C.dim(' ๐ 1.9.175 โ :web / :pc / :lsp ์ผ๋ก Bridge 3์ข
REPL ์์์ ์ฆ์ ํธ์ถ (์ฝ๋ ๋ถ์/์น/PC)'));
|
|
11139
|
-
log(C.dim(' ๐ 1.9.176 โ :review "<์์ฒญ>" ์ผ๋ก ์ฌ์ฉ์ ์์ฒญ ์ฌ์ ๊ฒํ (์ถฉ๋/์ฌ์ฌ์ฉ/ํจ์จ/๊ถ์ฅ ๋จ๊ณ)'));
|
|
11140
|
-
log(C.dim(` ํ์ฌ โ provider=${state.provider} model=${state.model || '(๊ธฐ๋ณธ)'} role=${state.role} permissions=${_readPermissions(root).mode}`));
|
|
11199
|
+
log(C.dim(' โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ ์ฑํ
์์ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ'));
|
|
11200
|
+
log(C.dim(' ๋ฉ์์ง ์
๋ ฅ ํ Enter ยท :help ์ผ๋ก ๋ช
๋ น ๋ชฉ๋ก ยท Ctrl+C ๋ก ์ข
๋ฃ'));
|
|
11141
11201
|
// 1.9.155: REPL ์ง์
์ handoff ์ปจํ
์คํธ ์๋ ๋
ธ์ถ (UX ๊ฐ์ โ ์ฌ์ฉ์๊ฐ ๋งค๋ฒ :handoff ์ ํด๋ ์ปจํ
์คํธ ์ธ์ง)
|
|
11142
11202
|
try {
|
|
11143
11203
|
const hf = cp.spawnSync(process.execPath, [__filename, 'handoff', root, '--compact', '--no-drift-check', '--no-headline'], {
|
|
@@ -11175,20 +11235,34 @@ async function _agentRepl(root, opts) {
|
|
|
11175
11235
|
} catch {}
|
|
11176
11236
|
return _PROVIDER_CYCLE_ORDER.slice();
|
|
11177
11237
|
};
|
|
11238
|
+
// 1.9.180: cycleProvider/cycleModel โ ์๊ฐ ํผ๋๋ฐฑ ๊ฐํ (์ฌ์ฉ์ ๋ช
์ "์ํํ์ง ์๋ค").
|
|
11239
|
+
// ์ด์ : ํ ์ค โ ๋ฉ์์ง๋ง. 1.9.180: provider ์์น ํ์ [1/5] + bold highlight + ํ์ฑ ์ฌ๋ถ ํ์.
|
|
11178
11240
|
const cycleProvider = (reverse) => {
|
|
11179
11241
|
const list = getProviders();
|
|
11180
11242
|
let idx = list.indexOf(state.provider);
|
|
11181
11243
|
if (idx < 0) idx = 0;
|
|
11182
11244
|
idx = reverse ? (idx - 1 + list.length) % list.length : (idx + 1) % list.length;
|
|
11183
11245
|
state.provider = list[idx];
|
|
11184
|
-
state.model = null;
|
|
11246
|
+
state.model = null;
|
|
11185
11247
|
const cat = _PROVIDER_MODEL_CATALOG[state.provider];
|
|
11186
|
-
|
|
11187
|
-
|
|
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 {}
|
|
11188
11259
|
process.stdout.write('\r\x1b[K');
|
|
11189
|
-
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
|
+
}
|
|
11190
11264
|
rl.setPrompt(prompt());
|
|
11191
|
-
rl.prompt(true);
|
|
11265
|
+
rl.prompt(true);
|
|
11192
11266
|
};
|
|
11193
11267
|
const cycleModel = (reverse) => {
|
|
11194
11268
|
const cat = _PROVIDER_MODEL_CATALOG[state.provider] || [];
|
|
@@ -11203,17 +11277,25 @@ async function _agentRepl(root, opts) {
|
|
|
11203
11277
|
idx = reverse ? (idx - 1 + cat.length) % cat.length : (idx + 1) % cat.length;
|
|
11204
11278
|
state.model = cat[idx].id;
|
|
11205
11279
|
process.stdout.write('\r\x1b[K');
|
|
11206
|
-
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
|
+
}
|
|
11207
11284
|
rl.setPrompt(prompt());
|
|
11208
11285
|
rl.prompt(true);
|
|
11209
11286
|
};
|
|
11210
11287
|
process.stdin.on('keypress', (str, key) => {
|
|
11211
11288
|
if (!key) return;
|
|
11212
11289
|
if (key.name === 'tab') {
|
|
11213
|
-
|
|
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
|
+
}
|
|
11214
11298
|
}
|
|
11215
|
-
// Shift+\ ๋๋ ๋ค๋ฅธ ๋ชจ๋ธ cycle alias โ ์ผ๋ถ ํฐ๋ฏธ๋์์ Shift+Tab ์ฒ๋ฆฌ ์ด๋ ค์ ๋๋น
|
|
11216
|
-
// (Shift+Tab์ key.name='tab' + key.shift=true ๋ก ์์์ ์ฒ๋ฆฌ๋จ)
|
|
11217
11299
|
});
|
|
11218
11300
|
} catch (e) {
|
|
11219
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",
|