deel-local-cli 0.8.0 → 0.9.0
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.en.md +217 -2
- package/README.md +94 -2
- package/bin/deel.js +29 -3
- package/package.json +2 -2
- package/src/agent/loop.js +2 -2
- package/src/agent/modes.js +116 -17
- package/src/agent/route.js +156 -0
- package/src/agent/session.js +15 -1
- package/src/backend/ctxsize.js +174 -0
- package/src/backend/http.js +23 -0
- package/src/backend/probe.js +15 -14
- package/src/backend/scan.js +97 -3
- package/src/commands.js +359 -24
- package/src/repl.js +67 -2
- package/src/report.js +1 -1
- package/src/ui/ansi.js +19 -1
- package/src/ui/level.js +4 -2
- package/src/ui/status.js +17 -7
package/README.en.md
CHANGED
|
@@ -47,7 +47,10 @@ Zero dependencies · Node 20+ · Exactly one place your source can go
|
|
|
47
47
|
- [Where your data can go](#where-your-data-can-go)
|
|
48
48
|
- [Multiple local runtimes](#multiple-local-runtimes)
|
|
49
49
|
- [Slash commands](#slash-commands)
|
|
50
|
+
- [Work modes](#work-modes)
|
|
51
|
+
- [Simple vs developer](#simple-vs-developer)
|
|
50
52
|
- [Tools](#tools)
|
|
53
|
+
- [Korean text and Excel](#korean-text-and-excel)
|
|
51
54
|
- [Skills and plugins](#skills-and-plugins)
|
|
52
55
|
- [Reasoning effort](#reasoning-effort)
|
|
53
56
|
- [Auto-compaction](#auto-compaction)
|
|
@@ -207,11 +210,16 @@ Names follow Claude Code / Codex conventions.
|
|
|
207
210
|
|---|---|
|
|
208
211
|
| `/help` | Command list |
|
|
209
212
|
| `/context` | What is consuming the context window |
|
|
213
|
+
| `/ctx [auto\|number]` | Context **length** — re-read it off the model, or set it yourself |
|
|
210
214
|
| `/compact` | Summarise and fold older turns |
|
|
211
215
|
| `/clear` | Clear the conversation (keeps link and rules) |
|
|
212
216
|
| `/model` | Switch connection / model |
|
|
213
217
|
| `/think <level\|profile>` | `off·low·medium·high·max` or `even·save·deep` |
|
|
214
|
-
| `/mode <mode>` | `auto` · `confirm` · `strict` |
|
|
218
|
+
| `/mode <mode>` | Approval policy — how much it asks (`auto` · `confirm` · `strict`) |
|
|
219
|
+
| `/work [mode]` | Work mode — what kind of work you are doing |
|
|
220
|
+
| `/auto` | Hand the wheel back — it picks the mode from what you type |
|
|
221
|
+
| `/code` `/plan` `/architect` `/debug` `/ask` `/orchestrator` | Switch work mode directly (pins it) |
|
|
222
|
+
| `/level [level]` | How much to show (`쉬움` simple · `개발자` developer) |
|
|
215
223
|
| `/undo [turns]` | Revert file changes |
|
|
216
224
|
| `/tools` | Available tools |
|
|
217
225
|
| `/skills [query\|all\|off]` | Browse, search, load skills |
|
|
@@ -252,13 +260,104 @@ Pressing Ctrl+C again on an empty line quits.
|
|
|
252
260
|
|
|
253
261
|
---
|
|
254
262
|
|
|
263
|
+
## Work modes
|
|
264
|
+
|
|
265
|
+
What you are working on changes **which tools the model is given and how hard it thinks.**
|
|
266
|
+
Cycle with `Shift+Tab`, or type the name.
|
|
267
|
+
|
|
268
|
+
| Mode | For | Can edit files | Reasoning |
|
|
269
|
+
|---|---|---|---|
|
|
270
|
+
| `/auto` ◎ Auto | **Default.** Reads your message and switches for you | Yes | Normal (`save`) |
|
|
271
|
+
| `/code` ◆ Code | Writing and fixing | Yes | Normal (`save`) |
|
|
272
|
+
| `/plan` ☰ Plan | Planning first | **No** | Deep (`deep`·high) |
|
|
273
|
+
| `/architect` ◈ Architect | Shaping structure | **No** | Deep (`deep`·high) |
|
|
274
|
+
| `/debug` ◉ Debug | Finding causes | Yes | Deep, more steps (32) |
|
|
275
|
+
| `/ask` ◇ Ask | Explaining only | **No** | Shallow (`low`) |
|
|
276
|
+
| `/orchestrator` ❋ Orchestrator | Breaking up large work | Yes | Many steps (40) |
|
|
277
|
+
|
|
278
|
+
In read-only modes, `Write`, `Edit` and `Bash` are **never sent to the model at all.**
|
|
279
|
+
It is not asked politely not to edit — models forget requests. A tool that isn't there can't be used.
|
|
280
|
+
|
|
281
|
+
Don't confuse this with `/mode`. They are separate axes:
|
|
282
|
+
|
|
283
|
+
- `/mode` — **how much it asks you** (auto · confirm · strict)
|
|
284
|
+
- `/work` — **what kind of work you are doing** (the seven above)
|
|
285
|
+
|
|
286
|
+
If you have explicitly set `/think` or `/mode`, your choice wins. A work mode never
|
|
287
|
+
overrides something a person chose.
|
|
288
|
+
|
|
289
|
+
### Switching by itself (Auto mode)
|
|
290
|
+
|
|
291
|
+
You start in **Auto**. Nothing has been decided about what kind of work is coming.
|
|
292
|
+
Every turn, deel reads what you typed, picks the mode that fits, and works in it.
|
|
293
|
+
|
|
294
|
+
```
|
|
295
|
+
❯ why won't the login go through?
|
|
296
|
+
|
|
297
|
+
◉ Debug because your message contained "why won't", "won't"
|
|
298
|
+
Not what you wanted? Type /code to pin a mode yourself.
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Switching brings **the whole mode** with it — its working protocol, its tool set, its
|
|
302
|
+
reasoning settings. It isn't a label saying "debug mode": the model is actually walked
|
|
303
|
+
through symptom → reproduce → hypothesis → evidence, and in Plan mode `Write` and `Edit`
|
|
304
|
+
are not handed over at all.
|
|
305
|
+
|
|
306
|
+
| When you say | It goes to |
|
|
307
|
+
|---|---|
|
|
308
|
+
| why won't · error · fails · crashes · what's causing | ◉ Debug |
|
|
309
|
+
| plan · roadmap · what order · let's map it out first | ☰ Plan |
|
|
310
|
+
| design · architecture · how should this be structured · how to split | ◈ Architect |
|
|
311
|
+
| what is · explain · how does it work · difference between | ◇ Ask |
|
|
312
|
+
| all of · everything · one by one · to the end · unify | ❋ Orchestrator |
|
|
313
|
+
| fix · add · implement · rename · delete | ◆ Code |
|
|
314
|
+
|
|
315
|
+
**When it's close, it doesn't switch.** "ok", "go on", "that thing from earlier" leave you
|
|
316
|
+
in Auto. So does a near-tie between first and second place — a wrong switch into a read-only
|
|
317
|
+
mode leaves you blocked without knowing *why*. Read-only modes (Plan, Architect, Ask)
|
|
318
|
+
therefore carry a higher bar: "explain this and fix it" routes to Code, not Ask.
|
|
319
|
+
|
|
320
|
+
A switch lasts **one turn only.** The next message is judged fresh.
|
|
321
|
+
A `~` in the status line means it switched by itself; no `~` means you chose it.
|
|
322
|
+
|
|
323
|
+
```
|
|
324
|
+
◎ Auto ← waiting
|
|
325
|
+
~◉ Debug ← this turn only, chosen for you
|
|
326
|
+
◉ Debug ← you typed /debug. It stays.
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
Choosing a mode yourself **pins** it. `/auto` (or `/work auto`) hands the wheel back.
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
## Simple vs developer
|
|
334
|
+
|
|
335
|
+
Twenty commands on first launch means nothing gets chosen. Locking features away means
|
|
336
|
+
hitting a wall later. So only **what is shown** differs.
|
|
337
|
+
|
|
338
|
+
| | Simple (`쉬움`, default) | Developer (`개발자`) |
|
|
339
|
+
|---|---|---|
|
|
340
|
+
| `/help` listing | Common commands only | Everything |
|
|
341
|
+
| Error messages | What to do about it | The original text |
|
|
342
|
+
| Safety | **Identical** | **Identical** |
|
|
343
|
+
|
|
344
|
+
`/level 개발자` is saved to config and persists across sessions.
|
|
345
|
+
|
|
346
|
+
Two things matter here:
|
|
347
|
+
|
|
348
|
+
- **Hidden commands still work.** `/think high` works in simple mode. It just isn't listed.
|
|
349
|
+
- **Beginners do not get fewer safeguards.** Undo, workspace scope and dangerous-command
|
|
350
|
+
blocking are identical. A beginner needs the undo more, not less.
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
255
354
|
## Tools
|
|
256
355
|
|
|
257
356
|
Names and arguments match Claude Code, so skills written for that convention work unchanged.
|
|
258
357
|
|
|
259
358
|
| Tool | What it does |
|
|
260
359
|
|---|---|
|
|
261
|
-
| `Read` | Read a file (line numbers, `offset`/`limit
|
|
360
|
+
| `Read` | Read a file (line numbers, `offset`/`limit`, **Excel as CSV**) |
|
|
262
361
|
| `Write` | Write / overwrite a file |
|
|
263
362
|
| `Edit` | Replace an exact string (`replace_all` supported) |
|
|
264
363
|
| `Glob` | Find files by name pattern |
|
|
@@ -320,6 +419,74 @@ On failure it points at the closest line in the file.
|
|
|
320
419
|
|
|
321
420
|
---
|
|
322
421
|
|
|
422
|
+
## Korean text and Excel
|
|
423
|
+
|
|
424
|
+
### Encoding — written back the way it was read
|
|
425
|
+
|
|
426
|
+
Corporate documents are often not UTF-8. Files saved by old Windows Notepad in a legacy
|
|
427
|
+
codepage (CP949 in Korea, CP932 in Japan, GBK in China) are still around. Reading one as
|
|
428
|
+
UTF-8 garbles it completely: `한글` becomes `�ѱ�`.
|
|
429
|
+
|
|
430
|
+
Writing is the dangerous part. Read it garbled, save it as UTF-8, and the original is gone.
|
|
431
|
+
So there is one rule: **write it back in the encoding it was read in.**
|
|
432
|
+
|
|
433
|
+
Which encoding that is comes from **the file's contents, not the machine's settings.**
|
|
434
|
+
Each candidate is decoded strictly, then scored on whether the result looks like real text
|
|
435
|
+
written in that encoding. So the same CP949 document reads identically on Ubuntu, on a US
|
|
436
|
+
Windows machine, and on a Korean one.
|
|
437
|
+
|
|
438
|
+
```
|
|
439
|
+
› Read report.txt
|
|
440
|
+
└ 4 lines · CP949
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
If you try to insert a character that encoding **cannot hold**, it refuses instead of saving.
|
|
444
|
+
|
|
445
|
+
```
|
|
446
|
+
› Edit report.txt note → note 🚀
|
|
447
|
+
└ This file is CP949, and you are inserting a character that encoding does not have: 🚀
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
Silently substituting question marks would be worse than not writing at all.
|
|
451
|
+
Newly created files are UTF-8.
|
|
452
|
+
|
|
453
|
+
Command output is handled the same way. A Windows console is not UTF-8, so taking `Bash`
|
|
454
|
+
output as utf8 garbles non-ASCII text. It is collected as bytes and decoded afterwards.
|
|
455
|
+
|
|
456
|
+
### Excel — read as CSV
|
|
457
|
+
|
|
458
|
+
An Excel file is a compressed archive, not text, so normally you get "this is a binary file"
|
|
459
|
+
and somebody has to export a CSV by hand. `Read` just does it.
|
|
460
|
+
|
|
461
|
+
```
|
|
462
|
+
› Read report.xlsx
|
|
463
|
+
└ 3 sheets · 128 rows · unpacked directly
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
- **Still zero dependencies.** An xlsx is a zip full of XML, so Node's built-in `zlib` is enough.
|
|
467
|
+
- Every sheet is returned. Hidden sheets too, marked as hidden.
|
|
468
|
+
- Dates come back as dates, not serial numbers — the cell format is read to decide.
|
|
469
|
+
- Formulas come back as **computed values**, and error values like `#REF!` are not dropped.
|
|
470
|
+
|
|
471
|
+
**Password-protected files and legacy `.xls`** are handed to Excel itself; those cannot be
|
|
472
|
+
unpacked directly. You are asked for the password at that point.
|
|
473
|
+
|
|
474
|
+
The password is **not stored anywhere**:
|
|
475
|
+
|
|
476
|
+
- not in the config file
|
|
477
|
+
- not in the session log
|
|
478
|
+
- not in the audit log
|
|
479
|
+
- not as a command-line argument (other people can see your command lines)
|
|
480
|
+
|
|
481
|
+
The only path out is the child process's stdin, and a test asserts that this stays true.
|
|
482
|
+
Extracted intermediate files are deleted after use.
|
|
483
|
+
|
|
484
|
+
> **Excel files are read-only here.** `Edit` and `Write` refuse them, and say why and what
|
|
485
|
+
> to do instead. Round-tripping a file with formatting, formulas and charts through CSV
|
|
486
|
+
> always loses something. Better not to write than to write knowing you'll lose data.
|
|
487
|
+
|
|
488
|
+
---
|
|
489
|
+
|
|
323
490
|
## Skills and plugins
|
|
324
491
|
|
|
325
492
|
**deel does not carry skills with it.** On startup it scans the machine it is running on and uses
|
|
@@ -389,6 +556,52 @@ $ /think
|
|
|
389
556
|
| `save` (default) | Hard on the first decision only |
|
|
390
557
|
| `deep` | Everything one notch up — for hard work |
|
|
391
558
|
|
|
559
|
+
### Context length is read off the model
|
|
560
|
+
|
|
561
|
+
This one number sizes the whole program: how many files fit in one read, when the
|
|
562
|
+
conversation gets folded, how long a single reply may be — **all of it comes from here.**
|
|
563
|
+
|
|
564
|
+
So deel asks the server on every launch rather than trusting the saved value. The same
|
|
565
|
+
model name can be loaded at a different length each time, and if that difference never
|
|
566
|
+
reaches the screen there is no way to notice. **It just quietly gets smaller.**
|
|
567
|
+
|
|
568
|
+
```
|
|
569
|
+
│ Model qwen3-coder (640k tokens) │
|
|
570
|
+
╰─────────────────────────────────────────────────────────╯
|
|
571
|
+
✓ Context adjusted 32,768 → 655,360 (read from LM Studio)
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
Every server puts this number under a different name in a different place, so deel checks
|
|
575
|
+
all of them.
|
|
576
|
+
|
|
577
|
+
| Server | Where it reads |
|
|
578
|
+
|---|---|
|
|
579
|
+
| LM Studio | `/api/v0/models` — `max_context_length`, `loaded_context_length` |
|
|
580
|
+
| llama.cpp | `/props` — `n_ctx` |
|
|
581
|
+
| vLLM | `/v1/models` — `max_model_len` |
|
|
582
|
+
| Ollama | `/api/show` — `<model>.context_length` |
|
|
583
|
+
| Other OpenAI-compatible | `/v1/models/<model>` — `context_window`, `context_length`, `max_input_tokens`, `max_position_embeddings` (found even when nested) |
|
|
584
|
+
|
|
585
|
+
**Model maximum and loaded length are not the same thing.** LM Studio will happily load a
|
|
586
|
+
655,360-capable model at 8,192. Trusting the maximum there gets your requests rejected. So
|
|
587
|
+
the **loaded length is what deel uses**, and the maximum is reported separately.
|
|
588
|
+
|
|
589
|
+
```
|
|
590
|
+
⚠ This model goes up to 655,360 — raise it on the server, then /ctx auto
|
|
591
|
+
```
|
|
592
|
+
|
|
593
|
+
| Command | What it does |
|
|
594
|
+
|---|---|
|
|
595
|
+
| `/ctx` | Current length and remaining room |
|
|
596
|
+
| `/ctx auto` | Ask the server again and match the model |
|
|
597
|
+
| `/ctx 655360` | Set it yourself (`640k`, `128k`, `1m` also work) |
|
|
598
|
+
| `/ctx out 32k` | Cap on a **single reply** — a different axis from context |
|
|
599
|
+
| `deel --ctx 655360` | Start at this value (skips the lookup) |
|
|
600
|
+
|
|
601
|
+
**`k` means 1024 here.** Context lengths are all powers of two, so that is the only base
|
|
602
|
+
that lines up: 655,360 is `640k`, not `655k`; 131,072 is `128k`, not `131k`. The display and
|
|
603
|
+
`/ctx` use the same unit, so typing back what you see gives you the same number.
|
|
604
|
+
|
|
392
605
|
**Caps are not fixed numbers.** They are computed from the model's context window and how
|
|
393
606
|
much of it is currently used — the profile decides what share of the remaining room a stage gets.
|
|
394
607
|
|
|
@@ -565,6 +778,8 @@ Auth style is detected automatically: `Authorization: Bearer` → `x-api-key`
|
|
|
565
778
|
```bash
|
|
566
779
|
deel --root <folder> Working scope. Defaults to the current folder
|
|
567
780
|
deel --mode <mode> auto (default) / confirm / strict
|
|
781
|
+
deel --work <mode> auto (default) / code / plan / architect / debug / ask / orchestrator
|
|
782
|
+
deel --level <level> 쉬움 (simple) / 개발자 (developer)
|
|
568
783
|
deel --think <level> off / low / medium (default) / high / max
|
|
569
784
|
deel --effort <profile> even / save (default) / deep
|
|
570
785
|
deel --offline Nothing leaves this machine
|
package/README.md
CHANGED
|
@@ -219,13 +219,15 @@ LM Studio 는 `/api/v0/models`, llama.cpp 는 `/props`. 못 알아보면 `(추
|
|
|
219
219
|
|---|---|
|
|
220
220
|
| `/help` | 명령 목록 |
|
|
221
221
|
| `/context` | 무엇이 컨텍스트를 먹고 있는지 |
|
|
222
|
+
| `/ctx [auto\|숫자]` | 컨텍스트 **길이** — 모델에 맞춰 다시 재거나 직접 지정 |
|
|
222
223
|
| `/compact` | 앞선 대화를 요약해서 접기 |
|
|
223
224
|
| `/clear` | 대화 비우기 (연결·규칙은 유지) |
|
|
224
225
|
| `/model` | 연결·모델 바꾸기 |
|
|
225
226
|
| `/think <강도\|배분>` | 추론 강도 (`off·low·medium·high·max`) 또는 배분 (`even·save·deep`) |
|
|
226
227
|
| `/mode <모드>` | 승인 정책 — 얼마나 물어보나 (`auto` · `confirm` · `strict`) |
|
|
227
228
|
| `/work [모드]` | 작업 모드 — 무슨 일을 하는 중인가 |
|
|
228
|
-
| `/
|
|
229
|
+
| `/auto` | 다시 맡기기 — 말을 보고 알맞은 모드로 저절로 옮겨 갑니다 |
|
|
230
|
+
| `/code` `/plan` `/architect` `/debug` `/ask` `/orchestrator` | 작업 모드 바로 바꾸기 (그때부터 고정) |
|
|
229
231
|
| `/level [수준]` | 화면에 무엇을 내놓을지 (`쉬움` · `개발자`) |
|
|
230
232
|
| `/undo [턴수]` | 파일 변경 되돌리기 |
|
|
231
233
|
| `/tools` | 쓸 수 있는 도구 |
|
|
@@ -273,6 +275,7 @@ LM Studio 는 `/api/v0/models`, llama.cpp 는 `/props`. 못 알아보면 `(추
|
|
|
273
275
|
|
|
274
276
|
| 모드 | 하는 일 | 파일을 고치나 | 추론 |
|
|
275
277
|
|---|---|---|---|
|
|
278
|
+
| `/auto` ◎ 종합 | **처음 값.** 말을 보고 알맞은 모드로 옮겨 간다 | 예 | 보통 (`save`) |
|
|
276
279
|
| `/code` ◆ 코드 | 고치고 만든다 | 예 | 보통 (`save`) |
|
|
277
280
|
| `/plan` ☰ 계획 | 먼저 계획만 세운다 | **아니오** | 깊게 (`deep`·high) |
|
|
278
281
|
| `/architect` ◈ 설계 | 구조를 짠다 | **아니오** | 깊게 (`deep`·high) |
|
|
@@ -286,11 +289,53 @@ LM Studio 는 `/api/v0/models`, llama.cpp 는 `/props`. 못 알아보면 `(추
|
|
|
286
289
|
`/mode` 와 헷갈리지 마세요. 둘은 다른 축입니다.
|
|
287
290
|
|
|
288
291
|
- `/mode` — **얼마나 물어보나** (auto · confirm · strict)
|
|
289
|
-
- `/work` — **무슨 일을 하는 중인가** (위
|
|
292
|
+
- `/work` — **무슨 일을 하는 중인가** (위 일곱 가지)
|
|
290
293
|
|
|
291
294
|
`/think` 나 `/mode` 를 직접 고른 적이 있으면 그 선택이 우선합니다.
|
|
292
295
|
모드가 사람이 고른 값을 덮어쓰지 않습니다.
|
|
293
296
|
|
|
297
|
+
### 저절로 옮겨 가기 (종합 모드)
|
|
298
|
+
|
|
299
|
+
처음에는 **종합** 으로 시작합니다. 무슨 일이 올지 모르는 상태입니다.
|
|
300
|
+
한마디를 받을 때마다 그 말을 보고 알맞은 모드로 옮겨 간 다음 일합니다.
|
|
301
|
+
|
|
302
|
+
```
|
|
303
|
+
❯ 로그인이 왜 안 되지?
|
|
304
|
+
|
|
305
|
+
◉ 디버그 (debug) 말 속에 '왜 안 되', '왜 안' 가 있어서
|
|
306
|
+
다르면 /code 처럼 직접 고르세요. 그때부터는 안 바뀝니다.
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
옮겨 가면 그 모드의 **절차·도구·추론 설정이 전부** 따라옵니다.
|
|
310
|
+
"디버그 모드입니다" 라고 이름만 붙는 게 아니라, 실제로 증상→재현→가설→증거 순서를
|
|
311
|
+
밟게 하고, 계획 모드에서는 `Write`·`Edit` 를 아예 안 줍니다.
|
|
312
|
+
|
|
313
|
+
| 이런 말이면 | 이 모드로 |
|
|
314
|
+
|---|---|
|
|
315
|
+
| 왜 안 돼 · 에러 · 실패 · 죽어요 · 원인 | ◉ 디버그 |
|
|
316
|
+
| 계획 · 순서 · 로드맵 · 먼저 잡자 | ☰ 계획 |
|
|
317
|
+
| 설계 · 구조를 어떻게 · 아키텍처 · 어떻게 나눌까 | ◈ 설계 |
|
|
318
|
+
| 뭐야? · 설명해줘 · 어떻게 동작해 · 차이가 뭐야 | ◇ 묻기 |
|
|
319
|
+
| 전체 · 전부 · 하나씩 · 끝까지 · 통일 | ❋ 총괄 |
|
|
320
|
+
| 고쳐줘 · 만들어줘 · 구현해줘 · 지워줘 | ◆ 코드 |
|
|
321
|
+
|
|
322
|
+
**애매하면 안 옮깁니다.** "음", "ㅇㅇ", "계속해줘", "아까 그거" 같은 말에는
|
|
323
|
+
종합 그대로 있습니다. 1등과 2등이 비슷할 때도 안 옮깁니다 —
|
|
324
|
+
잘못 옮겨서 읽기 전용 모드에 갇히면 사용자는 *왜* 막혔는지 모른 채 막힙니다.
|
|
325
|
+
그래서 읽기 전용 모드(계획·설계·묻기)는 문턱을 더 높게 뒀습니다.
|
|
326
|
+
"설명해주고 고쳐줘" 는 묻기가 아니라 코드로 갑니다.
|
|
327
|
+
|
|
328
|
+
옮겨 간 것은 **그 한마디에만** 붙습니다. 다음 말은 다시 처음부터 고릅니다.
|
|
329
|
+
상태줄에 `~` 가 붙으면 저절로 옮겨 간 것이고, 없으면 직접 고르신 것입니다.
|
|
330
|
+
|
|
331
|
+
```
|
|
332
|
+
◎ 종합 ← 대기 중
|
|
333
|
+
~◉ 디버그 ← 이번 한마디만 저절로
|
|
334
|
+
◉ 디버그 ← /debug 로 직접 고름. 저절로 안 바뀝니다
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
직접 고르면 그때부터 **고정** 됩니다. 다시 맡기려면 `/auto` 또는 `/work 종합`.
|
|
338
|
+
|
|
294
339
|
---
|
|
295
340
|
|
|
296
341
|
## 쉬움 · 개발자
|
|
@@ -527,6 +572,51 @@ $ /think
|
|
|
527
572
|
| `save` (절약, 기본) | 첫 판단만 세게, 이어가기는 얕게 |
|
|
528
573
|
| `deep` (깊게) | 전 단계 한 칸씩 위로 — 어려운 일에만 |
|
|
529
574
|
|
|
575
|
+
### 컨텍스트 길이는 모델에서 긁어옵니다
|
|
576
|
+
|
|
577
|
+
이 숫자 하나가 프로그램 전체 크기를 정합니다. 한 번에 읽힐 수 있는 파일 수,
|
|
578
|
+
대화가 접히는 시점, 한 번에 쓸 수 있는 답 길이가 **전부 여기서 나옵니다.**
|
|
579
|
+
|
|
580
|
+
그래서 켤 때마다 서버에 물어봅니다. 저장된 값을 그대로 믿지 않습니다 —
|
|
581
|
+
같은 이름의 모델이라도 서버에서 몇 k 로 올렸는지가 그때그때 다르고,
|
|
582
|
+
그 차이는 화면에 안 뜨면 알 길이 없습니다. **그냥 조용히 작아집니다.**
|
|
583
|
+
|
|
584
|
+
```
|
|
585
|
+
│ 모델 qwen3-coder (640k 토큰) │
|
|
586
|
+
╰─────────────────────────────────────────────────────────╯
|
|
587
|
+
✓ 컨텍스트를 32,768 → 655,360 로 맞췄습니다 (LM Studio에서 읽음)
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
서버마다 이 숫자를 다른 이름, 다른 자리에 둡니다. 한 군데만 보지 않습니다.
|
|
591
|
+
|
|
592
|
+
| 서버 | 어디서 읽나 |
|
|
593
|
+
|---|---|
|
|
594
|
+
| LM Studio | `/api/v0/models` — `max_context_length` · `loaded_context_length` |
|
|
595
|
+
| llama.cpp | `/props` — `n_ctx` |
|
|
596
|
+
| vLLM | `/v1/models` — `max_model_len` |
|
|
597
|
+
| Ollama | `/api/show` — `<모델>.context_length` |
|
|
598
|
+
| 그 밖의 OpenAI 호환 | `/v1/models/<모델>` — `context_window` · `context_length` · `max_input_tokens` · `max_position_embeddings` (깊이 박혀 있어도 찾습니다) |
|
|
599
|
+
|
|
600
|
+
**모델 최대와 올려 둔 길이를 구분합니다.** LM Studio 는 655,360 까지 되는 모델을
|
|
601
|
+
8,192 로 올려 둘 수 있습니다. 그 상태에서 최대치를 믿고 보내면 서버가 거절합니다.
|
|
602
|
+
그래서 **실제로 쓸 값은 올려 둔 길이**로 잡고, 최대치는 따로 알려 줍니다.
|
|
603
|
+
|
|
604
|
+
```
|
|
605
|
+
⚠ 이 모델은 655,360 까지 됩니다 — 서버에서 더 올린 뒤 /ctx auto
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
| 명령 | 하는 일 |
|
|
609
|
+
|---|---|
|
|
610
|
+
| `/ctx` | 지금 값과 남은 자리 |
|
|
611
|
+
| `/ctx auto` | 서버에 다시 물어 모델에 맞춤 |
|
|
612
|
+
| `/ctx 655360` | 직접 지정 (`640k` · `128k` · `1m` 도 됩니다) |
|
|
613
|
+
| `/ctx out 32k` | 한 번에 받을 **답 길이** 상한 — 컨텍스트와 다른 축 |
|
|
614
|
+
| `deel --ctx 655360` | 켤 때부터 이 값으로 (긁어오기를 건너뜁니다) |
|
|
615
|
+
|
|
616
|
+
**`k` 는 1024 입니다.** 컨텍스트 길이는 전부 2의 거듭제곱이라 그래야 아귀가 맞습니다 —
|
|
617
|
+
655,360 은 `655k` 가 아니라 `640k`, 131,072 는 `131k` 가 아니라 `128k` 입니다.
|
|
618
|
+
화면에 뜨는 표기와 `/ctx` 가 받는 단위가 같아서, 보이는 대로 쳐도 같은 값이 됩니다.
|
|
619
|
+
|
|
530
620
|
**출력 상한은 고정 숫자가 아닙니다.** 모델 컨텍스트와 지금 찬 양에서 매번 계산합니다 —
|
|
531
621
|
남은 자리의 몇 %를 이 단계에 내줄지가 배분입니다.
|
|
532
622
|
|
|
@@ -709,6 +799,8 @@ node bin/deel.js diagnose --url <게이트웨이주소> --key <키> --model <모
|
|
|
709
799
|
```bash
|
|
710
800
|
deel --root <폴더> 작업 범위. 기본은 지금 폴더
|
|
711
801
|
deel --mode <모드> auto(기본) / confirm / strict
|
|
802
|
+
deel --work <모드> auto(기본·종합) / code / plan / architect / debug / ask / orchestrator
|
|
803
|
+
deel --level <수준> 쉬움 / 개발자
|
|
712
804
|
deel --think <강도> off / low / medium(기본) / high / max
|
|
713
805
|
deel --effort <배분> even / save(기본) / deep
|
|
714
806
|
deel --offline 이 컴퓨터 밖으로 아무것도 안 보냄
|
package/bin/deel.js
CHANGED
|
@@ -6,6 +6,8 @@ import { runSetup, runDiagnose, showStatus, banner } from '../src/setup.js';
|
|
|
6
6
|
import { chatLoop } from '../src/repl.js';
|
|
7
7
|
import { packSelf, audit, reviewSheet } from '../src/pack/selfpack.js';
|
|
8
8
|
import { runScan } from '../src/backend/scanui.js';
|
|
9
|
+
import { closeConnections } from '../src/backend/http.js';
|
|
10
|
+
import { parseSize } from '../src/backend/ctxsize.js';
|
|
9
11
|
import { runSessions } from '../src/agent/sessionui.js';
|
|
10
12
|
|
|
11
13
|
const MIN_NODE = 20;
|
|
@@ -85,6 +87,9 @@ function help() {
|
|
|
85
87
|
say('');
|
|
86
88
|
say(` ${c.gray('--root <폴더>')} 작업 범위. 기본은 지금 폴더`);
|
|
87
89
|
say(` ${c.gray('--mode <모드>')} auto(기본) / confirm / strict`);
|
|
90
|
+
say(` ${c.gray('--work <모드>')} auto(기본·종합) / code / plan / architect / debug / ask / orchestrator`);
|
|
91
|
+
say(` ${c.gray('--level <수준>')} 쉬움(기본) / 개발자`);
|
|
92
|
+
say(` ${c.gray('--ctx <길이>')} 컨텍스트 길이 직접 지정 (655360 · 640k · 128k). 없으면 서버에 맞춤`);
|
|
88
93
|
say(` ${c.gray('--think <수준>')} off / low / medium(기본) / high / max`);
|
|
89
94
|
say(` ${c.gray('--effort <배분>')} even(균일) / save(절약, 기본) / deep(깊게)`);
|
|
90
95
|
say(` ${c.gray('--offline')} 이 컴퓨터 밖으로는 아무것도 안 보냄 (자물쇠)`);
|
|
@@ -119,6 +124,9 @@ async function main() {
|
|
|
119
124
|
return chatLoop({
|
|
120
125
|
root: flags.root ? String(flags.root) : undefined,
|
|
121
126
|
mode: flags.mode ? String(flags.mode) : undefined,
|
|
127
|
+
work: flags.work ? String(flags.work) : undefined,
|
|
128
|
+
level: flags.level ? String(flags.level) : undefined,
|
|
129
|
+
ctx: flags.ctx ? parseSize(String(flags.ctx)) : undefined,
|
|
122
130
|
think: flags.think ? String(flags.think) : undefined,
|
|
123
131
|
effort: flags.effort ? String(flags.effort) : undefined,
|
|
124
132
|
offline: flags.offline === true || flags.offline === 'true',
|
|
@@ -149,12 +157,30 @@ async function main() {
|
|
|
149
157
|
}
|
|
150
158
|
}
|
|
151
159
|
|
|
160
|
+
/**
|
|
161
|
+
* 끝낸다.
|
|
162
|
+
*
|
|
163
|
+
* process.exit() 을 바로 부르면 안 된다. fetch 가 살려 둔 소켓이 닫히는 중일 때
|
|
164
|
+
* 끊으면 윈도우에서 libuv 가 abort 한다 — 화면에는 정상으로 보이는데 종료코드가
|
|
165
|
+
* 3221226505 로 나온다. `deel scan` 이 실제로 그랬다.
|
|
166
|
+
*
|
|
167
|
+
* 그래서 연결을 먼저 닫고, 종료코드만 정해 두고 이벤트 루프가 저절로 비기를
|
|
168
|
+
* 기다린다. 그래도 안 비면(무언가 물고 있으면) 잠깐 뒤에 확실히 끝낸다.
|
|
169
|
+
* 그 타이머는 unref 라서, 정상적으로 끝나는 길을 막지 않는다.
|
|
170
|
+
*/
|
|
171
|
+
async function 끝내기(code) {
|
|
172
|
+
process.exitCode = code;
|
|
173
|
+
await closeConnections();
|
|
174
|
+
const 마지막수단 = setTimeout(() => process.exit(code), 400);
|
|
175
|
+
마지막수단.unref();
|
|
176
|
+
}
|
|
177
|
+
|
|
152
178
|
main()
|
|
153
|
-
.then((code) =>
|
|
154
|
-
.catch((err) => {
|
|
179
|
+
.then((code) => 끝내기(code ?? 0))
|
|
180
|
+
.catch(async (err) => {
|
|
155
181
|
say('');
|
|
156
182
|
say(` ${c.red('오류')} ${err?.message ?? err}`);
|
|
157
183
|
if (process.env.DEEL_DEBUG) say(c.gray(err?.stack ?? ''));
|
|
158
184
|
say('');
|
|
159
|
-
|
|
185
|
+
await 끝내기(1);
|
|
160
186
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deel-local-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "로컬 모델·사내 게이트웨이 전용 코딩 에이전트 CLI — 외부 의존성 0개 / Zero-dependency coding agent CLI for local LLMs and private gateways",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"verify": "node test/no-bundle.test.js && node test/network.test.js && node test/web.test.js",
|
|
47
47
|
"bench": "node test/edit-bench.js",
|
|
48
48
|
"demo": "node test/demo.js",
|
|
49
|
-
"check": "node --check bin/deel.js && node --check src/repl.js && node --check src/commands.js && node --check src/agent/loop.js && node --check src/agent/session.js && node --check src/agent/effort.js && node --check src/agent/modes.js && node --check src/tools/encoding.js && node --check src/tools/excel-com.js && node --check src/tools/excel.js && node --check src/tools/xlsx.js && node --check src/agent/compact.js && node --check src/agent/store.js && node --check src/agent/sessionui.js && node --check src/backend/adapter.js && node --check src/backend/probe.js && node --check src/backend/detect.js && node --check src/backend/http.js && node --check src/backend/scan.js && node --check src/backend/scanui.js && node --check src/tools/index.js && node --check src/tools/fsutil.js && node --check src/tools/edit-match.js && node --check src/tools/webfetch.js && node --check src/tools/todo.js && node --check src/skills/discover.js && node --check src/plugins/manage.js && node --check src/pack/zip.js && node --check src/pack/tar.js && node --check src/pack/selfpack.js && node --check src/safety/guard.js && node --check src/safety/undo.js && node --check src/safety/audit.js && node --check src/safety/network.js && node --check src/setup.js && node --check src/report.js && node --check src/config.js && node --check src/ui/ansi.js && node --check src/ui/status.js && node --check src/ui/level.js && node --check src/ui/prompt.js && node --check src/ui/spinner.js && echo OK"
|
|
49
|
+
"check": "node --check bin/deel.js && node --check src/repl.js && node --check src/commands.js && node --check src/agent/loop.js && node --check src/agent/session.js && node --check src/agent/effort.js && node --check src/agent/modes.js && node --check src/agent/route.js && node --check src/tools/encoding.js && node --check src/tools/excel-com.js && node --check src/tools/excel.js && node --check src/tools/xlsx.js && node --check src/agent/compact.js && node --check src/agent/store.js && node --check src/agent/sessionui.js && node --check src/backend/adapter.js && node --check src/backend/ctxsize.js && node --check src/backend/probe.js && node --check src/backend/detect.js && node --check src/backend/http.js && node --check src/backend/scan.js && node --check src/backend/scanui.js && node --check src/tools/index.js && node --check src/tools/fsutil.js && node --check src/tools/edit-match.js && node --check src/tools/webfetch.js && node --check src/tools/todo.js && node --check src/skills/discover.js && node --check src/plugins/manage.js && node --check src/pack/zip.js && node --check src/pack/tar.js && node --check src/pack/selfpack.js && node --check src/safety/guard.js && node --check src/safety/undo.js && node --check src/safety/audit.js && node --check src/safety/network.js && node --check src/setup.js && node --check src/report.js && node --check src/config.js && node --check src/ui/ansi.js && node --check src/ui/status.js && node --check src/ui/level.js && node --check src/ui/prompt.js && node --check src/ui/spinner.js && echo OK"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {},
|
|
52
52
|
"devDependencies": {}
|
package/src/agent/loop.js
CHANGED
|
@@ -68,10 +68,10 @@ export async function* run(session, ctx, userText, { signal = null } = {}) {
|
|
|
68
68
|
const tools = toolSchemas(null, {
|
|
69
69
|
hasSkills: (session.skills?.length ?? 0) > 0,
|
|
70
70
|
web: session.web !== false && !isOffline(), // 오프라인이면 웹 도구는 아예 안 보여 준다
|
|
71
|
-
work: session.
|
|
71
|
+
work: session.effectiveWork(), // 작업 모드가 쓰는 것만 (modes.js)
|
|
72
72
|
});
|
|
73
73
|
// 모드마다 생각의 배분과 걸음 수가 다르다. 사용자가 따로 정했으면 그걸 존중한다.
|
|
74
|
-
const 모드 = workMode(session.
|
|
74
|
+
const 모드 = workMode(session.effectiveWork());
|
|
75
75
|
const effort = session.effortSet ? session.effort : (모드.effort ?? session.effort);
|
|
76
76
|
const think = session.thinkSet ? session.think : (모드.think ?? session.think);
|
|
77
77
|
const maxSteps = session.stepsSet ? session.maxSteps : (모드.steps ?? session.maxSteps);
|