@mrtrinhvn/ag-kit 1.1.7 → 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 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.1.9",
4
4
  "description": "Antigravity Kit Base Framework - Generic Agentic AI Programming Core",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -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 "----------------------------------------------------"
@@ -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."