@noobdemon/noob-cli 1.10.1 → 1.10.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@noobdemon/noob-cli",
3
- "version": "1.10.1",
3
+ "version": "1.10.3",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
package/src/agent.js CHANGED
@@ -242,24 +242,6 @@ export function compact(history, budget) {
242
242
  return [...head, elided, ...out.slice(tailStart)];
243
243
  }
244
244
 
245
- // Trích xuất todo items chưa hoàn thành từ history assistant messages.
246
- // Format: `- [ ] task` (unchecked) / `- [x] task` (checked).
247
- // Trả về mảng text của các item chưa check, giữ nguyên thứ tự.
248
- function extractUncheckedTodos(history) {
249
- const todos = [];
250
- for (const m of history) {
251
- if (m.role !== "assistant" || typeof m.content !== "string") continue;
252
- for (const line of m.content.split("\n")) {
253
- const unchecked = line.match(/^[\s]*-\s*\[\s?\]\s+(.+)/);
254
- if (unchecked) todos.push(unchecked[1].trim());
255
- }
256
- }
257
- // Dedupe: giữ item cuối cùng (model có thể repeat todo).
258
- const seen = new Map();
259
- for (const t of todos) seen.set(t, t);
260
- return [...seen.values()];
261
- }
262
-
263
245
  // Bộ nhớ dài hạn cho phiên: khi history phình to, gọi model phụ TÓM TẮT các
264
246
  // lượt cũ thành một message system gọn (giữ quyết định, file đã sửa, lý do,
265
247
  // việc dở) rồi thay phần đầu history bằng tóm tắt đó. Mutates `history` in place.
@@ -509,7 +491,7 @@ function extractJsonObject(s, from) {
509
491
  * @param {(msg:string)=>void} opts.onStatus thinking/streaming status
510
492
  * @returns {Promise<string>} the final assistant answer (no tool block)
511
493
  */
512
- export async function runAgent({ history, model, signal, onTool, onStatus, onDelta, onSteer, tokenMeter, extraToolsDoc, goal, recentSessions }) {
494
+ export async function runAgent({ history, model, signal, onTool, onStatus, onDelta, onSteer, tokenMeter, extraToolsDoc, goal, recentSessions, pendingTasks }) {
513
495
  // [GỠ BUDGET 2026-06-06] Không còn token budget enforcement. Agent/loop/sub-agent
514
496
  // chạy không giới hạn token. Dừng theo: GOAL đạt, <<LOOP_DONE>>, <<ULTRA_DONE>>,
515
497
  // model tự kết thúc reply không có tool block, hoặc user Ctrl+C.
@@ -584,16 +566,15 @@ export async function runAgent({ history, model, signal, onTool, onStatus, onDel
584
566
  });
585
567
 
586
568
  // ── Todo continuation nudge ──────────────────────────────────────────
587
- // Sau mỗi tool result, kiểm tra xem còn todo item nào chưa check không.
588
- // Nếu inject nudge nhắc model TIẾP TỤC, KHÔNG dừng.
569
+ // Sau mỗi tool result, inject nudge nếu còn task chưa xong.
570
+ // Dùng pendingTasks (caller gửi vào) thay parse output của model.
589
571
  {
590
- const unchecked = extractUncheckedTodos(history);
591
- if (unchecked.length > 0) {
592
- const next = unchecked[0];
572
+ const tasks = pendingTasks || [];
573
+ if (tasks.length > 0) {
574
+ const next = tasks[0];
593
575
  history.push({
594
- role: "tool",
595
- name: "todo_nudge",
596
- content: `[TODO] Còn ${unchecked.length} việc chưa xong. Việc tiếp theo: "${next}". HÃY LÀM NGAY — gọi tool (write_file/edit_file/run_command) để hoàn thành việc này. KHÔNG dừng, KHÔNG tóm tắt, KHÔNG hỏi lại.`,
576
+ role: "user",
577
+ content: `[SYSTEM] Việc "${call.name}" đã hoàn thành. Còn ${tasks.length} việc: ${tasks.map((t) => `"${t}"`).join(", ")}. Việc tiếp theo BẮT BUỘC phải làm ngay: "${next}". Gọi tool (write_file/edit_file/run_command) để làm việc này. KHÔNG dừng, KHÔNG tóm tắt.`,
597
578
  });
598
579
  }
599
580
  }
package/src/repl.js CHANGED
@@ -151,13 +151,13 @@ export async function startRepl(opts = {}) {
151
151
  const tokenMeter = new TokenMeter();
152
152
 
153
153
  // Set terminal title bar — hiện trên CMD/PowerShell.
154
+ // session chưa được khai báo ở đây → updateTitle() gọi SAU khi session = null (dòng ~295).
154
155
  const updateTitle = () => {
155
156
  const name = session?.title
156
157
  ? session.title.slice(0, 40) + (session.title.length > 40 ? "…" : "")
157
158
  : state.model.name;
158
159
  process.title = `noob — ${name}`;
159
160
  };
160
- updateTitle();
161
161
 
162
162
  // Prompt = dòng trạng thái sống. Luôn phản ánh yolo + version theo thời gian
163
163
  // thực (vẽ lại mỗi lượt và ngay khi Shift+Tab), nên không cần gõ /status.
@@ -291,6 +291,7 @@ export async function startRepl(opts = {}) {
291
291
 
292
292
  // ── phiên (session): lưu lịch sử + resume giống Claude Code ───────────────
293
293
  let session = null;
294
+ updateTitle(); // gọi lần đầu — state.model đã có, session chưa
294
295
  const persist = () => {
295
296
  if (!session || !state.history.length) return; // đừng lưu phiên rỗng
296
297
  session.history = state.history; // giữ đồng bộ tuyệt đối với history sống
@@ -1314,11 +1315,11 @@ NGUYÊN TẮC:
1314
1315
  signal: abort.signal,
1315
1316
  tokenMeter,
1316
1317
  goal: state.goal,
1317
- // Breadcrumbs: 5 phiên gần nhất CÙNG workspace, trừ phiên hiện tại.
1318
- // Model thấy "đã làm gì" trước đó dù chưa /resume — sửa cảm giác
1319
- // "model không nhớ session" khi user mở phiên mới trong cùng dự án.
1320
1318
  recentSessions: sessions.list(5, process.cwd()).filter((s) => s.id !== session?.id),
1321
1319
  extraToolsDoc: state.agentMode ? spawnAgentToolsDoc(0) : "",
1320
+ // Pending tasks: todo items chưa hoàn thành từ lượt trước → model tiếp tục ngay.
1321
+ pendingTasks: (state.todos || []).filter((t) => !t.done).map((t) => t.text),
1322
+ extraToolsDoc: state.agentMode ? spawnAgentToolsDoc(0) : "",
1322
1323
  onStatus: () => tick(t.thinking),
1323
1324
  onSteer: () => {
1324
1325
  if (!pending.length) return [];