deel-local-cli 1.20.8 → 1.20.10
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/bin/deel.js +27 -0
- package/package.json +1 -1
- package/src/agent/effort.js +25 -2
- package/src/agent/evidence.js +12 -2
- package/src/agent/loop.js +3 -1
- package/src/agent/models.js +22 -0
- package/src/agent/modes.js +67 -7
- package/src/agent/session.js +13 -2
- package/src/backend/ctxsize.js +17 -3
- package/src/commands.js +251 -31
- package/src/configexplain.js +15 -3
- package/src/i18n/en.js +2 -1
- package/src/i18n/ko.js +2 -1
- package/src/repl.js +379 -24
- package/src/tools/index.js +11 -1
- package/src/tools/pdf.js +168 -44
- package/src/ui/ansi.js +30 -8
- package/src/ui/export.js +5 -2
- package/src/ui/inputbox.js +105 -25
- package/src/ui/level.js +9 -1
- package/src/ui/office.js +16 -2
- package/src/ui/pastechip.js +3 -0
- package/src/ui/status.js +46 -5
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.10 ⌂ 이 안
|
|
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.10](docs/ko/releases/1.20.md#12010) | 답하지 않았는데 답한 것이 되어 있었습니다 |
|
|
1293
|
+
| [1.20.9](docs/ko/releases/1.20.md#1209) | 안 보이는 것이 아니라 다른 것이 보이고 있었습니다 |
|
|
1292
1294
|
| [1.20.8](docs/ko/releases/1.20.md#1208) | 못 쟀다는 것을 안 된다고 적고 있었습니다 |
|
|
1293
1295
|
| [1.20.7](docs/ko/releases/1.20.md#1207) | 서버가 말해 준 것과 반대를 배우고 있었습니다 |
|
|
1294
1296
|
| [1.20.6](docs/ko/releases/1.20.md#1206) | 2차 리뷰가 판을 조용히 잃고 있었습니다 |
|
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.10 ⌂ 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.10](docs/en/releases/1.20.md#12010) | Nobody answered, yet an answer had been given |
|
|
1354
|
+
| [1.20.9](docs/en/releases/1.20.md#1209) | Nothing was missing from the screen — something else was on it |
|
|
1353
1355
|
| [1.20.8](docs/en/releases/1.20.md#1208) | We were writing down "can't" where the truth was "couldn't measure" |
|
|
1354
1356
|
| [1.20.7](docs/en/releases/1.20.md#1207) | We were learning the opposite of what the server said |
|
|
1355
1357
|
| [1.20.6](docs/en/releases/1.20.md#1206) | The second review was losing rounds silently |
|
package/bin/deel.js
CHANGED
|
@@ -701,6 +701,33 @@ async function main() {
|
|
|
701
701
|
|
|
702
702
|
if (flags.help || cmd === 'help') { help(); return 0; }
|
|
703
703
|
|
|
704
|
+
/*
|
|
705
|
+
* `--work` 에 오타가 났으면 **여기서 멈춘다.**
|
|
706
|
+
*
|
|
707
|
+
* 모르는 이름은 조용히 기본값(종합)으로 떨어진다. 그런데 종합은 Write·Edit·
|
|
708
|
+
* Bash 를 다 가진 모드다 — `deel --work architcet` 한 번으로, 파일을 안
|
|
709
|
+
* 건드리는 모드로 켠 줄 알고 **고칠 수 있는 상태**로 돌게 된다. 화면에
|
|
710
|
+
* 남는 단서는 상태줄 글자 하나뿐이다.
|
|
711
|
+
*
|
|
712
|
+
* 대화 중에 치는 `/work` 는 관대하게 받아도 된다(틀리면 바로 화면에 뜨고
|
|
713
|
+
* 다시 치면 된다). 깃발은 한 번 켜면 그 세션이 끝까지 그걸로 간다.
|
|
714
|
+
*
|
|
715
|
+
* 판 번호·도움말보다 뒤에 둔다 — 그 둘은 무엇을 잘못 쳤든 답해야 한다.
|
|
716
|
+
*/
|
|
717
|
+
if (flags.work !== undefined && flags.work !== true) {
|
|
718
|
+
const { normalize: 모드이름, MODES: 모드들, 보일이름: 모드보임 } = await import('../src/agent/modes.js');
|
|
719
|
+
if (!모드이름(String(flags.work))) {
|
|
720
|
+
const 있는것 = Object.keys(모드들).map((k) => `${모드보임(k)}(${k})`).join(' · ');
|
|
721
|
+
say('');
|
|
722
|
+
say(` 그런 작업 모드가 없습니다: ${String(flags.work)}`);
|
|
723
|
+
say(` 있는 것: ${있는것}`);
|
|
724
|
+
say('');
|
|
725
|
+
say(' 그냥 켜면 「종합」 으로 돕니다 — 그건 파일을 고칠 수 있는 모드입니다.');
|
|
726
|
+
say('');
|
|
727
|
+
return 2;
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
704
731
|
switch (cmd) {
|
|
705
732
|
// 한 번만 돌고 끝난다. 스크립트·배치에서 부르는 자리다.
|
|
706
733
|
//
|
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
|
@@ -1523,7 +1523,9 @@ export async function* run(session, ctx, userText, { signal = null, 깊이 = 0,
|
|
|
1523
1523
|
continue;
|
|
1524
1524
|
}
|
|
1525
1525
|
|
|
1526
|
-
|
|
1526
|
+
// 물려받은 이름(`constructor` 등)이면 여기가 참이 되어 「모르는 도구」
|
|
1527
|
+
// 관문을 그냥 통과했다. hasOwn 으로만 묻는다 (tools/index.js 도 같다).
|
|
1528
|
+
if (!Object.hasOwn(TOOLS, call.name)) {
|
|
1527
1529
|
거절(call, `모르는 도구입니다. 쓸 수 있는 것: ${Object.keys(TOOLS).join(', ')}`);
|
|
1528
1530
|
// 이것도 세야 한다. 없는 이름을 계속 부르며 걸음 수를 다 쓰는 길이 있었다 —
|
|
1529
1531
|
// 71초 증상과 겉모습이 똑같은데 문만 다르다. 아래 거부·중복도 마찬가지다.
|
package/src/agent/models.js
CHANGED
|
@@ -36,6 +36,9 @@ import { load, activeProfile, resolveKey } from '../config.js';
|
|
|
36
36
|
import { isLocalHost, isOffline } from '../safety/network.js';
|
|
37
37
|
import { 잠잠기본, 무소식기본, 연결기본 } from '../backend/http.js';
|
|
38
38
|
import { 인증서설정 } from '../backend/clientcert.js';
|
|
39
|
+
import { 받기설정 } from '../safety/authcmd.js';
|
|
40
|
+
// 열쇠받기 명령을 정책이 못박아 뒀을 수 있다 — 받기설정 이 그 값을 같이 본다.
|
|
41
|
+
import { 정책읽기 } from '../safety/policy.js';
|
|
39
42
|
|
|
40
43
|
// 컨텍스트를 못 알아냈을 때 쓰는 값. repl.js 와 같은 값을 봐야 한다.
|
|
41
44
|
export const CTX_DEFAULT = 32768;
|
|
@@ -67,6 +70,25 @@ export function 연결만들기(prof, { ctx = null, maxTokens = null } = {}) {
|
|
|
67
70
|
tools: prof.tools ?? false,
|
|
68
71
|
json: prof.json ?? false,
|
|
69
72
|
think: prof.think ?? false,
|
|
73
|
+
/*
|
|
74
|
+
* ── 이 두 줄을 빼면 회사 프로필로는 물어볼 수가 없다 ────────────────
|
|
75
|
+
*
|
|
76
|
+
* conn 을 짓는 자리는 다섯이다 — repl.js · oneshot.js · acp/serve.js ·
|
|
77
|
+
* commands.js 의 연결적용, 그리고 여기. 앞의 넷은 이 둘을 넣는데 여기만
|
|
78
|
+
* 빠져 있었다. 이 함수를 쓰는 자리가 둘인데 **둘 다 남에게 넘기는
|
|
79
|
+
* 자리**다 — /consult 로 한 번 물어보기, Task 로 하위에 떼어 주기.
|
|
80
|
+
*
|
|
81
|
+
* 열쇠를 명령으로 받아 오는 프로필(SSO 토큰)은 prof.key 가 비어 있다.
|
|
82
|
+
* 그래서 열쇠받기 없이 지으면 Authorization 이 안 실려 401 이 나고,
|
|
83
|
+
* 열쇠를 다시 받는 길도 잠긴다(adapter.js 의 열쇠다시받을까 는
|
|
84
|
+
* conn.열쇠받기 를 본다). `/model 회사창구` 는 되는데 `/consult
|
|
85
|
+
* 회사창구` 만 안 되는, 까닭이 화면에 안 적히는 꼴이 된다.
|
|
86
|
+
*
|
|
87
|
+
* vision 도 같다 — 안 넣으면 그림을 볼 수 있는 모델에 하위 작업을
|
|
88
|
+
* 떼어 주면서 그림을 못 보는 것으로 친다.
|
|
89
|
+
*/
|
|
90
|
+
열쇠받기: 받기설정(prof, { 정책값: 정책읽기().값 }),
|
|
91
|
+
vision: prof.vision ?? false,
|
|
70
92
|
};
|
|
71
93
|
}
|
|
72
94
|
|
package/src/agent/modes.js
CHANGED
|
@@ -115,7 +115,7 @@ export const MODES = {
|
|
|
115
115
|
id: 'auto',
|
|
116
116
|
hintEn: "picks the right mode for what you ask",
|
|
117
117
|
sayEn: "You are in **Auto** mode. What comes next is not fixed.\n\n- Work out what kind of job this is first, then do it that way.\n If it is an edit, read before editing. If it is a diagnosis, confirm before concluding.\n If it is an explanation, back it with the files.\n- For a large job, break it into steps with TodoWrite and **finish everything you wrote down.**\n Do not write the list and then ask. If there are several chunks, hand them off with Task —\n a subtask runs in its own window, so yours does not fill up.\n- For code you did not write, get the shape with Outline. Use Grep to gather every place it\n touches, then Read **only around the lines you found** (offset/limit). Do not read whole\n files - pour it all in at once and the earlier turns fold away, and you answer having\n forgotten them.\n- Fire unrelated reads **together in one message.** Read tools run side by side; one call at\n a time adds that many round trips, and that is the waiting the person feels.\n- Making several files: one Write call (files array). Do not call it once per file.\n Several places to edit: one Edit call the same way (edits array).\n- Commands that never end (dev servers, watch) need background: true on Bash. Called plainly\n they die on timeout. After starting one, read its output with Jobs, and end it with Jobs when done.\n- Verify what can be verified — call Verify. Do not call something done that you did not check.\n- Do what the job needs. Do not start work the job did not ask for.",
|
|
118
|
-
say짧게En: "**Auto** mode. What comes next is not fixed.\n- Work out what kind of job this is, then do it that way.\n- Large job: break it up with TodoWrite and **finish it all.** Several chunks: hand off with Task.\n- Code you did not write: Outline -> Grep -> Read **only around what you found** (offset/limit).\n- Fire unrelated reads together in one message - they run side by side.\n- Several files: one Write (files array). Several edits: one Edit (edits array).\n- Commands that never end (dev server, watch): background: true on Bash. Read with Jobs, end with Jobs.\n- Verify before you finish. Do not call something done that you did not check.",
|
|
118
|
+
say짧게En: "**Auto** mode. What comes next is not fixed.\n- Work out what kind of job this is, then do it that way.\n- Large job: break it up with TodoWrite and **finish it all.** Several chunks: hand off with Task.\n- Code you did not write: Outline -> Grep -> Read **only around what you found** (offset/limit).\n- Fire unrelated reads together in one message - they run side by side.\n- Several files: one Write (files array). Several edits: one Edit (edits array).\n- Commands that never end (dev server, watch): background: true on Bash. Read with Jobs, end with Jobs.\n- Verify before you finish. Do not call something done that you did not check.\n- Do what the job needs. Do not start work the job did not ask for.",
|
|
119
119
|
name: '종합',
|
|
120
120
|
en: 'Auto',
|
|
121
121
|
glyph: '◎',
|
|
@@ -132,6 +132,9 @@ export const MODES = {
|
|
|
132
132
|
'- 파일 여러 개는 Write 한 번에 (files 배열), 고칠 자리 여럿은 Edit 한 번에 (edits 배열).',
|
|
133
133
|
'- 끝내지 않는 명령(dev 서버·watch)은 Bash 에 background: true. Jobs 로 읽고 끝낸다.',
|
|
134
134
|
'- 끝내기 전에 Verify. 확인 못 한 것을 됐다고 하지 마라.',
|
|
135
|
+
// 「빠진 규칙은 없다」 는 위 주석대로 되려면 이 줄이 있어야 한다.
|
|
136
|
+
// 시키지 않은 일을 벌이는 것은 작은 창에서 더 비싸다.
|
|
137
|
+
'- 시키는 일을 해라. 시키지 않은 일을 벌이지 마라.',
|
|
135
138
|
].join('\n'),
|
|
136
139
|
say: [
|
|
137
140
|
'지금은 **종합** 모드다. 무슨 일이 올지 정해져 있지 않다.',
|
|
@@ -206,6 +209,7 @@ export const MODES = {
|
|
|
206
209
|
id: 'architect',
|
|
207
210
|
hintEn: "shapes the structure · touches no files",
|
|
208
211
|
sayEn: "This is **design**. You have not been given the tools that change files.\n\nRead first. Designing without knowing the current structure is imagining, not designing.\n - Start with Outline for the shape of the folder. Narrow with Glob/Grep, then Read\n **only around the lines you found** (offset/limit). Read whole files and the earlier\n ones fold away after a handful - then you have not seen the structure, only the last file\n - Fire unrelated reads together in one message - they run side by side\n - Work out what depends on what, and in which direction\n\nThen answer in this order.\n 1. Current structure — files, their roles, where the boundaries are (point with path:line)\n 2. What is wrong — why the current shape does not hold\n 3. Two or three options — what each gains, what each costs, how much work it is\n 4. One recommendation with the reason, and why you dropped the others\n 5. The files this affects\n\nFind the answer inside the conventions this code already uses. Bringing in a new framework is\nthe last resort, and if you go there, first say why the existing conventions cannot do it.",
|
|
212
|
+
say짧게En: "**Design** mode. You have no tools that change files.\n- Read first — designing without the current structure is imagining, not designing.\n Outline -> Glob/Grep -> Read **only around what you found** (offset/limit). Never whole files.\n Fire unrelated reads together in one message. Work out what depends on what, and which way.\n- Answer in this order: 1) current structure (path:line) 2) what is wrong 3) two or three options\n (what each gains, costs, how much work) 4) one recommendation with the reason, and why you dropped\n the others 5) the files this affects.\n- Find it inside the conventions this code already uses. A new framework is the last resort — if you\n go there, first say why the existing conventions cannot do it.",
|
|
209
213
|
name: '설계',
|
|
210
214
|
en: 'Architect',
|
|
211
215
|
glyph: '◈',
|
|
@@ -213,6 +217,16 @@ export const MODES = {
|
|
|
213
217
|
tools: [...읽기, ...계획],
|
|
214
218
|
effort: 'deep',
|
|
215
219
|
think: 'high',
|
|
220
|
+
say짧게: [
|
|
221
|
+
'**설계** 모드다. 파일을 바꾸는 도구는 없다.',
|
|
222
|
+
'- 먼저 읽어라 — 구조를 모르면 설계가 아니라 상상이다.',
|
|
223
|
+
' Outline → Glob/Grep → **짚은 자리 앞뒤만** Read (offset·limit). 통째로 읽지 마라.',
|
|
224
|
+
' 상관없는 읽기는 한 번에 같이 부른다. 무엇이 무엇에 기대는지(의존 방향)를 본다.',
|
|
225
|
+
'- 이 차례로 답한다: 1) 지금 구조(경로:줄) 2) 무엇이 문제인가 3) 선택지 2~3개(얻는 것·잃는',
|
|
226
|
+
' 것·드는 손) 4) 추천 하나와 버린 이유 5) 영향받는 파일.',
|
|
227
|
+
'- 이 코드가 이미 쓰는 관례 안에서 찾아라. 새 틀은 마지막 수단이고, 그때는 기존 관례로',
|
|
228
|
+
' 왜 안 되는지 먼저 밝혀라.',
|
|
229
|
+
].join('\n'),
|
|
216
230
|
say: [
|
|
217
231
|
"지금 하는 일은 **설계**다. 파일을 바꾸는 도구는 주어지지 않았다.",
|
|
218
232
|
"",
|
|
@@ -238,7 +252,11 @@ export const MODES = {
|
|
|
238
252
|
ask: {
|
|
239
253
|
id: 'ask',
|
|
240
254
|
hintEn: "explains only · changes nothing",
|
|
241
|
-
|
|
255
|
+
// 영어 쪽이 「Keep it short」 로 남아 있었다. 한국어는 그 말 때문에 여러
|
|
256
|
+
// 가지를 물으면 몇 가지가 빠지던 것을 고쳐 「물음의 크기에 맞춰라」 로
|
|
257
|
+
// 바꿨는데, 영어는 안 바꿔서 **영어로 쓰는 사람에게만 옛 결함이 남아
|
|
258
|
+
// 있었다.** 읽는 절차도 빠져 있어 읽어야 나오는 답을 짐작으로 냈다.
|
|
259
|
+
sayEn: "This is **explanation**. You change nothing.\n\n- Back it with the files. Give the path and line number (src/a.js:42).\n- If you do not know, say so. Do not invent a plausible answer.\n- **Match the size of the answer to the size of the question.** One line asked, one line back;\n several things asked, every one of them answered. Short is not the goal.\n- If it takes reading to answer, read — Outline -> Grep -> Read **only around what you found**.\n Fire unrelated reads together in one message.\n- Do not propose fixes unless asked to fix something. Do not start work you were not asked for.",
|
|
242
260
|
name: '묻기',
|
|
243
261
|
en: 'Ask',
|
|
244
262
|
glyph: '◇',
|
|
@@ -364,6 +382,7 @@ export const MODES = {
|
|
|
364
382
|
id: 'debug',
|
|
365
383
|
hintEn: "finds the cause",
|
|
366
384
|
sayEn: "This is **finding the cause**. Do not fix by guessing.\n\nFollow this order.\n 1. Restate the symptom in one sentence — what happens when you do what.\n 2. Get a reproduction. If there is none, build one. Without it you cannot tell whether you fixed it.\n 3. Form two or three hypotheses. For each, write down what you should see if it is true.\n 4. Check them one at a time, for real — read the logs, run something small, print the value.\n Only what you checked is fact. What you did not check is still a hypothesis.\n If several hypotheses turn on reading alone, read for all of them in one message.\n 5. When you name the cause, bring the evidence. A cause that starts with \"probably\" is not a cause.\n 6. After fixing, run the reproduction from step 2 again. If it is not fixed, go back to step 3.\n\nDo not change several places at once. You will not know which one fixed it.",
|
|
385
|
+
say짧게En: "**Finding the cause.** Do not fix by guessing.\n1. Restate the symptom in one sentence — what happens when you do what.\n2. Get a reproduction. If there is none, build one — without it you cannot tell whether you fixed it.\n3. Form two or three hypotheses. For each, write what you should see if it is true.\n4. Check them one at a time, for real. Only what you checked is fact.\n If several turn on reading alone, read for all of them in one message.\n5. Name the cause with the evidence. A cause that starts with \"probably\" is not a cause.\n6. After fixing, run the reproduction from step 2 again. Not fixed — back to step 3.\nDo not change several places at once. You will not know which one fixed it.",
|
|
367
386
|
name: '디버그',
|
|
368
387
|
en: 'Debug',
|
|
369
388
|
glyph: '◉',
|
|
@@ -371,6 +390,17 @@ export const MODES = {
|
|
|
371
390
|
tools: [...읽기, ...계획, ...쓰기, ...확인, ...쪼개기],
|
|
372
391
|
effort: 'deep',
|
|
373
392
|
think: 'high',
|
|
393
|
+
say짧게: [
|
|
394
|
+
'**원인 찾기** 모드다. 짐작으로 고치지 마라.',
|
|
395
|
+
'1. 증상을 한 문장으로 다시 적는다 — 무엇을 했을 때 무엇이 일어나는가.',
|
|
396
|
+
'2. 재현 방법을 확보한다. 없으면 만든다 — 재현 못 하면 고쳤는지도 알 수 없다.',
|
|
397
|
+
'3. 가설 2~3개. 각각 「맞다면 무엇이 보여야 하는가」 를 같이 적는다.',
|
|
398
|
+
'4. 하나씩 실제로 확인한다. 확인한 것만 사실이다.',
|
|
399
|
+
' 읽기로 가릴 가설이 여럿이면 한 번에 같이 읽는다 — 나란히 돈다.',
|
|
400
|
+
'5. 원인에는 증거를 같이 댄다. 「아마」 로 시작하는 원인은 원인이 아니다.',
|
|
401
|
+
'6. 고친 뒤 2번 절차로 다시 확인한다. 안 고쳐졌으면 3번으로 돌아간다.',
|
|
402
|
+
'한 번에 여러 곳을 고치지 마라 — 무엇이 고쳤는지 알 수 없게 된다.',
|
|
403
|
+
].join('\n'),
|
|
374
404
|
say: [
|
|
375
405
|
"지금 하는 일은 **원인 찾기**다. 짐작으로 고치지 마라.",
|
|
376
406
|
"",
|
|
@@ -391,7 +421,8 @@ export const MODES = {
|
|
|
391
421
|
plan: {
|
|
392
422
|
id: 'plan',
|
|
393
423
|
hintEn: "plan first · run it after approval",
|
|
394
|
-
sayEn: "This is **planning**. You have not been given the tools that change files.\nDo not try to edit code. Produce a plan and stop.\n\nConfirm first — a plan built without knowing the current state is a wish, not a plan.\n Start with Outline for the shape, narrow with Glob/Grep, then Read **only around the lines\n you found** (offset/limit). Fire unrelated reads together in one message.\n\nThen write it in this order.\n 1. Goal — what does \"done\" look like (as a sentence you can check)\n 2. Current state — the files involved and what they do now (point with path:line)\n 3. What changes — per file, what and why\n 4. Order — step by step. Each step small enough to check on its own\n 5. Risks — what could break, and how to get back if it does\n 6. How to check — what do you run to know it worked\n\nWrite the steps into TodoWrite as well. After approval you continue straight from them.\n The number of steps is not fixed — match it to the size of the job. Do not force it to three.\n A small job ends in two or three; a large one lists all ten or more.\nIf something is unknown, do not invent it — write \"this needs to be confirmed\".\n\nEnd with \"Shall I go ahead with this?\". Once approved
|
|
424
|
+
sayEn: "This is **planning**. You have not been given the tools that change files.\nDo not try to edit code. Produce a plan and stop.\n\nConfirm first — a plan built without knowing the current state is a wish, not a plan.\n Start with Outline for the shape, narrow with Glob/Grep, then Read **only around the lines\n you found** (offset/limit). Fire unrelated reads together in one message.\n\nThen write it in this order.\n 1. Goal — what does \"done\" look like (as a sentence you can check)\n 2. Current state — the files involved and what they do now (point with path:line)\n 3. What changes — per file, what and why\n 4. Order — step by step. Each step small enough to check on its own\n 5. Risks — what could break, and how to get back if it does\n 6. How to check — what do you run to know it worked\n\nWrite the steps into TodoWrite as well. After approval you continue straight from them.\n The number of steps is not fixed — match it to the size of the job. Do not force it to three.\n A small job ends in two or three; a large one lists all ten or more.\nIf something is unknown, do not invent it — write \"this needs to be confirmed\".\n\nEnd with \"Shall I go ahead with this?\".\n You cannot make the edits in this mode — you have no tools for it. Once approved,\n **tell the person to type `/code`** — you have no way to switch modes yourself.",
|
|
425
|
+
say짧게En: "**Planning.** You have no tools that change files. Produce a plan and stop.\n- Confirm first — a plan built without the current state is a wish, not a plan.\n Outline -> Glob/Grep -> Read **only around what you found** (offset/limit). Unrelated reads together.\n- Write it in this order: 1) goal (a sentence you can check) 2) current state (path:line)\n 3) what changes, per file, and why 4) order — each step small enough to check on its own\n 5) risks and how to get back 6) how to check it worked.\n- Put the steps in TodoWrite too. Match the number to the size of the job — do not force it to three.\n- If something is unknown, do not invent it — write \"this needs to be confirmed\".\n- End with \"Shall I go ahead with this?\". You have no tools to make the edits, so once approved,\n **tell the person to type `/code`** — you cannot switch modes yourself.",
|
|
395
426
|
name: '계획',
|
|
396
427
|
en: 'Plan',
|
|
397
428
|
glyph: '☰',
|
|
@@ -399,6 +430,17 @@ export const MODES = {
|
|
|
399
430
|
tools: [...읽기, ...계획],
|
|
400
431
|
effort: 'deep',
|
|
401
432
|
think: 'high',
|
|
433
|
+
say짧게: [
|
|
434
|
+
'**계획** 모드다. 파일을 바꾸는 도구는 없다. 계획을 내고 멈춘다.',
|
|
435
|
+
'- 먼저 확인하라 — 지금 상태를 모르면 계획이 아니라 희망이다.',
|
|
436
|
+
' Outline → Glob/Grep → **짚은 자리 앞뒤만** Read (offset·limit). 상관없는 읽기는 한 번에.',
|
|
437
|
+
'- 이 차례로 적어라: 1) 목표(확인할 수 있는 문장) 2) 지금 상태(경로:줄) 3) 바꿀 것(파일별로',
|
|
438
|
+
' 무엇을 왜) 4) 순서(각 단계는 따로 확인할 수 있는 크기로) 5) 위험과 되돌리는 길 6) 확인 방법.',
|
|
439
|
+
'- 단계는 TodoWrite 로도 적어라. 수는 일의 크기에 맞춘다 — 세 개로 맞추지 마라.',
|
|
440
|
+
'- 모르는 것은 지어내지 말고 「이건 확인이 필요하다」 고 적어라.',
|
|
441
|
+
'- 「이대로 진행할까요?」 로 끝내라. 고치는 도구가 없으니, 승인을 받으면',
|
|
442
|
+
' **사람에게 `/code` 를 치라고 적어 줘라** — 네가 모드를 바꿀 길은 없다.',
|
|
443
|
+
].join('\n'),
|
|
402
444
|
say: [
|
|
403
445
|
"지금 하는 일은 **계획 세우기**다. 파일을 바꾸는 도구는 주어지지 않았다.",
|
|
404
446
|
"코드를 고치려 들지 마라. 계획을 내고 멈춘다.",
|
|
@@ -420,7 +462,12 @@ export const MODES = {
|
|
|
420
462
|
" 작은 일이면 두세 개로 끝내고, 큰 일이면 열 개가 넘어도 그대로 다 적어라.",
|
|
421
463
|
"모르는 것이 있으면 지어내지 말고 \"이건 확인이 필요하다\" 고 적어라.",
|
|
422
464
|
"",
|
|
423
|
-
|
|
465
|
+
// 모드를 바꾸는 도구는 모델에게 없다. `/code` 는 사람이 치는 명령이다.
|
|
466
|
+
// 「바꿔 실행한다」 고 적어 두면, 승인을 받은 모델이 고칠 도구도 없이
|
|
467
|
+
// 고치려 들다 아무것도 못 하고 멈춘다 — 사람은 기다리고만 있게 된다.
|
|
468
|
+
"마지막에 \"이대로 진행할까요?\" 로 끝내라.",
|
|
469
|
+
" 실제로 고치는 것은 이 모드에서 안 된다(고치는 도구가 없다). 승인을 받으면",
|
|
470
|
+
" **사람에게 `/code` 를 치라고 적어 줘라** — 네가 모드를 바꿀 길은 없다.",
|
|
424
471
|
].join('\n'),
|
|
425
472
|
},
|
|
426
473
|
|
|
@@ -473,7 +520,16 @@ export const DEFAULT = 'auto';
|
|
|
473
520
|
export function normalize(v) {
|
|
474
521
|
const s = String(v ?? '').trim().toLowerCase();
|
|
475
522
|
if (!s) return null;
|
|
476
|
-
|
|
523
|
+
/*
|
|
524
|
+
* 열쇠가 **제 것인지**를 본다.
|
|
525
|
+
*
|
|
526
|
+
* 그냥 `MODES[s]` 로 보면 `constructor`·`__proto__` 같은 이름에 물려받은
|
|
527
|
+
* 것이 잡혀 참이 된다. 그러면 그 이름이 모드로 통과하고, `get()` 이
|
|
528
|
+
* 돌려준 것에는 `tools` 가 없어 **터진다** — 하필 터지는 자리가
|
|
529
|
+
* `canWrite()` 이고, 그것은 하위 작업이 부모보다 셀 수 없게 막는
|
|
530
|
+
* 자리(tools/task.js 의 하위모드)다. 아래 별명 표도 같은 이유로 같이 막는다.
|
|
531
|
+
*/
|
|
532
|
+
if (Object.hasOwn(MODES, s)) return s;
|
|
477
533
|
const 별명 = {
|
|
478
534
|
'종합': 'auto', '자동': 'auto', '기본': 'auto', 'auto': 'auto', '맡김': 'auto',
|
|
479
535
|
'코드': 'code', 'c': 'code',
|
|
@@ -488,7 +544,7 @@ export function normalize(v) {
|
|
|
488
544
|
'inspect': 'inspect', 'audit': 'inspect', 'review': 'inspect', 'i': 'inspect',
|
|
489
545
|
'총괄': 'orchestrator', '오케': 'orchestrator', 'orch': 'orchestrator', 'o': 'orchestrator',
|
|
490
546
|
};
|
|
491
|
-
return 별명[s]
|
|
547
|
+
return Object.hasOwn(별명, s) ? 별명[s] : null;
|
|
492
548
|
}
|
|
493
549
|
|
|
494
550
|
export function get(id) {
|
|
@@ -502,7 +558,11 @@ export function get(id) {
|
|
|
502
558
|
* 규칙(session.js)이 줄어드는 자리와 같은 경계다. 셋이 같이 움직여야
|
|
503
559
|
* '작은 창에서는 고정 몫을 줄인다' 가 흩어진 세 결정이 아니라 한 결정이 된다.
|
|
504
560
|
*
|
|
505
|
-
* 짧은 판이 없는
|
|
561
|
+
* 짧은 판이 없는 것은 **묻기 하나**다(340자 — 원래 짧다). 그냥 그대로 쓴다.
|
|
562
|
+
*
|
|
563
|
+
* 앞서는 설계·디버그·계획에도 짧은 판이 없었다. 「원래 짧은 것들」 이라고
|
|
564
|
+
* 적어 두었지만 계획은 761자였다 — 작은 창에서 줄이자고 만든 자리가 정작 큰
|
|
565
|
+
* 모드에서 안 줄었다. 그래서 지금은 검사가 그 짝을 지킨다(test/modes.test.js).
|
|
506
566
|
*/
|
|
507
567
|
export function 말(id, ctx) {
|
|
508
568
|
const m = get(id);
|
package/src/agent/session.js
CHANGED
|
@@ -262,7 +262,7 @@ export class Session {
|
|
|
262
262
|
* 것만큼 나쁜 것이 없다. repl 이 턴이 끝날 때 한 번씩 채워 준다.
|
|
263
263
|
*/
|
|
264
264
|
this.되돌릴턴 = 0;
|
|
265
|
-
this.검증 = { 돈횟수: 0, 확인: 0, 탈: 0 };
|
|
265
|
+
this.검증 = { 돈횟수: 0, 확인: 0, 탈: 0, 못확인: 0 };
|
|
266
266
|
this.skills = []; // 켜질 때 이 PC 에서 찾은 것들
|
|
267
267
|
/*
|
|
268
268
|
* 이 자리에 언어 서버가 있나 (Def·Refs 를 목록에 넣을지).
|
|
@@ -899,8 +899,18 @@ export class Session {
|
|
|
899
899
|
{ label: 옮긴말('ctx.toolResults', { n: this.filesRead.size }), n: files },
|
|
900
900
|
];
|
|
901
901
|
const used = rows.reduce((a, r) => a + r.n, 0);
|
|
902
|
+
/*
|
|
903
|
+
* 창 크기를 **알아낸 것인지**도 같이 내놓는다.
|
|
904
|
+
*
|
|
905
|
+
* 안 알려 주는 창구에서는 32k 로 둔다(그래야 무엇이든 돌아간다). 그런데
|
|
906
|
+
* 화면이 그 값을 잰 것과 똑같은 낯으로 `5.6k/32k · 17%` 라고 적으면,
|
|
907
|
+
* 실제 창이 8k 인 자리에서 답이 잘리는 동안 게이지는 초록이다. 같은
|
|
908
|
+
* 상태줄이 모델 급은 짐작일 때 `◈ 보통?` 으로 흐리게 적는다 — 창 크기도
|
|
909
|
+
* 같은 규칙을 따라야 한다(ui/status.js).
|
|
910
|
+
*/
|
|
911
|
+
const 잰것 = this.conn.ctx != null;
|
|
902
912
|
const total = this.conn.ctx ?? 32768;
|
|
903
|
-
return { rows, used, total, left: Math.max(0, total - used) };
|
|
913
|
+
return { rows, used, total, 총잰것: 잰것, left: Math.max(0, total - used) };
|
|
904
914
|
}
|
|
905
915
|
|
|
906
916
|
/**
|
|
@@ -918,6 +928,7 @@ export class Session {
|
|
|
918
928
|
rows,
|
|
919
929
|
used,
|
|
920
930
|
total: 날것.total,
|
|
931
|
+
총잰것: 날것.총잰것,
|
|
921
932
|
left: Math.max(0, 날것.total - used),
|
|
922
933
|
보정: this.보정,
|
|
923
934
|
보정잰것: this.보정잰것,
|
package/src/backend/ctxsize.js
CHANGED
|
@@ -187,7 +187,10 @@ export async function probeCtx(conn, { timeout = 6000 } = {}) {
|
|
|
187
187
|
tried.push({ label, url, status: r.status ?? 0, ok: !!r.ok });
|
|
188
188
|
return { label, json: r.ok ? r.json : null };
|
|
189
189
|
} catch (err) {
|
|
190
|
-
|
|
190
|
+
// **누가 막았나**를 같이 적는다. 우리 문지기(safety/network.js)가 막은 것과
|
|
191
|
+
// 서버가 죽은 것은 사람이 할 일이 전혀 다르다 — 앞엣것은 허락을 주면 되고
|
|
192
|
+
// 뒤엣것은 서버를 봐야 한다. 아래에서 이 표시로 갈라 말한다.
|
|
193
|
+
tried.push({ label, url, status: 0, ok: false, why: String(err?.message ?? err), 막힘: err?.name === 'NetBlocked' });
|
|
191
194
|
return { label, json: null };
|
|
192
195
|
}
|
|
193
196
|
};
|
|
@@ -247,9 +250,20 @@ export async function probeCtx(conn, { timeout = 6000 } = {}) {
|
|
|
247
250
|
|
|
248
251
|
// 실제로 쓸 값: 올려 둔 길이가 있으면 그것. 없으면 모델 최대.
|
|
249
252
|
const value = loaded ?? max ?? null;
|
|
253
|
+
/*
|
|
254
|
+
* 못 알아낸 까닭. **서버 탓으로 뭉개지 않는다.**
|
|
255
|
+
*
|
|
256
|
+
* 두드린 자리가 전부 우리 문지기에 막혔으면 서버는 이 물음을 **받아 본 적도
|
|
257
|
+
* 없다.** 그런데 여태 이 자리는 그때도 「아무 응답도 못 받았습니다」 였고,
|
|
258
|
+
* repl 은 그걸 「서버가 안 알려줍니다」 로 옮겼다 — 켤 때 바깥 연결을 처음
|
|
259
|
+
* 붙이는 사람이 보는 첫 문장이 이것이다. 허락을 아직 안 준 것뿐인데 서버가
|
|
260
|
+
* 이상한 줄 알고 서버를 뒤진다.
|
|
261
|
+
*/
|
|
262
|
+
const 문지기가막음 = tried.length > 0 && tried.every((t) => t.막힘);
|
|
250
263
|
const why = value ? null
|
|
251
|
-
:
|
|
252
|
-
: '
|
|
264
|
+
: 문지기가막음 ? '이 주소로 나갈 허락이 아직 없어서 물어보지도 못했습니다'
|
|
265
|
+
: tried.some((t) => t.ok) ? '서버가 응답은 했지만 길이를 안 알려 줍니다'
|
|
266
|
+
: '두드린 자리에서 아무 응답도 못 받았습니다';
|
|
253
267
|
|
|
254
268
|
return { value, max, loaded, out, source, outSource, maxKey, loadedKey, tried, why };
|
|
255
269
|
}
|