@mrtrinhvn/ag-kit 1.1.7 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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);
@@ -77,18 +97,33 @@ program.command('init')
77
97
  fs.writeFileSync(path.join(TARGET_AGENT_DIR, '.version'), pkg.version);
78
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 tạo .env nếu chưa có
100
+ // Khởi động .env nếu chưa có
81
101
  const envPath = path.join(process.cwd(), '.env');
82
- if (!fs.existsSync(envPath)) {
83
- fs.writeFileSync(envPath, 'CDP_PORT=9555\n');
84
- console.log('\x1b[34mℹ️ Đã tạo file .env mẫu với CDP_PORT=9555\x1b[0m');
85
- } else {
86
- const envContent = fs.readFileSync(envPath, 'utf-8');
87
- if (!envContent.includes('CDP_PORT=')) {
88
- fs.appendFileSync(envPath, '\nCDP_PORT=9555\n');
89
- console.log('\x1b[34mℹ️ Đã thêm cấu hình CDP_PORT=9555 vào file .env hiện tại\x1b[0m');
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} 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');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrtrinhvn/ag-kit",
3
- "version": "1.1.7",
3
+ "version": "1.2.0",
4
4
  "description": "Antigravity Kit Base Framework - Generic Agentic AI Programming Core",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -32,4 +32,4 @@
32
32
  "commander": "^14.0.3",
33
33
  "inquirer": "^8.2.5"
34
34
  }
35
- }
35
+ }
@@ -0,0 +1,105 @@
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
+ if curl -s "http://127.0.0.1:$p/json" | grep -q "$PROJECT_DIR" > /dev/null 2>&1; then
42
+ echo $p
43
+ return 0
44
+ fi
45
+ fi
46
+ done
47
+ echo ""
48
+ return 1
49
+ }
50
+
51
+ # --- Main Logic ---
52
+
53
+ # Nạp config cũ
54
+ if [ -f "$ENV_FILE" ]; then
55
+ source "$ENV_FILE"
56
+ fi
57
+
58
+ DEFAULT_IDE_START=9555
59
+ IDE_RANGE_END=9655
60
+ BRIDGE_OFFSET=101 # IDE 9555 -> Bridge 9656
61
+
62
+ CURRENT_CONFIG_IDE=${IDE_PORT:-$DEFAULT_IDE_START}
63
+
64
+ echo "🔍 Đang rà soát "Brain Portal" (Dải 100 cổng) cho dự án: $(basename "$PROJECT_DIR")..."
65
+
66
+ # Bước 1: Quét xem có IDE nào đang mở dự án này không (Dải 9555 - 9655)
67
+ FOUND_PORT=$(scan_project_ide $DEFAULT_IDE_START $IDE_RANGE_END)
68
+
69
+ if [ ! -z "$FOUND_PORT" ]; then
70
+ echo "✅ Phát hiện IDE đang chạy tại cổng: $FOUND_PORT"
71
+ export IDE_PORT=$FOUND_PORT
72
+ export BRIDGE_PORT=$((FOUND_PORT + BRIDGE_OFFSET))
73
+
74
+ # Cập nhật .env nếu có thay đổi
75
+ if [ "$FOUND_PORT" != "$CURRENT_CONFIG_IDE" ]; then
76
+ echo "📝 Cập nhật cổng mới vào .env..."
77
+ update_env_port "IDE_PORT" "$FOUND_PORT"
78
+ update_env_port "BRIDGE_PORT" "$BRIDGE_PORT"
79
+ fi
80
+ else
81
+ # 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
82
+ echo "❓ Không tìm thấy IDE đang chạy. Tiến hành rà soát cổng khả dụng..."
83
+
84
+ # Nếu cổng hiện tại bị "người lạ" chiếm
85
+ if netstat -atn | grep -q ":$CURRENT_CONFIG_IDE "; then
86
+ echo "⚠️ Cổng mặc định $CURRENT_CONFIG_IDE đã bị dự án khác chiếm."
87
+ # Tìm IDE trống trong dải
88
+ FREE_IDE=$(find_free_port $DEFAULT_IDE_START)
89
+ FREE_BRIDGE=$(find_free_port $((FREE_IDE + BRIDGE_OFFSET)))
90
+
91
+ echo "🚀 Đã phân bổ cặp cổng trống mới: IDE=$FREE_IDE, BRIDGE=$FREE_BRIDGE"
92
+ update_env_port "IDE_PORT" "$FREE_IDE"
93
+ update_env_port "BRIDGE_PORT" "$FREE_BRIDGE"
94
+
95
+ export IDE_PORT=$FREE_IDE
96
+ export BRIDGE_PORT=$FREE_BRIDGE
97
+ else
98
+ # Cổng trong .env vẫn trống, dùng luôn
99
+ export IDE_PORT=$CURRENT_CONFIG_IDE
100
+ # Đảm bảo BRIDGE_PORT tương ứng
101
+ export BRIDGE_PORT=$((CURRENT_CONFIG_IDE + BRIDGE_OFFSET))
102
+ update_env_port "BRIDGE_PORT" "$BRIDGE_PORT"
103
+ echo "✅ Sử dụng cổng cấu hình: $IDE_PORT (Bridge: $BRIDGE_PORT)"
104
+ fi
105
+ fi
@@ -0,0 +1,39 @@
1
+ #!/bin/bash
2
+
3
+ # --- Antigravity Unified Shutdown (Golden V6 - High Precision) ---
4
+ # Dọn dẹp trạm gác Agentic.
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 Sentinel Monitor
20
+ SENTINEL_PID_FILE=".sentinel_${BRIDGE_PORT}.pid"
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"
28
+ if [ -f "$BRIDGE_PID_FILE" ]; then
29
+ kill $(cat "$BRIDGE_PID_FILE") 2>/dev/null && rm "$BRIDGE_PID_FILE"
30
+ echo "✅ HUD Bridge stopped."
31
+ fi
32
+
33
+ # 3. Tắt Bot (Tùy chỉnh theo dự án)
34
+ # echo "[3/3] 🤖 Stopping Bot..."
35
+ # [TEMPLATE_NOTE]: Sếp hãy gõ lệnh dừng Bot của mình vào đây.
36
+
37
+ echo "════════════════════════════════════════════════════"
38
+ echo "✅ PROJECT IS IDLE."
39
+ echo "════════════════════════════════════════════════════"
@@ -0,0 +1,85 @@
1
+ #!/bin/bash
2
+
3
+ # --- Antigravity Unified Receptionist (Golden V6 - High Precision) ---
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
+ # 2. Kiểm tra/Khởi độ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 " 🚀 Launching Antigravity with CDP on port $IDE_PORT..."
30
+ nohup antigravity --remote-debugging-port=$IDE_PORT "$PROJECT_DIR" > /dev/null 2>&1 &
31
+ sleep 3
32
+ if curl -s http://127.0.0.1:$IDE_PORT/json/version > /dev/null; then
33
+ echo " ✅ IDE Launched successfully."
34
+ else
35
+ echo " ⚠️ Could not launch IDE automatically. Please open it manually."
36
+ fi
37
+ fi
38
+
39
+ # 3. Khởi động Portal Bridge (HUD Injector)
40
+ echo "[2/4] 🧪 Injected Golden HUD Bridge... "
41
+ BRIDGE_PID_FILE=".portal_bridge_${BRIDGE_PORT}.pid"
42
+
43
+ # Tắt bridge cũ nếu đang chạy trên port này
44
+ if [ -f "$BRIDGE_PID_FILE" ]; then
45
+ kill $(cat "$BRIDGE_PID_FILE") 2>/dev/null
46
+ fi
47
+
48
+ nohup node scripts/ag_portal_bridge.js > ".portal_bridge_${BRIDGE_PORT}.log" 2>&1 &
49
+ echo $! > "$BRIDGE_PID_FILE"
50
+ echo " ✅ Bridge running (PID: $(cat "$BRIDGE_PID_FILE") on Port $BRIDGE_PORT)"
51
+
52
+ # 4. Khởi động Bot (Tùy chỉnh theo dự án)
53
+ echo "[3/4] 🤖 Waking up Agent Bot... "
54
+ # [TEMPLATE_NOTE]: Sếp hãy gõ lệnh khởi động Bot của mình vào đây.
55
+ echo " ⚠️ Vui lòng cấu hình lệnh khởi động Bot trong .agent/scripts/receptionist_up.sh"
56
+
57
+ # 5. Sentinel Monitor (Giám sát Trí não)
58
+ echo "[4/4] 🛡️ Sentinel Active: Auto-shutdown if IDE connection lost."
59
+ SENTINEL_PID_FILE=".sentinel_${BRIDGE_PORT}.pid"
60
+
61
+ function start_sentinel() {
62
+ (
63
+ local fail_count=0
64
+ while true; do
65
+ sleep 30
66
+ if ! curl -s "http://127.0.0.1:$IDE_PORT/json" | grep -q "$PROJECT_DIR" > /dev/null 2>&1; then
67
+ fail_count=$((fail_count + 1))
68
+ if [ $fail_count -ge 3 ]; then
69
+ echo "$(date): ⚠️ IDE Lost. Auto-shutting down project..." >> .sentinel_crash.log
70
+ bash .agent/scripts/receptionist_down.sh
71
+ exit 0
72
+ fi
73
+ else
74
+ fail_count=0
75
+ fi
76
+ done
77
+ ) &
78
+ echo $! > "$SENTINEL_PID_FILE"
79
+ }
80
+ start_sentinel
81
+
82
+ # Monitor
83
+ echo "----------------------------------------------------"
84
+ echo "✅ SYNC COMPLETE. PORTAL IS BROADCASTING."
85
+ # tail -f interaction_final.log
@@ -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
@@ -17,6 +17,6 @@ if [ $? -ne 0 ]; then
17
17
  echo "⚠️ Cảnh báo: Cổng CDP ${IDE_PORT:-9555} chưa mở. Đang chờ Antigravity khởi động..."
18
18
  fi
19
19
 
20
- # 4. Khởi động Bridge và Bot (Sử dụng Lễ tân/Receptionist pattern)
20
+ # 4. Khởi động Bridge và Bot (Agent-Defined)
21
21
  echo "🚀 Khởi động Lễ tân trực chiến (Agentic Gateway)..."
22
- ./receptionist_up.sh
22
+ bash .agent/scripts/receptionist_up.sh
@@ -3,7 +3,7 @@
3
3
 
4
4
  echo "🛑 Đang tắt toàn bộ trạm điều hành Agentic..."
5
5
 
6
- # Gọi script hạ cánh tiêu chuẩn
7
- ./receptionist_down.sh
6
+ # Gọi script hạ cánh tiêu chuẩn (Agent-Defined)
7
+ bash .agent/scripts/receptionist_down.sh
8
8
 
9
9
  echo "✅ Đã dọn dẹp xong."