leerness 1.9.172 β 1.9.174
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 +119 -0
- package/README.md +3 -3
- package/bin/harness.js +112 -41
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,124 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.9.174 β 2026-05-21
|
|
4
|
+
|
|
5
|
+
**π μ¬μ©μ λͺ
μ β install κΆν prompt μ κ±° + REPL `:permissions` μ¦μ λ³κ²½.**
|
|
6
|
+
|
|
7
|
+
μμ¨ λͺ¨λ 104 λΌμ΄λ. μ¬μ©μ λͺ
μ: *"κΆν μ€μ λ¬Ένμ μ κ±°νκ³ REPL λͺ¨λμμ κ°νΈνκ² κΆν λ³κ²½ν μ μλλ‘"*.
|
|
8
|
+
|
|
9
|
+
### 1. Install κΆν prompt μ κ±°
|
|
10
|
+
μ΄μ (1.9.146): install μ 3-tier κΆν λͺ¨λ μ ν prompt (basic/extended/full).
|
|
11
|
+
**λ¬Έμ **: μ¬μ©μ κ²½ν 볡μ‘λ μ¦κ° + μλͺ»λ μ ν (full) μ μν.
|
|
12
|
+
|
|
13
|
+
**1.9.174**:
|
|
14
|
+
- install μ κΆν **νμ `basic` μλ μ μ©** (μμ default).
|
|
15
|
+
- prompt μ½λ (resolveInstallOptions μ κΆν λͺ¨λ _selectOne λΈλ‘) μμ μ κ±°.
|
|
16
|
+
- μλ΄ λΌμΈ: `Agent κΆν λͺ¨λ: basic (1.9.174 β REPLμμ :permissions extended|full λ‘ μ¦μ λ³κ²½ κ°λ₯)`.
|
|
17
|
+
|
|
18
|
+
### 2. REPL `:permissions` μ¦μ λ³κ²½ κ°λ₯
|
|
19
|
+
μ΄μ (1.9.146~1.9.173): `:permissions` λ©ν λͺ
λ Ήμ list λ§ (μ‘°ν).
|
|
20
|
+
|
|
21
|
+
**1.9.174**:
|
|
22
|
+
```
|
|
23
|
+
agent[claude/actor/βΆ]> :permissions
|
|
24
|
+
π νμ¬ κΆν λͺ¨λ: basic
|
|
25
|
+
|
|
26
|
+
λ³κ²½:
|
|
27
|
+
:permissions basic β μμ (.harness λ§ μ°κΈ°, κΆμ₯)
|
|
28
|
+
:permissions extended β νλ‘μ νΈ ν΄λ + shell allowlist
|
|
29
|
+
:permissions full β β μ 체 (λ§μ°μ€/ν€λ³΄λ/μΉ, IDE ν΅ν© μλ§)
|
|
30
|
+
|
|
31
|
+
μΈλΆ κΆν (mouse/keyboard/browser/admin):
|
|
32
|
+
mouse: β κ±°λΆ
|
|
33
|
+
keyboard: β κ±°λΆ
|
|
34
|
+
browser: β κ±°λΆ
|
|
35
|
+
admin: β κ±°λΆ
|
|
36
|
+
|
|
37
|
+
agent[claude/actor/βΆ]> :permissions extended
|
|
38
|
+
β κΆν λͺ¨λ λ³κ²½: extended (μ¦μ μ μ© β λ€μ λͺ
λ ΉλΆν°)
|
|
39
|
+
|
|
40
|
+
agent[claude/actor/βΆ]> :permissions full
|
|
41
|
+
β κΆν λͺ¨λ λ³κ²½: full (μ¦μ μ μ© β λ€μ λͺ
λ ΉλΆν°)
|
|
42
|
+
β full λͺ¨λ β λ§μ°μ€/ν€λ³΄λ/μΉ/κ΄λ¦¬μ μ 체 νμ©. IDE ν΅ν© μΈ νκ²½μμλ μν.
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
- μΈμ μμ β νμ¬ λͺ¨λ + μΈλΆ κΆν (mouse/keyboard/browser/admin) νμ + λ³κ²½ μ΅μ
μλ΄
|
|
46
|
+
- `:permissions basic|extended|full` β μ¦μ λ³κ²½ (`permissionsSetCmd` νΈμΆ)
|
|
47
|
+
- `:perm` alias μΆκ° (λ¨μΆ)
|
|
48
|
+
- `full` λͺ¨λ λ³κ²½ μ β λͺ
μμ κ²½κ³
|
|
49
|
+
- μλͺ»λ λͺ¨λ β μΉμ ν μλ΄ (`μλͺ»λ λͺ¨λ: xyz (basic | extended | full)`)
|
|
50
|
+
|
|
51
|
+
### νΈνμ±
|
|
52
|
+
- CLI λͺ
λ Ή `leerness permissions list|set` κ·Έλλ‘ μ μ§ (1.9.146 νΈν).
|
|
53
|
+
- κΈ°μ‘΄ `.harness/agent-permissions.json` νμ κ·Έλλ‘ (mode + 4-tier μΈλΆ).
|
|
54
|
+
|
|
55
|
+
### Verified
|
|
56
|
+
- e2e 217/217 baseline μ μ§
|
|
57
|
+
- stress-v119: **20/20** (install μ κ±° 5 + REPL :permissions 7 + CLI νΈν 2 + λμ νκ· 6)
|
|
58
|
+
- VERSION = 1.9.174 / autonomous-rounds = 104 / main μλ push 35 λΌμ΄λ μ°μ
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 1.9.173 β 2026-05-21
|
|
63
|
+
|
|
64
|
+
**π LSP μ΄λν° λ€κ΅μ΄ νμ₯ β JavaScript + Python + Go + Rust + Java (5κ° μΈμ΄ regex fallback).**
|
|
65
|
+
|
|
66
|
+
μμ¨ λͺ¨λ 103 λΌμ΄λ. 1.9.167 codeIntel (JS/TS only) β 5κ° μΈμ΄ νμ₯.
|
|
67
|
+
|
|
68
|
+
### `_LSP_LANG_PATTERNS` β 5κ° μΈμ΄ ν¨ν΄
|
|
69
|
+
| μΈμ΄ | μΆμΆ κ°λ₯ |
|
|
70
|
+
|---|---|
|
|
71
|
+
| **javascript** (.ts/.tsx/.js/.jsx/.mjs/.cjs) | function, class, interface, type, enum, arrow function |
|
|
72
|
+
| **python** (.py/.pyw/.pyi) | def, async def, class |
|
|
73
|
+
| **go** (.go) | func (receiver ν¬ν¨), type struct/interface, type alias |
|
|
74
|
+
| **rust** (.rs) | fn (pub/async), struct, enum, trait, impl, type |
|
|
75
|
+
| **java** (.java/.kt/.scala) | class (public/private/abstract), interface, enum, method |
|
|
76
|
+
|
|
77
|
+
### `_detectLspLang(file)` β νμ₯μ μλ λΌμ°ν
|
|
78
|
+
νμΌ νμ₯μ κΈ°λ° μΈμ΄ μλ κ°μ§. λ―Έμ§μ νμ₯μλ javascript κΈ°λ³Έ (1.9.167 νΈν).
|
|
79
|
+
|
|
80
|
+
### μ¬μ© μμ
|
|
81
|
+
```bash
|
|
82
|
+
$ leerness lsp symbols src/api.py
|
|
83
|
+
# leerness lsp symbols (1.9.173 λ€κ΅μ΄)
|
|
84
|
+
file: src/api.py Β· lang: python
|
|
85
|
+
mode: regex-fallback (python) Β· 12 symbols Β· 4ms
|
|
86
|
+
1:function parse_request
|
|
87
|
+
8:function fetch_data
|
|
88
|
+
15:class Handler
|
|
89
|
+
16:function __init__
|
|
90
|
+
...
|
|
91
|
+
|
|
92
|
+
$ leerness lsp symbols src/main.rs
|
|
93
|
+
# leerness lsp symbols (1.9.173 λ€κ΅μ΄)
|
|
94
|
+
file: src/main.rs Β· lang: rust
|
|
95
|
+
mode: regex-fallback (rust) Β· 9 symbols Β· 5ms
|
|
96
|
+
1:function hello
|
|
97
|
+
5:struct User
|
|
98
|
+
9:impl User
|
|
99
|
+
15:trait Greeter
|
|
100
|
+
...
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### ν€μλ false-positive μ κ±°
|
|
104
|
+
Java method μ κ·μμ΄ `if(`, `for(`, `while(`, `switch(`, `catch(`, `return(`, `throw(`, `new(` λ± ν€μλμ λ§€μΉλλ κ²½μ° νν°.
|
|
105
|
+
|
|
106
|
+
### references λ€κ΅μ΄ νμΌ μ€μΊ
|
|
107
|
+
`leerness lsp references <name>` κ° `.py/.go/.rs/.java/.kt/.scala` νμΌλ μ€μΊ (κΈ°μ‘΄ `.ts/.js/.md` μ μΆκ°).
|
|
108
|
+
|
|
109
|
+
### μ€μΈ‘ (regex fallback)
|
|
110
|
+
- Python (5 symbols): 472ms
|
|
111
|
+
- Go (4 symbols): 566ms
|
|
112
|
+
- Rust (6 symbols): 531ms
|
|
113
|
+
- Java (4 symbols): 1229ms
|
|
114
|
+
|
|
115
|
+
### Verified
|
|
116
|
+
- e2e 217/217 baseline μ μ§
|
|
117
|
+
- stress-v118: **15/15** (ν¨ν΄ μ μ 4 + Python 1 + Go 1 + Rust 1 + Java 1 + JS νΈν 1 + references 1 + λμ νκ· 5)
|
|
118
|
+
- VERSION = 1.9.173 / autonomous-rounds = 103 / main μλ push 34 λΌμ΄λ μ°μ
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
3
122
|
## 1.9.172 β 2026-05-21
|
|
4
123
|
|
|
5
124
|
**π¨ μ€νΈλ¦¬λ° UX κ°ν β spinner + Claude tool_use κ°μν + diff ν¨ν΄ μλ μκΉ (μ¬μ©μ λͺ
μ κ°ν).**
|
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.174 AI Agent Reliability Harness + Sandbox β
|
|
16
16
|
β verify Β· remember Β· orchestrate Β· audit Β· sandbox Β· drift β
|
|
17
|
-
β
|
|
17
|
+
β π install κΆν prompt μ κ±° Β· REPL :permissions μ¦μ λ³κ²½ β
|
|
18
18
|
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
19
19
|
```
|
|
20
20
|
|
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.
|
|
9
|
+
const VERSION = '1.9.174';
|
|
10
10
|
const MARK = '<!-- leerness:managed -->';
|
|
11
11
|
const README_START = '<!-- leerness:project-readme:start -->';
|
|
12
12
|
const README_END = '<!-- leerness:project-readme:end -->';
|
|
@@ -739,25 +739,11 @@ async function resolveInstallOptions(root, opts = {}) {
|
|
|
739
739
|
}
|
|
740
740
|
}
|
|
741
741
|
}
|
|
742
|
-
// 1.9.
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
{ label: 'basic (μμ ) β μ½κΈ°/μ°κΈ° .harness/ λ§', description: 'κΆμ₯ β νμΌμμ€ν
/λ€νΈμν¬ κ±°λΆ, .harness μλ§ μ°κΈ°', id: 'basic' },
|
|
748
|
-
{ label: 'extended β νλ‘μ νΈ ν΄λ + shell allowlist', description: 'νλ‘μ νΈ ν΄λ read/write, μ¬μ μ μλ λͺ
λ Ήλ§ exec', id: 'extended' },
|
|
749
|
-
{ label: 'full β μ 체 (λ§μ°μ€/ν€λ³΄λ/μΉ/κ΄λ¦¬μ) β μν', description: 'β IDE ν΅ν© μμλ§ κΆμ₯ β λͺ¨λ PC μμ
κ°λ₯', id: 'full' }
|
|
750
|
-
], { defaultIndex: 0 });
|
|
751
|
-
permissionMode = pOpt ? pOpt.id : 'basic';
|
|
752
|
-
} else {
|
|
753
|
-
log('\nagent κΆν λͺ¨λ (leerness agent λͺ
λ Ή μ¬μ© μ):');
|
|
754
|
-
log('1) basic (μμ ) β .harness/ λ§');
|
|
755
|
-
log('2) extended β νλ‘μ νΈ ν΄λ + shell allowlist');
|
|
756
|
-
log('3) full β β λ§μ°μ€/ν€λ³΄λ/μΉ/κ΄λ¦¬μ μ 체 (IDE ν΅ν© μμλ§)');
|
|
757
|
-
const a = await ask('μ ν [1]: ');
|
|
758
|
-
permissionMode = a === '2' ? 'extended' : a === '3' ? 'full' : 'basic';
|
|
759
|
-
}
|
|
760
|
-
}
|
|
742
|
+
// 1.9.174: κΆν prompt μ κ±° (μ¬μ©μ λͺ
μ) β install μ νμ basic μλ μ μ©.
|
|
743
|
+
// REPL μμμ `:permissions <basic|extended|full>` λ‘ μ¦μ λ³κ²½ κ°λ₯ (REPL UX κ°ν).
|
|
744
|
+
// μ΄μ 1.9.146 μ 3-tier μ ν prompt λ μ¬μ©μ κ²½ν 볡μ‘λ μ¦κ° + μλͺ»λ μ ν (full) μ μν β
|
|
745
|
+
// μμ ν κΈ°λ³Έ (basic) μλ μμ + REPL μ§μ
μμ μ νμ μ λ³κ²½νλ νλ¦μ΄ λ μμ νκ³ κ°νΈ.
|
|
746
|
+
const permissionMode = 'basic';
|
|
761
747
|
// 1.9.151: λͺ¨λ λ¬Έν μ’
λ£ ν β REPL λͺ¨λ μ¦μ νμ±ν μ¬λΆ (μ¬μ©μ λͺ
μ μμ²)
|
|
762
748
|
// μ νλ μμ΄μ νΈκ° μμ λλ§ νμ. μ€μΉ μλ£ ν install() κ° μ²λ¦¬.
|
|
763
749
|
let startRepl = false;
|
|
@@ -807,7 +793,7 @@ async function install(root, opts = {}) {
|
|
|
807
793
|
log(`Agents νμ±ν: ${list}`);
|
|
808
794
|
}
|
|
809
795
|
if (resolved.startRepl) log(`REPL μλ μμ: μ (μ€μΉ μλ£ ν \`leerness agent\` μ§μ
)`);
|
|
810
|
-
if (resolved.permissionMode) log(`Agent κΆν λͺ¨λ: ${resolved.permissionMode}`);
|
|
796
|
+
if (resolved.permissionMode) log(`Agent κΆν λͺ¨λ: ${resolved.permissionMode} (1.9.174 β REPLμμ \`:permissions extended|full\` λ‘ μ¦μ λ³κ²½ κ°λ₯)`);
|
|
811
797
|
// 1.9.10: μ€ν¬ μΉ΄νλ‘κ·Έ μΆμ² μλ΄
|
|
812
798
|
if (SKILLPACK_SOURCE === 'builtin') log(`Skill catalog source: builtin (leerness-skillpack λ―Έμ€μΉ β \`npm i leerness-skillpack\`λ‘ νμ₯ κ°λ₯)`);
|
|
813
799
|
else log(`Skill catalog source: ${SKILLPACK_SOURCE} (leerness-skillpack${SKILLPACK_META ? ` v${SKILLPACK_META.version}` : ''})`);
|
|
@@ -11019,6 +11005,7 @@ async function _agentRepl(root, opts) {
|
|
|
11019
11005
|
log(C.dim(' Slash λͺ
λ Ή (1.9.150): :verify | :audit | :handoff | :health'));
|
|
11020
11006
|
log(C.dim(' Memory Slash (1.9.161): :lessons | :brainstorm <topic> | :tasks | :plan'));
|
|
11021
11007
|
log(C.dim(' π 1.9.170 β Tab=provider cycle, Shift+Tab=model cycle, :stream on|off (μ€μκ° μΆλ ₯)'));
|
|
11008
|
+
log(C.dim(' π 1.9.174 β :permissions [basic|extended|full] λ‘ μ¦μ κΆν λ³κ²½ (default: basic μμ )'));
|
|
11022
11009
|
log(C.dim(` νμ¬ β provider=${state.provider} model=${state.model || '(κΈ°λ³Έ)'} role=${state.role} permissions=${_readPermissions(root).mode}`));
|
|
11023
11010
|
// 1.9.155: REPL μ§μ
μ handoff 컨ν
μ€νΈ μλ λ
ΈμΆ (UX κ°μ β μ¬μ©μκ° λ§€λ² :handoff μ ν΄λ 컨ν
μ€νΈ μΈμ§)
|
|
11024
11011
|
try {
|
|
@@ -11123,7 +11110,8 @@ async function _agentRepl(root, opts) {
|
|
|
11123
11110
|
log(' :reset β history μ΄κΈ°ν');
|
|
11124
11111
|
log(' :history β λν history νμ');
|
|
11125
11112
|
log(' :save β μΈμ
μ¦μ μ μ₯');
|
|
11126
|
-
log(' :permissions
|
|
11113
|
+
log(' :permissions [mode] β π 1.9.174 νμ¬ λͺ¨λ νμ / λλ μ¦μ λ³κ²½ (basic/extended/full)');
|
|
11114
|
+
log(' :perm [mode] β :permissions λ¨μΆ alias');
|
|
11127
11115
|
log(' :quit / :exit / :q β μ’
λ£ (μλ μ μ₯)');
|
|
11128
11116
|
log(C.bold('\n π 1.9.170 ν€λ³΄λ λ¨μΆν€:'));
|
|
11129
11117
|
log(' Tab β λ€μ provider λ‘ cycle (ollama β claude β codex β gemini β copilot)');
|
|
@@ -11231,7 +11219,42 @@ async function _agentRepl(root, opts) {
|
|
|
11231
11219
|
return false;
|
|
11232
11220
|
}
|
|
11233
11221
|
if (op === 'save') { saveSession(); log(C.dim(` β ${rel(root, sessionPath())}`)); return false; }
|
|
11234
|
-
if (op === 'permissions'
|
|
11222
|
+
if (op === 'permissions' || op === 'perm') {
|
|
11223
|
+
// 1.9.174: REPLμμ κΆν λ³κ²½ κ°λ₯ (μ¬μ©μ λͺ
μ μμ²).
|
|
11224
|
+
// :permissions β νμ¬ λͺ¨λ νμ + λ³κ²½ μ΅μ
μλ΄
|
|
11225
|
+
// :permissions basic β κΆν λͺ¨λ μ¦μ λ³κ²½
|
|
11226
|
+
const target = (rest[0] || '').toLowerCase();
|
|
11227
|
+
if (!target) {
|
|
11228
|
+
const p = _readPermissions(root);
|
|
11229
|
+
log('');
|
|
11230
|
+
log(C.bold(` π νμ¬ κΆν λͺ¨λ: ${C.cy(p.mode || 'basic')}`));
|
|
11231
|
+
log('');
|
|
11232
|
+
log(C.dim(' λ³κ²½:'));
|
|
11233
|
+
log(` ${C.green(':permissions basic')} β μμ (.harness λ§ μ°κΈ°, κΆμ₯)`);
|
|
11234
|
+
log(` ${C.yel(':permissions extended')} β νλ‘μ νΈ ν΄λ + shell allowlist`);
|
|
11235
|
+
log(` ${C.mag(':permissions full')} β β μ 체 (λ§μ°μ€/ν€λ³΄λ/μΉ, IDE ν΅ν© μλ§)`);
|
|
11236
|
+
log('');
|
|
11237
|
+
log(C.dim(' μΈλΆ κΆν (mouse/keyboard/browser/admin):'));
|
|
11238
|
+
Object.entries(p).filter(([k]) => k !== 'mode' && typeof p[k] === 'boolean').forEach(([k, v]) => {
|
|
11239
|
+
log(` ${k}: ${v ? C.green('β νμ©') : C.dim('β κ±°λΆ')}`);
|
|
11240
|
+
});
|
|
11241
|
+
return false;
|
|
11242
|
+
}
|
|
11243
|
+
if (!['basic', 'extended', 'full'].includes(target)) {
|
|
11244
|
+
log(C.yel(` β μλͺ»λ λͺ¨λ: ${target} (basic | extended | full)`));
|
|
11245
|
+
return false;
|
|
11246
|
+
}
|
|
11247
|
+
try {
|
|
11248
|
+
permissionsSetCmd(root, target);
|
|
11249
|
+
log(C.green(` β κΆν λͺ¨λ λ³κ²½: ${target} (μ¦μ μ μ© β λ€μ λͺ
λ ΉλΆν°)`));
|
|
11250
|
+
if (target === 'full') {
|
|
11251
|
+
log(C.yel(' β full λͺ¨λ β λ§μ°μ€/ν€λ³΄λ/μΉ/κ΄λ¦¬μ μ 체 νμ©. IDE ν΅ν© μΈ νκ²½μμλ μν.'));
|
|
11252
|
+
}
|
|
11253
|
+
} catch (e) {
|
|
11254
|
+
log(C.yel(` β κΆν λ³κ²½ μ€ν¨: ${e.message}`));
|
|
11255
|
+
}
|
|
11256
|
+
return false;
|
|
11257
|
+
}
|
|
11235
11258
|
if (op === 'status') {
|
|
11236
11259
|
// 1.9.155: REPL μμμ νμ¬ μΈμ
μν μμΈν (provider/model/role/permissions/history/runs)
|
|
11237
11260
|
log(C.bold('\n π REPL μΈμ
μν (1.9.155)'));
|
|
@@ -12560,22 +12583,69 @@ function _tryLoadLSP() {
|
|
|
12560
12583
|
return { ok: false, error: 'typescript λ―Έμ€μΉ β `npm i -g typescript` ν λ€μ μλ (λλ μ κ·μ fallback μ¬μ©)' };
|
|
12561
12584
|
}
|
|
12562
12585
|
|
|
12563
|
-
//
|
|
12564
|
-
|
|
12565
|
-
|
|
12566
|
-
|
|
12567
|
-
const patterns = [
|
|
12586
|
+
// 1.9.173: λ€κ΅μ΄ νμ₯ β Python/Go/Rust/Java ν¨ν΄ μΆκ° (regex fallback)
|
|
12587
|
+
// νμΌ νμ₯μ κΈ°λ° μλ λΌμ°ν
. TypeScript Compiler API λ―Έμ€μΉ μμλ 5κ° μΈμ΄ μ§μ.
|
|
12588
|
+
const _LSP_LANG_PATTERNS = {
|
|
12589
|
+
javascript: [
|
|
12568
12590
|
{ re: /^\s*(?:export\s+)?(?:async\s+)?function\s+([A-Za-z_$][\w$]*)\s*\(/, kind: 'function' },
|
|
12569
12591
|
{ re: /^\s*(?:export\s+)?class\s+([A-Za-z_$][\w$]*)/, kind: 'class' },
|
|
12570
12592
|
{ re: /^\s*(?:export\s+)?interface\s+([A-Za-z_$][\w$]*)/, kind: 'interface' },
|
|
12571
12593
|
{ re: /^\s*(?:export\s+)?(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*(?:async\s+)?(?:function|\()/, kind: 'function' },
|
|
12572
12594
|
{ re: /^\s*(?:export\s+)?type\s+([A-Za-z_$][\w$]*)\s*=/, kind: 'type' },
|
|
12573
|
-
{ re: /^\s*(?:export\s+)?enum\s+([A-Za-z_$][\w$]*)/, kind: 'enum' }
|
|
12574
|
-
]
|
|
12595
|
+
{ re: /^\s*(?:export\s+)?enum\s+([A-Za-z_$][\w$]*)/, kind: 'enum' }
|
|
12596
|
+
],
|
|
12597
|
+
python: [
|
|
12598
|
+
{ re: /^\s*async\s+def\s+([A-Za-z_][\w]*)\s*\(/, kind: 'function' },
|
|
12599
|
+
{ re: /^\s*def\s+([A-Za-z_][\w]*)\s*\(/, kind: 'function' },
|
|
12600
|
+
{ re: /^\s*class\s+([A-Za-z_][\w]*)\s*[(:]/, kind: 'class' }
|
|
12601
|
+
],
|
|
12602
|
+
go: [
|
|
12603
|
+
{ re: /^\s*func\s+(?:\([^)]*\)\s+)?([A-Za-z_][\w]*)\s*\(/, kind: 'function' },
|
|
12604
|
+
{ re: /^\s*type\s+([A-Za-z_][\w]*)\s+struct\b/, kind: 'struct' },
|
|
12605
|
+
{ re: /^\s*type\s+([A-Za-z_][\w]*)\s+interface\b/, kind: 'interface' },
|
|
12606
|
+
{ re: /^\s*type\s+([A-Za-z_][\w]*)\s+[A-Za-z]/, kind: 'type' }
|
|
12607
|
+
],
|
|
12608
|
+
rust: [
|
|
12609
|
+
{ re: /^\s*(?:pub(?:\([^)]+\))?\s+)?(?:async\s+)?fn\s+([A-Za-z_][\w]*)/, kind: 'function' },
|
|
12610
|
+
{ re: /^\s*(?:pub(?:\([^)]+\))?\s+)?struct\s+([A-Za-z_][\w]*)/, kind: 'struct' },
|
|
12611
|
+
{ re: /^\s*(?:pub(?:\([^)]+\))?\s+)?enum\s+([A-Za-z_][\w]*)/, kind: 'enum' },
|
|
12612
|
+
{ re: /^\s*(?:pub(?:\([^)]+\))?\s+)?trait\s+([A-Za-z_][\w]*)/, kind: 'trait' },
|
|
12613
|
+
{ re: /^\s*impl\s+(?:[^{]+\s+for\s+)?([A-Za-z_][\w]*)/, kind: 'impl' },
|
|
12614
|
+
{ re: /^\s*(?:pub(?:\([^)]+\))?\s+)?type\s+([A-Za-z_][\w]*)\s*=/, kind: 'type' }
|
|
12615
|
+
],
|
|
12616
|
+
java: [
|
|
12617
|
+
{ re: /^\s*(?:public|private|protected)?\s*(?:final\s+)?(?:abstract\s+)?class\s+([A-Za-z_][\w]*)/, kind: 'class' },
|
|
12618
|
+
{ re: /^\s*(?:public|private|protected)?\s*(?:abstract\s+)?interface\s+([A-Za-z_][\w]*)/, kind: 'interface' },
|
|
12619
|
+
{ re: /^\s*(?:public|private|protected)?\s*(?:static\s+)?(?:final\s+)?enum\s+([A-Za-z_][\w]*)/, kind: 'enum' },
|
|
12620
|
+
// method: visibility + return type + name( (heuristic β 첫 λ²μ§Έ ( λ§€μΉ, ν€μλ νν°)
|
|
12621
|
+
{ re: /^\s*(?:public|private|protected)\s+(?:static\s+)?(?:final\s+)?(?:[A-Za-z_<>,\s\[\]]+\s+)?([A-Za-z_][\w]*)\s*\(/, kind: 'method' }
|
|
12622
|
+
]
|
|
12623
|
+
};
|
|
12624
|
+
|
|
12625
|
+
function _detectLspLang(file) {
|
|
12626
|
+
const ext = (file.match(/\.[a-zA-Z0-9]+$/) || [''])[0].toLowerCase();
|
|
12627
|
+
if (/^\.(py|pyw|pyi)$/.test(ext)) return 'python';
|
|
12628
|
+
if (ext === '.go') return 'go';
|
|
12629
|
+
if (ext === '.rs') return 'rust';
|
|
12630
|
+
if (/^\.(java|kt|scala)$/.test(ext)) return 'java';
|
|
12631
|
+
if (/^\.(ts|tsx|js|jsx|mjs|cjs)$/.test(ext)) return 'javascript';
|
|
12632
|
+
return 'javascript'; // default β κΈ°λ³Έ JS ν¨ν΄ (.txt/.md λ± λ―Έμ§μ νμ₯μ)
|
|
12633
|
+
}
|
|
12634
|
+
|
|
12635
|
+
// μ κ·μ fallback β 5κ° μΈμ΄ (JS/TS/Python/Go/Rust/Java) symbol μΆμΆ (LSP μμ΄λ λμ)
|
|
12636
|
+
// 1.9.173: lang μΈμ μΆκ° β λ―Έμ§μ μ javascript ν¨ν΄ (1.9.167 νΈν).
|
|
12637
|
+
function _lspRegexSymbols(content, lang) {
|
|
12638
|
+
const symbols = [];
|
|
12639
|
+
const lines = content.split(/\r?\n/);
|
|
12640
|
+
const patterns = _LSP_LANG_PATTERNS[lang || 'javascript'] || _LSP_LANG_PATTERNS.javascript;
|
|
12575
12641
|
lines.forEach((line, idx) => {
|
|
12576
12642
|
for (const p of patterns) {
|
|
12577
12643
|
const m = line.match(p.re);
|
|
12578
|
-
|
|
12644
|
+
// ν€μλ false-positive μ κ±° (μ: java method μ κ·μμ΄ `if(`, `for(` λ±μ λ§€μΉλλ κ²½μ°)
|
|
12645
|
+
if (m && !/^(if|for|while|switch|catch|return|throw|new)$/.test(m[1])) {
|
|
12646
|
+
symbols.push({ name: m[1], kind: p.kind, line: idx + 1 });
|
|
12647
|
+
break;
|
|
12648
|
+
}
|
|
12579
12649
|
}
|
|
12580
12650
|
});
|
|
12581
12651
|
return symbols;
|
|
@@ -12641,31 +12711,32 @@ function lspCmd(root, sub, ...args) {
|
|
|
12641
12711
|
if (!fs.existsSync(file)) return fail(`νμΌ μμ: ${file}`);
|
|
12642
12712
|
const content = fs.readFileSync(file, 'utf8');
|
|
12643
12713
|
const t0 = Date.now();
|
|
12714
|
+
const lang = _detectLspLang(file); // 1.9.173: μΈμ΄ μλ κ°μ§
|
|
12644
12715
|
const r = _tryLoadLSP();
|
|
12645
12716
|
let symbols, mode;
|
|
12646
12717
|
try {
|
|
12647
|
-
if (r.ok && /\.(ts|tsx|js|jsx|mjs|cjs)$/.test(file)) {
|
|
12718
|
+
if (r.ok && lang === 'javascript' && /\.(ts|tsx|js|jsx|mjs|cjs)$/.test(file)) {
|
|
12648
12719
|
symbols = _lspTsSymbols(r.lib, content, file);
|
|
12649
12720
|
mode = 'typescript-compiler';
|
|
12650
12721
|
} else {
|
|
12651
|
-
symbols = _lspRegexSymbols(content);
|
|
12652
|
-
mode =
|
|
12722
|
+
symbols = _lspRegexSymbols(content, lang); // 1.9.173: lang μ λ¬
|
|
12723
|
+
mode = `regex-fallback (${lang})`;
|
|
12653
12724
|
}
|
|
12654
12725
|
} catch (e) {
|
|
12655
|
-
symbols = _lspRegexSymbols(content);
|
|
12656
|
-
mode =
|
|
12726
|
+
symbols = _lspRegexSymbols(content, lang);
|
|
12727
|
+
mode = `regex-fallback (${lang}, after error: ${e.message})`;
|
|
12657
12728
|
}
|
|
12658
12729
|
const dt = Date.now() - t0;
|
|
12659
12730
|
if (has('--json')) {
|
|
12660
|
-
log(JSON.stringify({ file, symbols, count: symbols.length, mode, durationMs: dt }, null, 2));
|
|
12731
|
+
log(JSON.stringify({ file, lang, symbols, count: symbols.length, mode, durationMs: dt }, null, 2));
|
|
12661
12732
|
} else {
|
|
12662
|
-
log(`# leerness lsp symbols (1.9.
|
|
12663
|
-
log(`file: ${file}`);
|
|
12733
|
+
log(`# leerness lsp symbols (1.9.173 λ€κ΅μ΄)`);
|
|
12734
|
+
log(`file: ${file} Β· lang: ${lang}`);
|
|
12664
12735
|
log(`mode: ${mode} Β· ${symbols.length} symbols Β· ${dt}ms`);
|
|
12665
12736
|
symbols.slice(0, 50).forEach(s => log(` ${String(s.line).padStart(5)}:${s.kind.padEnd(10)} ${s.name}`));
|
|
12666
12737
|
if (symbols.length > 50) log(` ... ${symbols.length - 50} more`);
|
|
12667
12738
|
}
|
|
12668
|
-
try { _recordRun(root, { kind: 'lsp_symbols', file, count: symbols.length, mode, durationMs: dt, ok: true }); } catch {}
|
|
12739
|
+
try { _recordRun(root, { kind: 'lsp_symbols', file, lang, count: symbols.length, mode, durationMs: dt, ok: true }); } catch {}
|
|
12669
12740
|
return;
|
|
12670
12741
|
}
|
|
12671
12742
|
if (sub === 'references') {
|
|
@@ -12683,7 +12754,7 @@ function lspCmd(root, sub, ...args) {
|
|
|
12683
12754
|
if (e.name.startsWith('.') || e.name === 'node_modules' || e.name === 'dist' || e.name === 'build') continue;
|
|
12684
12755
|
const p = path.join(d, e.name);
|
|
12685
12756
|
if (e.isDirectory()) walk(p);
|
|
12686
|
-
else if (/\.(ts|tsx|js|jsx|mjs|cjs|md)$/.test(e.name)) {
|
|
12757
|
+
else if (/\.(ts|tsx|js|jsx|mjs|cjs|md|py|pyw|pyi|go|rs|java|kt|scala)$/.test(e.name)) {
|
|
12687
12758
|
try {
|
|
12688
12759
|
const lines = fs.readFileSync(p, 'utf8').split(/\r?\n/);
|
|
12689
12760
|
lines.forEach((ln, idx) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "leerness",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.174",
|
|
4
4
|
"description": "Leerness: λΉνκ΄΄ λ§μ΄κ·Έλ μ΄μ
, μλ λ²μ κ°μ§Β·μ
λ°μ΄νΈ, κ³ν/μ§ν/νΈλμ€ν μλν, κ²μΌλ¦Β·μν¬λ¦ΏΒ·μΈμ½λ© μλ κ°λ, Claude Code μ¬λμ ν΅ν©μ κ°μΆ νκ΅μ΄ μ°μ AI κ°λ° νλ€μ€.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"leerness",
|