@mrtrinhvn/ag-kit 1.1.6 → 1.1.9
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/bin/cli.js +91 -24
- package/package.json +1 -1
- package/template/.agent/knowledge/tele-agentic-standard.md +19 -21
- package/template/.agent/scripts/port_utils.sh +67 -0
- package/template/.agent/scripts/receptionist_down.sh +37 -0
- package/template/.agent/scripts/receptionist_up.sh +53 -0
- package/template/.agent/skills/knowledge-management/SKILL.md +1 -1
- package/template/.agent/skills/telegram-agentic-gateway/SKILL.md +61 -44
- package/template/.env.example +5 -1
- package/template/scripts/ag_hud.js +162 -0
- package/template/scripts/ag_portal_bridge.js +141 -0
- package/template/start.sh +16 -19
- package/template/stop_bot.sh +5 -13
package/bin/cli.js
CHANGED
|
@@ -1,12 +1,32 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
2
|
const { program } = require('commander');
|
|
4
3
|
const fs = require('fs');
|
|
5
4
|
const path = require('path');
|
|
5
|
+
const net = require('net');
|
|
6
6
|
|
|
7
7
|
const TEMPLATE_DIR = path.join(__dirname, '..', 'template');
|
|
8
8
|
const TARGET_AGENT_DIR = path.join(process.cwd(), '.agent');
|
|
9
9
|
|
|
10
|
+
function isPortAvailable(port) {
|
|
11
|
+
return new Promise((resolve) => {
|
|
12
|
+
const server = net.createServer();
|
|
13
|
+
server.once('error', () => resolve(false));
|
|
14
|
+
server.once('listening', () => {
|
|
15
|
+
server.close();
|
|
16
|
+
resolve(true);
|
|
17
|
+
});
|
|
18
|
+
server.listen(port, '127.0.0.1');
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function findNextAvailablePort(startPort) {
|
|
23
|
+
let port = startPort;
|
|
24
|
+
while (!(await isPortAvailable(port))) {
|
|
25
|
+
port++;
|
|
26
|
+
}
|
|
27
|
+
return port;
|
|
28
|
+
}
|
|
29
|
+
|
|
10
30
|
// Helper copy đệ quy
|
|
11
31
|
function copyRecursiveSync(src, dest) {
|
|
12
32
|
const exists = fs.existsSync(src);
|
|
@@ -75,20 +95,35 @@ program.command('init')
|
|
|
75
95
|
copyRecursiveSync(srcAgent, TARGET_AGENT_DIR);
|
|
76
96
|
// Ghi lại version vào .agent/.version
|
|
77
97
|
fs.writeFileSync(path.join(TARGET_AGENT_DIR, '.version'), pkg.version);
|
|
78
|
-
console.log(
|
|
98
|
+
console.log(`\x1b[32m✅ Đã cài ráp thành công thư mục .agent (phiên bản v${pkg.version}) vào Project!\x1b[0m`);
|
|
79
99
|
|
|
80
|
-
// Khởi
|
|
100
|
+
// Khởi động .env nếu chưa có
|
|
81
101
|
const envPath = path.join(process.cwd(), '.env');
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
fs.
|
|
89
|
-
console.log(
|
|
102
|
+
(async () => {
|
|
103
|
+
const idePort = await findNextAvailablePort(9555);
|
|
104
|
+
const bridgePort = await findNextAvailablePort(idePort + 1);
|
|
105
|
+
|
|
106
|
+
if (!fs.existsSync(envPath)) {
|
|
107
|
+
const envTemplate = `# --- Remote Orchestration (Golden Combo) ---\nIDE_PORT=${idePort}\nBRIDGE_PORT=${bridgePort}\n\nPROJECT_NAME=ag-project\n`;
|
|
108
|
+
fs.writeFileSync(envPath, envTemplate);
|
|
109
|
+
console.log(`\x1b[34mℹ️ Đã tạo .env với IDE_PORT=${idePort} và BRIDGE_PORT=${bridgePort}\x1b[0m`);
|
|
110
|
+
} else {
|
|
111
|
+
let envContent = fs.readFileSync(envPath, 'utf-8');
|
|
112
|
+
let changed = false;
|
|
113
|
+
if (!envContent.includes('IDE_PORT=')) {
|
|
114
|
+
envContent += `\nIDE_PORT=${idePort}\n`;
|
|
115
|
+
changed = true;
|
|
116
|
+
}
|
|
117
|
+
if (!envContent.includes('BRIDGE_PORT=')) {
|
|
118
|
+
envContent += `BRIDGE_PORT=${bridgePort}\n`;
|
|
119
|
+
changed = true;
|
|
120
|
+
}
|
|
121
|
+
if (changed) {
|
|
122
|
+
fs.writeFileSync(envPath, envContent);
|
|
123
|
+
console.log(`\x1b[34mℹ️ Đã bổ sung cổng tự động: IDE_PORT=${idePort}, BRIDGE_PORT=${bridgePort}\x1b[0m`);
|
|
124
|
+
}
|
|
90
125
|
}
|
|
91
|
-
}
|
|
126
|
+
})();
|
|
92
127
|
} else {
|
|
93
128
|
console.log('\x1b[33m⚠️ Thư mục .agent đã tồn tại.\x1b[0m');
|
|
94
129
|
const vPath = path.join(TARGET_AGENT_DIR, '.version');
|
|
@@ -97,7 +132,7 @@ program.command('init')
|
|
|
97
132
|
if (installedVersion !== pkg.version) {
|
|
98
133
|
console.log(`\x1b[35m👉 Phát hiện phiên bản cũ (v${installedVersion}). Hãy dùng lệnh "ag-kit update" để cập nhật lên v${pkg.version}.\x1b[0m`);
|
|
99
134
|
} else {
|
|
100
|
-
console.log(
|
|
135
|
+
console.log(`\x1b[34mℹ️ Bạn đang sử dụng phiên bản khớp với bộ công cụ (v${pkg.version}).\x1b[0m`);
|
|
101
136
|
}
|
|
102
137
|
} else {
|
|
103
138
|
console.log('\x1b[35m👉 Hãy dùng lệnh "ag-kit update" để đồng bộ cấu trúc mới.\x1b[0m');
|
|
@@ -112,11 +147,12 @@ program.command('update')
|
|
|
112
147
|
.action(() => {
|
|
113
148
|
console.log('\x1b[36m🔄 Đang cập nhật siêu luân xa Lập trình (AG-Kit)...\x1b[0m');
|
|
114
149
|
const srcAgent = path.join(TEMPLATE_DIR, '.agent');
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
150
|
+
const vPath = path.join(TARGET_AGENT_DIR, '.version');
|
|
151
|
+
let oldVersion = '0.0.0';
|
|
152
|
+
if (fs.existsSync(vPath)) {
|
|
153
|
+
oldVersion = fs.readFileSync(vPath, 'utf-8').trim();
|
|
118
154
|
}
|
|
119
|
-
|
|
155
|
+
|
|
120
156
|
// Chỉ cập nhật não bộ chuẩn (Agents, Skills, Workflows, Scripts, Rules)
|
|
121
157
|
// Tôn trọng dữ liệu Knowledge của dự án đang có
|
|
122
158
|
['agents', 'skills', 'workflows', 'scripts', 'rules'].forEach(folder => {
|
|
@@ -129,8 +165,9 @@ program.command('update')
|
|
|
129
165
|
|
|
130
166
|
migrateLegacyMemories();
|
|
131
167
|
// Cập nhật version vào .agent/.version
|
|
132
|
-
fs.writeFileSync(
|
|
133
|
-
console.log(
|
|
168
|
+
fs.writeFileSync(vPath, pkg.version);
|
|
169
|
+
console.log(`\x1b[32m✅ Cập nhật thành công! Phiên bản hiện tại: v${oldVersion} -> v${pkg.version}\x1b[0m`);
|
|
170
|
+
console.log('\x1b[34m⚡️ Toàn bộ cấu trúc kỹ năng đã được đồng bộ.\x1b[0m');
|
|
134
171
|
});
|
|
135
172
|
|
|
136
173
|
program.command('check')
|
|
@@ -243,10 +280,13 @@ program.command('status')
|
|
|
243
280
|
});
|
|
244
281
|
|
|
245
282
|
|
|
246
|
-
|
|
283
|
+
async function runInteractiveMenu() {
|
|
247
284
|
const inquirer = require('inquirer');
|
|
285
|
+
console.clear();
|
|
248
286
|
console.log('\x1b[35m\n🧠 ANTIGRAVITY KIT - BẢNG ĐIỀU KHIỂN TÁC VỤ\x1b[0m');
|
|
249
|
-
|
|
287
|
+
console.log('\x1b[34m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m');
|
|
288
|
+
|
|
289
|
+
const { action } = await inquirer.prompt([
|
|
250
290
|
{
|
|
251
291
|
type: 'list',
|
|
252
292
|
name: 'action',
|
|
@@ -260,10 +300,37 @@ if (process.argv.length <= 2) {
|
|
|
260
300
|
{ name: '❌ Thoát', value: 'exit' }
|
|
261
301
|
]
|
|
262
302
|
}
|
|
263
|
-
])
|
|
264
|
-
|
|
265
|
-
|
|
303
|
+
]);
|
|
304
|
+
|
|
305
|
+
if (action === 'exit') {
|
|
306
|
+
console.log('\x1b[36m👋 Tạm biệt! Hợp tác vui vẻ.\x1b[0m\n');
|
|
307
|
+
process.exit(0);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Thực thi command
|
|
311
|
+
console.log('\n\x1b[34m--- ĐANG THỰC THI ---\x1b[0m');
|
|
312
|
+
|
|
313
|
+
// Chúng ta parse lại command với action đã chọn
|
|
314
|
+
// Lưu ý: commander parse() trả về promise với parseAsync
|
|
315
|
+
await program.parseAsync([process.argv[0], process.argv[1], action]);
|
|
316
|
+
|
|
317
|
+
console.log('\n\x1b[34m--- HOÀN TẤT TÁC VỤ ---\x1b[0m');
|
|
318
|
+
|
|
319
|
+
const { resume } = await inquirer.prompt([
|
|
320
|
+
{
|
|
321
|
+
type: 'input',
|
|
322
|
+
name: 'resume',
|
|
323
|
+
message: 'Nhấn Enter để quay lại Menu quản trị...'
|
|
266
324
|
}
|
|
325
|
+
]);
|
|
326
|
+
|
|
327
|
+
return runInteractiveMenu();
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (process.argv.length <= 2) {
|
|
331
|
+
runInteractiveMenu().catch(err => {
|
|
332
|
+
console.error('\x1b[31m❌ Lỗi thực thi Menu:\x1b[0m', err);
|
|
333
|
+
process.exit(1);
|
|
267
334
|
});
|
|
268
335
|
} else {
|
|
269
336
|
program.parse(process.argv);
|
package/package.json
CHANGED
|
@@ -1,32 +1,30 @@
|
|
|
1
1
|
# TIÊU CHUẨN GIAO TIẾP TẬP TRUNG (TELE-AGENTIC STANDARD)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Hệ thống kế thừa tinh hoa từ các tiêu chuẩn điều khiển từ xa: **Remoat**, **LazyGravity** và tối ưu token **VFS**.
|
|
4
4
|
|
|
5
5
|
## 📡 KIẾN TRÚC "COMBO VÀNG" (GOLDEN COMBO)
|
|
6
6
|
|
|
7
|
-
Hệ thống được vận hành bởi 3 trụ cột:
|
|
8
|
-
1. **IDE
|
|
9
|
-
2. **Telegram
|
|
10
|
-
3. **CDP Bridge
|
|
7
|
+
Hệ thống được vận hành bởi 3 trụ cột (Nguồn: [Remoat Strategy](https://github.com/optimistengineer/Remoat)):
|
|
8
|
+
1. **IDE Participant**: Antigravity đóng vai trò là thực thể thực thi duy nhất, khởi động ở chế độ Debug (`--remote-debugging-port=9555`).
|
|
9
|
+
2. **Telegram Gateway**: Cổng giao tiếp tập trung qua Bot & Group Topics (Nguồn: [LazyGravity Patterns](https://github.com/tokyoweb3/LazyGravity)).
|
|
10
|
+
3. **CDP Bridge**: Cầu nối WebSocket kết nối "Lễ tân" (Bot) và "Quản đốc" (IDE).
|
|
11
11
|
|
|
12
|
-
### 1. Phân Lập Trí Nhớ
|
|
13
|
-
|
|
14
|
-
- **Topic 🔴 Surgery (Phẫu thuật)**: Chuyên dụng cho các lệnh `/heal` và workflow `@brain-surgeon`.
|
|
15
|
-
- **Topic 🟢 Signals (Tín hiệu)**: Hiển thị lệnh mua/bán từ AI.
|
|
16
|
-
- **Topic 🔵 General (Tổng quan)**: Quản trị hệ thống, lệnh `/status`.
|
|
12
|
+
### 1. Phân Lập Trí Nhớ (Topic Memory)
|
|
13
|
+
Sử dụng Telegram Topics để cô lập bối cảnh công việc. Lựa chọn Topic phù hợp giúp Agent không bị "loạn não" giữa các Task khác nhau.
|
|
17
14
|
|
|
18
|
-
### 2. Giao Diện
|
|
19
|
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
- **Doctor Call**: Nút bấm kích hoạt Logic tự chữa lành.
|
|
15
|
+
### 2. Giao Diện Premium (Aesthetics)
|
|
16
|
+
Dựa trên [awesome-grammY](https://github.com/grammyjs/awesome-grammY), giao diện phải đủ sang trọng (Premium) và rõ ràng:
|
|
17
|
+
- **Dashboard**: Lệnh `/status` hiển thị bảng sức khỏe AI chuyên sâu.
|
|
18
|
+
- **Micro-interactions**: Nút bấm Inline với ID ngắn (ShortID) để quản trị nhanh trên Mobile.
|
|
23
19
|
|
|
24
|
-
## 🛠️
|
|
20
|
+
## 🛠️ CHIẾN LƯỢC TOÀN DIỆN (STRATEGIC PROTOCOL)
|
|
25
21
|
|
|
26
|
-
1. **
|
|
27
|
-
2. **
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
1. **Tiết kiệm Token (VFS Protocol)**: PHẢI sử dụng công cụ [vfs](https://github.com/TrNgTien/vfs) để quét cấu trúc mã nguồn trước khi đọc file. Kỹ thuật này giúp tiết kiệm 98% chi phí vận hành.
|
|
23
|
+
2. **Model Selection (Local vs Cloud)**:
|
|
24
|
+
- Sử dụng **Local Models** (Ollama Host) cho các bước phân tích, tìm lỗi và lập phác đồ (Regent mode).
|
|
25
|
+
- Sử dụng **Cloud Models** (Claude/Gemini) cho bước ghi mã nguồn (Implementation) và giải quyết logic cực khó.
|
|
26
|
+
3. **Scripts Đồng Bộ**: Hệ thống phải đi kèm bộ đôi `start.sh` (khởi chạy bot + debugger) và `stop_bot.sh` (tắt an toàn).
|
|
30
27
|
|
|
31
28
|
---
|
|
32
|
-
*Tham chiếu: .agent/skills/telegram-agentic-gateway*
|
|
29
|
+
*Tham chiếu Skill: .agent/skills/telegram-agentic-gateway*
|
|
30
|
+
*Nguồn gốc Kiến thức: Remoat, LazyGravity, VFS, grammY.*
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# --- Port Management Utility (Golden V4) ---
|
|
4
|
+
# Finds free ports and updates .env to ensure consistent project-wide communication.
|
|
5
|
+
|
|
6
|
+
ENV_FILE=".env"
|
|
7
|
+
|
|
8
|
+
# Logic tìm cổng trống
|
|
9
|
+
function find_free_port() {
|
|
10
|
+
local port=$1
|
|
11
|
+
while netstat -atn | grep -q ":$port "; do
|
|
12
|
+
port=$((port + 1))
|
|
13
|
+
done
|
|
14
|
+
echo $port
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
# Cập nhật hoặc thêm cổng vào .env
|
|
18
|
+
function update_env_port() {
|
|
19
|
+
local key=$1
|
|
20
|
+
local value=$2
|
|
21
|
+
|
|
22
|
+
if grep -q "^${key}=" "$ENV_FILE"; then
|
|
23
|
+
# OS-compatible sed (Linux/macOS)
|
|
24
|
+
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
25
|
+
sed -i '' "s/^${key}=.*/${key}=${value}/" "$ENV_FILE"
|
|
26
|
+
else
|
|
27
|
+
sed -i "s/^${key}=.*/${key}=${value}/" "$ENV_FILE"
|
|
28
|
+
fi
|
|
29
|
+
else
|
|
30
|
+
echo "${key}=${value}" >> "$ENV_FILE"
|
|
31
|
+
fi
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
# --- Main Logic ---
|
|
35
|
+
# 1. Đọc cổng hiện tại
|
|
36
|
+
if [ -f "$ENV_FILE" ]; then
|
|
37
|
+
source "$ENV_FILE"
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
ORIGINAL_IDE_PORT=${IDE_PORT:-9555}
|
|
41
|
+
ORIGINAL_BRIDGE_PORT=${BRIDGE_PORT:-9556}
|
|
42
|
+
|
|
43
|
+
# 2. Kiểm tra xung đột (IDE_PORT)
|
|
44
|
+
# Nếu cổng IDE bận, và không phải là do IDE của chính dự án này chiếm giữ (kiểm tra qua /json endpoint)
|
|
45
|
+
PORT_TAKEN=false
|
|
46
|
+
if netstat -atn | grep -q ":$ORIGINAL_IDE_PORT "; then
|
|
47
|
+
# Kiểm tra xem folder dự án hiện tại có nằm trong danh sách tab/window của IDE không
|
|
48
|
+
if ! curl -s "http://127.0.0.1:$ORIGINAL_IDE_PORT/json" | grep -q "$PROJECT_DIR" > /dev/null 2>&1; then
|
|
49
|
+
PORT_TAKEN=true
|
|
50
|
+
fi
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
if [ "$PORT_TAKEN" = true ]; then
|
|
54
|
+
echo "⚠️ Xung đột PORT phaát hieện! Đang tìm cổng mới..."
|
|
55
|
+
NEW_IDE_PORT=$(find_free_port $ORIGINAL_IDE_PORT)
|
|
56
|
+
NEW_BRIDGE_PORT=$(find_free_port $((NEW_IDE_PORT + 1)))
|
|
57
|
+
|
|
58
|
+
update_env_port "IDE_PORT" "$NEW_IDE_PORT"
|
|
59
|
+
update_env_port "BRIDGE_PORT" "$NEW_BRIDGE_PORT"
|
|
60
|
+
|
|
61
|
+
echo "✅ Đã cập nhật .env: IDE_PORT=$NEW_IDE_PORT, BRIDGE_PORT=$NEW_BRIDGE_PORT"
|
|
62
|
+
export IDE_PORT=$NEW_IDE_PORT
|
|
63
|
+
export BRIDGE_PORT=$NEW_BRIDGE_PORT
|
|
64
|
+
else
|
|
65
|
+
export IDE_PORT=$ORIGINAL_IDE_PORT
|
|
66
|
+
export BRIDGE_PORT=$ORIGINAL_BRIDGE_PORT
|
|
67
|
+
fi
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# --- Antigravity Unified Shutdown (Agent-Defined V3) ---
|
|
4
|
+
# Dọn dẹp trạm gác theo Port Isolation.
|
|
5
|
+
|
|
6
|
+
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
7
|
+
cd "$PROJECT_DIR"
|
|
8
|
+
|
|
9
|
+
if [ -f .env ]; then
|
|
10
|
+
source .env
|
|
11
|
+
fi
|
|
12
|
+
|
|
13
|
+
BRIDGE_PORT=${BRIDGE_PORT:-9556}
|
|
14
|
+
|
|
15
|
+
echo "════════════════════════════════════════════════════"
|
|
16
|
+
echo " 🚑 SHUTTING DOWN GATEWAY [$BRIDGE_PORT]..."
|
|
17
|
+
echo "════════════════════════════════════════════════════"
|
|
18
|
+
|
|
19
|
+
# 1. Tắt Portal Bridge (HUD)
|
|
20
|
+
BRIDGE_PID_FILE=".portal_bridge_${BRIDGE_PORT}.pid"
|
|
21
|
+
if [ -f "$BRIDGE_PID_FILE" ]; then
|
|
22
|
+
PID=$(cat "$BRIDGE_PID_FILE")
|
|
23
|
+
echo "[1/2] 🧪 Stopping Portal Bridge [$BRIDGE_PORT] (PID: $PID)..."
|
|
24
|
+
kill $PID 2>/dev/null && rm "$BRIDGE_PID_FILE"
|
|
25
|
+
echo " ✅ Bridge stopped."
|
|
26
|
+
else
|
|
27
|
+
echo "[1/2] 🧪 Portal Bridge on port $BRIDGE_PORT not running."
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
# 2. Tắt Docker Backend (Bot)
|
|
31
|
+
echo "[2/2] 🤖 Stopping Receptionist (Docker)..."
|
|
32
|
+
docker compose -f docker-compose.dev.yml stop ck-backend-dev
|
|
33
|
+
echo " ✅ Bot stopped."
|
|
34
|
+
|
|
35
|
+
echo "════════════════════════════════════════════════════"
|
|
36
|
+
echo "✅ SYSTEM IDLE."
|
|
37
|
+
echo "════════════════════════════════════════════════════"
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# --- Antigravity Unified Receptionist (Agent-Defined V4) ---
|
|
4
|
+
# Trạm gác hợp nhất: Bot + Portal Bridge (HUD) + Monitor Dashboard.
|
|
5
|
+
# Hỗ trợ Đa dự án & Tự động xử lý Cổng (Smart Port Orchestration).
|
|
6
|
+
|
|
7
|
+
# 1. Load Cấu hình & Xử lý Cổng Thông minh
|
|
8
|
+
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
9
|
+
cd "$PROJECT_DIR"
|
|
10
|
+
|
|
11
|
+
if [ -f .agent/scripts/port_utils.sh ]; then
|
|
12
|
+
source .agent/scripts/port_utils.sh
|
|
13
|
+
else
|
|
14
|
+
source .env
|
|
15
|
+
export IDE_PORT=${IDE_PORT:-9555}
|
|
16
|
+
export BRIDGE_PORT=${BRIDGE_PORT:-9556}
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
echo "════════════════════════════════════════════════════"
|
|
20
|
+
echo " 🚑 AGENTIC GATEWAY - PORTAL [$BRIDGE_PORT]"
|
|
21
|
+
echo "════════════════════════════════════════════════════"
|
|
22
|
+
|
|
23
|
+
# 1. Kiểm tra Cổng IDE (CDP)
|
|
24
|
+
echo -n "[1/4] 🛰️ Checking IDE Portal (Port $IDE_PORT)... "
|
|
25
|
+
if curl -s http://127.0.0.1:$IDE_PORT/json/version > /dev/null; then
|
|
26
|
+
echo "✅ READY."
|
|
27
|
+
else
|
|
28
|
+
echo "❌ NOT FOUND."
|
|
29
|
+
echo " 👉 Please start Antigravity in Debug mode on port $IDE_PORT"
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
# 2. Khởi động Portal Bridge (HUD Injector)
|
|
33
|
+
echo "[2/4] 🧪 Injected Golden HUD Bridge... "
|
|
34
|
+
BRIDGE_PID_FILE=".portal_bridge_${BRIDGE_PORT}.pid"
|
|
35
|
+
|
|
36
|
+
# Tắt bridge cũ nếu đang chạy trên port này
|
|
37
|
+
if [ -f "$BRIDGE_PID_FILE" ]; then
|
|
38
|
+
kill $(cat "$BRIDGE_PID_FILE") 2>/dev/null
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
nohup node scripts/ag_portal_bridge.js > ".portal_bridge_${BRIDGE_PORT}.log" 2>&1 &
|
|
42
|
+
echo $! > "$BRIDGE_PID_FILE"
|
|
43
|
+
echo " ✅ Bridge running (PID: $(cat "$BRIDGE_PID_FILE") on Port $BRIDGE_PORT)"
|
|
44
|
+
|
|
45
|
+
# 3. Khởi động Bot (Tùy chỉnh theo dự án)
|
|
46
|
+
echo "[3/4] 🤖 Waking up Agent Bot... "
|
|
47
|
+
# [TEMPLATE_NOTE]: Sếp hãy gõ lệnh khởi động Bot của mình vào đây.
|
|
48
|
+
# Ví dụ: docker compose up -d (nếu dùng docker) hoặc npx tsx src/index.ts (nếu dùng local)
|
|
49
|
+
echo " ⚠️ Vui lòng cấu hình lệnh khởi động Bot trong .agent/scripts/receptionist_up.sh"
|
|
50
|
+
|
|
51
|
+
# 4. Monitor
|
|
52
|
+
echo "[4/4] 📊 Ready."
|
|
53
|
+
echo "----------------------------------------------------"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: knowledge-management
|
|
3
|
-
description: Hệ thống tư duy và giao thức duy trì tri thức (Systems Thinking & Knowledge Retention).
|
|
3
|
+
description: Hệ thống tư duy và giao thức duy trì tri thức (Systems Thinking & Knowledge Retention). **QUY TẮC CỐI THƯỢNG: Khi cập nhật ag-kit, phải đồng bộ sang thư mục `template/`. Khi cập nhật Skills, BẮT BUỘC phải đảm bảo tính toàn vẹn cấu trúc (Indexing A, B, C... không được nhảy cóc).**
|
|
4
4
|
allowed-tools: Read, Write, Glob, Grep
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -1,50 +1,67 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: telegram-agentic-gateway
|
|
3
|
-
description: Tiêu chuẩn Giao tiếp Telegram (Telegram Gateway) cho các Agentic Projects.
|
|
3
|
+
description: Tiêu chuẩn Giao tiếp Telegram (Telegram Gateway) cho các Agentic Projects. Cổng điều phối hợp nhất IDE, Bot và Ký ức.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# KỸ NĂNG: XÂY DỰNG TRẠM ĐIỀU HÀNH TELEGRAM (Telegram Agentic Gateway)
|
|
7
7
|
|
|
8
|
-
Khi
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
## PHẦN
|
|
23
|
-
|
|
24
|
-
-
|
|
25
|
-
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
**
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
8
|
+
Khi triển khai "Cổng điều khiển Telegram", bạn (AI) phải thiết kế một `TelegramGateway` chuyên nghiệp, tuân thủ nghiêm ngặt cấu trúc **7 Phôi (7 Layers)** dưới đây. Tuyệt đối không được bỏ sót hoặc làm xáo trộn thứ tự các mục khi cập nhật.
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## PHẦN A: BỘ LỆNH QUẢN TRỊ SINH TỒN (Core Commands)
|
|
13
|
+
Mọi Gateway phải hỗ trợ các lệnh điều khiển hệ thống sau:
|
|
14
|
+
1. **`/start`**: Kiểm tra kết nối. Trả về thông số `IDE_PORT` (CDP), trạng thái Node/Ollama và phiên bản Agent.
|
|
15
|
+
2. **`/status` (Dashboard)**: Hiển thị bảng điều khiển Premium về sức khỏe AI, các Agent đang chạy ngầm và Task hiện tại.
|
|
16
|
+
3. **`/model`**: Menu chọn Model linh hoạt. Cho phép chuyển đổi giữa **Local Ollama** (tiết kiệm token) và **Cloud models** (tác vụ phức tạp).
|
|
17
|
+
4. **`/screenshot` (Visual Support)**: Chụp màn hình IDE qua CDP (`Page.captureScreenshot`).
|
|
18
|
+
5. **`/heal` / `/healplan`**: Luồng tự chữa lành (Self-Healing) tích hợp phê duyệt người dùng.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## PHẦN B: TRÍ NHỚ PHÂN NHIỆM (Context Isolation)
|
|
23
|
+
Kế thừa từ tiêu chuẩn **LazyGravity**, bắt buộc cô lập trí nhớ dựa trên **Telegram Topics** (Threads):
|
|
24
|
+
- Trích xuất `msg.message_thread_id` để định danh file context (Vd: `topic_123.json`).
|
|
25
|
+
- Mỗi Topic là một bộ não làm việc riêng biệt, ngăn chặn hiện tượng chập cheng ký ức giữa các tác vụ khác nhau.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## PHẦN C: GIAO DIỆN PREMIUM (UI/UX Standards)
|
|
30
|
+
Tuân thủ tiêu chuẩn thẩm mỹ của [awesome-grammY](https://github.com/grammyjs/awesome-grammY):
|
|
31
|
+
- **Cấu trúc khối**: Sử dụng `<b>` cho Header, ký tự `━━━━━` làm phân cách.
|
|
32
|
+
- **Emoji Logic**: ✅ Active, 🚨 Warning, 🛠️ Debugging, 🏥 Surgery.
|
|
33
|
+
- **ShortID Mapping**: Vì Telegram giới hạn callback data (64 bytes), hãy map ID dài vào biến tạm và nhả ra mã ngắn (Vd: `sess_1`).
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## PHẦN D: CHIẾN LƯỢC TIẾT KIỆM TOKEN (Model & VFS Strategy)
|
|
38
|
+
Tối ưu chi phí vận hành thông qua Token Efficiency:
|
|
39
|
+
1. **VFS First (Virtual File System)**: Tuyệt đối không đọc file thô hàng ngàn dòng. PHẢI dùng kỹ năng `vfs-assistant` để quét chữ ký (signatures) trước. (Nguồn: [vfs](https://github.com/TrNgTien/vfs)).
|
|
40
|
+
2. **Regent Agent (Chế độ Nhiếp chính)**: Sử dụng các model Local (Ollama) cho các bước phân tích bối cảnh, refactor nhỏ. Chỉ dùng Cloud cho bước Implementation cuối cùng.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## PHẦN E: CỔNG PORTAL IDE & CDP (Golden Loop Participant)
|
|
45
|
+
Biến IDE thành một thực thể tham gia trực tiếp dự án (Participant):
|
|
46
|
+
1. **Remoat Strategy**: IDE Antigravity **BẮT BUỘC** khởi động với `--remote-debugging-port=9555`.
|
|
47
|
+
2. **HUD Injection**: Tiêm `ag_hud.js` vào IDE qua CDP để hiển thị chỉ số sức khỏe AI (Gen, WinRate) trực quan trong không gian code.
|
|
48
|
+
3. **Bidirectional Sync**: Đồng bộ trạng thái từ Bot -> IDE (HUD) và ngược lại một cách liên tục.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## PHẦN F: THIẾT LẬP HẠ TẦNG (Deployment & Scripts)
|
|
53
|
+
1. **Group Creation**: Tạo Telegram Group, thêm Bot làm Admin, bật tính năng Multi-Topics.
|
|
54
|
+
2. **Environment (.env)**: Phải cấu hình thống nhất `IDE_PORT`, `TELEGRAM_BOT_TOKEN`, `ALLOWED_USER_IDS` và `OLLAMA_HOST`.
|
|
55
|
+
3. **Standard Scripts**: Sử dụng bộ đôi `start.sh` (khởi chạy bot + gateway) và `stop_bot.sh` (tắt an toàn).
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## PHẦN G: NGUỒN GỐC TRI THỨC (Knowledge Roots)
|
|
60
|
+
Mọi kỹ năng đều có nguồn gốc rõ ràng, không được làm mất gốc kiến thức:
|
|
61
|
+
- **[Remoat](https://github.com/optimistengineer/Remoat)**: Remote Management & CDP Control.
|
|
62
|
+
- **[LazyGravity](https://github.com/tokyoweb3/LazyGravity)**: Project Coordination & Session Isolation.
|
|
63
|
+
- **[vfs](https://github.com/TrNgTien/vfs)**: Token Efficiency standard.
|
|
64
|
+
- **[grammY Aesthetics](https://github.com/grammyjs/awesome-grammY)**: UI/UX standards.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
*(Ghi chú cho AI)*: Khi cập nhật Template, BẮT BUỘC phải kiểm tra toàn vẹn cấu trúc (A -> G), không được tạo các mục nhảy cóc.
|
package/template/.env.example
CHANGED
|
@@ -12,11 +12,15 @@ ALLOWED_USER_IDS="123456789,987654321"
|
|
|
12
12
|
# ID Chat/Group được phép hoạt động (Để tránh Bot bị kéo vào group lạ)
|
|
13
13
|
ALLOWED_CHAT_IDS="-100123456789"
|
|
14
14
|
|
|
15
|
-
# [Cấu Hình IDE]
|
|
15
|
+
# [Cấu Hình IDE & Remote]
|
|
16
16
|
# Cổng Debug của Antigravity (Mặc định là 9555)
|
|
17
17
|
# Phải khớp với tham số --remote-debugging-port khi mở Editor
|
|
18
18
|
IDE_PORT=9555
|
|
19
19
|
|
|
20
|
+
# Cổng của Portal Bridge (Mặc định là 9556)
|
|
21
|
+
# Phải khớp với script start.sh và bot callback
|
|
22
|
+
BRIDGE_PORT=9556
|
|
23
|
+
|
|
20
24
|
# Tên dự án để Bot tự động tìm kiếm target phù hợp trong CDP
|
|
21
25
|
PROJECT_NAME="ceogravity"
|
|
22
26
|
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Antigravity Golden HUD - Medical/Trading Theme
|
|
3
|
+
* Purpose: Inject a premium status dashboard into the IDE.
|
|
4
|
+
*/
|
|
5
|
+
export const AG_HUD_JS = `(async () => {
|
|
6
|
+
const HUD_ID = 'antigravity-golden-hud';
|
|
7
|
+
if (document.getElementById(HUD_ID)) return "ALREADY_EXISTS";
|
|
8
|
+
|
|
9
|
+
// 1. Create Styles
|
|
10
|
+
const style = document.createElement('style');
|
|
11
|
+
style.innerHTML = \`
|
|
12
|
+
#\${HUD_ID} {
|
|
13
|
+
position: fixed;
|
|
14
|
+
top: 15px;
|
|
15
|
+
right: 15px;
|
|
16
|
+
z-index: 999999;
|
|
17
|
+
background: rgba(10, 10, 10, 0.85);
|
|
18
|
+
backdrop-filter: blur(12px);
|
|
19
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
20
|
+
border-radius: 12px;
|
|
21
|
+
padding: 12px;
|
|
22
|
+
width: 280px;
|
|
23
|
+
color: #fff;
|
|
24
|
+
font-family: 'Inter', system-ui, sans-serif;
|
|
25
|
+
box-shadow: 0 8px 32px rgba(0,0,0,0.5);
|
|
26
|
+
transition: all 0.3s ease;
|
|
27
|
+
user-select: none;
|
|
28
|
+
}
|
|
29
|
+
#\${HUD_ID}:hover {
|
|
30
|
+
border-color: #4caf50;
|
|
31
|
+
box-shadow: 0 0 20px rgba(76, 175, 80, 0.2);
|
|
32
|
+
}
|
|
33
|
+
#\${HUD_ID} .header {
|
|
34
|
+
display: flex;
|
|
35
|
+
align-items: center;
|
|
36
|
+
justify-content: space-between;
|
|
37
|
+
margin-bottom: 10px;
|
|
38
|
+
font-weight: 700;
|
|
39
|
+
letter-spacing: 0.5px;
|
|
40
|
+
}
|
|
41
|
+
#\${HUD_ID} .status-dot {
|
|
42
|
+
width: 8px;
|
|
43
|
+
height: 8px;
|
|
44
|
+
border-radius: 50%;
|
|
45
|
+
background: #4caf50;
|
|
46
|
+
display: inline-block;
|
|
47
|
+
margin-right: 6px;
|
|
48
|
+
animation: pulse 2s infinite;
|
|
49
|
+
}
|
|
50
|
+
@keyframes pulse {
|
|
51
|
+
0% { transform: scale(1); opacity: 1; }
|
|
52
|
+
50% { transform: scale(1.5); opacity: 0.5; }
|
|
53
|
+
100% { transform: scale(1); opacity: 1; }
|
|
54
|
+
}
|
|
55
|
+
#\${HUD_ID} .metric {
|
|
56
|
+
display: flex;
|
|
57
|
+
justify-content: space-between;
|
|
58
|
+
font-size: 12px;
|
|
59
|
+
margin-bottom: 6px;
|
|
60
|
+
color: #ccc;
|
|
61
|
+
}
|
|
62
|
+
#\${HUD_ID} .metric b { color: #fff; }
|
|
63
|
+
#\${HUD_ID} .action-btn {
|
|
64
|
+
background: #1a1a1a;
|
|
65
|
+
border: 1px solid #333;
|
|
66
|
+
color: #4caf50;
|
|
67
|
+
font-size: 11px;
|
|
68
|
+
padding: 6px;
|
|
69
|
+
border-radius: 6px;
|
|
70
|
+
width: 100%;
|
|
71
|
+
margin-top: 8px;
|
|
72
|
+
cursor: pointer;
|
|
73
|
+
text-align: center;
|
|
74
|
+
font-weight: 600;
|
|
75
|
+
transition: all 0.2s;
|
|
76
|
+
}
|
|
77
|
+
#\${HUD_ID} .action-btn:hover {
|
|
78
|
+
background: #4caf50;
|
|
79
|
+
color: #000;
|
|
80
|
+
}
|
|
81
|
+
#\${HUD_ID} .surgery-alert {
|
|
82
|
+
background: rgba(244, 67, 54, 0.2);
|
|
83
|
+
border: 1px solid #f44336;
|
|
84
|
+
color: #f44336;
|
|
85
|
+
padding: 8px;
|
|
86
|
+
border-radius: 8px;
|
|
87
|
+
font-size: 11px;
|
|
88
|
+
margin-top: 10px;
|
|
89
|
+
display: none;
|
|
90
|
+
animation: shake 0.5s infinite;
|
|
91
|
+
}
|
|
92
|
+
@keyframes shake {
|
|
93
|
+
0% { transform: translateX(0); }
|
|
94
|
+
25% { transform: translateX(2px); }
|
|
95
|
+
50% { transform: translateX(0); }
|
|
96
|
+
75% { transform: translateX(-2px); }
|
|
97
|
+
100% { transform: translateX(0); }
|
|
98
|
+
}
|
|
99
|
+
\`;
|
|
100
|
+
document.head.appendChild(style);
|
|
101
|
+
|
|
102
|
+
// 2. Create UI
|
|
103
|
+
const hud = document.createElement('div');
|
|
104
|
+
hud.id = HUD_ID;
|
|
105
|
+
hud.innerHTML = \`
|
|
106
|
+
<div class="header">
|
|
107
|
+
<span>🧠 CORE AGENT B1</span>
|
|
108
|
+
<span id="ag-status"><span class="status-dot"></span>ONLINE</span>
|
|
109
|
+
</div>
|
|
110
|
+
<div class="metric">AI Evolution: <b id="ag-gen">GEN-439</b></div>
|
|
111
|
+
<div class="metric">Win Rate: <b id="ag-win">47.7%</b></div>
|
|
112
|
+
<div class="metric">Current Phase: <b id="ag-phase">5m VSA Trading</b></div>
|
|
113
|
+
|
|
114
|
+
<div class="surgery-alert" id="ag-alert">
|
|
115
|
+
🛑 <b>DOCTOR CALL REQUIRED!</b><br>AI Learning Stalled. Surgery needed.
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
<div id="ag-toast" style="display:none; background:rgba(33, 150, 243, 0.9); color:#fff; padding:8px; border-radius:8px; margin-top:10px; font-size:11px; border-left:4px solid #0d47a1; backdrop-filter: blur(8px); box-shadow: 0 4px 12px rgba(0,0,0,0.3);">
|
|
119
|
+
<b>💬 TELEGRAM:</b> <span id="ag-toast-msg"></span>
|
|
120
|
+
</div>
|
|
121
|
+
|
|
122
|
+
<div class="action-btn" id="ag-btn-surgery">🏥 START BRAIN SURGERY</div>
|
|
123
|
+
\`;
|
|
124
|
+
document.body.appendChild(hud);
|
|
125
|
+
|
|
126
|
+
// 3. Logic to update from Bridge
|
|
127
|
+
window.addEventListener('ag-portal-update', (e) => {
|
|
128
|
+
const data = e.detail;
|
|
129
|
+
if (data.gen) document.getElementById('ag-gen').innerText = data.gen;
|
|
130
|
+
if (data.win) document.getElementById('ag-win').innerText = data.win;
|
|
131
|
+
if (data.phase) document.getElementById('ag-phase').innerText = data.phase;
|
|
132
|
+
|
|
133
|
+
const alert = document.getElementById('ag-alert');
|
|
134
|
+
if (data.status === 'DOCTOR_REQUIRED' || data.status === 'STALLED') {
|
|
135
|
+
alert.style.display = 'block';
|
|
136
|
+
document.getElementById('ag-status').innerHTML = '<span class="status-dot" style="background:#f44336"></span>REPAIR';
|
|
137
|
+
} else {
|
|
138
|
+
alert.style.display = 'none';
|
|
139
|
+
document.getElementById('ag-status').innerHTML = '<span class="status-dot" style="background:#4caf50"></span>ONLINE';
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
window.addEventListener('ag-portal-alert', (e) => {
|
|
144
|
+
const data = e.detail;
|
|
145
|
+
const toast = document.getElementById('ag-toast');
|
|
146
|
+
const toastMsg = document.getElementById('ag-toast-msg');
|
|
147
|
+
|
|
148
|
+
toastMsg.innerText = data.message || "New message from Telegram.";
|
|
149
|
+
toast.style.display = 'block';
|
|
150
|
+
if (data.color) toast.style.background = data.color;
|
|
151
|
+
|
|
152
|
+
// Auto-hide after 10 seconds
|
|
153
|
+
setTimeout(() => { toast.style.display = 'none'; }, 10000);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
document.getElementById('ag-btn-surgery').onclick = () => {
|
|
157
|
+
console.log("AG_PORTAL_ACTION:START_SURGERY");
|
|
158
|
+
document.getElementById('ag-btn-surgery').innerText = "🚑 REQUESTING SURGEON...";
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
return "GOLDEN_HUD_INJECTED";
|
|
162
|
+
})()`;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import WebSocket from 'ws';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import fetch from 'node-fetch';
|
|
5
|
+
import http from 'http';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
import dotenv from 'dotenv';
|
|
8
|
+
|
|
9
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
dotenv.config({ path: path.join(__dirname, '../.env') });
|
|
11
|
+
|
|
12
|
+
const HUD_JS_FILE = path.join(__dirname, 'ag_hud.js');
|
|
13
|
+
const STATE_FILE = path.join(__dirname, '../backend/data/ai_state.json');
|
|
14
|
+
const REQUEST_FILE = path.join(__dirname, '../backend/data/remote_requests.json');
|
|
15
|
+
const IDE_PORT = process.env.IDE_PORT || 9555;
|
|
16
|
+
const BRIDGE_PORT = process.env.BRIDGE_PORT || 9556;
|
|
17
|
+
|
|
18
|
+
let globalWs = null;
|
|
19
|
+
|
|
20
|
+
async function getWsUrl() {
|
|
21
|
+
try {
|
|
22
|
+
const resp = await fetch(`http://127.0.0.1:${IDE_PORT}/json/version`);
|
|
23
|
+
const data = await resp.json();
|
|
24
|
+
return data.webSocketDebuggerUrl;
|
|
25
|
+
} catch (err) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function injectHud(ws) {
|
|
31
|
+
const hudJsContent = fs.readFileSync(HUD_JS_FILE, 'utf8');
|
|
32
|
+
const script = hudJsContent.match(/export const AG_HUD_JS = `([\s\S]*)`;/)[1];
|
|
33
|
+
|
|
34
|
+
const message = {
|
|
35
|
+
id: 1,
|
|
36
|
+
method: "Runtime.evaluate",
|
|
37
|
+
params: {
|
|
38
|
+
expression: script,
|
|
39
|
+
awaitPromise: true,
|
|
40
|
+
userGesture: true
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
ws.send(JSON.stringify(message));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function updateHud(ws, state) {
|
|
47
|
+
const updateEvent = {
|
|
48
|
+
id: Date.now(),
|
|
49
|
+
method: "Runtime.evaluate",
|
|
50
|
+
params: {
|
|
51
|
+
expression: `window.dispatchEvent(new CustomEvent('ag-portal-update', { detail: ${JSON.stringify(state)} }));`
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
ws.send(JSON.stringify(updateEvent));
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function pushInstantAlert(ws, alertData) {
|
|
58
|
+
const alertEvent = {
|
|
59
|
+
id: Date.now(),
|
|
60
|
+
method: "Runtime.evaluate",
|
|
61
|
+
params: {
|
|
62
|
+
expression: `window.dispatchEvent(new CustomEvent('ag-portal-alert', { detail: ${JSON.stringify(alertData)} }));`
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
ws.send(JSON.stringify(alertEvent));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function startHttpServer() {
|
|
69
|
+
const server = http.createServer((req, res) => {
|
|
70
|
+
if (req.method === 'POST' && (req.url === '/alert' || req.url === '/update')) {
|
|
71
|
+
let body = '';
|
|
72
|
+
req.on('data', chunk => { body += chunk; });
|
|
73
|
+
req.on('end', async () => {
|
|
74
|
+
try {
|
|
75
|
+
const data = JSON.parse(body);
|
|
76
|
+
if (globalWs && globalWs.readyState === WebSocket.OPEN) {
|
|
77
|
+
if (req.url === '/alert') {
|
|
78
|
+
await pushInstantAlert(globalWs, data);
|
|
79
|
+
} else {
|
|
80
|
+
await updateHud(globalWs, data);
|
|
81
|
+
}
|
|
82
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
83
|
+
res.end(JSON.stringify({ status: 'ok' }));
|
|
84
|
+
} else {
|
|
85
|
+
res.writeHead(503, { 'Content-Type': 'application/json' });
|
|
86
|
+
res.end(JSON.stringify({ error: 'Bridge not connected to IDE' }));
|
|
87
|
+
}
|
|
88
|
+
} catch (e) {
|
|
89
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
90
|
+
res.end(JSON.stringify({ error: 'Invalid JSON' }));
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
} else {
|
|
94
|
+
res.writeHead(404);
|
|
95
|
+
res.end();
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
server.listen(BRIDGE_PORT, '0.0.0.0', () => {
|
|
100
|
+
console.log(`📡 Instant Alert Server listening on port ${BRIDGE_PORT}`);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
async function startBridge() {
|
|
105
|
+
console.log(`🛰️ Connecting to Antigravity Portal on port ${IDE_PORT}...`);
|
|
106
|
+
|
|
107
|
+
const wsUrl = await getWsUrl();
|
|
108
|
+
if (!wsUrl) {
|
|
109
|
+
console.log("❌ IDE is not running or port 9555 is closed.");
|
|
110
|
+
process.exit(1);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const ws = new WebSocket(wsUrl);
|
|
114
|
+
globalWs = ws;
|
|
115
|
+
|
|
116
|
+
ws.on('open', async () => {
|
|
117
|
+
console.log("✅ Bridge Established. Injecting Golden HUD...");
|
|
118
|
+
await injectHud(ws);
|
|
119
|
+
|
|
120
|
+
// Start HTTP server for instant pushes
|
|
121
|
+
startHttpServer();
|
|
122
|
+
|
|
123
|
+
// Background polling for legacy state compatibility
|
|
124
|
+
setInterval(async () => {
|
|
125
|
+
if (fs.existsSync(STATE_FILE)) {
|
|
126
|
+
const state = JSON.parse(fs.readFileSync(STATE_FILE, 'utf8'));
|
|
127
|
+
await updateHud(ws, state);
|
|
128
|
+
}
|
|
129
|
+
}, 5000);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
ws.on('message', (data) => {
|
|
133
|
+
const msg = JSON.parse(data);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
ws.on('error', (err) => {
|
|
137
|
+
console.error("❌ WS Error:", err);
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
startBridge();
|
package/template/start.sh
CHANGED
|
@@ -1,25 +1,22 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
+
# start.sh - Khởi động Cổng Agentic (Remoat + LazyGravity standard)
|
|
2
3
|
|
|
3
|
-
#
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
# 1. Load configuration
|
|
8
|
-
if [ -f .env ]; then
|
|
9
|
-
export $(grep -v '^#' .env | xargs)
|
|
10
|
-
else
|
|
11
|
-
echo "❌ Lỗi: Không tìm thấy file .env. Vui lòng tạo từ .env.example"
|
|
12
|
-
exit 1
|
|
4
|
+
# 1. Kiểm tra .env
|
|
5
|
+
if [ ! -f .env ]; then
|
|
6
|
+
echo "❌ Lỗi: Không tìm thấy file .env. Vui lòng tạo dựa trên .env.example"
|
|
7
|
+
exit 1
|
|
13
8
|
fi
|
|
14
9
|
|
|
15
|
-
# 2.
|
|
16
|
-
|
|
17
|
-
PROJECT_NAME=${PROJECT_NAME:-"ceogravity"}
|
|
10
|
+
# 2. Đọc cấu hình
|
|
11
|
+
source .env
|
|
18
12
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
# 3. Khởi động IDE ở chế độ Debug (nếu chưa chạy)
|
|
14
|
+
# Lưu ý: User nên chạy ./launch_remote_ide.sh trước hoặc script này sẽ kiểm tra port
|
|
15
|
+
nc -z localhost ${IDE_PORT:-9555}
|
|
16
|
+
if [ $? -ne 0 ]; then
|
|
17
|
+
echo "⚠️ Cảnh báo: Cổng CDP ${IDE_PORT:-9555} chưa mở. Đang chờ Antigravity khởi động..."
|
|
18
|
+
fi
|
|
22
19
|
|
|
23
|
-
#
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
# 4. Khởi động Bridge và Bot (Agent-Defined)
|
|
21
|
+
echo "🚀 Khởi động Lễ tân trực chiến (Agentic Gateway)..."
|
|
22
|
+
bash .agent/scripts/receptionist_up.sh
|
package/template/stop_bot.sh
CHANGED
|
@@ -1,17 +1,9 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
+
# stop_bot.sh - Hạ cánh an toàn (Remoat + LazyGravity standard)
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
# --------------------------------------------------
|
|
4
|
+
echo "🛑 Đang tắt toàn bộ trạm điều hành Agentic..."
|
|
5
5
|
|
|
6
|
-
#
|
|
7
|
-
|
|
6
|
+
# Gọi script hạ cánh tiêu chuẩn (Agent-Defined)
|
|
7
|
+
bash .agent/scripts/receptionist_down.sh
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
PIDS=$(pgrep -f "tsx src/index.ts")
|
|
11
|
-
|
|
12
|
-
if [ -z "$PIDS" ]; then
|
|
13
|
-
echo "⚠️ Không tìm thấy tiến trình Bot đang chạy."
|
|
14
|
-
else
|
|
15
|
-
kill $PIDS
|
|
16
|
-
echo "✅ Đã dừng Bot (PIDs: $PIDS)"
|
|
17
|
-
fi
|
|
9
|
+
echo "✅ Đã dọn dẹp xong."
|