@noobdemon/noob-cli 1.10.20 → 1.11.1
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 +476 -0
- package/README.md +113 -27
- package/bin/noob.js +40 -27
- package/package.json +30 -2
- package/src/agent.js +213 -124
- package/src/api.js +126 -52
- package/src/config.js +11 -11
- package/src/i18n.js +171 -148
- package/src/memory.js +24 -13
- package/src/models.js +96 -46
- package/src/prompts/system.md +85 -0
- package/src/repl/complete.js +120 -0
- package/src/repl/todos.js +38 -0
- package/src/repl/ultra.js +62 -0
- package/src/repl/workflow-commands.js +238 -0
- package/src/repl.js +794 -769
- package/src/sessions.js +20 -20
- package/src/skills.js +13 -9
- package/src/subagent.js +3 -3
- package/src/tokens.js +37 -12
- package/src/tools.js +211 -122
- package/src/tui.js +240 -124
- package/src/ui.js +44 -44
- package/src/update.js +21 -21
- package/src/workflows-builtin.js +16 -14
- package/src/workflows.js +29 -27
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Tất cả thay đổi đáng kể của `@noobdemon/noob-cli` được ghi vào file này.
|
|
4
|
+
|
|
5
|
+
## [1.11.1] - 2026-06-10
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- **Câu trả lời không còn bị cắt cụt khi viết về web search / SEO** (`src/api.js`): regex dọn block `## Web Search Results` chỉ chạy ở `/search` mode. Trước đây nó chạy luôn ở chat → nếu bạn đang viết content/SEO có heading dạng đó, phần còn lại của câu trả lời bị nuốt mất.
|
|
9
|
+
- **SSE stream bền hơn với reverse proxy CRLF**: chuẩn hoá `\r\n` → `\n` trước khi parse, tránh dòng SSE bị bỏ sót khi gateway trả line-ending hỗn tạp.
|
|
10
|
+
- **Cờ `--insecure-tls` áp dụng đúng thời điểm** (`src/api.js`): bỏ lệnh áp dụng top-level (chạy trước parse argv vì ESM hoist). Giờ chỉ áp dụng đúng một lần từ `bin/noob.js` sau khi đọc argv.
|
|
11
|
+
- **Không còn `MaxListenersExceededWarning` khi chạy test / dynamic import** (`src/tools.js`): handler cleanup tiến trình nền (`exit` + `SIGTERM`) có guard chống đăng ký kép.
|
|
12
|
+
|
|
13
|
+
### Chore
|
|
14
|
+
- **`.gitignore` / `.npmignore`**: bổ sung `*.bak`, `*.swp`, `Thumbs.db`, `Desktop.ini`, lockfile backup của npm/yarn/pnpm — defence-in-depth, không ảnh hưởng nội dung package đã publish.
|
|
15
|
+
|
|
16
|
+
## [1.11.0] - 2026-06-10
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
- **Token count chính xác hơn cho GPT-4o/5/o-series** (`src/tokens.js`): trước đây dùng chung encoder `cl100k_base` cho tất cả model → đếm sai cho các model mới của OpenAI (chênh ~10-20%). Giờ tự switch sang `o200k_base` khi dùng `gpt-4o`/`gpt-5`/`o1`/`o3`/`o4`. Claude/Gemini/DeepSeek/etc vẫn dùng `cl100k_base` (xấp xỉ).
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
- **README mở rộng**: thêm sơ đồ kiến trúc Mermaid, cấu trúc project, hướng dẫn development + troubleshooting (TLS, model refusal, token count).
|
|
23
|
+
- **Refactor nội bộ** (`src/repl.js` -10 KB): tách logic todos/ULTRA mode/workflow read-only commands ra `src/repl/{todos,ultra,workflow-commands}.js`. Không ảnh hưởng hành vi.
|
|
24
|
+
|
|
25
|
+
### Added
|
|
26
|
+
- **Test suite mở rộng**: 19 → 96 tests (vitest), bao phủ `config`, `memory`, `sessions`, `tools`, `tokens`, `repl/todos`, `models`. Chạy bằng `npm test`.
|
|
27
|
+
- **JSDoc cho `src/tools.js`**: thêm typedef `ToolName`/`ToolInput`/`ToolRunOpts` để IDE autocomplete chuẩn hơn khi viết skill/sub-agent.
|
|
28
|
+
- **`.npmignore`** + cập nhật `.gitignore`: defence-in-depth tránh leak file dev (`.opencode/`, `AGENTS.md`, `*.tgz`).
|
|
29
|
+
|
|
30
|
+
## [1.10.20] - 2026-06-10
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
- **Effort classifier luôn trả về `high`** (`src/agent.js`): benchmark 5 task × 3 effort levels. Không có mức nào nhanh nhất cho mọi task — giữ `high` để đảm bảo chất lượng.
|
|
34
|
+
- **Gỡ budget enforcement** (`src/agent.js`, `src/repl.js`): agent/sub-agent chạy không giới hạn token.
|
|
35
|
+
- **Tối ưu token tracking** (`src/tokens.js`): thêm `setContext()`, `endOutput()`, `pushOutputDelta()`, `formatWithPct()`.
|
|
36
|
+
- **Tăng max continues** (`src/api.js`): mặc định từ 10 → `Infinity`.
|
|
37
|
+
- **Dọn scripts/ test cũ**: xoá 11 smoke/test scripts không còn dùng.
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
- **Effort classification sai** (`src/agent.js`): loại bỏ `goal` khỏi HIGH_PATTERNS — gây false positive. Mở rộng LOW_PATTERNS.
|
|
41
|
+
- **Session restore lỗi** (`src/sessions.js`): `writeSession` thiếu await.
|
|
42
|
+
- **Startup crash khi mất mạng** (`src/update.js`): `fetch` không catch.
|
|
43
|
+
- **TUI text wrap sai** (`src/tui.js`): không handle ký tự đặc biệt.
|
|
44
|
+
|
|
45
|
+
## [1.10.18] - 2026-06-09
|
|
46
|
+
|
|
47
|
+
### Fixed
|
|
48
|
+
- **Context % hiển thị sai** (`src/repl.js`): 1.10.17 fix agent.js nhưng repl.js vẫn ghi đè ctx% bằng `countMessages(history)` sau mỗi lượt → ctx% lại sai. Bỏ `setContext` trong repl.js để giữ giá trị cumulative từ agent.
|
|
49
|
+
|
|
50
|
+
## [1.10.17] - 2026-06-09
|
|
51
|
+
|
|
52
|
+
### Fixed
|
|
53
|
+
- **Context % hiển thị sai** (`src/agent.js`): ctx% đang tính = kích thước prompt gửi lên API / 300k, nên luôn thấp (~6-10%) dù tổng token đã 400k+. Fix: ctx% = tổng input+output đã dùng / 300k — phản ánh đúng tỷ lệ context window đã chiếm.
|
|
54
|
+
|
|
55
|
+
## [1.10.16] - 2026-06-09
|
|
56
|
+
|
|
57
|
+
### Fixed
|
|
58
|
+
- **Model gọi `./gradlew` trên Windows** (`src/agent.js`): runtime context thiếu hướng dẫn dùng `.bat`/`.cmd`. Thêm dòng nhắc model dùng `gradlew.bat` thay vì `./gradlew`.
|
|
59
|
+
|
|
60
|
+
## [1.10.15] - 2026-06-09
|
|
61
|
+
|
|
62
|
+
### Fixed
|
|
63
|
+
- **Loop detection bỏ sót pattern vòng A-B-A-B** (`src/agent.js`): model thoát detection cũ bằng cách xen kẽ 2-3 tool call khác nhau (vd `read_file build.gradle` → `list_dir` → lặp). Fix: thêm phát hiện pattern cycle độ dài 2-3, mở window 3→6, không reset `loopDetectedCount` sai khi gặp tool khác trong cycle.
|
|
64
|
+
|
|
65
|
+
## [1.10.14] - 2026-06-09
|
|
66
|
+
|
|
67
|
+
### Fixed
|
|
68
|
+
- **Context percentage stuck at 8-9%** (`src/agent.js`): `MAX_PROMPT_CHARS = 80000` (~20k tokens) và `SUMMARIZE_THRESHOLD_CHARS = 60000` (~15k tokens) là char budgets từ thời context window 200k — không scale khi lên 300k (v1.10.11). Compaction trigger quá thấp nên ctx % luôn hiển thị kích thước đã compact (~25k tokens) thay vì tỷ lệ thực tế so với window 300k. Fix: tăng `MAX_PROMPT_CHARS` lên 1200000 (~300k tokens = ngang window) để `compact()` không chạy trước auto-compact 80% (240k tokens) của repl.js. `SUMMARIZE_THRESHOLD_CHARS` lên 1000000 (~250k tokens/83%).
|
|
69
|
+
|
|
70
|
+
## [1.10.13] - 2026-06-09
|
|
71
|
+
|
|
72
|
+
### Fixed
|
|
73
|
+
- **Context percentage stuck at 8-9%** (hotfix reverted values — xem 1.10.14 cho fix đúng)
|
|
74
|
+
|
|
75
|
+
## [1.10.12] - 2026-06-09
|
|
76
|
+
|
|
77
|
+
### Fixed
|
|
78
|
+
- **Auto-stop vì proxy chèn web search blocks** (`src/api.js` + `src/agent.js`): proxy unlimited.surf chèn `web_search_results`/`web_search_summary` vào stream → AI tưởng prompt injection, tốn context cảnh báo thay vì làm việc. Fix: `cleanResponseText()` tự động strip các block này + system prompt dặn model ignore + handle `{finish: true}` event của proxy.
|
|
79
|
+
|
|
80
|
+
## [1.10.11] - 2026-06-09
|
|
81
|
+
|
|
82
|
+
### Changed
|
|
83
|
+
- **Context window 200k → 300k** (`src/tokens.js`): `ctx 100%` giờ = 300k tokens.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## [1.10.10] - 2026-06-09
|
|
88
|
+
|
|
89
|
+
### Removed
|
|
90
|
+
- **Bỏ idle timeout CLI** (`src/api.js`): xóa hoàn toàn cơ chế idle timeout (content timer, wire timer, warn/probe). Trước đây nếu upstream im >45s → auto abort. Giờ CLI chỉ dừng khi user Ctrl+C hoặc upstream chết thật (TCP timeout).
|
|
91
|
+
|
|
92
|
+
### Fixed
|
|
93
|
+
- **Fix `idleMs is not defined`** (`src/api.js`):残留 reference `idleMs` trong `streamOnce()` call gây crash khi dùng `/improve` hoặc bất kỳ lệnh nào stream data.
|
|
94
|
+
|
|
95
|
+
## [1.10.9] - 2026-06-09
|
|
96
|
+
|
|
97
|
+
### Fixed
|
|
98
|
+
- **Loop detection hard stop** (`src/agent.js`): thêm `loopDetectedCount` đếm số lần loop detection liên tiếp. Sau 3 lần detect liên tiếp cùng tool + input → force stop, trả `[LOOP STOPPED]`. Trước đây loop detection chỉ inject warning rồi reset → model lặp vô tận.
|
|
99
|
+
|
|
100
|
+
## [1.10.8] - 2026-06-09
|
|
101
|
+
|
|
102
|
+
### Changed
|
|
103
|
+
- **Proxy idle timeout 45s → 10 phút** (`worker.js`): tăng `IDLE_MS` từ 45s lên 600000ms (10 phút). Gateway cho upstream suy nghĩ thoải mái, chỉ chống treo vĩnh viễn.
|
|
104
|
+
- **Proxy heartbeat gate 45s → 10 phút** (`worker.js`): tăng `HB_GATE_MS` match idle timeout mới.
|
|
105
|
+
|
|
106
|
+
## [1.10.7] - 2026-06-09
|
|
107
|
+
|
|
108
|
+
### Changed
|
|
109
|
+
- **Idle timeout 45s → 240s** (`src/api.js`): tăng `idleMs` mặc định từ 45s lên 4 phút (sau đó bị bỏ hoàn toàn ở 1.10.10).
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## [1.10.6] - 2026-06-08
|
|
114
|
+
|
|
115
|
+
### Fixed
|
|
116
|
+
- **Assignment to constant variable**: fix `const answer` bị gán lại trong idle verification loop → đổi thành `let answer`.
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## [1.10.5] - 2026-06-08
|
|
121
|
+
|
|
122
|
+
### Added
|
|
123
|
+
- **Idle verification loop** (`src/repl.js`): khi model dừng (không tool call) → repl gọi model verify task completion (max 3 lần). Prompt yêu cầu model: đọc file kết quả bằng read_file, chạy test/build, so sánh yêu cầu gốc. Nếu model trả lời "XÁC NHẬN: [tóm tắt]" → done. Nếu chưa xong → model gọi tool tiếp tục. Thay thế idle recovery/verify cũ (max 5 + max 2 nudge) bằng flow verify chủ động.
|
|
124
|
+
|
|
125
|
+
### Fixed
|
|
126
|
+
- **Ctrl+C abort immediate** (`src/agent.js`): thêm check `signal?.aborted` ở đầu mỗi iteration của agent loop. Trước đây Ctrl+C hiển thị "✗ đã ngắt" nhưng vẫn chạy tiếp vài bước mới dừng hẳn.
|
|
127
|
+
- **Context % calculation** (`src/agent.js` + `src/repl.js`): fix mismatch giữa agent (system + message) và repl (chỉ history). Export `buildSystem`/`buildUserMessage` từ agent.js, import `countTokens` trong repl.js. Giờ context % tính đúng bao gồm system prompt (~5k tokens) thay vì chỉ history → hiển thị chính xác (vd 10% → ~25-30%).
|
|
128
|
+
|
|
129
|
+
### Internal
|
|
130
|
+
- Bỏ idle recovery (max 5) + completion verify (max 2) cũ trong `src/agent.js` — logic verify chuyển sang `src/repl.js` chủ động hơn.
|
|
131
|
+
- Export `buildSystem`/`buildUserMessage` từ agent.js để repl.js dùng chung logic build prompt.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
Format theo [Keep a Changelog](https://keepachangelog.com/vi/1.1.0/),
|
|
136
|
+
phiên bản theo [SemVer](https://semver.org/lang/vi/).
|
|
137
|
+
|
|
138
|
+
Quy ước: trước mỗi lần `npm publish`, **noob (AI) phải tự viết entry mới** cho version sắp publish vào đầu file này. Script `scripts/notify-discord.js` (chạy ở `postpublish`) sẽ đọc section tương ứng và bắn lên Discord.
|
|
139
|
+
|
|
140
|
+
Mỗi entry nên có các nhóm con (chỉ giữ nhóm có nội dung):
|
|
141
|
+
- **Added** — tính năng mới
|
|
142
|
+
- **Changed** — thay đổi hành vi
|
|
143
|
+
- **Fixed** — sửa lỗi
|
|
144
|
+
- **Removed** — bỏ tính năng
|
|
145
|
+
- **Internal** — refactor/chore không ảnh hưởng user
|
|
146
|
+
|
|
147
|
+
## [1.10.4] - 2026-06-08
|
|
148
|
+
|
|
149
|
+
### Added
|
|
150
|
+
- **Idle recovery**: khi model dừng giữa chừng (không gọi tool) nhưng còn pending tasks → inject nudge user message rồi continue loop. Max 5 lần recovery để tránh infinite loop.
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## [1.10.3] - 2026-06-08
|
|
155
|
+
|
|
156
|
+
### Fixed
|
|
157
|
+
- **Todo continuation nudge rewrite**: bỏ `extractUncheckedTodos` (parse output → không tin cậy). Thay bằng `pendingTasks` parameter — caller gửi list tasks trực tiếp vào `runAgent`. Nudge dùng danh sách thật, không phụ thuộc model output `- [ ]` markers.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## [1.10.2] - 2026-06-08
|
|
162
|
+
|
|
163
|
+
### Fixed
|
|
164
|
+
- **Startup crash**: fix `ReferenceError: Cannot access 'session' before initialization` — `updateTitle()` gọi khi `session` chưa được khai báo. Di chuyển lần gọi đầu tiên xuống sau `let session = null`.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## [1.10.1] - 2026-06-08
|
|
169
|
+
|
|
170
|
+
### Added
|
|
171
|
+
- **Todo continuation nudge** (`src/agent.js`): sau MỖI tool result, kiểm tra còn todo unchecked không → inject `[TODO]` nudge nhắc model làm item tiếp theo ngay. `extractUncheckedTodos()` scan assistant messages, dedupe, trả về list unchecked. Nudge rõ ràng: tên task cụ thể + "HÃY LÀM NGAY — KHÔNG dừng".
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## [1.10.0] - 2026-06-08
|
|
176
|
+
|
|
177
|
+
### Added
|
|
178
|
+
- **`/status` enhanced**: hiển thị context % theo tokens (màu theo mức), token usage (`↑45k ↓8k`), todo progress (`✓ 2/5`), session ID, cwd.
|
|
179
|
+
- **Terminal title auto-name**: title bar tự cập nhật `noob — {session title}` khi gõ message đầu tiên (trích từ nội dung user).
|
|
180
|
+
- **Ctrl+L clear screen**: xóa màn hình giữ nguyên context (giống `cls` nhưng không mất input).
|
|
181
|
+
|
|
182
|
+
### Changed
|
|
183
|
+
- **Context % threshold colors**: `ctx 27%` (dim) → `ctx 45%` (tool) → `ctx 65%` (accent) → `ctx 80%+` (err).
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## [1.9.12] - 2026-06-08
|
|
188
|
+
|
|
189
|
+
### Added
|
|
190
|
+
- **Terminal title bar**: hiện `noob — {model name}` trên title bar của CMD/PowerShell khi CLI chạy. Tự update khi đổi model qua `/model`.
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## [1.9.11] - 2026-06-08
|
|
195
|
+
|
|
196
|
+
### Fixed
|
|
197
|
+
- **Todo execution stronger**: fix model dừng sau 2-3 items — system prompt giờ rõ ràng hơn: "After EVERY tool result, check off the completed item AND IMMEDIATELY start the next unchecked item". Chỉ được dừng khi (a) tất cả items xong hoặc (b) đang chờ user reply. Sau write_file/edit_file PHẢI tiếp tục item tiếp theo.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## [1.9.10] - 2026-06-08
|
|
202
|
+
|
|
203
|
+
### Fixed
|
|
204
|
+
- **Todo execution flow**: fix model dừng sau khi viết todo list — system prompt giờ yêu cầu (1) viết todo VÀ (2) NGAY LẬP TỨC bắt đầu item đầu tiên TRONG CÙNG 1 response. Todo list là planning step, không phải output. Chỉ dừng khi tất cả items đều `- [x]`.
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## [1.9.9] - 2026-06-08
|
|
209
|
+
|
|
210
|
+
### Fixed
|
|
211
|
+
- **Context % realtime**: fix bug `ctx 0%` dù token đã lên 21k — `setContext` giờ được gọi bên trong `runAgent` loop sau mỗi lần `buildSystem`+`buildUserMessage`, cập nhật realtime khi history thay đổi (tool calls, steer, summarization). Trước đây chỉ gọi 1 lần trước API call → contextTokens cũ.
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## [1.9.8] - 2026-06-08
|
|
216
|
+
|
|
217
|
+
### Added
|
|
218
|
+
- **Context usage tracker** (`src/tokens.js` + `src/repl.js`): hiển thị context % realtime trên status bar — `↑45k ↓8k (53k) · ctx 27%`. Đếm token bằng `countMessages()` (gpt-tokenizer) trước mỗi lượt API. Context window 200k tokens.
|
|
219
|
+
|
|
220
|
+
### Changed
|
|
221
|
+
- **Auto-compact by tokens**: chuyển ngưỡng auto-compact từ char-based (240k chars) sang token-based — 80% context window (160k tokens) → auto compact, 70% → cảnh báo mạnh, 60% → nhắc nhẹ. Messages thay bằng token count + context %.
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## [1.9.7] - 2026-06-08
|
|
226
|
+
|
|
227
|
+
### Added
|
|
228
|
+
- **Todo progress bar** (`src/tui.js` + `src/repl.js`): render todo list trên status bar — hiển thị `✓ 2/5 ████░░░░ 40%` + task đang làm. Parse `- [ ]` / `- [x]` từ model output real-time. Tự clear khi `/clear` hoặc `/new`. System prompt cập nhật: model emit todo trực tiếp trong reply text (không cần write_file).
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## [1.9.6] - 2026-06-08
|
|
233
|
+
|
|
234
|
+
### Fixed
|
|
235
|
+
- **Câu trả lời bị cắt giữa chừng** (`src/agent.js`): thêm `isIncompleteResponse()` — detect khi model trả lời không tool call nhưng text bị cắt đột ngột (dangling option "A.", "B.", câu hỏi dở dang, từ nối cuối dòng "ví", "hay", "hoặc"). Nếu bị cắt → inject `stream_recovery` để model viết tiếp thay vì return câu hỏi dở cho user.
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## [1.9.5] - 2026-06-08
|
|
240
|
+
|
|
241
|
+
### Added
|
|
242
|
+
- **Effort classifier** (`src/agent.js`): tự phân loại mức độ phức tạp task → set effort level (`low`/`medium`/`high`) gửi lên model. Task đơn (list, read, grep, câu hỏi) → `low` (nhanh hơn, ít token). Task vừa (edit, test, build) → `medium`. Task phức tạp (refactor, debug, workflow) → `high`. Regex-based, 3 tier pattern matching + fallback theo độ dài message. Export `classifyEffort` để test.
|
|
243
|
+
|
|
244
|
+
### Changed
|
|
245
|
+
- `streamWithRetry` nhận + forward `effort` xuống `stream()` → gateway → upstream Anthropic API. Trước đây effort luôn `undefined` → worker default `high` → mọi task đều suy nghĩ chậm.
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## [1.9.4] - 2026-06-08
|
|
250
|
+
|
|
251
|
+
### Changed
|
|
252
|
+
- **System prompt: TODO-based execution** (`src/agent.js`): thêm rule "TODO-BASED EXECUTION" — với mọi task 3+ bước, model PHẢI tạo todo list trước, làm từng item, tự verify đã xong hết trước khi dừng. Tránh model dừng giữa chừng khi task chưa hoàn thành.
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## [1.9.3] - 2026-06-08
|
|
257
|
+
|
|
258
|
+
### Fixed
|
|
259
|
+
- **Timeout treo khi model suy nghĩ lâu** (`src/api.js`): tăng content idle timeout từ 25s lên 45s, wire timeout từ 50s lên 135s — tránh abort nhầm khi model xử lý task phức tạp (đọc nhiều file, suy nghĩ dài). Warning message rõ ràng hơn ("Model đang suy nghĩ…" thay vì "Đang chờ proxy…"). Thêm hướng dẫn "Đang thử lại…" trong error message.
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## [1.9.2] - 2026-06-08
|
|
264
|
+
|
|
265
|
+
### Fixed
|
|
266
|
+
- **Loop detection chống model bị kẹt** (`src/agent.js`): tự phát hiện khi model gọi cùng 1 tool với input giống nhau liên tiếp ≥2 lần → inject cảnh báo `loop_detection` bắt model chuyển bước. System prompt cũng thêm rule "Do NOT call the same tool with the same input repeatedly". Ngăn lặp vô hạn (vd: `read_file` cùng 1 file 15+ lần) mà không ngắt task đang chạy.
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## [1.9.1] - 2026-06-07
|
|
271
|
+
|
|
272
|
+
**`/workflow` align với bài Thariq + 3 built-in ship sẵn + UX polish**
|
|
273
|
+
|
|
274
|
+
- **3 built-in workflow** (module mới `src/workflows-builtin.js`, run ngay không cần save): `deep-research` (fan-out + adversarial verify), `verify-claims` (list claims + fan-out verify chống codebase), `triage` (classify + dedupe + route, có QUARANTINE).
|
|
275
|
+
- **Sub-command mới**: `/workflow help` (alias `?`), `/workflow patterns`, `/workflow builtins`.
|
|
276
|
+
- **Pattern list 7 → 6** theo article (bỏ 1 pattern tự bịa).
|
|
277
|
+
- Save hỏi description, run in preview banner, enforce PLAN bước 1, delete refuse built-in, empty `/workflow` show help.
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
## [1.9.0] - 2026-06-07
|
|
283
|
+
|
|
284
|
+
**`/add-dir` thông minh hơn + `/workflow` xin phép khi cần spawn_agent**
|
|
285
|
+
|
|
286
|
+
### Added
|
|
287
|
+
- **`/add-dir` persist theo workspace** (`src/tools.js`): mỗi lần `addRoot()`/`removeRoot()` đều ghi/xoá khỏi `<cwd>/.noob/dirs.json`. Lần sau mở project, `loadWorkspaceRoots()` auto-load lại — user không phải `/add-dir` lại từ đầu. Nếu folder trong file đã bị xoá → bỏ qua lặng lẽ. Nếu read-only / permission deny → addRoot vẫn áp dụng cho phiên hiện tại, chỉ fail persist.
|
|
288
|
+
- **Auto-prompt khi model tag folder ngoài scope** (`src/tools.js` + `src/repl.js`): tool `abs()` ném `OutOfScopeError` (code `OUT_OF_SCOPE`, có `.path` + `.suggestedRoot`) thay vì Error thường. `execTool` ở repl catch riêng → gọi `askAddRoot(root, path)` với 3 lựa chọn: `y` (chỉ lần này) / `a` (luôn auto-approve mọi add-root trong phiên) / `n` (từ chối). Approve → `addRoot` + persist + sync `state.extraRoots` + chạy lại tool qua `execToolCore({retried:true})`. Tương đối escape cwd **không** auto-prompt (thường model tính sai path, để error message giúp model tự sửa).
|
|
289
|
+
- **Helper `nearestExistingDir(p)`** (`src/tools.js`): tìm folder gần nhất tồn tại để suggest add — file có thật → trả parent; folder có thật → trả p; không tồn tại → walk lên tới khi gặp folder (hoặc trả null nếu đi tới filesystem root).
|
|
290
|
+
- **`/add-dir remove|rm <path>`** sub-command (`src/repl.js`): gỡ khỏi scope + persist xoá khỏi `.noob/dirs.json`. Thông báo rõ nếu path không có trong scope.
|
|
291
|
+
- **System prompt mới cho filesystem scope** (`src/agent.js::runtimeContext`): liệt kê `cwd + N extra root(s)`, dặn model "nếu cần folder NGOÀI scope → cứ dùng path tuyệt đối, repl tự hỏi user + auto-persist". Model không còn mơ hồ "có /add-dir không?" — cứ thử, hệ thống lo.
|
|
292
|
+
|
|
293
|
+
### Changed
|
|
294
|
+
- **`/workflow` không còn tự bật agent mode im lặng** (`src/repl.js`): trước đó `state.agent === false` → auto-on + in dòng "agent mode tự bật cho /workflow" mơ hồ, user bất ngờ. Giờ HỎI QUYỀN y/n (Enter = yes) qua helper `askWorkflowAgentMode()` trước khi bật. Nếu `n` → huỷ workflow sạch sẽ + gợi ý gõ `/agent` rồi chạy lại. Tái sử dụng pattern `ask()` + `pending.push` (paste-spam protection) + `tui.setBusy(false/true)` (tắt spinner lúc prompt) y hệt `askPermission`/`askAddRoot` — 3 hàm hỏi quyền trong noob giờ đồng nhất UX. i18n 4 key mới: `workflowAgentAskHint`, `workflowAgentAskPrompt`, `workflowAgentEnabled`, `workflowAgentDenied`.
|
|
295
|
+
|
|
296
|
+
### Fixed
|
|
297
|
+
- **TUI `wrapText` không tail-follow stream** (`src/tui.js:42-74`): trước đó wrap dừng ở `maxLines` dòng ĐẦU → status bar hiện phần text cũ nhất trong khi AI đang viết phần mới (head-follow). Fix: wrap toàn bộ text trước, sau đó `slice(-maxLines)` chỉ giữ page cuối. Dòng đầu page prepend `…` + cắt 1 ký tự cuối (giữ nguyên độ rộng terminal, tránh re-wrap). Apply cho cả 3 call site của `wrapText` trong `topRow()`: liveOut, statusText, busyLabel.
|
|
298
|
+
|
|
299
|
+
### Internal
|
|
300
|
+
- 19 i18n key mới: 4 cho workflow ask-gate + 4 cho add-dir auto-prompt + cập nhật `cmdAddDir` description + list 6 key CRUD (cộng dồn từ 1.8.0).
|
|
301
|
+
- 2 smoke test mới: `scripts/test-add-dir.mjs` 19/19 (OutOfScopeError code/path/suggestedRoot, nearestExistingDir 3 case, persist round-trip, auto-prompt qua read_file, relative path escape); `scripts/smoke-workflow-agent-gate.mjs` 25/25 (i18n key + cấu trúc code helper `askWorkflowAgentMode` + pattern y hệt `askPermission`).
|
|
302
|
+
- `src/agent.js` import thêm `listRoots` từ `src/tools.js` (đã có sẵn từ 1.7.x) — phục vụ rewrite block filesystem scope.
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## [1.8.0] - 2026-06-07
|
|
307
|
+
|
|
308
|
+
**Memory layer** — model nhớ rõ hơn giữa các phiên:
|
|
309
|
+
- RECENT SESSIONS block (5 phiên gần nhất cùng workspace) trong system prompt
|
|
310
|
+
- noob.md status hiện ở startup banner + footer mỗi lượt
|
|
311
|
+
- /new auto-suggest /learn khi phiên ≥5 lượt
|
|
312
|
+
- Paste chip có first-line preview
|
|
313
|
+
|
|
314
|
+
**TUI text wrap** — status + input không bị cắt cứng:
|
|
315
|
+
- Status bar soft-wrap 2 dòng (word boundary, ANSI-safe)
|
|
316
|
+
- Input bar wrap dọc 5 dòng, indent theo prompt, cursor track row + col
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
## [1.8.1] - 2026-06-07
|
|
321
|
+
|
|
322
|
+
**Hotfix** — TUI wipe bug trên Windows:
|
|
323
|
+
- `placeCursor` cũ dùng `totalRows` (gồm top+menu+bar) làm `upBy` → khi có spinner phía trên bar, cursor bị kéo lên quá cao. Lần `commit` kế tiếp `ESC[J` wipe luôn spinner+bar+dòng response trên cùng → mất hết output.
|
|
324
|
+
- Fix: dùng `barRows` (chỉ số dòng BAR) — chỉ move cursor trong phạm vi bar.
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## [1.7.10] - 2026-06-07
|
|
329
|
+
|
|
330
|
+
### Fixed
|
|
331
|
+
- **Timeout khi bắt đầu phiên chat** (`src/api.js`): upstream gateway yêu cầu `memoryToken` mỗi phiên để duy trì trạng thái hội thoại khi bật lưu nhớ (`remember`). Khi không có token, gateway treo chờ không trả delta → CLI timeout sau ~25 giây. Fix: sinh `memoryToken` ngẫu nhiên (2 UUID v4 nối `_`) cho mỗi session, gửi kèm `remember: true` trong request body. Các lượt sau cùng phiên dùng chung token, đảm bảo upstream nhận diện đúng phiên và trả lời ngay.
|
|
332
|
+
|
|
333
|
+
### Changed
|
|
334
|
+
- **`/clear`, `/new`, `--resume`, `--continue` tự động refresh token** (`src/repl.js` + `src/api.js`): khi user xoá ngữ cảnh hoặc khởi động phiên mới, `resetMemoryToken()` được gọi để upstream cấp phát trạng thái mới. Không ảnh hưởng conversation array quản lý cục bộ của CLI.
|
|
335
|
+
|
|
336
|
+
---
|
|
337
|
+
|
|
338
|
+
## [1.7.9] - 2026-06-07
|
|
339
|
+
|
|
340
|
+
### Fixed
|
|
341
|
+
- **System prompt now routes through `customInstructions`** (`src/agent.js` + `src/api.js`): tách `buildPrompt(history)` cũ thành `buildSystem(history)` + `buildUserMessage(history)` — system instructions (template, context, WIP, workflow, goal) gửi qua field `customInstructions` trong request body, user text gửi qua `message`. Trước đó toàn bộ prompt bị nối hết vào `message`, khiến upstream gateway coi phần system prompt là user message và **bỏ qua hoàn toàn** — tính năng như `noob.md`, `/goal`, hay workflow không có tác dụng. Thêm `remember: true` vào body để gateway forward đúng. Đây là regression từ refactor body shape trước đó; giờ mới phát hiện vì proxy chỉ chuyển `customInstructions` chứ không parse `message`.
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
## [1.7.8] - 2026-06-06
|
|
346
|
+
|
|
347
|
+
### Added
|
|
348
|
+
- **`/goal <text>` — HARD GOAL cho phiên**: đặt completion requirement model phải bám tới khi `/goal clear`. Inject vào MỌI prompt (vị trí attention cao thứ 2, ngay sau `noob.md`) qua `goalBlock()` trong `src/agent.js::buildPrompt`. Bền qua `--continue`/`--resume` (lưu `session.goal`). Combo với `/ultra` + `/loop` để tự chạy tới khi goal đạt — chống agentic laziness (model tự tuyên bố xong sớm) và goal drift (lạc đề sau nhiều turn). Cú pháp: `/goal <mục tiêu>` để đặt, `/goal` không arg để xem, `/goal clear|off|xoá` để xoá.
|
|
349
|
+
- **`/loop <interval> [budget] <task>` — chạy task định kỳ**: cảm hứng từ tweet_dump.txt ("pair triage workflows with /loop to have Claude do this continuously"). Interval parser linh hoạt (`30s`/`5m`/`1h`/`2h30m`, tối thiểu 5s chống hammer). Token budget tùy chọn ở vị trí thứ 2 (`10k`/`50k`/`1m`/`200000`) — vượt budget thì loop tự dừng + log số token đã dùng. Model tự dừng bằng cách phát token `<<LOOP_DONE>>` ở cuối reply khi task hoàn tất / goal đạt. `/loop stop` để dừng thủ công, `/loop` không arg xem trạng thái. Chống re-entrant (tick trước chưa xong thì skip tick sau).
|
|
350
|
+
- **`/workflow` CRUD đầy đủ (saved workflows)**: theo tweet_dump ("save workflows by pressing 's' in the workflow menu... check into ~/.claude/workflows or distribute via skill"). Mở rộng từ ad-hoc cũ thành: `/workflow save <name> <yêu cầu>`, `/workflow list`, `/workflow load <name>`, `/workflow run <name> [ngữ cảnh]`, `/workflow delete|rm <name>`. Lưu Markdown + front-matter YAML-lite vào `~/.noob/workflows/<name>.md`. Tên sanitize `^[a-z0-9][a-z0-9_-]{0,63}$` (chống path traversal). `/workflow <yêu cầu>` không có sub-command vẫn fallback về ad-hoc như cũ — backward compat.
|
|
351
|
+
- **Skill mới `dynamic-workflows`** (`skills/dynamic-workflows/SKILL.md`): playbook orchestrate multi-agent — 7 Critical Rules + 7 pattern (Fan-out+Synthesize, Adversarial Verification, Generate-and-Filter, Tournament, Loop-Until-Done, Classify-and-Route, Diverse-Hypothesis Debug) + prompt template 5 mục (GOAL/INPUTS/METHOD/OUTPUT SHAPE/STOP CONDITION) + token budget guide + 8 anti-pattern + checklist cuối. Nạp tự động khi gõ `/workflow`. Cảm hứng từ bài "A harness for every task: dynamic workflows in Claude Code" (Anthropic/Thariq Shihipar).
|
|
352
|
+
- **Per-sub-agent model routing & token budget**: `spawn_agent`/`spawn_agents` nhận thêm 2 field tùy chọn — `model` (route từng task theo độ khó: task dễ → model rẻ, task khó → model mạnh) và `tokenBudget` (cap chi phí từng sub-agent độc lập). Doc tool trong `src/subagent.js::spawnAgentToolsDoc` dạy model rule routing với gợi ý cụ thể. Log tiến độ kèm `[model]` + `[budget N]` tag để dễ debug.
|
|
353
|
+
- **Help text & autocomplete bổ sung 3 entry mới** (`/workflow`, `/goal`, `/loop`) — trước đây các lệnh này có code nhưng không xuất hiện trong `/help` lẫn slash autocomplete (UX bug, user không biết lệnh tồn tại).
|
|
354
|
+
|
|
355
|
+
### Changed
|
|
356
|
+
- **`findModel()` nâng cấp 3-tier fuzzy match** (`src/models.js`): exact id → normalized id/name (bỏ prefix `gateway-`, chuẩn hoá dấu/spaces) → contains unique (reject ambiguous match nhiều model). Phục vụ sub-agent routing — model nội bộ luôn có prefix `gateway-` (vd `gateway-claude-opus-4-7`) nhưng AI khi spawn sẽ gõ tên ngắn (`claude-opus-4-7`, `deepseek-v4-flash`, `kimi`) — fuzzy match xử lý cả hai phía mà không nhầm.
|
|
357
|
+
- **`runAgent` hỗ trợ `tokenBudget` + `onBudgetExceeded`** (`src/agent.js`): vượt budget thì model bị ép tóm tắt rồi dừng, không tự đốt tiếp. Cùng cơ chế cho sub-agent.
|
|
358
|
+
- **Status bar realtime kèm token cho sub-agent**: token meter của sub-agent dùng chung instance với cha (truyền qua `runSubAgent({tokenMeter})`) → tổng phiên cộng đúng cả sub.
|
|
359
|
+
|
|
360
|
+
### Internal
|
|
361
|
+
- Module mới `src/workflows.js` (~143 dòng): `saveWorkflow`/`loadWorkflow`/`listWorkflows`/`deleteWorkflow`/`workflowsDir`. Front-matter YAML-lite parser tối giản, không thêm dependency.
|
|
362
|
+
- `buildPrompt(history, extraToolsDoc, goal)` thêm tham số `goal` thứ 3 — `goalBlock(goal)` chèn ngay sau `memoryBlock()` (vị trí attention cao thứ 2 trong system prompt).
|
|
363
|
+
- `persist()` lưu thêm `session.goal`; `restore()` khôi phục — HARD GOAL bền qua `--continue`/`--resume`.
|
|
364
|
+
- 15 i18n key mới cho `/workflow` CRUD (workflowListEmpty/Header/SaveNeedArgs/SaveBadName/SaveError/SaveOk/RunNeedName/RunError/RunOk/LoadNeedName/LoadError/LoadOk/DeleteNeedName/DeleteError/DeleteOk) — function-style cho key cần arg.
|
|
365
|
+
- 9 i18n key mới cho `/loop` (loopNeedArgs/BadInterval/Started/BadBudget/BudgetExceeded/Stopped/NotRunning/Status/Tick/AutoStop/AlreadyRunning).
|
|
366
|
+
- Smoke test mới: `scripts/smoke-workflow.mjs` (verify skill load + prompt build + 7 marker + 4 i18n), `scripts/smoke-workflow-save.mjs` (21/21 pass CRUD round-trip + 8 edge case path traversal/empty/overwrite/missing), `scripts/smoke-loop-budget.mjs` (28/28 pass: 9 static wire + 4 i18n + 10 parser unit + 5 peek behavior), `scripts/smoke-subagent-model.mjs` (9/9 routing check + doc check). Pattern: smoke test dùng dynamic import + verify export shape, KHÔNG chạy `bin/noob.js` (treo TUI trên Windows).
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
370
|
+
## [1.7.7] - 2026-06-05
|
|
371
|
+
|
|
372
|
+
### Internal
|
|
373
|
+
- **Test fixture drift fix** — `scripts/test-files-ledger.js` dùng fixture `"Wrote N bytes to PATH"` từ đầu, nhưng `src/tools.js::write_file` thực tế trả `"Wrote N line(s) to PATH"`. Test vẫn xanh suốt vì regex parser `/\s to (.+)$/m` đủ rộng để match cả hai → fixture trở thành documentation sai. Sửa 5 chỗ trong fixture đổi `bytes` → `line(s)` cho khớp reality, thêm comment chỉ rõ format thật trong `tools.js`.
|
|
374
|
+
- **Integration test mới** `scripts/test-files-ledger-integration.js` (16 assertion, exit 0) chạy `tools.write_file`/`edit_file` thật trên FS rồi feed output thật vào `filesLedger()` — chống fixture drift im lặng trong tương lai. Nếu format output của `tools.js` đổi mà fixture không update, integration sẽ vỡ ngay (unit test có thể vẫn xanh do regex rộng). Note pattern `scripts/` không nằm trong field `files` của `package.json` nên không lọt vào tarball publish (verify `npm pack --dry-run`: 20 entry, 65.5 KB tarball — không đổi so với 1.7.6).
|
|
375
|
+
- **Update noob.md** — bỏ trạng thái stale "đang điều tra" của bug "token meter chèn vào prose" thành "FIXED" với reference cụ thể `src/tui.js:163-179` (nhánh `if (liveOut)` chỉ append meta khi `liveLen + metaLen <= cols()` để tránh terminal wrap kẹt meta trong prose). Code thực tế đã ship fix từ trước, chỉ note documentation bị lệch.
|
|
376
|
+
|
|
377
|
+
---
|
|
378
|
+
|
|
379
|
+
## [1.7.6] - 2026-06-05
|
|
380
|
+
|
|
381
|
+
### Fixed
|
|
382
|
+
- **Skill `frontend-design` không chạy khi cài qua npm** (bug nghiêm trọng, ảnh hưởng MỌI máy dùng `npm i -g @noobdemon/noob-cli`). Hai root cause độc lập: (1) `package.json` field `files` thiếu `"skills/"` → thư mục `skills/frontend-design/SKILL.md` KHÔNG được đóng gói vào tarball publish — verify bằng `npm pack --dry-run --json` trước fix không thấy entry `skills/*`, sau fix có `skills/frontend-design/SKILL.md` (4440 bytes). (2) `src/skills.js::skillsDir()` resolve qua `process.cwd()` → khi user chạy `noob` từ project bất kỳ, `cwd` là project của họ (không có `skills/`) → `loadSkill('frontend-design')` trả `null` → `/frontend-design` báo lỗi `frontendDesignNoSkill`. Fix: resolve hai tầng — ưu tiên `<cwd>/skills/<name>/SKILL.md` (cho phép user override skill riêng trong project của họ), fallback `<noob-cli-package>/skills/<name>/SKILL.md` qua `import.meta.url` (built-in luôn đi cùng CLI). `listSkills()` gộp Set hai nguồn để `/help` hiển thị đầy đủ. Smoke test từ `C:\Users\...\Temp` (cwd hoàn toàn khác): `loadSkill('frontend-design')` resolve đúng về package dir, đọc đủ 4440 bytes. Sau bản này, `npm i -g @noobdemon/noob-cli` xong là `/frontend-design` chạy được ngay trên mọi thiết bị, không cần clone repo.
|
|
383
|
+
|
|
384
|
+
---
|
|
385
|
+
|
|
386
|
+
## [1.7.5] - 2026-06-05
|
|
387
|
+
|
|
388
|
+
### Added
|
|
389
|
+
- Slash command `/improve` (alias `/imp`) — bắt model khảo sát workspace (list_dir → đọc README/package.json/noob.md/CHANGELOG → grep TODO/FIXME) rồi viết báo cáo Markdown tiếng Việt: Tóm tắt dự án, Điểm mạnh, 5–10 Gợi ý cải thiện (mỗi cái kèm Vấn đề, Đề xuất, Lợi ích, Công sức S/M/L, Ưu tiên P0/P1/P2), Top P0 nên làm trước. Có thể truyền hint để nhấn mạnh hướng (vd `/improve hiệu năng`). KHÔNG sửa code, KHÔNG ghi noob.md — chỉ phân tích & đề xuất.
|
|
390
|
+
|
|
391
|
+
---
|
|
392
|
+
|
|
393
|
+
## [1.7.4] - 2026-06-04
|
|
394
|
+
|
|
395
|
+
### Fixed
|
|
396
|
+
- `/add-dir <path>` trước đây accept path đúng ở tools layer nhưng model vẫn KHÔNG 'thấy' thư mục mới — triệu chứng: user `/add-dir` xong gõ yêu cầu liên quan, model vẫn bảo 'không có thư mục đó' hoặc bỏ qua. Root cause: `runtimeContext()` trong `src/agent.js` chỉ liệt kê `cwd` vào prompt ENVIRONMENT, không liệt kê extras từ `listRoots()`. Giờ inject thêm dòng `Extra roots cấp quyền qua /add-dir:` + bullet từng path tuyệt đối → model chủ động dùng được ngay sau khi `/add-dir`. Có try/catch fail-safe để không vỡ prompt nếu tools layer lỗi.
|
|
397
|
+
|
|
398
|
+
---
|
|
399
|
+
|
|
400
|
+
## [1.7.3] - 2026-06-04
|
|
401
|
+
|
|
402
|
+
### Added
|
|
403
|
+
- Auto-compact tier 3: khi phiên vượt **240k chars**, noob TỰ ĐỘNG gọi `maybeSummarize(force=true)` ngay trong vòng REPL — không hỏi, không chờ user gõ `/compact`. In báo cáo before/after (vd `✓ Auto-compact: 245k → 38k chars (giảm 84%)`). Mục tiêu: giữ model chạy mượt khi user mải làm việc dài, không để phiên phình mãi gây chậm/lú.
|
|
404
|
+
|
|
405
|
+
### Changed
|
|
406
|
+
- 3 mốc cảnh báo phiên dài giờ rõ ràng: **120k** (nhắc nhẹ 1 lần, dim), **200k–240k** (cảnh báo mạnh mỗi lượt, đỏ), **>240k** (auto-compact, không cần user can thiệp). Mốc 2 cũ in lại mỗi lượt cho đến vô hạn — giờ có trần ở 240k vì auto-compact sẽ xử lý.
|
|
407
|
+
|
|
408
|
+
### Internal
|
|
409
|
+
- Cờ `state._autoCompacting` chống re-entrant: nếu compact đang chạy mà lượt tiếp theo tới trước khi xong, skip không gọi lần 2. Sau auto-compact thành công: reset `_longSessionWarned=false` + `persist()` để session restore không mất ngữ cảnh đã tóm tắt.
|
|
410
|
+
|
|
411
|
+
---
|
|
412
|
+
|
|
413
|
+
## [1.7.2] - 2026-06-04
|
|
414
|
+
|
|
415
|
+
### Fixed
|
|
416
|
+
- `--insecure-tls` flag trước đây không có effect: do ESM hoist `import` nên `applyInsecureTLS()` ở top-level `api.js` chạy TRƯỚC khi argv kịp set `NOOB_INSECURE_TLS=1`. Giờ `bin/noob.js` parse argv xong mới gọi lại `applyInsecureTLS()` → flag thật sự tắt verify TLS như mô tả trong `--help`.
|
|
417
|
+
- `grep` trước chỉ nhận `path` là thư mục, truyền file vào sẽ throw `EISDIR`/không match. Giờ detect `stat.isFile()` → search trực tiếp trên 1 file đó, đỡ phải workaround bằng `path=<dir>` + filter glob.
|
|
418
|
+
- `edit_file` đôi khi báo `Edited` nhưng diff hiển thị lạ / có vẻ không apply: ở Tier 1+2 khi `cand === old_string` match raw, `new_string` được ghi RAW không qua `adapt()` → file CRLF bị inject `\n` rời, line ending mix → git/editor render diff sai lệch → user tưởng "không apply". Giờ luôn `applyExact(cand, adapt(new_string))` bất kể tier, file giữ nguyên line ending nhất quán.
|
|
419
|
+
|
|
420
|
+
### Internal
|
|
421
|
+
- `pushOutputDelta` (token meter realtime) tối ưu O(n²) → O(n) bằng sliding window 256 chars + cut tại whitespace boundary (BPE align tốt → drift < 0.2%). Benchmark: 81k chars / 6.3k chunks giảm từ 30,961ms xuống 333ms (~93× nhanh hơn). Tác động user: status bar tick mỗi 200ms không còn block event loop khi model stream output dài → status mượt, không đứng hình.
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
## [1.7.1] - 2026-06-03
|
|
426
|
+
|
|
427
|
+
### Fixed
|
|
428
|
+
- Token usage không stream realtime trên status bar: `tick()` cũ chỉ in `${label}… ${elapsed}s` nên trong lúc model đang stream, người dùng không thấy số token cộng dồn. Giờ chèn `tokenMeter.format()` vào status (`thinking… 3s · ↑1.2k ↓340 (1.5k)`), cập nhật mỗi 200ms.
|
|
429
|
+
- Nhánh non-chat (`/merge`, `/search`) cũng bị thiếu token trên status — `onStatus` chỉ in label. Đã kèm `tokenMeter.format()` để đồng nhất với chat mode.
|
|
430
|
+
|
|
431
|
+
---
|
|
432
|
+
|
|
433
|
+
## [1.7.0] - 2026-06-03
|
|
434
|
+
|
|
435
|
+
### Fixed
|
|
436
|
+
- Slash command `/agent` và `/tokens` trước đó rơi vào nhánh `default` của switch → in "unknown command". Đã thêm case xử lý đúng: `/agent on|off` (hỗ trợ cả "bật"/"tắt") để bật/tắt agent mode, `/tokens` xem tổng token phiên.
|
|
437
|
+
- Token của sub-agent không được cộng vào tổng phiên (mỗi sub tạo `TokenMeter` riêng → user nhìn `/tokens` thấy thiếu so với quota thực tốn). Giờ sub-agent dùng chung meter của cha.
|
|
438
|
+
|
|
439
|
+
### Changed
|
|
440
|
+
- `runSubAgent` trả về **string sạch** thay vì object `{result, tokens}` → model cha đọc kết quả dễ hơn, không phải parse JSON lồng.
|
|
441
|
+
- `spawn_agents` (song song) gom kết quả thành các block `── sub-agent #N ──` ngăn cách rõ ràng thay vì `JSON.stringify` — dễ đọc cho cả model lẫn người xem log.
|
|
442
|
+
- Log tiến độ sub-agent đổi sang màu tím (`#8b5cf6`) trong scrollback để phân biệt với output của agent cha.
|
|
443
|
+
|
|
444
|
+
### Internal
|
|
445
|
+
- Dispatcher `spawn_agent`/`spawn_agents` chuyển từ `tools.js` sang `repl.js` (vì cần truy cập `model`/`signal`/`abort` của phiên hiện tại). Giữ depth guard `MAX_SUBAGENT_DEPTH = 3` chống đệ quy vô hạn.
|
|
446
|
+
- Khi `agentMode=false`, tool doc `spawn_agent`/`spawn_agents` không được inject vào system prompt — model không thấy, không gọi nhầm.
|
|
447
|
+
|
|
448
|
+
---
|
|
449
|
+
|
|
450
|
+
## [1.6.0] - 2026-06-03
|
|
451
|
+
|
|
452
|
+
### Added
|
|
453
|
+
- **Agent mode** (`/agent on|off`): với task lớn, noob có thể tự chia việc cho nhiều sub-agent — chạy **song song** khi việc độc lập, **tuần tự** khi cần đúng thứ tự, **phân cấp** khi việc phức tạp (sub-agent tự đẻ sub-agent tiếp, tối đa 3 tầng). Mặc định TẮT để giữ nguyên hành vi cũ.
|
|
454
|
+
- **Bộ đếm token realtime**: hiện ngay trên thanh trạng thái khi model đang chạy (`↑input ↓output (total)`). Đếm cục bộ, cập nhật theo từng đoạn stream. Lệnh mới `/tokens` xem tổng phiên.
|
|
455
|
+
- **Bộ nhớ dài hạn cho phiên**: khi hội thoại quá dài, noob tự tóm tắt phần cũ thành bản ghi gọn (mục tiêu, quyết định, file đã đụng, việc dở) thay vì cắt cụt — model không còn quên ngữ cảnh khi làm task dài nhiều giờ. Bản tóm tắt được lưu cùng phiên nên `--resume` vẫn giữ trí nhớ.
|
|
456
|
+
|
|
457
|
+
### Changed
|
|
458
|
+
- Giới hạn số bước tool mỗi lượt nâng lên rất cao (gần như không tự dừng) — task dài cứ chạy tới khi xong. Ctrl+C vẫn ngắt được bất cứ lúc nào; mỗi 100 bước hiển thị mốc tiến độ.
|
|
459
|
+
- **Bộ nhớ dự án (`noob.md`) được model tuân thủ sát hơn**: nâng vị trí lên ngay sau SYSTEM trong prompt (tránh bị bỏ qua khi context dài) và đổi framing thành luật dự án bắt buộc thay vì ghi chú tham khảo. Phần `## Rules` trong noob.md giờ được coi như mở rộng của system prompt; `## Notes` vẫn là quan sát tham khảo.
|
|
460
|
+
|
|
461
|
+
### Internal
|
|
462
|
+
- Thêm dependency `gpt-tokenizer` (~200KB, pure JS) để đếm token cục bộ, không gọi mạng.
|
|
463
|
+
|
|
464
|
+
---
|
|
465
|
+
|
|
466
|
+
## [1.5.5] - 2026-06-03
|
|
467
|
+
|
|
468
|
+
### Added
|
|
469
|
+
- Tự động gửi webhook Discord sau khi `npm publish` thành công (`scripts/notify-discord.js`, hook `postpublish`).
|
|
470
|
+
- File `CHANGELOG.md` này — noob sẽ tự cập nhật entry mới trước mỗi lần publish.
|
|
471
|
+
- Hỗ trợ đọc cấu hình từ `.env` ở project root (parser tối giản, không thêm dependency). Biến đã có trong `process.env` không bị ghi đè.
|
|
472
|
+
- File `.env.example` làm mẫu cấu hình.
|
|
473
|
+
|
|
474
|
+
### Internal
|
|
475
|
+
- `.gitignore` chặn `.env` / `.env.*` (giữ lại `.env.example`).
|
|
476
|
+
- Field `files` của `package.json` đã whitelist nên `.env` và `scripts/` không lọt vào tarball npm publish (đã verify bằng `npm pack --dry-run`).
|