@mrtrinhvn/ag-kit 1.4.12 → 1.5.2
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/bin/cli.js +18 -6
- package/package.json +2 -2
- package/template/.agent/knowledge/artifacts/claude-code-system-prompt.md +1490 -0
- package/template/.agent/scripts/brain_builder.py +25 -10
- package/template/.agent/scripts/memory_mcp_server.py +29 -14
- package/template/.agent/skills/ag-kit-core/SKILL.md +35 -11
- package/template/.agent/skills/clean-code/SKILL.md +12 -0
- package/template/.agent/skills/frontend-design/SKILL.md +6 -0
- package/template/.agent/skills/knowledge-management/SKILL.md +5 -3
- package/template/.agent/skills/mcp-builder/SKILL.md +5 -0
- package/template/.agent/skills/memory-architecture/SKILL.md +31 -0
- package/template/.agent/skills/python-patterns/SKILL.md +5 -0
- package/template/.agent/skills/telegram-agentic-gateway/SKILL.md +1 -0
|
@@ -88,18 +88,33 @@ def get_tech_stack(root: Path) -> list[str]:
|
|
|
88
88
|
|
|
89
89
|
def get_memory_nodes(root: Path, limit=8) -> list[str]:
|
|
90
90
|
db_path = root / ".agent" / "memory" / "graph.db"
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
nodes = []
|
|
92
|
+
if db_path.exists():
|
|
93
|
+
try:
|
|
94
|
+
conn = sqlite3.connect(str(db_path))
|
|
95
|
+
rows = conn.execute(
|
|
96
|
+
"SELECT content, category FROM nodes ORDER BY energy DESC, updated_at DESC LIMIT ?",
|
|
97
|
+
(limit,)
|
|
98
|
+
).fetchall()
|
|
99
|
+
conn.close()
|
|
100
|
+
nodes = [f"[{r[1]}] {r[0][:120]}" for r in rows]
|
|
101
|
+
except Exception:
|
|
102
|
+
pass
|
|
103
|
+
|
|
104
|
+
# Tự động hút thành tựu (Trò trống) từ Git Log để AI Không bao giờ quên!
|
|
105
|
+
import subprocess
|
|
93
106
|
try:
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
return [f"[{r[1]}] {r[0][:120]}" for r in rows]
|
|
107
|
+
git_log = subprocess.run(
|
|
108
|
+
["git", "log", "-n", "3", "--pretty=format:- %s (%cr)"],
|
|
109
|
+
cwd=str(root), capture_output=True, text=True, timeout=5
|
|
110
|
+
)
|
|
111
|
+
if git_log.stdout:
|
|
112
|
+
nodes.insert(0, "\n**[Auto-Git-Memory] Thành tựu gần nhất:**\n" + git_log.stdout + "\n")
|
|
101
113
|
except Exception:
|
|
102
|
-
|
|
114
|
+
pass
|
|
115
|
+
|
|
116
|
+
return nodes
|
|
117
|
+
|
|
103
118
|
|
|
104
119
|
|
|
105
120
|
def get_knowledge_summary(root: Path) -> str:
|
|
@@ -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,25 +101,37 @@ 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
|
|
|
119
121
|
---
|
|
120
122
|
|
|
121
|
-
## 4. 🔗 THE DUO-CORE (Kiến Trúc Multi-Tenant
|
|
122
|
-
Hãy khắc cốt ghi tâm quy tắc
|
|
123
|
+
## 4. 🔗 THE DUO-CORE (Kiến Trúc Multi-Tenant & Dual-Port Cơ Sở)
|
|
124
|
+
Hãy khắc cốt ghi tâm quy tắc phân bổ cổng dịch vụ: `IDE_PORT` (Nhận lệnh AI - ví dụ: 9555) và bước nhảy 101 để sinh ra `BRIDGE_PORT` (Portal Bridge Server - ví dụ: 9656). Không bao giờ được phép gán phần kết nối IDE và phần Broadcast UI vào cùng 1 cổng.
|
|
125
|
+
|
|
126
|
+
### 4.1. Sự khác biệt kiến trúc: Headless LSP vs CDP UI
|
|
127
|
+
Mọi ứng dụng thuộc quyền quản trị của AG-KIT bắt buộc phải thẩm thấu sức mạnh của chiến thuật **Dual-Port Strategy**:
|
|
128
|
+
1. **Trục xương sống (Headless LSP / DeckServer)**: Dùng cho các luồng giao tiếp AI nền ngầm định tuyến (ví dụ gọi hàm `lsGateway.startCascade()`). Đặc điểm nhận dạng:
|
|
129
|
+
- Truyền tải thông điệp siêu tốc qua RPC/Sockets mà không cần vẽ lên màn hình IDE Chat.
|
|
130
|
+
- Tránh 100% tỷ lệ xuất hiện lỗi rác (Visual Hallucination) do việc đọc màn hình dính các chữ "Generating...", "Planning...".
|
|
131
|
+
- **Sự liên kết với AG_LITE HUD**: Luồng Headless này KHÔNG có nghĩa là HUD bị mất tác dụng. Việc User chọn Model (như Gemini 1.5, hay Claude 3.5) trên HUD AG_ELITE vẫn sẽ định đoạt cái "não" nào sẽ được dùng để xử lý cái Headless Cascade đó ở hậu trường!
|
|
132
|
+
2. **Xúc tu Tương tác Cơ học (CDP - Chrome DevTools Protocol)**:
|
|
133
|
+
- KHÔNG được lạm dụng để truyền lệnh ngầm thuần túy (Text Generation) nếu API Headless LSP đã có thể đáp ứng.
|
|
134
|
+
- CHỈ ĐƯỢC DÙNG khi AI bắt buộc phải tác động trực quan (Ví dụ: Click UI web, inject bảng điều khiển HUD bằng script lơ lửng, kéo cuộn trang web (scroll), hoặc trích xuất (scrape) trạng thái hình ảnh DOM Canvas).
|
|
123
135
|
|
|
124
136
|
---
|
|
125
137
|
|
|
@@ -134,7 +146,8 @@ Hãy khắc cốt ghi tâm quy tắc: `IDE_PORT` (Nhận lệnh AI - ví dụ: 9
|
|
|
134
146
|
3. Nếu cần đi sâu hơn: dùng `vfs <project_root>/src` hoặc `memory_tool.py search`.
|
|
135
147
|
4. **CẤM** scan toàn bộ thư mục project khác khi chưa đọc `summary.md` trước.
|
|
136
148
|
- **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
|
-
- **
|
|
149
|
+
- **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!**
|
|
150
|
+
- *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
151
|
|
|
139
152
|
---
|
|
140
153
|
|
|
@@ -152,3 +165,14 @@ Hệ sinh thái `ag-kit` được cung cấp sức mạnh cài đặt và cập
|
|
|
152
165
|
2. **Trạm Khởi Tạo Tốc Độ Cao (create-ag-kit):**
|
|
153
166
|
- Lệnh chính: `npx create-ag-kit`
|
|
154
167
|
- *=> Dùng 1 Lần Đầu Tiên: Giống như create-react-app, đây là hạt giống cấy ghép nhanh toàn bộ thư mục `.agent/` và sinh ra `package.json` trống để tạo hẳn một dự án Bot hoàn toàn mới nằm cạnh nhau.*
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## 7. 🧬 CLAUDE CODE AGENTIC PROTOCOL (MANDATORY)
|
|
172
|
+
Dự án này đã cấy ghép MÃ GEN Tư Duy của Claude Code (v2.1.50). Tuy nhiên, để đảm bảo tính Đa Dạng Nhân Cách (Trader vs Coder), luật này chạy theo Cơ chế Phân Luồng:
|
|
173
|
+
- **Ngữ cảnh Kích hoạt:** CHỈ áp dụng các luật dưới đây nếu User yêu cầu "Sửa code, fix bug, viết tính năng mới, /agent, /code". Nếu User hỏi phân tích dữ liệu trade, phân tích thị trường, Hãy trả lời thẳng mạch lạc như bình thường!
|
|
174
|
+
- **Khi đã ở chế độ Kích hoạt (Agent Mode), PHẢI rập khuôn 3 điều luật sau:**
|
|
175
|
+
|
|
176
|
+
1. **LUẬT LẬP KẾ HOẠCH (TodoWrite - Thinking Before Acting):** KHÔNG BAO GIỜ đâm đầu vào code ngay lập tức khi gặp Request lớn. Hành động ĐẦU TIÊN CỦA BẠN phải là sử dụng tính năng Planning (hoặc TodoWrite) để chẻ nhỏ Task thành Checklist `[ ]`. Suy nghĩ như Kỹ Sư Trưởng, sau đó mới dùng công cụ Replace Code.
|
|
177
|
+
2. **LUẬT SỬ DỤNG TOOL (Anti-Bash Spam):** Khi đọc và trích xuất mã nguồn thư mục lớn, BẮT BUỘC dùng các công cụ thông minh (Grep, VFS, ReadFile chuyên dụng). CẤM lạm dụng Bash/Shell thô sơ (như `cat`, `head`, `find`) để duyệt file vì lãng phí Token Context VRAM trầm trọng. Chỉ dùng Bash để chạy Build hoặc Python test.
|
|
178
|
+
3. **LUẬT DỪNG HỎI (EnterPlanMode):** Nếu Request liên quan đến thay đổi kiến trúc, Database, hoặc các quyết định cấu trúc thư mục, BẠN PHẢI DỪNG HOẠT ĐỘNG (Pause Execution) và Báo cáo Sếp bằng `implementation_plan.md`. Cấm hành vi "Cầm đèn chạy trước ô tô".
|
|
@@ -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
|
|
@@ -14,9 +14,11 @@ allowed-tools: Read, Write, Glob, Grep
|
|
|
14
14
|
|
|
15
15
|
**PRINCIPLE:** Never rely on assumptions or ephemeral conversation memory for project characteristics. Store them permanently.
|
|
16
16
|
|
|
17
|
-
### Mandatory Read Before Action
|
|
18
|
-
Before interacting with any third-party API, database schema, or core system component, you **MUST**
|
|
19
|
-
|
|
17
|
+
### Mandatory Read Before Action (Text vs Vector Search)
|
|
18
|
+
Before interacting with any third-party API, database schema, or core system component, you **MUST** actively seek out existing documentation using the CORRECT tool for the data type:
|
|
19
|
+
- If retrieving explicit Markdown documentation (e.g., API schemas, strict rules), use `grep_search` or open the file directly in `.agent/knowledge/`.
|
|
20
|
+
- If retrieving historical experience, bug fixes, or unstructured project configurations, you **MUST** use the MCP tool `mcp_ag-kit-memory_memory_search` (Semantic Cosine Vector Search) to scan the memory graphs.
|
|
21
|
+
*Example: Use grep/file reader for reading schema in `stripe_api.md`, but strictly use `memory_search` for "how did we handle the stripe CORS error last time?".*
|
|
20
22
|
|
|
21
23
|
### Mandatory Proactive Updates (Zero Prompting Rule)
|
|
22
24
|
When you successfully:
|
|
@@ -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,34 @@ 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. CHIẾN LƯỢC TRUY VẤN PHÂN CẤP: VECTOR VS TEXT (BOOTSTRAP)
|
|
111
|
+
|
|
112
|
+
> **LƯU Ý:** Trí nhớ của hệ thống lưu ở hai dạng (Văn bản phẳng và Vector không gian). Bạn (AI) phải linh hoạt lựa chọn CÔNG CỤ TÌM KIẾM phù hợp với lớp dữ liệu. Không dùng lẫn lộn!
|
|
113
|
+
|
|
114
|
+
**A. KHI TÌM KIẾM VĂN BẢN (TEXT/STATIC FILES):**
|
|
115
|
+
Khi cần tra cứu Code Convention, API Schema, Hướng dẫn đặc tả, hoặc các file Markdown tĩnh `.md` nằm rải rác trong `knowledge`:
|
|
116
|
+
👉 Hãy dùng công cụ gốc: `grep_search`, `vfs` hoặc xem trọn vẹn file (`view_file`). Vì text schema cần độ chính xác cấu trúc tuyệt đối.
|
|
117
|
+
|
|
118
|
+
**B. KHI TÌM KIẾM KÝ ỨC NGỮ NGHĨA (VECTOR MEMORY):**
|
|
119
|
+
Khi cần truy xuất "Kinh nghiệm fix bug cũ", "Thói quen tuỳ chỉnh dự án", hoặc "Luồng sự kiện (Graph Context)" được lưu dạng Node/Edge mà không nhớ nó nằm ở file nào:
|
|
120
|
+
👉 **BẮT BUỘC** dùng thư viện MCP (Model Context Protocol) có sẵn trên Profile để thao tác bằng Vector:
|
|
121
|
+
1. **Tìm kiếm (Search):** Dùng công cụ `mcp_ag-kit-memory_memory_search` với từ khóa cốt lõi. Nó sẽ dùng Cosine Similarity trả về đúng các Node có ngữ nghĩa liên quan nhất, vượt qua giới hạn của keyword match rập khuôn.
|
|
122
|
+
2. **Lưu trữ (Save):** Dùng công cụ `mcp_ag-kit-memory_memory_save` khi muốn lưu lại bài học / giải pháp để sau này xài lại, tự động tính toán Embedding Vector vào không gian não.
|
|
123
|
+
3. **Phân tích Luồng (Graph):** Dùng `mcp_ag-kit-memory_memory_graph` để xem các liên kết (Edges) của một sự kiện/Node cụ thể.
|
|
124
|
+
|
|
125
|
+
ĐÂY LÀ TIÊU CHUẨN KÉP QUAN TRỌNG. Hãy tự hỏi: "Mình đang tìm tài liệu tĩnh hay tìm trí nhớ (trải nghiệm)?" trước khi chọn công cụ!
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## 9. Công cụ Gỡ Rối Định Tuyến (Brain Debugging CLI)
|
|
130
|
+
|
|
131
|
+
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.
|
|
132
|
+
|
|
133
|
+
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ộ.
|
|
134
|
+
- **Trên Ubuntu/Debian:** Yêu cầu User chạy `sudo apt install sqlite3 -y`
|
|
135
|
+
- **Trên Mac (Homebrew):** Yêu cầu User chạy `brew install sqlite`
|
|
136
|
+
- **Trên Windows:** Cài đặt thông qua Winget hoặc tải Binaries.
|
|
137
|
+
|
|
138
|
+
> **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ũ.
|