deel-local-cli 1.17.3 → 1.17.5
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 +5 -3
- package/README.md +5 -3
- package/package.json +1 -1
- package/src/agent/compact.js +106 -6
- package/src/agent/evolve.js +83 -9
- package/src/agent/loop.js +251 -19
- package/src/agent/modes.js +4 -1
- package/src/agent//353/213/250/352/263/204.js +133 -0
- package/src/agent//354/204/261/355/225/234/352/270/260/353/241/235.js +66 -0
- package/src/agent//354/213/240/353/242/260/353/217/204.js +191 -0
- package/src/backend/adapter.js +60 -1
- package/src/commands.js +16 -1
- package/src/i18n/en.js +4 -0
- package/src/i18n/ja.js +4 -0
- package/src/i18n/ko.js +4 -0
- package/src/i18n/zh.js +4 -0
- package/src/oneshot.js +16 -1
- package/src/repl.js +75 -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)
|
|
@@ -268,7 +268,7 @@ deel --offline
|
|
|
268
268
|
무엇이 어디로 갈 수 있는지는 켤 때 화면 맨 위에 늘 적혀 있습니다.
|
|
269
269
|
|
|
270
270
|
```
|
|
271
|
-
deel 1.17.
|
|
271
|
+
deel 1.17.5 ⌂ 이 안
|
|
272
272
|
보냄 이 컴퓨터 안 127.0.0.1:11434 ← 여기 말고는 어디로도 안 갑니다
|
|
273
273
|
```
|
|
274
274
|
|
|
@@ -1185,7 +1185,7 @@ deel stats # 이 폴더에서 실제로 무엇을 했나 (.de
|
|
|
1185
1185
|
## 개발
|
|
1186
1186
|
|
|
1187
1187
|
```bash
|
|
1188
|
-
npm test 전체 검증 (7,
|
|
1188
|
+
npm test 전체 검증 (7,991항목 — 몇몇은 터미널에 따라 갈립니다)
|
|
1189
1189
|
npm run coverage 검사가 소스의 어디를 밟았는지
|
|
1190
1190
|
npm run verify 반입·통신 검증만
|
|
1191
1191
|
npm run bench 편집 성공률 측정
|
|
@@ -1254,6 +1254,8 @@ zip 은 진짜 `unzip` 으로, tar 는 진짜 `tar` 가 만든 것을 읽혀 교
|
|
|
1254
1254
|
|
|
1255
1255
|
| 판 | 무엇이 바뀌었나 |
|
|
1256
1256
|
|---|---|
|
|
1257
|
+
| [1.17.5](docs/ko/releases/1.17.md#1175) | 한 턴 안에서 단계가 일을 따라갑니다 — 그리고 읽기 도구 넷이 여태 줄을 서 있었습니다 |
|
|
1258
|
+
| [1.17.4](docs/ko/releases/1.17.md#1174) | 같은 요청을 한 번 더 보내던 자리들 — 그리고 배운 것이 스스로를 봉인하던 자리 |
|
|
1257
1259
|
| [1.17.3](docs/ko/releases/1.17.md#1173) | 「같은 대화다」 를 적는 표준 이름이 없습니다 — 아는 이름을 다 답니다 |
|
|
1258
1260
|
| [1.17.2](docs/ko/releases/1.17.md#1172) | 다른 눈으로 한 번 더 — 한글이 못 여는 hwpx · 이름 없이 나가던 요청 둘 |
|
|
1259
1261
|
| [1.17.1](docs/ko/releases/1.17.md#1171) | 내 PC 에서만 초록이던 것 둘 — 지운 폴더에 쓰기 · 소스에 박힌 날 NUL |
|
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)
|
|
@@ -339,7 +339,7 @@ deel --offline
|
|
|
339
339
|
The destination is printed at the top of every session:
|
|
340
340
|
|
|
341
341
|
```
|
|
342
|
-
deel 1.17.
|
|
342
|
+
deel 1.17.5 ⌂ inside
|
|
343
343
|
Sends to this machine 127.0.0.1:11434 ← nowhere else
|
|
344
344
|
```
|
|
345
345
|
|
|
@@ -1258,7 +1258,7 @@ Stored in `~/.deel/config.json`. A `.deel/config.json` in the project folder tak
|
|
|
1258
1258
|
## Development
|
|
1259
1259
|
|
|
1260
1260
|
```bash
|
|
1261
|
-
npm test Full suite (7,
|
|
1261
|
+
npm test Full suite (7,991 checks; a few are TTY-dependent)
|
|
1262
1262
|
npm run coverage Which lines the tests actually execute
|
|
1263
1263
|
npm run verify Import + network checks only
|
|
1264
1264
|
npm run bench Edit success rate
|
|
@@ -1313,6 +1313,8 @@ so one run tells you everything.
|
|
|
1313
1313
|
|
|
1314
1314
|
| Version | What changed |
|
|
1315
1315
|
|---|---|
|
|
1316
|
+
| [1.17.5](docs/en/releases/1.17.md#1175) | The phase now follows the work inside a turn — and four read tools had been queueing up |
|
|
1317
|
+
| [1.17.4](docs/en/releases/1.17.md#1174) | The places that sent the same request twice — and where what it learned sealed itself in |
|
|
1316
1318
|
| [1.17.3](docs/en/releases/1.17.md#1173) | No standard name for "same conversation" — it sends every name it knows |
|
|
1317
1319
|
| [1.17.2](docs/en/releases/1.17.md#1172) | A second pair of eyes — an hwpx Hancom cannot open · two requests going out unnamed |
|
|
1318
1320
|
| [1.17.1](docs/en/releases/1.17.md#1171) | Two things only green on one machine — writing into a deleted directory · raw NUL in the source |
|
package/package.json
CHANGED
package/src/agent/compact.js
CHANGED
|
@@ -40,6 +40,81 @@ export const KEEP_RECENT = 4; // 최근 도구 결과 이만큼은 원문
|
|
|
40
40
|
export const FOLD_MIN = 300; // 이보다 작으면 접어도 자리가 안 준다 (글자 수)
|
|
41
41
|
export const 접힘표 = '(접힘)';
|
|
42
42
|
|
|
43
|
+
/*
|
|
44
|
+
* ── 캐시가 도는 연결에서는 접기가 **돈을 쓴다** ─────────────────────────
|
|
45
|
+
*
|
|
46
|
+
* 위 글은 「읽는 값은 싸고, 하던 일을 잊는 값은 비싸다」 로 끝난다. 캐시가
|
|
47
|
+
* 없는 자리에서는 그 말이 그대로 맞다 — 안 접으면 옛 파일 내용을 걸음마다
|
|
48
|
+
* 전액 다시 보낸다.
|
|
49
|
+
*
|
|
50
|
+
* 캐시가 도는 자리에서는 셈이 뒤집힌다. 안 접으면 그 옛 파일 내용은
|
|
51
|
+
* **캐시에서 읽힌다.** 우리가 재 본 게이트웨이에서 쓰기는 읽기의 12.5배였다
|
|
52
|
+
* (읽기 $0.50 · 쓰기 $6.25 / MTok). 그러니 접는 순간 그 자리 뒤가 전부 새 글이
|
|
53
|
+
* 되어, **싸게 읽히던 것을 비싸게 다시 쓴다.**
|
|
54
|
+
*
|
|
55
|
+
* 손익분기를 풀면 이렇다. P = 접기 전 프리픽스, S = 비운 토큰, k = 쓰기/읽기 비,
|
|
56
|
+
* N = 본전을 뽑기까지 도는 턴 수라고 하면
|
|
57
|
+
*
|
|
58
|
+
* 이번에 더 내는 값 = (P−S)·k − P 턴당 아끼는 값 = S
|
|
59
|
+
* N턴 안에 본전을 뽑으려면 S ≥ P·(k−1)/(N+k)
|
|
60
|
+
*
|
|
61
|
+
* k=12.5, N=4 를 넣으면 S ≥ 0.7P 다. 프리픽스의 7할을 비워야 넉 턴 만에 본전인데,
|
|
62
|
+
* 오래된 도구 결과만으로 7할을 비우는 대화는 드물다. 실제로 잰 판에서는
|
|
63
|
+
* 65,619 토큰을 비우고 본전까지 아홉 턴이 걸렸고, 그 아홉 턴이 오기 전에 0.8
|
|
64
|
+
* 요약 압축이 와서 캐시가 한 번 더 끊겼다.
|
|
65
|
+
*
|
|
66
|
+
* 그래서 캐시가 도는 연결에서는 **접기를 뒤로 민다.** 다만 요약 압축(0.8)에
|
|
67
|
+
* 너무 붙이면 안 된다 — 접고 한두 턴 만에 요약이 오면 캐시를 연달아 두 번
|
|
68
|
+
* 깬다. 0.72 는 그 사이다.
|
|
69
|
+
*
|
|
70
|
+
* 그리고 문턱을 토큰 수가 아니라 **창에 견준 몫**으로 받는다. 2,000토큰은
|
|
71
|
+
* 32k 창에서는 6% 지만 200k 창에서는 1% 다. 1% 를 비우려고 프리픽스를 통째로
|
|
72
|
+
* 다시 쓰는 것이 여태 하던 일이었다.
|
|
73
|
+
*
|
|
74
|
+
* 「캐시가 돈다」 는 카드를 보고 정하지 않는다 — **읽힌 것을 봤나**로 정한다.
|
|
75
|
+
* 카드는 우리가 표식을 붙였다는 뜻일 뿐이고, 서버가 실제로 잡았는지는 다른
|
|
76
|
+
* 이야기다. 한 번도 안 읽힌 연결에서는 여태 하던 대로 0.55 에서 접는다.
|
|
77
|
+
*/
|
|
78
|
+
export const FOLD_AT_캐시 = 0.72;
|
|
79
|
+
|
|
80
|
+
/*
|
|
81
|
+
* 창의 이만큼은 비워야 접을 값어치가 있다.
|
|
82
|
+
*
|
|
83
|
+
* 순수 캐시 셈으로만 보면 이 문턱은 훨씬 높아야 한다 — 7할을 비워도 본전이
|
|
84
|
+
* 넉 턴이다. 그런데 **견줄 상대가 「안 접기」 가 아니다.** 0.72 는 요약
|
|
85
|
+
* 압축(0.80) 코앞이고, 요약은 캐시를 어차피 깨면서 대화까지 잃는다.
|
|
86
|
+
* 그러니 여기서 재야 하는 것은 「접기가 공짜인가」 가 아니라 「접어서 요약을
|
|
87
|
+
* 미룰 수 있나」 다.
|
|
88
|
+
*
|
|
89
|
+
* 창의 한 할이면 0.72 에서 0.62 로 내려간다 — 요약까지 두 배로 멀어진다.
|
|
90
|
+
* 그보다 적게 비우는 접기는 요약을 못 미루면서 캐시만 깬다.
|
|
91
|
+
*/
|
|
92
|
+
export const 캐시일때비울몫 = 0.10;
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* 이 연결에서 캐시가 도나.
|
|
96
|
+
*
|
|
97
|
+
* **모르는 동안에는 돈다고 친다.** 이게 이 함수에서 제일 중요한 줄이다.
|
|
98
|
+
*
|
|
99
|
+
* 읽힌 것을 봤나로 정하는 것이 옳지만, 첫 턴에는 볼 기회가 없다 — 첫 요청은
|
|
100
|
+
* 캐시를 쓰기만 하고 읽지는 못한다. 그 자리에서 「캐시가 없다」 로 읽으면,
|
|
101
|
+
* 첫 턴에 큰 파일 몇 개를 읽어 창이 반쯤 찬 대화가 **두 번째 턴 시작하자마자
|
|
102
|
+
* 방금 비싸게 만들어 둔 앞머리를 스스로 부순다.**
|
|
103
|
+
*
|
|
104
|
+
* 틀렸을 때 잃는 것이 양쪽으로 다르다. 캐시가 없는데 있다고 치면 접기가 좀
|
|
105
|
+
* 늦어질 뿐이고, 있는데 없다고 치면 방금 만든 캐시를 깬다. 그래서 모르는
|
|
106
|
+
* 쪽은 덜 잃는 쪽으로 기울인다.
|
|
107
|
+
*
|
|
108
|
+
* 두 번 넘게 불렀는데도 읽힌 것이 하나도 없으면, 그때는 정말 없는 것이다.
|
|
109
|
+
*/
|
|
110
|
+
export const 재볼기회 = 2;
|
|
111
|
+
|
|
112
|
+
export function 캐시가도나(session) {
|
|
113
|
+
const u = session?.usage ?? {};
|
|
114
|
+
if ((u.cacheRead ?? 0) > 0) return true;
|
|
115
|
+
return (u.calls ?? 0) < 재볼기회;
|
|
116
|
+
}
|
|
117
|
+
|
|
43
118
|
/*
|
|
44
119
|
* ── 접기는 **묶음으로** 한다 ────────────────────────────────────────────
|
|
45
120
|
*
|
|
@@ -102,9 +177,22 @@ ${접힘표} 그림 ${장수}장은 자리를 비우려고 뺐습니다. 필요
|
|
|
102
177
|
return { 뺀것: 뺄것.length, 뺀것들 };
|
|
103
178
|
}
|
|
104
179
|
|
|
105
|
-
export function shouldFold(session, at =
|
|
180
|
+
export function shouldFold(session, at = null) {
|
|
106
181
|
const b = session.breakdown();
|
|
107
|
-
|
|
182
|
+
const 문턱 = at ?? (캐시가도나(session) ? FOLD_AT_캐시 : FOLD_AT);
|
|
183
|
+
return b.total > 0 && b.used / b.total >= 문턱;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* 이 연결에서 「이만큼은 비워야 접는다」 는 값 (토큰).
|
|
188
|
+
*
|
|
189
|
+
* 캐시가 안 도는 자리에서는 여태 쓰던 고정값(최소이득)이다. 도는 자리에서는
|
|
190
|
+
* 창에 견준 몫으로 잰다 — 위 머리말의 손익분기 때문이다.
|
|
191
|
+
*/
|
|
192
|
+
export function 접을이득문턱(session) {
|
|
193
|
+
if (!캐시가도나(session)) return 최소이득;
|
|
194
|
+
const 창 = session?.breakdown?.()?.total ?? 0;
|
|
195
|
+
return 창 > 0 ? Math.max(최소이득, Math.floor(창 * 캐시일때비울몫)) : 최소이득;
|
|
108
196
|
}
|
|
109
197
|
|
|
110
198
|
/**
|
|
@@ -115,8 +203,10 @@ export function shouldFold(session, at = FOLD_AT) {
|
|
|
115
203
|
*
|
|
116
204
|
* @returns {{접은것: number, 아낀토큰: number}}
|
|
117
205
|
*/
|
|
118
|
-
export function foldToolResults(session, { keep = KEEP_RECENT, min = FOLD_MIN, 이득문턱 =
|
|
206
|
+
export function foldToolResults(session, { keep = KEEP_RECENT, min = FOLD_MIN, 이득문턱 = null } = {}) {
|
|
119
207
|
const ms = session.messages ?? [];
|
|
208
|
+
// 안 적어 주면 이 연결에 맞는 값으로 (위 접을이득문턱 — 캐시가 도는지가 가른다).
|
|
209
|
+
const 넘을것 = 이득문턱 ?? 접을이득문턱(session);
|
|
120
210
|
|
|
121
211
|
/*
|
|
122
212
|
* 호출 쪽에서 이름과 인자를 가져온다. 결과 메시지에는 그게 안 실려 있다.
|
|
@@ -206,10 +296,10 @@ export function foldToolResults(session, { keep = KEEP_RECENT, min = FOLD_MIN,
|
|
|
206
296
|
* 100자도 안 된다). 그래서 이 수는 언제나 **새로 접을 것**의 수다.
|
|
207
297
|
*/
|
|
208
298
|
const 예상이득 = 접을것.reduce((a, x) => a + estimateTokens(x.글), 0);
|
|
209
|
-
if (예상이득 <
|
|
299
|
+
if (예상이득 < 넘을것 || 접을것.length < keep) {
|
|
210
300
|
return {
|
|
211
301
|
접은것: 0, 아낀토큰: 0, 접은것들: [], 미룸: true,
|
|
212
|
-
모인것: 예상이득, 모인개수: 접을것.length,
|
|
302
|
+
모인것: 예상이득, 모인개수: 접을것.length, 넘을것,
|
|
213
303
|
};
|
|
214
304
|
}
|
|
215
305
|
|
|
@@ -253,7 +343,17 @@ export function foldToolResults(session, { keep = KEEP_RECENT, min = FOLD_MIN,
|
|
|
253
343
|
접은것들.push({ 도구: 도구이름, 곳, 경로, 줄수, 토큰: Math.max(0, 아낀것) });
|
|
254
344
|
}
|
|
255
345
|
|
|
256
|
-
|
|
346
|
+
/*
|
|
347
|
+
* 캐시를 다시 쓰게 된다는 것도 같이 올린다.
|
|
348
|
+
*
|
|
349
|
+
* 접기는 값이 드는 일인데(위 손익분기), 화면에는 「몇 토큰을 비웠다」 만
|
|
350
|
+
* 나왔다. 그러면 사람은 이득만 보고 대가는 며칠 뒤 청구서에서 본다.
|
|
351
|
+
* 캐시가 도는 자리에서만 참이므로, 실제로 읽힌 것을 봤을 때만 적는다.
|
|
352
|
+
*/
|
|
353
|
+
return {
|
|
354
|
+
접은것: 접을것.length, 아낀토큰: Math.max(0, 아낀토큰), 접은것들,
|
|
355
|
+
캐시다시씀: 캐시가도나(session),
|
|
356
|
+
};
|
|
257
357
|
}
|
|
258
358
|
|
|
259
359
|
/**
|
package/src/agent/evolve.js
CHANGED
|
@@ -36,6 +36,17 @@
|
|
|
36
36
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
37
37
|
import { join, dirname } from 'node:path';
|
|
38
38
|
import { estimateTokens } from './session.js';
|
|
39
|
+
/*
|
|
40
|
+
* 「이걸 사실로 말해도 되나」 는 **여기서 안 정한다** (agent/신뢰도.js).
|
|
41
|
+
*
|
|
42
|
+
* 이 파일은 무엇을 겪었나를 센다. 그 셈을 얼마나 믿을지는 다른 일이고,
|
|
43
|
+
* 섞어 두면 셈을 고칠 때마다 믿음의 문턱이 같이 흔들린다 — 그리고 그건
|
|
44
|
+
* 화면에 안 나타난다.
|
|
45
|
+
*/
|
|
46
|
+
import { 삭힘, 며칠됐나, 뭐라할까, 하루할인된다 } from './신뢰도.js';
|
|
47
|
+
// 파일에서 읽은 것이 **우리가 적은 모양이 맞나** (agent/성한기록.js).
|
|
48
|
+
// 통계와 문지기는 다른 일이라 따로 둔다.
|
|
49
|
+
import { 거른표 } from './성한기록.js';
|
|
39
50
|
|
|
40
51
|
export const 최대토큰 = 220; // 프롬프트에 실을 상한
|
|
41
52
|
const 명령최대 = 40; // 표가 끝없이 자라지 않게
|
|
@@ -43,11 +54,23 @@ const 모델최대 = 10;
|
|
|
43
54
|
|
|
44
55
|
const 빈것 = () => ({ 판: 1, 명령: {}, 모델: {} });
|
|
45
56
|
|
|
57
|
+
/*
|
|
58
|
+
* 파일에서 읽은 것을 **그대로 믿지 않는다** (agent/성한기록.js 의 거른표).
|
|
59
|
+
*
|
|
60
|
+
* 이 표의 열쇠는 시스템 프롬프트에 그대로 실린다. 그러니 여기가 프롬프트로
|
|
61
|
+
* 들어가는 문이고, 문에는 자물쇠가 있어야 한다. 손으로 고쳤을 수도, 쓰다 만
|
|
62
|
+
* 채로 남았을 수도, 다른 판이 다른 모양으로 적어 뒀을 수도 있다.
|
|
63
|
+
*
|
|
64
|
+
* 걸러낸 것은 **버린다** — 파일에는 그대로 두고 이 판에서 안 쓸 뿐이다.
|
|
65
|
+
* 모양이 안 맞는 것을 고쳐서 쓰려 들면 무엇을 어떻게 고쳤는지가 또 안 보인다.
|
|
66
|
+
*/
|
|
46
67
|
function 읽기(파일) {
|
|
47
68
|
try {
|
|
48
69
|
if (!existsSync(파일)) return 빈것();
|
|
49
70
|
const j = JSON.parse(readFileSync(파일, 'utf8'));
|
|
50
|
-
|
|
71
|
+
const 것 = { ...빈것(), ...(j && typeof j === 'object' ? j : {}) };
|
|
72
|
+
것.명령 = 거른표(것.명령);
|
|
73
|
+
return 것;
|
|
51
74
|
} catch { return 빈것(); }
|
|
52
75
|
}
|
|
53
76
|
|
|
@@ -99,8 +122,20 @@ export class 배움 {
|
|
|
99
122
|
const 열쇠 = (없는프로그램 ? 낱말.slice(0, 1) : 낱말.slice(0, 2)).join(' ').slice(0, 40);
|
|
100
123
|
if (!열쇠) return this;
|
|
101
124
|
const 표 = this.폴더.명령;
|
|
102
|
-
const
|
|
103
|
-
|
|
125
|
+
const 옛 = 표[열쇠] ?? { ok: 0, no: 0, at: this.지금 };
|
|
126
|
+
/*
|
|
127
|
+
* 지난 셈을 **오늘 기준으로 삭혀서** 이어 센다 (agent/신뢰도.js 의 삭힘).
|
|
128
|
+
*
|
|
129
|
+
* 그냥 더하면 석 달 전 실패와 오늘 실패가 같은 무게가 된다. 그러면 한번
|
|
130
|
+
* 「안 된다」 로 굳은 것이 영영 안 풀린다 — 프롬프트가 부르지 말라고 하니
|
|
131
|
+
* 안 부르고, 안 부르니 성공 셈이 안 늘고, 그래서 그 줄이 안 사라진다.
|
|
132
|
+
*
|
|
133
|
+
* 삭히면 그 고리가 저절로 끊긴다. 다시 안 겪은 것은 힘이 빠지고, 힘이
|
|
134
|
+
* 빠지면 말하기를 멈추고, 그러면 모델이 다시 해 본다. 잊는 것이 곧 다시
|
|
135
|
+
* 해 보는 것이다.
|
|
136
|
+
*/
|
|
137
|
+
const r = { ...옛, ...삭힘(옛, 며칠됐나(this.지금, 옛.at)) };
|
|
138
|
+
if (됐나) r.ok += 1; else r.no += 1;
|
|
104
139
|
r.at = this.지금;
|
|
105
140
|
표[열쇠] = r;
|
|
106
141
|
줄이기(표, 명령최대);
|
|
@@ -210,18 +245,36 @@ export class 배움 {
|
|
|
210
245
|
요약(모델 = '', 상한 = 최대토큰) {
|
|
211
246
|
const 줄 = [];
|
|
212
247
|
|
|
213
|
-
|
|
248
|
+
/*
|
|
249
|
+
* 되는 명령 / 안 되는 명령. 이 폴더의 사실이다.
|
|
250
|
+
*
|
|
251
|
+
* 문턱은 **여기서 안 정한다** (agent/신뢰도.js 의 뭐라할까). 여태 이 자리에
|
|
252
|
+
* `ok>=2 && no===0` 이 박혀 있었는데, 그 두 숫자가 어디서 왔는지는 아무 데도
|
|
253
|
+
* 안 적혀 있었고 섞인 증거(다섯 번 되고 한 번 안 됨)를 아예 못 다뤘다.
|
|
254
|
+
* 지금은 표본이 적으면 깎아서 보고(윌슨), 다시 안 겪은 것은 힘이 빠진다(할인).
|
|
255
|
+
*/
|
|
214
256
|
const 되는것 = [];
|
|
215
257
|
const 안되는것 = [];
|
|
216
258
|
for (const [열쇠, r] of Object.entries(this.폴더.명령 ?? {})) {
|
|
217
|
-
|
|
218
|
-
|
|
259
|
+
const 판정 = 뭐라할까(r, this.지금);
|
|
260
|
+
if (판정 === '된다') 되는것.push(열쇠);
|
|
261
|
+
else if (판정 === '안된다') 안되는것.push(열쇠);
|
|
219
262
|
}
|
|
220
263
|
if (되는것.length) 줄.push(`- 여기서 되는 명령: ${되는것.slice(0, 6).map((x) => `\`${x}\``).join(' · ')}`);
|
|
221
264
|
if (안되는것.length) 줄.push(`- 이 PC 에서 안 되는 명령(다시 부르지 마라): ${안되는것.slice(0, 6).map((x) => `\`${x}\``).join(' · ')}`);
|
|
222
265
|
|
|
223
266
|
// 모델 버릇. 걸음이 쌓여야 말이 된다.
|
|
224
|
-
|
|
267
|
+
//
|
|
268
|
+
// 버릇도 늙는다. 같은 이름의 모델이 게이트웨이 뒤에서 조용히 판이 오른다 —
|
|
269
|
+
// 석 달 전에 인자를 잘라 먹던 그 이름이 지금도 그런다는 보장이 없다.
|
|
270
|
+
//
|
|
271
|
+
// 여기도 삭힌 값으로 잰다. 이름이 같은 모델도 게이트웨이 뒤에서 조용히
|
|
272
|
+
// 판이 오른다 — 석 달 전에 인자를 잘라 먹던 그 이름이 지금도 그런다는
|
|
273
|
+
// 보장이 없다. 걸음 수가 삭아서 열 아래로 내려가면 말하기를 멈춘다.
|
|
274
|
+
const m0 = this.집.모델?.[String(모델 ?? '')];
|
|
275
|
+
const 삭은몫 = m0 ? Math.pow(하루할인된다, 며칠됐나(this.지금, m0.at)) : 0;
|
|
276
|
+
const m = m0 ? Object.fromEntries(Object.entries(m0)
|
|
277
|
+
.map(([k, v]) => [k, typeof v === 'number' ? v * 삭은몫 : v])) : null;
|
|
225
278
|
if (m && (m.걸음 ?? 0) >= 10) {
|
|
226
279
|
if ((m.잘린인자 ?? 0) / m.걸음 >= 0.15) {
|
|
227
280
|
줄.push('- 이 모델은 큰 인자를 자주 잘라 먹었다. 파일은 Write 한 번에 다 쓰지 말고 Append 로 나눠 써라.');
|
|
@@ -254,10 +307,31 @@ export class 배움 {
|
|
|
254
307
|
|
|
255
308
|
/** 화면에 뿌릴 것. */
|
|
256
309
|
현황(모델 = '') {
|
|
310
|
+
/*
|
|
311
|
+
* 나이와 **판정**을 같이 준다.
|
|
312
|
+
*
|
|
313
|
+
* 화면이 「됨 3 · 안 됨 0」 만 보여 주면, 그게 오늘 잰 것인지 두 달 전
|
|
314
|
+
* 것인지 사람이 못 가른다. 그런데 그 둘은 **다르게 취급된다** — 삭은
|
|
315
|
+
* 것은 프롬프트에 안 실린다(agent/신뢰도.js). 화면과 실제가 갈리면
|
|
316
|
+
* 사람은 안 실린 줄을 실린 줄로 읽는다.
|
|
317
|
+
*
|
|
318
|
+
* 판정도 여기서 같이 낸다. 화면이 문턱을 제 나름대로 다시 계산하면
|
|
319
|
+
* 언젠가 한쪽만 고쳐지고, 그때부터 화면은 실제와 다른 것을 말한다.
|
|
320
|
+
*/
|
|
257
321
|
const 명령 = Object.entries(this.폴더.명령 ?? {})
|
|
258
|
-
.map(([이름, r]) => ({
|
|
322
|
+
.map(([이름, r]) => ({
|
|
323
|
+
이름,
|
|
324
|
+
...r,
|
|
325
|
+
나이: 며칠됐나(this.지금, r?.at),
|
|
326
|
+
판정: 뭐라할까(r, this.지금),
|
|
327
|
+
}))
|
|
259
328
|
.sort((a, b) => (b.ok + b.no) - (a.ok + a.no));
|
|
260
329
|
const m = this.집.모델?.[String(모델 ?? '')] ?? null;
|
|
261
|
-
return {
|
|
330
|
+
return {
|
|
331
|
+
명령,
|
|
332
|
+
모델: m,
|
|
333
|
+
모델이름: String(모델 ?? ''),
|
|
334
|
+
모델나이: m ? 며칠됐나(this.지금, m.at) : Infinity,
|
|
335
|
+
};
|
|
262
336
|
}
|
|
263
337
|
}
|