@mrtrinhvn/ag-kit 1.4.3 → 1.4.6
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 +13 -0
- package/bin/cli.js +87 -16
- package/package.json +1 -1
- package/template/.agent/knowledge/ag-kit-ecosystem.md +15 -1
- package/template/.agent/scripts/receptionist_down.sh +11 -18
- package/template/.agent/scripts/receptionist_up.sh +26 -128
- package/template/.agent/skills/telegram-agentic-gateway/templates/start.sh.template +25 -12
- package/template/start.sh +25 -12
- package/template/.agent/scripts/port_utils.sh +0 -106
package/README.md
CHANGED
|
@@ -58,6 +58,19 @@ Gói `ag-kit` khuyến khích nguyên lý kết hợp 2 AI:
|
|
|
58
58
|
|
|
59
59
|
> Vui lòng tải model: `ollama pull nomic-embed-text` để kích hoạt tính năng Semantic Search của `ag-kit`.
|
|
60
60
|
|
|
61
|
+
## 🚀 Agentic Port Fusion (Cơ chế Hợp Thể Cổng)
|
|
62
|
+
|
|
63
|
+
AG-Kit sử dụng kỹ thuật **JSON Introspection** và **Chromium Multiplexing** để giải quyết vĩnh viễn bài toán đụng độ Cổng (Port) khi chạy nhiều Agent/IDE cùng lúc trên một máy:
|
|
64
|
+
|
|
65
|
+
1. **Lớp IDE (Cổng Trạm - `IDE_PORT`):**
|
|
66
|
+
- Mọi dự án có thể **dùng chung một cổng duy nhất (VD: 9555)**.
|
|
67
|
+
- `start.sh` sẽ tự động ping cổng 9555, dùng `curl` quét danh sách JSON (`/json/list`) xem dự án của mình đã mở chưa.
|
|
68
|
+
- Nếu chưa, nó ra lệnh cho Chrome tự động rẽ nhánh thêm một cửa sổ (Workspace) ngay trên cổng 9555 đó. Bot của dự án nào sẽ tự động bắt đúng UUID WebSocket của dự án đó! Chấm dứt cảnh spam Port làm rác cấu hình.
|
|
69
|
+
|
|
70
|
+
2. **Lớp Bot (Cổng Nội Bộ - `BRIDGE_PORT`):**
|
|
71
|
+
- Không thể xài chung do giới hạn của Node.js.
|
|
72
|
+
- Khi chạy lệnh `ag-kit init`, AG-Kit sẽ tự động săn tìm một cổng Bridge đang trống (từ 9656 trở lên) và cấp phát **độc quyền** cho dự án thông qua file `.env`.
|
|
73
|
+
|
|
61
74
|
---
|
|
62
75
|
|
|
63
76
|
## 🔄 Cập nhật & Bảo trì
|
package/bin/cli.js
CHANGED
|
@@ -32,16 +32,44 @@ program
|
|
|
32
32
|
|
|
33
33
|
program.command('init')
|
|
34
34
|
.description('Cấy ghép Lõi Trí Nhớ (.agent) vào dự án này')
|
|
35
|
-
.action(() => {
|
|
35
|
+
.action(async () => {
|
|
36
36
|
console.log('\x1b[36m🚀 Đang khởi tạo bộ Tủy Não Lập Trình AI (AG-Kit)...\x1b[0m');
|
|
37
37
|
|
|
38
38
|
const srcAgent = path.join(TEMPLATE_DIR, '.agent');
|
|
39
39
|
if (!fs.existsSync(TARGET_AGENT_DIR)) {
|
|
40
40
|
copyRecursiveSync(srcAgent, TARGET_AGENT_DIR);
|
|
41
41
|
fs.writeFileSync(path.join(TARGET_AGENT_DIR, '.version'), pkg.version);
|
|
42
|
-
|
|
42
|
+
|
|
43
|
+
['scripts', 'start.sh', 'stop_bot.sh', '.gitignore'].forEach(item => {
|
|
44
|
+
const srcPath = path.join(TEMPLATE_DIR, item);
|
|
45
|
+
const destPath = path.join(process.cwd(), item);
|
|
46
|
+
if (fs.existsSync(srcPath) && !fs.existsSync(destPath)) {
|
|
47
|
+
copyRecursiveSync(srcPath, destPath);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const net = require('net');
|
|
52
|
+
const getPort = (port) => new Promise((resolve) => {
|
|
53
|
+
const s = net.createServer();
|
|
54
|
+
s.listen(port, () => { s.close(() => resolve(port)); });
|
|
55
|
+
s.on('error', () => { resolve(getPort(port + 1)); });
|
|
56
|
+
});
|
|
57
|
+
const bridgePort = await getPort(9656);
|
|
58
|
+
|
|
59
|
+
const envEx = path.join(TEMPLATE_DIR, '.env.example');
|
|
60
|
+
if (fs.existsSync(envEx) && !fs.existsSync('.env')) {
|
|
61
|
+
let content = fs.readFileSync(envEx, 'utf-8');
|
|
62
|
+
const projectName = path.basename(process.cwd());
|
|
63
|
+
content = content.replace(/PROJECT_NAME=.*/, `PROJECT_NAME=${projectName}`);
|
|
64
|
+
content = content.replace(/BRIDGE_PORT=.*/, `BRIDGE_PORT=${bridgePort}`);
|
|
65
|
+
fs.writeFileSync('.env', content);
|
|
66
|
+
console.log(`\x1b[32m✅ Đã cấp phát .env với BRIDGE_PORT=${bridgePort} độc quyền.\x1b[0m`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
console.log(`\x1b[32m✅ Đã cấy ghép thành công AG-Kit (v${pkg.version}) vào Project!\x1b[0m`);
|
|
43
70
|
|
|
44
|
-
console.log('\x1b[35m👉 Bước
|
|
71
|
+
console.log('\x1b[35m👉 Bước 1: Mở .env và điền TELEGRAM_BOT_TOKEN.\x1b[0m');
|
|
72
|
+
console.log('\x1b[35m👉 Bước 2: Chạy "./start.sh" để gọi Bot thức dậy.\x1b[0m');
|
|
45
73
|
} else {
|
|
46
74
|
console.log('\x1b[33m⚠️ Thư mục .agent đã tồn tại.\x1b[0m');
|
|
47
75
|
const vPath = path.join(TARGET_AGENT_DIR, '.version');
|
|
@@ -122,7 +150,7 @@ program.command('memory')
|
|
|
122
150
|
|
|
123
151
|
program.command('gateway')
|
|
124
152
|
.description('Kiểm tra trạng thái Agentic Gateway (IDE, Ollama, Telegram)')
|
|
125
|
-
.action(() => {
|
|
153
|
+
.action(async () => {
|
|
126
154
|
console.log('\x1b[36m🤖 Đang kiểm tra hệ sinh thái Agentic Gateway...\x1b[0m');
|
|
127
155
|
if (!fs.existsSync(TARGET_AGENT_DIR)) {
|
|
128
156
|
console.log('\x1b[31m❌ Chưa cấy ghép .agent.\x1b[0m');
|
|
@@ -130,20 +158,43 @@ program.command('gateway')
|
|
|
130
158
|
}
|
|
131
159
|
const envPath = path.join(process.cwd(), '.env');
|
|
132
160
|
let targetPort = null;
|
|
161
|
+
let bridgePort = null;
|
|
133
162
|
if (fs.existsSync(envPath)) {
|
|
134
|
-
const
|
|
135
|
-
|
|
163
|
+
const content = fs.readFileSync(envPath, 'utf-8');
|
|
164
|
+
const matchIde = content.match(/IDE_PORT=(\d+)/);
|
|
165
|
+
if (matchIde) targetPort = parseInt(matchIde[1]);
|
|
166
|
+
const matchBridge = content.match(/BRIDGE_PORT=(\d+)/);
|
|
167
|
+
if (matchBridge) bridgePort = parseInt(matchBridge[1]);
|
|
136
168
|
}
|
|
137
169
|
|
|
170
|
+
// 1. Kiểm tra lớp IDE (Hub)
|
|
138
171
|
if (targetPort) {
|
|
139
172
|
try {
|
|
140
173
|
execSync(`curl -s --max-time 2 http://127.0.0.1:${targetPort}/json/version`, { stdio: 'ignore' });
|
|
141
|
-
console.log(`\x1b[32m✅ IDE CDP: Cổng
|
|
174
|
+
console.log(`\x1b[32m✅ IDE CDP: Cổng Trạm (Hub ${targetPort}) đang Online!\x1b[0m`);
|
|
142
175
|
} catch (e) {
|
|
143
|
-
console.log(`\x1b[31m❌ IDE CDP: Cổng
|
|
176
|
+
console.log(`\x1b[31m❌ IDE CDP: Cổng Trạm (Hub ${targetPort}) Offline. Chạy ./start.sh để tự gọi.\x1b[0m`);
|
|
144
177
|
}
|
|
145
178
|
} else {
|
|
146
|
-
console.log(`\x1b[33m⚠️ IDE CDP: Không tìm thấy IDE_PORT trong .env
|
|
179
|
+
console.log(`\x1b[33m⚠️ IDE CDP: Không tìm thấy IDE_PORT trong .env.\x1b[0m`);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// 2. Kiểm tra lớp Bot Nodejs (Bridge)
|
|
183
|
+
if (bridgePort) {
|
|
184
|
+
const net = require('net');
|
|
185
|
+
const checkBridge = () => new Promise((resolve) => {
|
|
186
|
+
const s = new net.Socket();
|
|
187
|
+
s.setTimeout(2000);
|
|
188
|
+
s.on('connect', () => { s.destroy(); resolve(true); });
|
|
189
|
+
s.on('error', () => { resolve(false); });
|
|
190
|
+
s.on('timeout', () => { s.destroy(); resolve(false); });
|
|
191
|
+
s.connect(bridgePort, '127.0.0.1');
|
|
192
|
+
});
|
|
193
|
+
const up = await checkBridge();
|
|
194
|
+
if (up) console.log(`\x1b[32m✅ BRIDGE: Cổng nội bộ Bot (${bridgePort}) đang Online!\x1b[0m`);
|
|
195
|
+
else console.log(`\x1b[31m❌ BRIDGE: Cổng nội bộ Bot (${bridgePort}) đang Offline. Bot chưa nhúng.\x1b[0m`);
|
|
196
|
+
} else {
|
|
197
|
+
console.log(`\x1b[33m⚠️ BRIDGE: Không tìm thấy BRIDGE_PORT trong .env.\x1b[0m`);
|
|
147
198
|
}
|
|
148
199
|
|
|
149
200
|
try {
|
|
@@ -196,28 +247,48 @@ program.command('status')
|
|
|
196
247
|
async function runInteractiveMenu() {
|
|
197
248
|
const inquirer = require('inquirer');
|
|
198
249
|
console.clear();
|
|
199
|
-
console.log('\x1b[35m\n🧠 AG-KIT - BẢNG ĐIỀU KHIỂN HỆ SINH THÁI AI\x1b[0m');
|
|
200
|
-
console.log('\x1b[34m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m');
|
|
201
250
|
|
|
202
251
|
const hasAgent = fs.existsSync(TARGET_AGENT_DIR);
|
|
203
252
|
const vPath = path.join(TARGET_AGENT_DIR, '.version');
|
|
204
253
|
let updateTag = '';
|
|
254
|
+
let hasUpdate = false;
|
|
255
|
+
let statusText = '\x1b[31mTrắng\x1b[0m';
|
|
256
|
+
|
|
205
257
|
if (hasAgent && fs.existsSync(vPath)) {
|
|
206
258
|
const installed = fs.readFileSync(vPath, 'utf-8').trim();
|
|
259
|
+
statusText = `\x1b[32mv${installed}\x1b[0m`;
|
|
207
260
|
if (installed !== pkg.version) {
|
|
208
|
-
updateTag = `\x1b[31m(
|
|
261
|
+
updateTag = `\x1b[31m(Cần lên v${pkg.version})\x1b[0m `;
|
|
262
|
+
hasUpdate = true;
|
|
209
263
|
}
|
|
210
264
|
}
|
|
211
265
|
|
|
212
|
-
|
|
266
|
+
let brainStatus = '\x1b[33mChưa quét\x1b[0m';
|
|
267
|
+
const brainPath = path.join(TARGET_AGENT_DIR, 'brain', 'summary.md');
|
|
268
|
+
if (hasAgent && fs.existsSync(brainPath)) {
|
|
269
|
+
brainStatus = '\x1b[32mĐã có não\x1b[0m';
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
console.log('\x1b[35m\n🧠 AG-KIT - BẢNG ĐIỀU KHIỂN HỆ SINH THÁI AI\x1b[0m');
|
|
273
|
+
console.log(` Lõi: ${statusText} | Nhận thức: ${brainStatus}`);
|
|
274
|
+
console.log('\x1b[34m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\x1b[0m');
|
|
275
|
+
|
|
276
|
+
const agentChoices = [
|
|
213
277
|
{ name: `🧠 Xây dựng / Cập nhật Bộ Não (build brain) - Thu thập Context`, value: 'brain' },
|
|
214
278
|
{ name: `🕸️ Khám phá Ký ức (memory) - Xem dữ liệu Vector`, value: 'memory' },
|
|
215
279
|
{ name: `🤖 Kiểm tra Agentic Gateway (gateway) - Test IDE/Bot`, value: 'gateway' },
|
|
216
|
-
|
|
217
|
-
|
|
280
|
+
];
|
|
281
|
+
|
|
282
|
+
if (hasUpdate) {
|
|
283
|
+
agentChoices.push({ name: `🔄 Nâng Cấp Kiến Thức (update) ${updateTag}`, value: 'update' });
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
agentChoices.push(
|
|
218
287
|
new inquirer.Separator(),
|
|
219
288
|
{ name: '❌ Thoát', value: 'exit' }
|
|
220
|
-
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
const choices = hasAgent ? agentChoices : [
|
|
221
292
|
{ name: '🚀 Khởi tạo (init) - Cấy ghép Tủy Não .agent vào thư mục này', value: 'init' },
|
|
222
293
|
new inquirer.Separator(),
|
|
223
294
|
{ name: '❌ Thoát', value: 'exit' }
|
package/package.json
CHANGED
|
@@ -141,7 +141,21 @@ Khi đang làm việc ở Project A và cần hiểu Project B:
|
|
|
141
141
|
|
|
142
142
|
---
|
|
143
143
|
|
|
144
|
-
## 8.
|
|
144
|
+
## 8. CƠ CHẾ PORT FUSION (Cấp phát động và Hợp thể)
|
|
145
|
+
|
|
146
|
+
Để giúp Agentic Server (Cầu nối) và Lõi Trí Tuệ (IDE Chromium) không dẫm chân lên nhau khi Owner chạy nhiềuvproject cùng lúc, hệ sinh thái sử dụng kiến trúc phân tầng Port:
|
|
147
|
+
|
|
148
|
+
- **`IDE_PORT` (Khuyến nghị dùng chung 9555)**:
|
|
149
|
+
Lớp hệ điều hành Chromium hỗ trợ **Multiplexing - Dùng chung Hub**, cho phép hàng chục dự án dùng chung 1 cổng mạng duy nhất. Script `start.sh` tích hợp "JSON X-Ray", tự động ping vào cổng 9555 để kiểm tra JSON API `/json/list` xem project của mình đã nạp chưa.
|
|
150
|
+
- Nếu có: Hệ thống tự trích xuất UUID (mấu WebSocket) và hợp thể.
|
|
151
|
+
- Nếu không: Nó ép tiến trình Chromium đang chạy rẽ thêm Workspace, tuyệt đối không spam port ảo.
|
|
152
|
+
|
|
153
|
+
- **`BRIDGE_PORT` (Cấp phát động từ 9656)**:
|
|
154
|
+
Lớp kết nối mạng nội bộ Node.js (phục vụ Gateway/Telegram) đòi hỏi giao thức **độc quyền**. Lệnh `ag-kit init` sẽ tự động săn một cổng rỗng trên hệ điều hành vật lý (9656++) và khắc tử vào trong file `.env` của project mới.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## 9. KHỞI ĐỘNG PROJECT MỚI (Bootstrap Protocol)
|
|
145
159
|
|
|
146
160
|
Khi anh muốn thêm một project mới vào hệ sinh thái:
|
|
147
161
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
|
|
3
|
-
# --- Antigravity Unified Shutdown (
|
|
3
|
+
# --- Antigravity Unified Shutdown (Port Fusion Edition) ---
|
|
4
4
|
# Dọn dẹp trạm gác Agentic Gateway.
|
|
5
5
|
|
|
6
6
|
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
@@ -10,36 +10,29 @@ if [ -f .env ]; then
|
|
|
10
10
|
source .env
|
|
11
11
|
fi
|
|
12
12
|
|
|
13
|
-
BRIDGE_PORT=${BRIDGE_PORT:-
|
|
13
|
+
BRIDGE_PORT=${BRIDGE_PORT:-9656}
|
|
14
14
|
|
|
15
15
|
echo "════════════════════════════════════════════════════"
|
|
16
|
-
echo " 🛑
|
|
16
|
+
echo " 🛑 ĐANG TẮT AG GATEWAY [$BRIDGE_PORT]..."
|
|
17
17
|
echo "════════════════════════════════════════════════════"
|
|
18
18
|
|
|
19
|
-
# 1. Tắt
|
|
20
|
-
|
|
21
|
-
if [ -f "$SENTINEL_PID_FILE" ]; then
|
|
22
|
-
kill $(cat "$SENTINEL_PID_FILE") 2>/dev/null && rm "$SENTINEL_PID_FILE"
|
|
23
|
-
echo "✅ Sentinel stopped."
|
|
24
|
-
fi
|
|
25
|
-
|
|
26
|
-
# 2. Tắt Portal Bridge
|
|
27
|
-
BRIDGE_PID_FILE=".portal_bridge_${BRIDGE_PORT}.pid"
|
|
19
|
+
# 1. Tắt Portal Bridge
|
|
20
|
+
BRIDGE_PID_FILE=".agent/logs/.portal_bridge_${BRIDGE_PORT}.pid"
|
|
28
21
|
if [ -f "$BRIDGE_PID_FILE" ]; then
|
|
29
22
|
kill $(cat "$BRIDGE_PID_FILE") 2>/dev/null && rm "$BRIDGE_PID_FILE"
|
|
30
|
-
echo "✅ HUD Bridge
|
|
23
|
+
echo "✅ HUD Bridge đã tắt."
|
|
31
24
|
fi
|
|
32
25
|
|
|
33
|
-
#
|
|
34
|
-
BOT_PID_FILE=".ag_gateway_bot.pid"
|
|
26
|
+
# 2. Tắt Bot
|
|
27
|
+
BOT_PID_FILE=".agent/logs/.ag_gateway_bot.pid"
|
|
35
28
|
if [ -f "$BOT_PID_FILE" ]; then
|
|
36
29
|
PID=$(cat "$BOT_PID_FILE")
|
|
37
30
|
# Kill the whole process group for the bash loop
|
|
38
|
-
pkill -P $PID
|
|
31
|
+
pkill -P $PID 2>/dev/null
|
|
39
32
|
kill $PID 2>/dev/null && rm "$BOT_PID_FILE"
|
|
40
|
-
echo "✅
|
|
33
|
+
echo "✅ Bot Telegram đã tắt."
|
|
41
34
|
fi
|
|
42
35
|
|
|
43
36
|
echo "════════════════════════════════════════════════════"
|
|
44
|
-
echo "✅ AG GATEWAY
|
|
37
|
+
echo "✅ HỆ THỐNG AG GATEWAY ĐĐA NGỦ."
|
|
45
38
|
echo "════════════════════════════════════════════════════"
|
|
@@ -1,159 +1,57 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
|
|
3
|
-
# --- Antigravity Unified Receptionist (
|
|
3
|
+
# --- Antigravity Unified Receptionist (Port Fusion Edition) ---
|
|
4
4
|
# Trạm gác hợp nhất: AG Gateway Bot + Portal Bridge (HUD)
|
|
5
|
-
# Dự án: Template Agentic Orchestrator
|
|
6
5
|
|
|
7
|
-
# 1. Load Cấu hình & Xử lý Cổng Thông minh
|
|
8
6
|
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
9
7
|
cd "$PROJECT_DIR"
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
mkdir -p .agent/logs
|
|
10
|
+
|
|
11
|
+
# 1. Load Cấu hình Tĩnh từ .env
|
|
12
|
+
if [ -f .env ]; then
|
|
14
13
|
source .env
|
|
15
|
-
export IDE_PORT=${IDE_PORT:-9557}
|
|
16
|
-
export BRIDGE_PORT=${BRIDGE_PORT:-9658}
|
|
17
14
|
fi
|
|
18
15
|
|
|
16
|
+
export IDE_PORT=${IDE_PORT:-9555}
|
|
17
|
+
export BRIDGE_PORT=${BRIDGE_PORT:-9656}
|
|
18
|
+
|
|
19
19
|
echo "════════════════════════════════════════════════════"
|
|
20
|
-
echo " 🏢 AG GATEWAY -
|
|
20
|
+
echo " 🏢 AG GATEWAY - CẦU NỐI NỘI BỘ [$BRIDGE_PORT]"
|
|
21
21
|
echo "════════════════════════════════════════════════════"
|
|
22
22
|
|
|
23
|
-
# 2.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
for arg in "$@"; do
|
|
27
|
-
if [ "$arg" == "--headless" ]; then HEADLESS=true; fi
|
|
28
|
-
if [ "$arg" == "--tunnel" ]; then TUNNEL=true; fi
|
|
29
|
-
done
|
|
30
|
-
|
|
31
|
-
# 3. Kiểm tra/Khởi động IDE
|
|
32
|
-
echo -n "[2/4] 🛰️ Checking IDE Portal (Port $IDE_PORT)... "
|
|
33
|
-
if curl -s http://127.0.0.1:$IDE_PORT/json/version > /dev/null; then
|
|
34
|
-
echo "✅ READY."
|
|
35
|
-
if [ "$HEADLESS" != true ]; then
|
|
36
|
-
echo " 🔄 Attempting to wake/focus UI..."
|
|
37
|
-
# Cố gắng push UI lên (nếu đang ngầm)
|
|
38
|
-
antigravity "$PROJECT_DIR" > /dev/null 2>&1 &
|
|
39
|
-
|
|
40
|
-
if [ -t 0 ]; then
|
|
41
|
-
echo -n " 🤔 Did the IDE window appear? [Y/n] (Auto-yes in 5s): "
|
|
42
|
-
read -t 5 -n 1 user_input
|
|
43
|
-
echo ""
|
|
44
|
-
user_input=${user_input:-Y}
|
|
45
|
-
else
|
|
46
|
-
user_input="Y"
|
|
47
|
-
fi
|
|
48
|
-
|
|
49
|
-
if [[ "$user_input" =~ ^[Nn]$ ]]; then
|
|
50
|
-
echo " 💀 UI Failed. Killing specific phantom instance for this project..."
|
|
51
|
-
# Chỉ kill những process chứa flag remote và project hiện tại
|
|
52
|
-
pkill -f "antigravity.*--remote-debugging-port=$IDE_PORT"
|
|
53
|
-
pkill -f "antigravity.*$PROJECT_DIR"
|
|
54
|
-
sleep 2
|
|
55
|
-
echo " 🚀 Launching fresh Antigravity with UI on port $IDE_PORT..."
|
|
56
|
-
nohup antigravity --remote-debugging-port=$IDE_PORT "$PROJECT_DIR" > /dev/null 2>&1 &
|
|
57
|
-
sleep 5
|
|
58
|
-
fi
|
|
59
|
-
fi
|
|
60
|
-
else
|
|
61
|
-
echo "❌ NOT FOUND."
|
|
62
|
-
if [ "$HEADLESS" = true ]; then
|
|
63
|
-
echo " 🚀 Launching Antigravity in HEADLESS mode on port $IDE_PORT..."
|
|
64
|
-
nohup antigravity --server --remote-debugging-port=$IDE_PORT "$PROJECT_DIR" > /dev/null 2>&1 &
|
|
65
|
-
else
|
|
66
|
-
echo " 🚀 Launching Antigravity with UI on port $IDE_PORT..."
|
|
67
|
-
nohup antigravity --remote-debugging-port=$IDE_PORT "$PROJECT_DIR" > /dev/null 2>&1 &
|
|
68
|
-
fi
|
|
69
|
-
sleep 5
|
|
70
|
-
fi
|
|
71
|
-
|
|
72
|
-
# 4. Cloudflare Tunnel & QR Code (If requested)
|
|
73
|
-
if [ "$TUNNEL" = true ]; then
|
|
74
|
-
echo "[T] 🌐 Starting Cloudflare Tunnel..."
|
|
75
|
-
if ! command -v cloudflared &> /dev/null; then
|
|
76
|
-
echo " ❌ Error: cloudflared not installed."
|
|
77
|
-
else
|
|
78
|
-
nohup cloudflared tunnel --url http://127.0.0.1:$BRIDGE_PORT > .tunnel.log 2>&1 &
|
|
79
|
-
sleep 5
|
|
80
|
-
TUNNEL_URL=$(grep -o 'https://.*\.trycloudflare\.com' .tunnel.log | head -n 1)
|
|
81
|
-
if [ -n "$TUNNEL_URL" ]; then
|
|
82
|
-
echo " ✅ Tunnel Active: $TUNNEL_URL"
|
|
83
|
-
echo " 📱 Generating QR Code..."
|
|
84
|
-
python3 -c "import qrcode; qr = qrcode.QRCode(); qr.add_data('$TUNNEL_URL'); qr.print_ascii()"
|
|
85
|
-
else
|
|
86
|
-
echo " ⚠️ Could not extract tunnel URL. Check .tunnel.log"
|
|
87
|
-
fi
|
|
88
|
-
fi
|
|
89
|
-
fi
|
|
90
|
-
echo "✅ READY."
|
|
91
|
-
|
|
92
|
-
# 3. Khởi động Portal Bridge (HUD Injector)
|
|
93
|
-
echo "[3/4] 🧪 Injected Golden HUD Bridge... "
|
|
94
|
-
BRIDGE_PID_FILE=".portal_bridge_${BRIDGE_PORT}.pid"
|
|
23
|
+
# 2. Khởi động Portal Bridge (HUD Injector)
|
|
24
|
+
echo "[1/2] 🧪 Đang gắn kết Golden HUD Bridge... "
|
|
25
|
+
BRIDGE_PID_FILE=".agent/logs/.portal_bridge_${BRIDGE_PORT}.pid"
|
|
95
26
|
if [ -f "$BRIDGE_PID_FILE" ]; then
|
|
96
27
|
kill $(cat "$BRIDGE_PID_FILE") 2>/dev/null
|
|
97
28
|
fi
|
|
98
|
-
nohup node scripts/ag_portal_bridge.js > ".portal_bridge_${BRIDGE_PORT}.log" 2>&1 &
|
|
29
|
+
nohup node scripts/ag_portal_bridge.js > ".agent/logs/portal_bridge_${BRIDGE_PORT}.log" 2>&1 &
|
|
99
30
|
echo $! > "$BRIDGE_PID_FILE"
|
|
100
|
-
echo " ✅ Bridge
|
|
31
|
+
echo " ✅ Bridge đang chạy (PID: $(cat "$BRIDGE_PID_FILE") tại Cổng $BRIDGE_PORT)"
|
|
101
32
|
|
|
102
|
-
#
|
|
103
|
-
echo "[
|
|
104
|
-
BOT_PID_FILE=".ag_gateway_bot.pid"
|
|
33
|
+
# 3. Khởi động AG Gateway Bot (Trợ lý Telegram)
|
|
34
|
+
echo "[2/2] 🤖 Đang đánh thức Truyền tin Telegram... "
|
|
35
|
+
BOT_PID_FILE=".agent/logs/.ag_gateway_bot.pid"
|
|
105
36
|
|
|
106
|
-
# Kill loop AND all tsx/node processes belonging to this token/project
|
|
107
|
-
# Chỉ kill nếu dự án có thư mục src/index.ts (tránh kill nhầm project khác chạy chung server)
|
|
108
37
|
if [ -f "src/index.ts" ] || [ -f "bot/index.ts" ]; then
|
|
109
38
|
pkill -f "tsx src/index.ts" 2>/dev/null
|
|
110
39
|
pkill -f "node src/index.ts" 2>/dev/null
|
|
111
40
|
fi
|
|
112
|
-
|
|
41
|
+
|
|
113
42
|
if [ -f "$BOT_PID_FILE" ]; then
|
|
114
43
|
kill -9 $(cat "$BOT_PID_FILE") 2>/dev/null
|
|
115
44
|
fi
|
|
116
|
-
sleep
|
|
45
|
+
sleep 1
|
|
117
46
|
|
|
118
|
-
# Start the bot with a more robust monitor
|
|
119
47
|
nohup bash -c "while true; do
|
|
120
|
-
echo \"\$(date):
|
|
121
|
-
npx tsx src/index.ts >>
|
|
48
|
+
echo \"\$(date): Khởi động Bot...\" >> .agent/logs/bot_interaction.log
|
|
49
|
+
npx tsx src/index.ts >> .agent/logs/bot_interaction.log 2>&1
|
|
122
50
|
EXIT_CODE=\$?
|
|
123
|
-
if [ \$EXIT_CODE -eq 0 ]; then break; fi
|
|
124
|
-
echo \"\$(date):
|
|
51
|
+
if [ \$EXIT_CODE -eq 0 ]; then break; fi
|
|
52
|
+
echo \"\$(date): Bot sụp đổ (Code: \$EXIT_CODE). Khởi động lại sau 5s...\" >> .agent/logs/bot_interaction.log
|
|
125
53
|
sleep 5
|
|
126
|
-
done" &
|
|
54
|
+
done" > /dev/null 2>&1 &
|
|
127
55
|
echo $! > "$BOT_PID_FILE"
|
|
128
|
-
echo " ✅
|
|
129
|
-
|
|
130
|
-
# 5. Sentinel Monitor (Giám sát Trí não)
|
|
131
|
-
echo "🛡️ Sentinel Active: Auto-shutdown if IDE connection lost."
|
|
132
|
-
SENTINEL_PID_FILE=".sentinel_${BRIDGE_PORT}.pid"
|
|
133
|
-
|
|
134
|
-
function start_sentinel() {
|
|
135
|
-
(
|
|
136
|
-
local fail_count=0
|
|
137
|
-
local PROJ_NAME=$(basename "$PROJECT_DIR")
|
|
138
|
-
# Give more time for the first check
|
|
139
|
-
sleep 60
|
|
140
|
-
while true; do
|
|
141
|
-
if ! curl -s "http://127.0.0.1:$IDE_PORT/json" | grep -q "$PROJ_NAME" > /dev/null 2>&1; then
|
|
142
|
-
fail_count=$((fail_count + 1))
|
|
143
|
-
if [ $fail_count -ge 3 ]; then
|
|
144
|
-
echo "$(date): ⚠️ IDE Lost. Auto-shutting down project..." >> .sentinel_crash.log
|
|
145
|
-
bash .agent/scripts/receptionist_down.sh
|
|
146
|
-
exit 0
|
|
147
|
-
fi
|
|
148
|
-
else
|
|
149
|
-
fail_count=0
|
|
150
|
-
fi
|
|
151
|
-
done
|
|
152
|
-
) &
|
|
153
|
-
echo $! > "$SENTINEL_PID_FILE"
|
|
154
|
-
}
|
|
155
|
-
start_sentinel
|
|
156
|
-
|
|
157
|
-
# Monitor
|
|
158
|
-
echo "----------------------------------------------------"
|
|
159
|
-
tail -f interaction_final.log
|
|
56
|
+
echo " ✅ Truyền tin Telegram đã lên sóng (PID: $(cat "$BOT_PID_FILE"))"
|
|
57
|
+
echo "✅ HOÀN TẤT. Hệ thống chạy ngầm, bạn có thể tắt Terminal này!"
|
|
@@ -10,25 +10,38 @@ else
|
|
|
10
10
|
fi
|
|
11
11
|
|
|
12
12
|
PORT=${IDE_PORT:-9555}
|
|
13
|
+
PROJ=${PROJECT_NAME:-"UnknownProject"}
|
|
13
14
|
|
|
14
|
-
echo "🔍 Đang kiểm tra IDE tại cổng $PORT..."
|
|
15
|
+
echo "🔍 Đang kiểm tra IDE cho [$PROJ] tại cổng $PORT..."
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
if
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
echo "⚠️ [MỞ MỚI]: Không tìm thấy IDE ở cổng $PORT. Đang tự động phóng một IDE mới chuyên biệt cho dự án này..."
|
|
21
|
-
|
|
22
|
-
if command -v cursor &> /dev/null; then
|
|
17
|
+
open_ide() {
|
|
18
|
+
if command -v antigravity &> /dev/null; then
|
|
19
|
+
antigravity --remote-debugging-port=$PORT . &
|
|
20
|
+
elif command -v cursor &> /dev/null; then
|
|
23
21
|
cursor --remote-debugging-port=$PORT . &
|
|
24
22
|
elif command -v code &> /dev/null; then
|
|
25
23
|
code --remote-debugging-port=$PORT . &
|
|
26
24
|
else
|
|
27
|
-
echo "❌ Lỗi: Không tìm thấy lệnh 'cursor' hoặc 'code'
|
|
28
|
-
echo "👉 Hãy tự mở IDE bằng tay cho thư mục này
|
|
25
|
+
echo "❌ Lỗi: Không tìm thấy lệnh 'antigravity', 'cursor' hoặc 'code'."
|
|
26
|
+
echo "👉 Hãy tự mở IDE bằng tay cho thư mục này."
|
|
29
27
|
fi
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
# 2. Logic Hợp thể & Mở mới linh hoạt
|
|
31
|
+
if nc -z 127.0.0.1 $PORT &>/dev/null; then
|
|
32
|
+
# Cổng đã mở, thám thính xem bên trong có dự án của mình không (lọc theo JSON Title/Url)
|
|
33
|
+
if curl -s --max-time 2 http://127.0.0.1:$PORT/json/list | grep -i "\"title\":.*$PROJ" &>/dev/null; then
|
|
34
|
+
echo "✅ [HỢP THỂ]: Cổng $PORT đang mở và Workspace [$PROJ] đang được hiển thị. Trực tiếp cắm ngầm Bot vào màn hình này..."
|
|
35
|
+
else
|
|
36
|
+
echo "⚠️ [GỌI CỬA]: Cổng $PORT có IDE đang chạy, nhưng chưa mở màn hình cho [$PROJ]. Đang ra lệnh mở thêm giao diện cho dự án này..."
|
|
37
|
+
open_ide
|
|
38
|
+
echo "⏳ Đang đợi màn hình phụ tải xong..."
|
|
39
|
+
sleep 4
|
|
40
|
+
fi
|
|
41
|
+
else
|
|
42
|
+
echo "⚠️ [MỞ MỚI TỪ ĐẦU]: Cổng CDP $PORT hoàn toàn trống. Đang phóng cỗ máy IDE chuyên biệt..."
|
|
43
|
+
open_ide
|
|
44
|
+
echo "⏳ Đang đợi rễ CDP bám rễ..."
|
|
32
45
|
sleep 4
|
|
33
46
|
fi
|
|
34
47
|
|
package/template/start.sh
CHANGED
|
@@ -10,25 +10,38 @@ else
|
|
|
10
10
|
fi
|
|
11
11
|
|
|
12
12
|
PORT=${IDE_PORT:-9555}
|
|
13
|
+
PROJ=${PROJECT_NAME:-"UnknownProject"}
|
|
13
14
|
|
|
14
|
-
echo "🔍 Đang kiểm tra IDE tại cổng $PORT..."
|
|
15
|
+
echo "🔍 Đang kiểm tra IDE cho [$PROJ] tại cổng $PORT..."
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
if
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
echo "⚠️ [MỞ MỚI]: Không tìm thấy IDE ở cổng $PORT. Đang tự động phóng một IDE mới chuyên biệt cho dự án này..."
|
|
21
|
-
|
|
22
|
-
if command -v cursor &> /dev/null; then
|
|
17
|
+
open_ide() {
|
|
18
|
+
if command -v antigravity &> /dev/null; then
|
|
19
|
+
antigravity --remote-debugging-port=$PORT . &
|
|
20
|
+
elif command -v cursor &> /dev/null; then
|
|
23
21
|
cursor --remote-debugging-port=$PORT . &
|
|
24
22
|
elif command -v code &> /dev/null; then
|
|
25
23
|
code --remote-debugging-port=$PORT . &
|
|
26
24
|
else
|
|
27
|
-
echo "❌ Lỗi: Không tìm thấy lệnh 'cursor' hoặc 'code'
|
|
28
|
-
echo "👉 Hãy tự mở IDE bằng tay cho thư mục này
|
|
25
|
+
echo "❌ Lỗi: Không tìm thấy lệnh 'antigravity', 'cursor' hoặc 'code'."
|
|
26
|
+
echo "👉 Hãy tự mở IDE bằng tay cho thư mục này."
|
|
29
27
|
fi
|
|
30
|
-
|
|
31
|
-
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
# 2. Logic Hợp thể & Mở mới linh hoạt
|
|
31
|
+
if nc -z 127.0.0.1 $PORT &>/dev/null; then
|
|
32
|
+
# Cổng đã mở, thám thính xem bên trong có dự án của mình không (lọc theo JSON Title/Url)
|
|
33
|
+
if curl -s --max-time 2 http://127.0.0.1:$PORT/json/list | grep -i "\"title\":.*$PROJ" &>/dev/null; then
|
|
34
|
+
echo "✅ [HỢP THỂ]: Cổng $PORT đang mở và Workspace [$PROJ] đang được hiển thị. Trực tiếp cắm ngầm Bot vào màn hình này..."
|
|
35
|
+
else
|
|
36
|
+
echo "⚠️ [GỌI CỬA]: Cổng $PORT có IDE đang chạy, nhưng chưa mở màn hình cho [$PROJ]. Đang ra lệnh mở thêm giao diện cho dự án này..."
|
|
37
|
+
open_ide
|
|
38
|
+
echo "⏳ Đang đợi màn hình phụ tải xong..."
|
|
39
|
+
sleep 4
|
|
40
|
+
fi
|
|
41
|
+
else
|
|
42
|
+
echo "⚠️ [MỞ MỚI TỪ ĐẦU]: Cổng CDP $PORT hoàn toàn trống. Đang phóng cỗ máy IDE chuyên biệt..."
|
|
43
|
+
open_ide
|
|
44
|
+
echo "⏳ Đang đợi rễ CDP bám rễ..."
|
|
32
45
|
sleep 4
|
|
33
46
|
fi
|
|
34
47
|
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
# --- Port Management Utility (Golden V6 - High Precision) ---
|
|
4
|
-
# Tự động quét và thu nạp cổng IDE theo từng dự án.
|
|
5
|
-
# Đảm bảo "Chính chủ" mới dùng, "Người lạ" thì né.
|
|
6
|
-
|
|
7
|
-
ENV_FILE=".env"
|
|
8
|
-
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
9
|
-
|
|
10
|
-
# 1. Tìm cổng trống dựa trên netstat
|
|
11
|
-
function find_free_port() {
|
|
12
|
-
local port=$1
|
|
13
|
-
while netstat -atn | grep -q ":$port "; do
|
|
14
|
-
port=$((port + 1))
|
|
15
|
-
done
|
|
16
|
-
echo $port
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
# 2. Cập nhật .env (Dùng sed tương thích đa hệ điều hành)
|
|
20
|
-
function update_env_port() {
|
|
21
|
-
local key=$1
|
|
22
|
-
local value=$2
|
|
23
|
-
if grep -q "^${key}=" "$ENV_FILE"; then
|
|
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
|
-
# 3. Quét dải cổng để tìm IDE của chính dự án này
|
|
35
|
-
function scan_project_ide() {
|
|
36
|
-
local start_p=$1
|
|
37
|
-
local end_p=$2
|
|
38
|
-
for ((p=start_p; p<=end_p; p++)); do
|
|
39
|
-
if netstat -atn | grep -q ":$p "; then
|
|
40
|
-
# Kiểm tra xem có đúng là IDE của dự án này đang ở cổng p không
|
|
41
|
-
PROJECT_NAME=$(basename "$PROJECT_DIR")
|
|
42
|
-
if curl -s "http://127.0.0.1:$p/json" | grep -q "$PROJECT_NAME" > /dev/null 2>&1; then
|
|
43
|
-
echo $p
|
|
44
|
-
return 0
|
|
45
|
-
fi
|
|
46
|
-
fi
|
|
47
|
-
done
|
|
48
|
-
echo ""
|
|
49
|
-
return 1
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
# --- Main Logic ---
|
|
53
|
-
|
|
54
|
-
# Nạp config cũ
|
|
55
|
-
if [ -f "$ENV_FILE" ]; then
|
|
56
|
-
source "$ENV_FILE"
|
|
57
|
-
fi
|
|
58
|
-
|
|
59
|
-
DEFAULT_IDE_START=9555
|
|
60
|
-
IDE_RANGE_END=9655
|
|
61
|
-
BRIDGE_OFFSET=101 # IDE 9555 -> Bridge 9656
|
|
62
|
-
|
|
63
|
-
CURRENT_CONFIG_IDE=${IDE_PORT:-$DEFAULT_IDE_START}
|
|
64
|
-
|
|
65
|
-
echo "🔍 Đang rà soát "Brain Portal" (Dải 100 cổng) cho dự án: $(basename "$PROJECT_DIR")..."
|
|
66
|
-
|
|
67
|
-
# Bước 1: Quét xem có IDE nào đang mở dự án này không (Dải 9555 - 9655)
|
|
68
|
-
FOUND_PORT=$(scan_project_ide $DEFAULT_IDE_START $IDE_RANGE_END)
|
|
69
|
-
|
|
70
|
-
if [ ! -z "$FOUND_PORT" ]; then
|
|
71
|
-
echo "✅ Phát hiện IDE đang chạy tại cổng: $FOUND_PORT"
|
|
72
|
-
export IDE_PORT=$FOUND_PORT
|
|
73
|
-
export BRIDGE_PORT=$((FOUND_PORT + BRIDGE_OFFSET))
|
|
74
|
-
|
|
75
|
-
# Cập nhật .env nếu có thay đổi
|
|
76
|
-
if [ "$FOUND_PORT" != "$CURRENT_CONFIG_IDE" ]; then
|
|
77
|
-
echo "📝 Cập nhật cổng mới vào .env..."
|
|
78
|
-
update_env_port "IDE_PORT" "$FOUND_PORT"
|
|
79
|
-
update_env_port "BRIDGE_PORT" "$BRIDGE_PORT"
|
|
80
|
-
fi
|
|
81
|
-
else
|
|
82
|
-
# Bước 2: Không thấy IDE cũ, kiểm tra cổng trong .env có bị "người lạ" chiếm không
|
|
83
|
-
echo "❓ Không tìm thấy IDE đang chạy. Tiến hành rà soát cổng khả dụng..."
|
|
84
|
-
|
|
85
|
-
# Nếu cổng hiện tại bị "người lạ" chiếm
|
|
86
|
-
if netstat -atn | grep -q ":$CURRENT_CONFIG_IDE "; then
|
|
87
|
-
echo "⚠️ Cổng mặc định $CURRENT_CONFIG_IDE đã bị dự án khác chiếm."
|
|
88
|
-
# Tìm IDE trống trong dải
|
|
89
|
-
FREE_IDE=$(find_free_port $DEFAULT_IDE_START)
|
|
90
|
-
FREE_BRIDGE=$(find_free_port $((FREE_IDE + BRIDGE_OFFSET)))
|
|
91
|
-
|
|
92
|
-
echo "🚀 Đã phân bổ cặp cổng trống mới: IDE=$FREE_IDE, BRIDGE=$FREE_BRIDGE"
|
|
93
|
-
update_env_port "IDE_PORT" "$FREE_IDE"
|
|
94
|
-
update_env_port "BRIDGE_PORT" "$FREE_BRIDGE"
|
|
95
|
-
|
|
96
|
-
export IDE_PORT=$FREE_IDE
|
|
97
|
-
export BRIDGE_PORT=$FREE_BRIDGE
|
|
98
|
-
else
|
|
99
|
-
# Cổng trong .env vẫn trống, dùng luôn
|
|
100
|
-
export IDE_PORT=$CURRENT_CONFIG_IDE
|
|
101
|
-
# Đảm bảo BRIDGE_PORT tương ứng
|
|
102
|
-
export BRIDGE_PORT=$((CURRENT_CONFIG_IDE + BRIDGE_OFFSET))
|
|
103
|
-
update_env_port "BRIDGE_PORT" "$BRIDGE_PORT"
|
|
104
|
-
echo "✅ Sử dụng cổng cấu hình: $IDE_PORT (Bridge: $BRIDGE_PORT)"
|
|
105
|
-
fi
|
|
106
|
-
fi
|