@mrtrinhvn/ag-kit 1.4.12 → 1.5.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.md +10 -0
- package/package.json +1 -1
- package/template/.agent/scripts/memory_mcp_server.py +29 -14
- package/template/.agent/skills/ag-kit-core/SKILL.md +12 -9
- package/template/.agent/skills/clean-code/SKILL.md +12 -0
- package/template/.agent/skills/frontend-design/SKILL.md +6 -0
- package/template/.agent/skills/mcp-builder/SKILL.md +5 -0
- package/template/.agent/skills/memory-architecture/SKILL.md +12 -0
- package/template/.agent/skills/python-patterns/SKILL.md +5 -0
- package/template/.agent/skills/telegram-agentic-gateway/SKILL.md +1 -0
package/README.md
CHANGED
|
@@ -73,6 +73,16 @@ AG-Kit sử dụng kỹ thuật **JSON Introspection** và **Chromium Multiplexi
|
|
|
73
73
|
|
|
74
74
|
---
|
|
75
75
|
|
|
76
|
+
## 🛡️ Zero Context-Contamination (Cách Ly Ruy Băng Phiên Bản 1.5.0+)
|
|
77
|
+
|
|
78
|
+
**AG-Kit 1.5.0 đánh dấu kỷ nguyên Kiến trúc Phân Tán (Federated Architecture)**, chặn đứng hoàn toàn hiện tượng AI râu ông nọ cắm cằm bà kia:
|
|
79
|
+
|
|
80
|
+
1. **MCP Memory Sandbox:** Mọi truy vấn Lưu/Ra-Đa Ký Ức đều bị ép khóa vào cờ `workspace_path`. Không bao giờ có chuyện AI tiêm nhầm dữ liệu chứng khoán vào dự án quản trị nhân sự.
|
|
81
|
+
2. **Process Lifecycle Shield:** Xóa bỏ bộ Lock PID truyền thống tại thư mục chung `/tmp`. AG-Kit v1.5 thiết lập cơ chế tự dọn rác Bóng Ma Task (Ghost Session) dựa trên sự kiện `lifespan` FastAPI / Node, giúp Bot chống sập trong môi trường Docker Container.
|
|
82
|
+
3. **Identity Shifting (Thuật Biến Hình):** Agent sử dụng AG-Kit có khả năng soi mã nguồn Xuyên Dự Án (Cross-Project Vision) để học lỏm mẫu thiết kế. Nhưng khi đóng góp code/trí nhớ cho nhà hàng xóm, Bot sẽ tự động **nhập gia tùy tục** và dùng chính ngôn ngữ của dự án đó!
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
76
86
|
## 🔄 Cập nhật & Bảo trì
|
|
77
87
|
|
|
78
88
|
Chúng tôi liên tục nâng cấp kỹ năng cho Agent (Skills, Workflows). Để bộ não dự án của bạn luôn thông minh nhất:
|
package/package.json
CHANGED
|
@@ -66,6 +66,11 @@ def cosine_similarity(v1: bytes, v2: bytes) -> float:
|
|
|
66
66
|
|
|
67
67
|
|
|
68
68
|
# ─── DB ────────────────────────────────────────────────────────────────────
|
|
69
|
+
def resolve_db_path(args: dict, fallback_db: Path) -> Path:
|
|
70
|
+
workspace_path = args.get("workspace_path")
|
|
71
|
+
if workspace_path:
|
|
72
|
+
return Path(workspace_path) / ".agent" / "memory" / "graph.db"
|
|
73
|
+
return fallback_db
|
|
69
74
|
|
|
70
75
|
def get_db(db_path: Path) -> sqlite3.Connection:
|
|
71
76
|
db_path.parent.mkdir(parents=True, exist_ok=True)
|
|
@@ -110,7 +115,8 @@ def _ensure_schema(conn):
|
|
|
110
115
|
|
|
111
116
|
# ─── Tool Implementations ──────────────────────────────────────────────────
|
|
112
117
|
|
|
113
|
-
def tool_memory_save(args: dict,
|
|
118
|
+
def tool_memory_save(args: dict, fallback_db: Path) -> str:
|
|
119
|
+
db = resolve_db_path(args, fallback_db)
|
|
114
120
|
content = args.get("content", "").strip()
|
|
115
121
|
if not content: return "❌ content is required"
|
|
116
122
|
category = args.get("category", "general")
|
|
@@ -131,7 +137,8 @@ def tool_memory_save(args: dict, db: Path) -> str:
|
|
|
131
137
|
return f"✅ {emb_status} Saved hot node #{cur.lastrowid} [{category}]: {content[:80]}"
|
|
132
138
|
|
|
133
139
|
|
|
134
|
-
def tool_memory_search(args: dict,
|
|
140
|
+
def tool_memory_search(args: dict, fallback_db: Path) -> str:
|
|
141
|
+
db = resolve_db_path(args, fallback_db)
|
|
135
142
|
keyword = args.get("keyword", "").strip()
|
|
136
143
|
if not keyword: return "❌ keyword is required"
|
|
137
144
|
tier = args.get("tier")
|
|
@@ -186,7 +193,8 @@ def tool_memory_search(args: dict, db: Path) -> str:
|
|
|
186
193
|
return "\n".join(lines)
|
|
187
194
|
|
|
188
195
|
|
|
189
|
-
def tool_memory_link(args: dict,
|
|
196
|
+
def tool_memory_link(args: dict, fallback_db: Path) -> str:
|
|
197
|
+
db = resolve_db_path(args, fallback_db)
|
|
190
198
|
from_id = args.get("from_id")
|
|
191
199
|
to_id = args.get("to_id")
|
|
192
200
|
relation = args.get("relation", "related_to")
|
|
@@ -207,7 +215,8 @@ def tool_memory_link(args: dict, db: Path) -> str:
|
|
|
207
215
|
return f"🔗 #{from_id} --[{relation}]--> #{to_id}\n From: {a['content'][:60]}\n To: {b['content'][:60]}"
|
|
208
216
|
|
|
209
217
|
|
|
210
|
-
def tool_memory_graph(args: dict,
|
|
218
|
+
def tool_memory_graph(args: dict, fallback_db: Path) -> str:
|
|
219
|
+
db = resolve_db_path(args, fallback_db)
|
|
211
220
|
node_id = args.get("node_id")
|
|
212
221
|
if not node_id: return "❌ node_id is required"
|
|
213
222
|
conn = get_db(db)
|
|
@@ -229,7 +238,8 @@ def tool_memory_graph(args: dict, db: Path) -> str:
|
|
|
229
238
|
return "\n".join(out)
|
|
230
239
|
|
|
231
240
|
|
|
232
|
-
def tool_memory_hot(args: dict,
|
|
241
|
+
def tool_memory_hot(args: dict, fallback_db: Path) -> str:
|
|
242
|
+
db = resolve_db_path(args, fallback_db)
|
|
233
243
|
limit = int(args.get("limit", 10))
|
|
234
244
|
conn = get_db(db)
|
|
235
245
|
rows = conn.execute(
|
|
@@ -245,7 +255,8 @@ def tool_memory_hot(args: dict, db: Path) -> str:
|
|
|
245
255
|
return "\n".join(lines)
|
|
246
256
|
|
|
247
257
|
|
|
248
|
-
def tool_memory_cold(args: dict,
|
|
258
|
+
def tool_memory_cold(args: dict, fallback_db: Path) -> str:
|
|
259
|
+
db = resolve_db_path(args, fallback_db)
|
|
249
260
|
limit = int(args.get("limit", 10))
|
|
250
261
|
conn = get_db(db)
|
|
251
262
|
rows = conn.execute(
|
|
@@ -262,7 +273,8 @@ def tool_memory_cold(args: dict, db: Path) -> str:
|
|
|
262
273
|
return "\n".join(lines)
|
|
263
274
|
|
|
264
275
|
|
|
265
|
-
def tool_memory_consolidate(args: dict,
|
|
276
|
+
def tool_memory_consolidate(args: dict, fallback_db: Path) -> str:
|
|
277
|
+
db = resolve_db_path(args, fallback_db)
|
|
266
278
|
days = int(args.get("days", 7))
|
|
267
279
|
category = args.get("category")
|
|
268
280
|
threshold = (datetime.now() - timedelta(days=days)).isoformat()
|
|
@@ -307,7 +319,8 @@ def tool_memory_consolidate(args: dict, db: Path) -> str:
|
|
|
307
319
|
return "\n".join(results) + f"\n\n✅ Done. Summary vectors calculated."
|
|
308
320
|
|
|
309
321
|
|
|
310
|
-
def tool_memory_status(args: dict,
|
|
322
|
+
def tool_memory_status(args: dict, fallback_db: Path) -> str:
|
|
323
|
+
db = resolve_db_path(args, fallback_db)
|
|
311
324
|
conn = get_db(db)
|
|
312
325
|
total = conn.execute("SELECT COUNT(*) FROM nodes").fetchone()[0]
|
|
313
326
|
hot = conn.execute("SELECT COUNT(*) FROM nodes WHERE tier='hot'").fetchone()[0]
|
|
@@ -334,6 +347,7 @@ TOOLS = {
|
|
|
334
347
|
"inputSchema": {
|
|
335
348
|
"type": "object",
|
|
336
349
|
"properties": {
|
|
350
|
+
"workspace_path": {"type": "string", "description": "Local workspace root path to avoid cross-project contamination"},
|
|
337
351
|
"content": {"type": "string", "description": "The knowledge to save"},
|
|
338
352
|
"category": {"type": "string", "enum": list(VALID_CATEGORIES), "description": "Category of knowledge"}
|
|
339
353
|
},
|
|
@@ -345,6 +359,7 @@ TOOLS = {
|
|
|
345
359
|
"inputSchema": {
|
|
346
360
|
"type": "object",
|
|
347
361
|
"properties": {
|
|
362
|
+
"workspace_path": {"type": "string", "description": "Local workspace root path"},
|
|
348
363
|
"keyword": {"type": "string", "description": "Keyword to search"},
|
|
349
364
|
"tier": {"type": "string", "enum": ["hot", "cold"], "description": "Search only in hot or cold tier"},
|
|
350
365
|
"limit": {"type": "integer", "description": "Max results (default 8)"}
|
|
@@ -354,13 +369,13 @@ TOOLS = {
|
|
|
354
369
|
},
|
|
355
370
|
"memory_link": {
|
|
356
371
|
"description": "Create a relationship (edge) between two memory nodes.",
|
|
357
|
-
"inputSchema": {"type": "object", "properties": {"from_id": {"type": "integer"}, "to_id": {"type": "integer"}, "relation": {"type": "string"}}, "required": ["from_id", "to_id"]}
|
|
372
|
+
"inputSchema": {"type": "object", "properties": {"workspace_path": {"type": "string"}, "from_id": {"type": "integer"}, "to_id": {"type": "integer"}, "relation": {"type": "string"}}, "required": ["from_id", "to_id"]}
|
|
358
373
|
},
|
|
359
|
-
"memory_graph": {"description": "Show all edges (incoming and outgoing) for a node.", "inputSchema": {"type": "object", "properties": {"node_id": {"type": "integer"}}, "required": ["node_id"]}},
|
|
360
|
-
"memory_hot": {"description": "List hot (working memory) nodes.", "inputSchema": {"type": "object", "properties": {"limit": {"type": "integer"}}}},
|
|
361
|
-
"memory_cold": {"description": "List cold (consolidated long-term memory) nodes.", "inputSchema": {"type": "object", "properties": {"limit": {"type": "integer"}}}},
|
|
362
|
-
"memory_consolidate": {"description": "Merge old hot nodes into cold consolidated summaries.", "inputSchema": {"type": "object", "properties": {"days": {"type": "integer"}, "category": {"type": "string"}}}},
|
|
363
|
-
"memory_status": {"description": "Show memory graph statistics.", "inputSchema": {"type": "object", "properties": {}}}
|
|
374
|
+
"memory_graph": {"description": "Show all edges (incoming and outgoing) for a node.", "inputSchema": {"type": "object", "properties": {"workspace_path": {"type": "string"}, "node_id": {"type": "integer"}}, "required": ["node_id"]}},
|
|
375
|
+
"memory_hot": {"description": "List hot (working memory) nodes.", "inputSchema": {"type": "object", "properties": {"workspace_path": {"type": "string"}, "limit": {"type": "integer"}}}},
|
|
376
|
+
"memory_cold": {"description": "List cold (consolidated long-term memory) nodes.", "inputSchema": {"type": "object", "properties": {"workspace_path": {"type": "string"}, "limit": {"type": "integer"}}}},
|
|
377
|
+
"memory_consolidate": {"description": "Merge old hot nodes into cold consolidated summaries.", "inputSchema": {"type": "object", "properties": {"workspace_path": {"type": "string"}, "days": {"type": "integer"}, "category": {"type": "string"}}}},
|
|
378
|
+
"memory_status": {"description": "Show memory graph statistics.", "inputSchema": {"type": "object", "properties": {"workspace_path": {"type": "string"}}}}
|
|
364
379
|
}
|
|
365
380
|
|
|
366
381
|
TOOL_FNS = {
|
|
@@ -101,18 +101,20 @@ Server `ag-kit-memory` được đăng ký sẵn trong `~/.gemini/antigravity/mc
|
|
|
101
101
|
|
|
102
102
|
| Tool | Khi nào gọi |
|
|
103
103
|
|---|---|
|
|
104
|
-
| `memory_search(keyword)` | **TRƯỚC** khi bắt đầu bất kỳ task nào — kiểm tra context cũ |
|
|
105
|
-
| `memory_save(content, category)` | **SAU** khi fix bug, ra quyết định, học được điều mới |
|
|
106
|
-
| `memory_link(from, to, relation)` | Khi phát hiện 2 kiến thức có quan hệ |
|
|
107
|
-
| `memory_consolidate(days=7)` | Hàng tuần: gộp hot → cold summaries |
|
|
108
|
-
| `memory_status()` | Kiểm tra sức khỏe của bộ não |
|
|
104
|
+
| `memory_search(keyword, workspace_path)` | **TRƯỚC** khi bắt đầu bất kỳ task nào — kiểm tra context cũ |
|
|
105
|
+
| `memory_save(content, category, workspace_path)` | **SAU** khi fix bug, ra quyết định, học được điều mới |
|
|
106
|
+
| `memory_link(from, to, relation, workspace_path)` | Khi phát hiện 2 kiến thức có quan hệ |
|
|
107
|
+
| `memory_consolidate(days=7, workspace_path)` | Hàng tuần: gộp hot → cold summaries |
|
|
108
|
+
| `memory_status(workspace_path)` | Kiểm tra sức khỏe của bộ não |
|
|
109
|
+
|
|
110
|
+
> **⚠️ QUAN TRỌNG VỀ ISO-WORKSPACE (MANDATORY)**: Tất cả các tool của `ag-kit-memory` BẮT BUỘC phải nhận tham số `workspace_path` là đường dẫn gốc CWD hiện tại của dự án (VD: `/home/tao/Projects/chungkhoan`). Nếu không truyền, MCP sẽ ghi đè database hoặc đọc sai ký ức của dự án khác gây thảm họa ô nhiễm dữ liệu!
|
|
109
111
|
|
|
110
112
|
```
|
|
111
113
|
Workflow đúng:
|
|
112
|
-
1. Bắt đầu task → memory_search("topic") → đọc context cũ
|
|
114
|
+
1. Bắt đầu task → memory_search("topic", workspace_path="/...") → đọc context cũ
|
|
113
115
|
2. Làm việc...
|
|
114
|
-
3. Xong task → memory_save("
|
|
115
|
-
4. Hàng tuần → memory_consolidate(
|
|
116
|
+
3. Xong task → memory_save(content="...", workspace_path="/...")
|
|
117
|
+
4. Hàng tuần → memory_consolidate(workspace_path="/...")
|
|
116
118
|
```
|
|
117
119
|
|
|
118
120
|
|
|
@@ -134,7 +136,8 @@ Hãy khắc cốt ghi tâm quy tắc: `IDE_PORT` (Nhận lệnh AI - ví dụ: 9
|
|
|
134
136
|
3. Nếu cần đi sâu hơn: dùng `vfs <project_root>/src` hoặc `memory_tool.py search`.
|
|
135
137
|
4. **CẤM** scan toàn bộ thư mục project khác khi chưa đọc `summary.md` trước.
|
|
136
138
|
- **Cấm ô nhiễm (No Leakage):** Tuyệt đối không ghi chép các từ khóa chuyên biệt (B1, B2, Sentinel, DNSE...) vào các file Skill dùng chung.
|
|
137
|
-
- **
|
|
139
|
+
- **Thuật Biến Hình (Identity Shifting - Nhập Gia Tùy Tục):** Khi Sếp giao phó điều hướng bạn sang thao tác hoặc sửa lỗi ở một Dự Án X (trong khi bạn đang ở máy chủ Dự Án Y), **thì ngay giây phút bạn đặt chân sang thư mục nhà X, bạn PHẢI tự coi mình chính là Agent của nhà X!**
|
|
140
|
+
- *Hành động:* Bạn nắm toàn quyền và **CÓ TRÁCH NHIỆM BẮT BUỘC** ghi chú những bài học, fix bug, và pattern trực tiếp vào cuốn sổ `.agent/knowledge/` hoặc gọi `memory_save(workspace_path="/home/tao/Projects/Dự_Án_X")` của chính nhà đó, bằng chính đặc thù ngôn ngữ của Dự Án đó (Ví dụ sang ceogravity thì cứ thoải mái gõ chữ B1, B2)! Đừng chỉ để lại lời nhắn như người dưng, hãy hành xử như một người quản gia thực thụ của bất kỳ dự án nào bạn được đưa tới. Mọi giá trị tri thức phải được gửi gắm chính xác vào Local Context của nơi nó nảy mầm.
|
|
138
141
|
|
|
139
142
|
---
|
|
140
143
|
|
|
@@ -60,6 +60,18 @@ priority: CRITICAL
|
|
|
60
60
|
|
|
61
61
|
---
|
|
62
62
|
|
|
63
|
+
## State & Process Management Rules (MANDATORY)
|
|
64
|
+
|
|
65
|
+
Để đảm bảo hệ thống không bị mắc kẹt (Ghost Sessions) khi các Service chạy trong Docker hoặc bị Reboot Host, mọi Agent **BẮT BUỘC** phải tuân thủ nghiêm ngặt 3 quy tắc sau khi viết các Background Tasks/Queues:
|
|
66
|
+
|
|
67
|
+
| 🚨 Rule Nhiễm Độc | ✅ Giải pháp Chuẩn mực |
|
|
68
|
+
|---|---|
|
|
69
|
+
| Dùng `os.kill(pid, 0)` để kiểm tra Task còn sống | **CẤM!** PID của Docker luôn reset về thấp (VD: 1, 8), vòng lặp PID sẽ gây ra "Ghost Session". Đổi sang dùng timeout check. |
|
|
70
|
+
| Lưu File Lock/PID ở `Root /tmp/` | **RỦI RO XUNG ĐỘT!** Các dự án chạy chung 1 VPS sẽ chọc nhầm PID của nhau. Bắt buộc lưu vào ranh giới nội bộ: `.agent/run/` |
|
|
71
|
+
| Quên làm sạch Database Trạng thái khi Server boot | **THẢM HỌA UI!** Task đang chạy dở mà Host sập, khi khởi động lại cờ `is_running` vẫn kẹt `true`. BẮT BUỘC phải cấy hàm `reset_all_ghost_sessions()` vào sự kiện `lifespan` lúc FastAPI/Node Server khởi chạy. |
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
63
75
|
## AI Coding Style
|
|
64
76
|
|
|
65
77
|
| Situation | Action |
|
|
@@ -340,6 +340,12 @@ For animation patterns: [animation-guide.md](animation-guide.md), for advanced:
|
|
|
340
340
|
- **Same layout structure / Vercel clone**
|
|
341
341
|
- **Not asking user preferences**
|
|
342
342
|
|
|
343
|
+
### ❌ Front-end Performance Anti-Patterns
|
|
344
|
+
|
|
345
|
+
- **Thảm họa Polling bằng `setInterval`**: Khi Fetch API liên tục, nếu mạng chậm, các request sẽ bị kẹt dồn ứ gây ra lỗi `ERR_INSUFFICIENT_RESOURCES` sập Browser Socket. **MANDATORY**: Thay vì `setInterval`, phải dùng đệ quy `setTimeout` (Chờ request Promise A hoàn tất thì mới trigger request B).
|
|
346
|
+
- Chèn trực tiếp quá nhiều thư viện nặng vào Bundle thay vì Lazy Load.
|
|
347
|
+
- Không có cơ chế Debounce/Throttle cho các thẻ Input Search.
|
|
348
|
+
|
|
343
349
|
### ❌ Dark Patterns (Unethical)
|
|
344
350
|
|
|
345
351
|
- Hidden costs
|
|
@@ -147,6 +147,11 @@ my-mcp-server/
|
|
|
147
147
|
| args | Command arguments |
|
|
148
148
|
| env | Environment variables |
|
|
149
149
|
|
|
150
|
+
### ⚠️ Database Context Mismatch (Global vs Local)
|
|
151
|
+
Khi thiết kế MCP lưu trữ dữ liệu State hoặc Vector DB, phải lường trước tình huống MCP chạy ở tư cách Global (ví dụ cài qua `npm install -g` hoặc qua Claude Desktop) nhưng System Client chạy ở Local project.
|
|
152
|
+
- **Rủi ro:** Lỗi "Lạc đường CSDL". MCP sẽ ghi cứng data vào biến Workspace lúc nó được start (Vd: ghi đè Database dự án A trong khi User đang thao tác bên dự án B).
|
|
153
|
+
- **Giải pháp:** Server MCP cần có khả năng linh hoạt đọc `cwd` (current working directory) của Client đang tương tác, hoặc nhận đường dẫn Database rõ ràng thông qua Argument Input của Tool để chắc chắn dữ liệu được tiêm đúng vào **Local Context** của User.
|
|
154
|
+
|
|
150
155
|
---
|
|
151
156
|
|
|
152
157
|
## 9. Testing
|
|
@@ -105,3 +105,15 @@ Khi bạn (AI) nhận thức được mình đang ở trong một dự án đã
|
|
|
105
105
|
|
|
106
106
|
Bằng giao thức này, kiến thức của dự án sẽ KHÔNG BAO GIỜ bị đứt gãy sau khi cập nhật kiến trúc. Mọi ký ức quá khứ sẽ tự động "tiến hóa" thành dạng Đồ thị tương lai!
|
|
107
107
|
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## 8. Công cụ Gỡ Rối Định Tuyến (Brain Debugging CLI)
|
|
111
|
+
|
|
112
|
+
Trong quá trình bảo trì trí nhớ (ví dụ: cần truy vấn SQL trực tiếp để tìm kiếm Vector, xóa các Node bị kẹt bằng tay gốc rễ), bạn hoặc User **BẮT BUỘC** phải cài đặt công cụ CLI `sqlite3` trên môi trường Terminal.
|
|
113
|
+
|
|
114
|
+
Lỗi **"Command 'sqlite3' not found"** là nguyên nhân số một khiến AI Agent hoặc Developer không thể thâm nhập sâu vào file `graph.db` để debug cục bộ.
|
|
115
|
+
- **Trên Ubuntu/Debian:** Yêu cầu User chạy `sudo apt install sqlite3 -y`
|
|
116
|
+
- **Trên Mac (Homebrew):** Yêu cầu User chạy `brew install sqlite`
|
|
117
|
+
- **Trên Windows:** Cài đặt thông qua Winget hoặc tải Binaries.
|
|
118
|
+
|
|
119
|
+
> **Trách nhiệm của AI:** Trước khi chạy các kịch bản python hoặc bash để truy vấn `.agent/memory/graph.db`, hãy kiểm tra xem `sqlite3` có tồn tại trên Host không. Nếu không, hãy thông báo ngay cho User để cài đặt công cụ tối thượng này! Mọi sự cố thiếu `sqlite3` không thuộc về bộ não AG-Kit mà là lỗi thiếu Dependencies môi trường.
|
|
@@ -337,6 +337,11 @@ Celery/ARQ:
|
|
|
337
337
|
└── Complex workflows
|
|
338
338
|
```
|
|
339
339
|
|
|
340
|
+
### ⚠️ Docker Ghost Session Warning
|
|
341
|
+
Khi thiết kế ứng dụng có Background task tracking lưu trữ State (VD: vào file/JSON hoặc SQLite) với cờ `is_running: true`.
|
|
342
|
+
**TUYỆT ĐỐI KHÔNG** phụ thuộc hoàn toàn vào check Process ID `os.kill(pid, 0)` để xác định tiến trình còn sống hay không. Trong Docker container khi restart, hệ điều hành reset PID về thấp (VD: cấp lại PID 1, 8), kiến `os.kill` quét nhầm và gây ra kẹt trạng thái **Ghost Session**.
|
|
343
|
+
**Giải pháp kiến trúc**: Gắn cơ chế ép dọn dẹp trạng thái `force_reset_all()` vào ngay `lifespan` hoặc `startup` event của FastAPI để triệt tiêu các bóng ma trước khi API online.
|
|
344
|
+
|
|
340
345
|
---
|
|
341
346
|
|
|
342
347
|
## 8. Error Handling Principles
|
|
@@ -86,6 +86,7 @@ Khi triển khai, hãy hướng dẫn User:
|
|
|
86
86
|
- **Tuyệt đối KHÔNG hardcode cổng cố định (như 9555).** Hạ tầng phải hỗ trợ Scale (sinh nhiều Agent song song).
|
|
87
87
|
- Hãy cấp một dải khoảng 100 cổng (Ví dụ: `9555-9655`).
|
|
88
88
|
- Script khởi động (`start.sh`) phải có logic tự dò cổng nào đang trống trong dải 100 cổng này $\rightarrow$ Gán cho tiến trình Antigravity IDE $\rightarrow$ Cập nhật `.env` (`IDE_PORT=95xx`) $\rightarrow$ Kẻ điều phối (Node.js) đọc file `.env` để kết nối vào đúng IDE đó.
|
|
89
|
+
- ⚠️ **Lưu ý Networking (Docker vs Host):** Nếu Kẻ điều phối (Gateway) chạy trực tiếp trên Host (qua Node.js) sử dụng Port `9656`, còn Hệ thống Lõi xử lý NLP (Python, Backend) chạy bên trong Docker Container, thì Hệ thống Lõi KHÔNG THỂ gọi ngược ra Gateway bằng `127.0.0.1` hay `localhost`. Bắt buộc phải cấu hình biến môi trường kết nối trỏ tới **IP Bridge của Docker** (thường là `172.17.0.1` trên Linux hoặc `host.docker.internal` trên Mac/Windows). VD: `GATEWAY_URL=http://172.17.0.1:9656`. Mặc định gọi localhost sẽ văng lỗi `Connection Refused` hoặc `Failed to fetch`.
|
|
89
90
|
5. **Độc Lập Tên Gọi (Project-Agnostic Naming)**:
|
|
90
91
|
- Các file script điều phối (`receptionist_up.sh`, `receptionist_down.sh`...) **TUYỆT ĐỐI KHÔNG ĐƯỢC MANG TÊN DỰ ÁN CỤ THỂ** (Ví dụ cấm gõ cứng: `Waking up CEOgravity Bot` hay `.ceogravity_bot.pid`).
|
|
91
92
|
- Phải sử dụng danh xưng danh chuẩn mực là **"AG Gateway Bot"** và các file tracking trung lập (Vd: `.ag_gateway_bot.pid`). Điều này là bắt buộc để biến hệ sinh thái `.agent/` thành một Template hoàn hảo có thể bưng thả (White-label) vào bất kỳ dự án nào (NextJS, Python, Rust...) mà không bị ô nhiễm tên dự án cũ.
|