deel-local-cli 1.20.9 → 1.20.11
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/README.ko.md +4 -2
- package/README.md +4 -2
- package/package.json +1 -1
- package/src/agent/effort.js +25 -2
- package/src/agent/evidence.js +12 -2
- package/src/agent/loop.js +42 -5
- package/src/agent/session.js +280 -34
- package/src/agent/threads.js +52 -1
- package/src/backend/ctxsize.js +17 -3
- package/src/commands.js +220 -23
- package/src/configexplain.js +15 -3
- package/src/i18n/en.js +3 -1
- package/src/i18n/ja.js +3 -1
- package/src/i18n/ko.js +3 -1
- package/src/i18n/zh.js +3 -1
- package/src/repl.js +421 -24
- package/src/safety/undo.js +98 -8
- package/src/tools/fsutil.js +7 -1
- package/src/tools/index.js +438 -31
- package/src/ui/export.js +5 -2
- package/src/ui/intro.js +2 -1
- package/src/ui/motion.js +40 -9
- package/src/ui/office.js +22 -1
- package/src/ui/pastechip.js +3 -0
- package/src/ui/screen.js +47 -4
- package/src/ui/status.js +20 -2
- package/src/ui/working.js +4 -1
package/README.ko.md
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
[](https://github.com/jysvai/deel-local-cli/actions/workflows/test.yml)
|
|
22
22
|
[](https://github.com/jysvai/deel-local-cli/actions/workflows/codeql.yml)
|
|
23
|
-
[](docs/ko/develop.md)
|
|
24
24
|
|
|
25
25
|
[](https://www.npmjs.com/package/deel-local-cli?activeTab=dependencies)
|
|
26
26
|
[](package.json)
|
|
@@ -301,7 +301,7 @@ deel --offline
|
|
|
301
301
|
무엇이 어디로 갈 수 있는지는 켤 때 화면 맨 위에 늘 적혀 있습니다.
|
|
302
302
|
|
|
303
303
|
```
|
|
304
|
-
deel 1.20.
|
|
304
|
+
deel 1.20.11 ⌂ 이 안
|
|
305
305
|
보냄 이 컴퓨터 안 127.0.0.1:11434 ← 여기 말고는 어디로도 안 갑니다
|
|
306
306
|
```
|
|
307
307
|
|
|
@@ -1289,6 +1289,8 @@ zip 은 진짜 `unzip` 으로, tar 는 진짜 `tar` 가 만든 것을 읽혀 교
|
|
|
1289
1289
|
|
|
1290
1290
|
| 판 | 무엇이 바뀌었나 |
|
|
1291
1291
|
|---|---|
|
|
1292
|
+
| [1.20.11](docs/ko/releases/1.20.md#12011) | 안전망이 있다고 말하는데 없었습니다 |
|
|
1293
|
+
| [1.20.10](docs/ko/releases/1.20.md#12010) | 답하지 않았는데 답한 것이 되어 있었습니다 |
|
|
1292
1294
|
| [1.20.9](docs/ko/releases/1.20.md#1209) | 안 보이는 것이 아니라 다른 것이 보이고 있었습니다 |
|
|
1293
1295
|
| [1.20.8](docs/ko/releases/1.20.md#1208) | 못 쟀다는 것을 안 된다고 적고 있었습니다 |
|
|
1294
1296
|
| [1.20.7](docs/ko/releases/1.20.md#1207) | 서버가 말해 준 것과 반대를 배우고 있었습니다 |
|
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ Vendor APIs connect too — **only when you say so**
|
|
|
20
20
|
|
|
21
21
|
[](https://github.com/jysvai/deel-local-cli/actions/workflows/test.yml)
|
|
22
22
|
[](https://github.com/jysvai/deel-local-cli/actions/workflows/codeql.yml)
|
|
23
|
-
[](docs/en/develop.md)
|
|
24
24
|
|
|
25
25
|
[](https://www.npmjs.com/package/deel-local-cli?activeTab=dependencies)
|
|
26
26
|
[](package.json)
|
|
@@ -374,7 +374,7 @@ deel --offline
|
|
|
374
374
|
The destination is printed at the top of every session:
|
|
375
375
|
|
|
376
376
|
```
|
|
377
|
-
deel 1.20.
|
|
377
|
+
deel 1.20.11 ⌂ inside
|
|
378
378
|
Sends to this machine 127.0.0.1:11434 ← nowhere else
|
|
379
379
|
```
|
|
380
380
|
|
|
@@ -1350,6 +1350,8 @@ so one run tells you everything.
|
|
|
1350
1350
|
|
|
1351
1351
|
| Version | What changed |
|
|
1352
1352
|
|---|---|
|
|
1353
|
+
| [1.20.11](docs/en/releases/1.20.md#12011) | The safety net said it was there when it wasn't |
|
|
1354
|
+
| [1.20.10](docs/en/releases/1.20.md#12010) | Nobody answered, yet an answer had been given |
|
|
1353
1355
|
| [1.20.9](docs/en/releases/1.20.md#1209) | Nothing was missing from the screen — something else was on it |
|
|
1354
1356
|
| [1.20.8](docs/en/releases/1.20.md#1208) | We were writing down "can't" where the truth was "couldn't measure" |
|
|
1355
1357
|
| [1.20.7](docs/en/releases/1.20.md#1207) | We were learning the opposite of what the server said |
|
package/package.json
CHANGED
package/src/agent/effort.js
CHANGED
|
@@ -101,9 +101,32 @@ export const MAX_CAP = 16384;
|
|
|
101
101
|
|
|
102
102
|
const ALIAS = { 균일: 'even', 절약: 'save', 깊게: 'deep', uniform: 'even', thrifty: 'save' };
|
|
103
103
|
|
|
104
|
+
/*
|
|
105
|
+
* 배분 이름을 표의 열쇠로 되돌린다.
|
|
106
|
+
*
|
|
107
|
+
* ── 있는지 없는지는 hasOwn 으로만 묻는다 ──────────────────────────────
|
|
108
|
+
*
|
|
109
|
+
* `PROFILES[k] ?` 는 **없는 이름에도 참**이 된다. 모든 객체가 물려받는
|
|
110
|
+
* `constructor` · `toString` · `valueOf` 가 그 자리다. 그래서:
|
|
111
|
+
*
|
|
112
|
+
* /think 배분 constructor
|
|
113
|
+
* -> 「모르는 배분입니다」 가 아니라 `✓ 배분 Object — undefined` 가 찍힌다.
|
|
114
|
+
* session.effort 에 'constructor' 가 박히고, 곧바로 단계표를 그리다
|
|
115
|
+
* p.shift[stage] 에서 터진다.
|
|
116
|
+
* /think 배분 toString
|
|
117
|
+
* -> ALIAS 쪽이 **함수**를 돌려준다. `?? null` 은 함수를 못 거른다.
|
|
118
|
+
* PROFILES[함수] 는 undefined 라 이름을 찍다 그 자리에서 터진다.
|
|
119
|
+
*
|
|
120
|
+
* 터지는 것만 문제가 아니다. 앞엣것은 **✓ 를 먼저 찍는다.** 사람은 배분을
|
|
121
|
+
* 바꿨다고 믿고, 그 판의 남은 턴은 전부 걸음 예산 계산에서 터진다.
|
|
122
|
+
* modes.js · /mode · /grade · ui/level.js 에서 같은 함정을 이미 닫았는데
|
|
123
|
+
* 여기만 옛 모양으로 남아 있었다.
|
|
124
|
+
*/
|
|
104
125
|
export function normalizeProfile(v) {
|
|
105
|
-
const
|
|
106
|
-
|
|
126
|
+
const 친것 = String(v ?? '').trim();
|
|
127
|
+
const k = 친것.toLowerCase();
|
|
128
|
+
if (Object.hasOwn(PROFILES, k)) return k;
|
|
129
|
+
return Object.hasOwn(ALIAS, 친것) ? ALIAS[친것] : null;
|
|
107
130
|
}
|
|
108
131
|
|
|
109
132
|
// 기준 강도에서 몇 칸 옮긴다. 끝을 넘지 않는다.
|
package/src/agent/evidence.js
CHANGED
|
@@ -176,13 +176,23 @@ export function 증거글(증거, { 제목 = '작업 증거' } = {}) {
|
|
|
176
176
|
* 파일로 남긴다. 화면은 스크롤로 사라지고, 검토는 나중에 다른 사람이 한다.
|
|
177
177
|
*
|
|
178
178
|
* @returns {string|null} 적은 자리. 못 적었으면 null — 못 적어도 대화는 계속된다.
|
|
179
|
+
*
|
|
180
|
+
* 못 적은 **까닭**은 버리지 않는다. 디스크가 찼는지, `.deel` 이 읽기 전용인지,
|
|
181
|
+
* 경로가 너무 긴지는 화면에 적혀야 사람이 손을 쓸 수 있다. 이 저장소의
|
|
182
|
+
* 저장시도()(config.js)가 이미 그렇게 한다 — 여기만 옛 모양이었다.
|
|
183
|
+
* 받을 그릇을 주면 거기 `왜` 를 담는다. 안 주면 여태처럼 조용히 null 이다.
|
|
184
|
+
*
|
|
185
|
+
* @param {{왜?: string}} [탈받을것]
|
|
179
186
|
*/
|
|
180
|
-
export function 증거적기(root, 증거, 이름 = '증거') {
|
|
187
|
+
export function 증거적기(root, 증거, 이름 = '증거', 탈받을것 = null) {
|
|
181
188
|
try {
|
|
182
189
|
const dir = join(root, '.deel', '증거');
|
|
183
190
|
mkdirSync(dir, { recursive: true });
|
|
184
191
|
const 자리 = join(dir, `${String(이름).replace(/[^\w가-힣.-]/g, '_')}.md`);
|
|
185
192
|
writeFileSync(자리, 증거글(증거), 'utf8');
|
|
186
193
|
return 자리;
|
|
187
|
-
} catch {
|
|
194
|
+
} catch (e) {
|
|
195
|
+
if (탈받을것) 탈받을것.왜 = String(e?.message ?? e);
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
188
198
|
}
|
package/src/agent/loop.js
CHANGED
|
@@ -90,8 +90,25 @@ function 빈답인가(msg) {
|
|
|
90
90
|
* 3) 둘 다 없으면 **없다고 말한다.** 침묵은 지어내기를 부른다.
|
|
91
91
|
*/
|
|
92
92
|
export function 실을글(result) {
|
|
93
|
-
if (result?.error) return `오류: ${result.error}`;
|
|
94
93
|
const 글 = result?.content;
|
|
94
|
+
/*
|
|
95
|
+
* ── 오류에도 **알아낸 것이 딸려 온다** ──────────────────────────
|
|
96
|
+
*
|
|
97
|
+
* 여태 오류면 그 한 줄만 싣고 content 를 버렸다. 그런데 오류와 글이
|
|
98
|
+
* 같이 오는 자리가 셋이나 된다 —
|
|
99
|
+
*
|
|
100
|
+
* · 끊긴 Bash 가 죽기 직전에 뱉은 몇 줄
|
|
101
|
+
* · 시간 초과로 끊긴 명령이 그때까지 찍은 것
|
|
102
|
+
* · 여덟 개를 서로 다른 까닭으로 다 실패한 Write·Edit 의 줄별 사유
|
|
103
|
+
*
|
|
104
|
+
* 마지막 것이 제일 아프다. 결과에는 여덟 줄이 다 적혀 있는데 모델은
|
|
105
|
+
* **첫 줄 하나**만 받고, 나머지 일곱은 왜 안 됐는지 모른 채 그대로
|
|
106
|
+
* 다시 보낸다. 오류는 오류대로 말하고, 알아낸 것은 같이 싣는다.
|
|
107
|
+
*/
|
|
108
|
+
if (result?.error) {
|
|
109
|
+
const 딸린것 = String(글 ?? '').trim();
|
|
110
|
+
return 딸린것 ? `오류: ${result.error}\n${딸린것}` : `오류: ${result.error}`;
|
|
111
|
+
}
|
|
95
112
|
if (String(글 ?? '').trim()) return String(글);
|
|
96
113
|
const 요약 = String(result?.summary ?? '').trim();
|
|
97
114
|
if (요약) return 요약;
|
|
@@ -288,14 +305,15 @@ export async function* run(session, ctx, userText, { signal = null, 깊이 = 0,
|
|
|
288
305
|
const 이카드 = ctx?.카드 ?? null;
|
|
289
306
|
const MAX_SAME = 이카드?.조정?.같은것한계 ?? 3;
|
|
290
307
|
let 멈출까 = null;
|
|
291
|
-
const 막힘셈 = (call,
|
|
308
|
+
const 막힘셈 = (call, 이유, { 몫 = 1 } = {}) => {
|
|
292
309
|
// 파일 하나가 아니라 **그 파일** 을 센다. 이름만 세면 서로 다른 파일 세 개를
|
|
293
310
|
// 고치다 실패한 것이 한 덩어리로 뭉쳐 턴이 죽는다. 다섯 군데 중 두 군데만
|
|
294
311
|
// 고쳐 놓고 '헛돌고 있어 멈췄습니다' 가 되는 것이 그 모습이다.
|
|
295
312
|
const 어디 = call.args?.file_path ?? call.args?.path ?? call.args?.pattern ?? call.args?.command
|
|
296
313
|
?? call.args?.purpose ?? call.args?.목적 ?? '';
|
|
297
314
|
const 서명 = `${call.name}|${이유}|${String(어디).slice(0, 200)}`;
|
|
298
|
-
|
|
315
|
+
// 몫: 도구가 「다시 해도 같다」(끝났다)고 말했으면 한 번을 두 번으로 센다.
|
|
316
|
+
const n = (막힘.get(서명) ?? 0) + 몫;
|
|
299
317
|
막힘.set(서명, n);
|
|
300
318
|
return n >= MAX_SAME;
|
|
301
319
|
};
|
|
@@ -1523,7 +1541,9 @@ export async function* run(session, ctx, userText, { signal = null, 깊이 = 0,
|
|
|
1523
1541
|
continue;
|
|
1524
1542
|
}
|
|
1525
1543
|
|
|
1526
|
-
|
|
1544
|
+
// 물려받은 이름(`constructor` 등)이면 여기가 참이 되어 「모르는 도구」
|
|
1545
|
+
// 관문을 그냥 통과했다. hasOwn 으로만 묻는다 (tools/index.js 도 같다).
|
|
1546
|
+
if (!Object.hasOwn(TOOLS, call.name)) {
|
|
1527
1547
|
거절(call, `모르는 도구입니다. 쓸 수 있는 것: ${Object.keys(TOOLS).join(', ')}`);
|
|
1528
1548
|
// 이것도 세야 한다. 없는 이름을 계속 부르며 걸음 수를 다 쓰는 길이 있었다 —
|
|
1529
1549
|
// 71초 증상과 겉모습이 똑같은데 문만 다르다. 아래 거부·중복도 마찬가지다.
|
|
@@ -1930,7 +1950,24 @@ export async function* run(session, ctx, userText, { signal = null, 깊이 = 0,
|
|
|
1930
1950
|
// 같은 도구가 같은 이유로 계속 실패하면 헛돌고 있는 것이다.
|
|
1931
1951
|
// 오류의 첫 줄만 본다 — 뒤에 붙는 경로·숫자는 매번 달라도 원인은 같다.
|
|
1932
1952
|
const 이유 = String(result.error).split('\n')[0].slice(0, 60);
|
|
1933
|
-
|
|
1953
|
+
/*
|
|
1954
|
+
* ── `끝났다` 는 **아무도 안 읽고 있었다** ──────────────────
|
|
1955
|
+
*
|
|
1956
|
+
* 도구 쪽 열대여섯 자리가 이 표를 달아 보낸다. 뜻은 「다시 물어도
|
|
1957
|
+
* 답이 같다」 — 옛 hwp, 못 읽는 확장자, 없는 폴더처럼 되풀이가
|
|
1958
|
+
* 아무 소용 없는 자리들이다. tools/index.js 의 주석은 아예
|
|
1959
|
+
* `끝났다: true → 되풀이 억제가 걸린다` 라고 적어 뒀는데,
|
|
1960
|
+
* 저장소를 통틀어 이 값을 **읽는 자리가 한 곳도 없었다.**
|
|
1961
|
+
* 걸린다고 적어 놓고 아무것도 안 걸고 있었다.
|
|
1962
|
+
*
|
|
1963
|
+
* 그래서 여기서 읽는다. 세 번을 기다리지 않고 두 몫으로 센다 —
|
|
1964
|
+
* 도구가 스스로 「이건 끝이다」 라고 말한 것이라, 같은 자리를 한
|
|
1965
|
+
* 번 더 두드리면 그것으로 충분하다. 그래도 곧바로 멈추지는
|
|
1966
|
+
* 않는다. 모델이 다른 길로 갈 여지는 남겨 둔다.
|
|
1967
|
+
*/
|
|
1968
|
+
if (막힘셈(call, 이유, { 몫: result.끝났다 ? 2 : 1 })) {
|
|
1969
|
+
멈출까 = `${call.name} 이 같은 이유로 계속 실패합니다 — ${이유}`;
|
|
1970
|
+
}
|
|
1934
1971
|
}
|
|
1935
1972
|
if (call.name === 'Read' && result.content) session.noteRead(call.args.file_path, result.content);
|
|
1936
1973
|
// 실제로 파일이 바뀐 것만 적는다. 턴 끝에 이 목록을 디스크와 견준다.
|