agent-host-protocol-ui 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +11 -3
  2. package/bin/cli.js +94 -18
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -90,14 +90,22 @@ Launch the UI directly in your browser without cloning or installing:
90
90
  npx agent-host-protocol-ui
91
91
  ```
92
92
 
93
- You can optionally pre-configure the host URL and specify a port:
93
+ #### CLI Options & External Network Access
94
94
 
95
95
  ```sh
96
- # Pre-configure your local or remote host connection
97
- npx agent-host-protocol-ui --host "ws://127.0.0.1:63877?tkn=your-token"
96
+ # Serve on all network interfaces (0.0.0.0) so it is accessible externally
97
+ npx agent-host-protocol-ui --host 0.0.0.0
98
+ # or:
99
+ npx agent-host-protocol-ui --bind 0.0.0.0
100
+
101
+ # Pre-configure your local or remote agent host connection
102
+ npx agent-host-protocol-ui --agent-host "ws://127.0.0.1:63877?tkn=your-token"
98
103
 
99
104
  # Specify a custom port
100
105
  npx agent-host-protocol-ui --port 3000
106
+
107
+ # Run headless without opening local browser (e.g. in remote VM or container)
108
+ npx agent-host-protocol-ui --bind 0.0.0.0 --port 8080 --no-open
101
109
  ```
102
110
 
103
111
  ---
package/bin/cli.js CHANGED
@@ -3,6 +3,7 @@
3
3
  import { exec } from "node:child_process";
4
4
  import { existsSync, readFileSync, statSync } from "node:fs";
5
5
  import http from "node:http";
6
+ import os from "node:os";
6
7
  import path from "node:path";
7
8
  import { fileURLToPath } from "node:url";
8
9
 
@@ -24,20 +25,70 @@ const MIME_TYPES = {
24
25
  ".woff2": "font/woff2",
25
26
  };
26
27
 
28
+ function getNetworkIps() {
29
+ const ips = [];
30
+ try {
31
+ const interfaces = os.networkInterfaces();
32
+ for (const name of Object.keys(interfaces)) {
33
+ const netInterface = interfaces[name];
34
+ if (!netInterface) continue;
35
+ for (const iface of netInterface) {
36
+ if (iface.family === "IPv4" && !iface.internal) {
37
+ ips.push(iface.address);
38
+ }
39
+ }
40
+ }
41
+ } catch {
42
+ // ignore network interface errors
43
+ }
44
+ return ips;
45
+ }
46
+
27
47
  // Parse command line arguments
28
48
  const args = process.argv.slice(2);
29
- let port = 5173;
49
+ let port = Number.parseInt(process.env.PORT || "", 10) || 5173;
50
+ let listenHost = process.env.HOST || "localhost";
30
51
  let autoOpen = true;
31
- let hostParam = "";
52
+ let agentHostParam = process.env.AGENT_HOST || "";
32
53
 
33
54
  for (let i = 0; i < args.length; i++) {
34
- const arg = args[i];
55
+ let arg = args[i];
56
+ let value;
57
+ if (arg.includes("=")) {
58
+ const eqIdx = arg.indexOf("=");
59
+ value = arg.slice(eqIdx + 1);
60
+ arg = arg.slice(0, eqIdx);
61
+ }
62
+
35
63
  if (arg === "--port" || arg === "-p") {
36
- port = Number.parseInt(args[++i], 10) || 5173;
64
+ port = Number.parseInt(value ?? args[++i], 10) || 5173;
37
65
  } else if (arg === "--no-open") {
38
66
  autoOpen = false;
67
+ } else if (arg === "--bind" || arg === "-b" || arg === "--hostname" || arg === "--listen") {
68
+ listenHost = value ?? args[++i] ?? "0.0.0.0";
39
69
  } else if (arg === "--host" || arg === "-h") {
40
- hostParam = args[++i] || "";
70
+ if (value !== undefined) {
71
+ if (value.startsWith("ws://") || value.startsWith("wss://")) {
72
+ agentHostParam = value;
73
+ } else {
74
+ listenHost = value;
75
+ }
76
+ } else {
77
+ const next = args[i + 1];
78
+ if (!next || next.startsWith("-")) {
79
+ // Flag present without value: bind to 0.0.0.0 (like Vite --host)
80
+ listenHost = "0.0.0.0";
81
+ } else {
82
+ i++;
83
+ if (next.startsWith("ws://") || next.startsWith("wss://")) {
84
+ agentHostParam = next;
85
+ } else {
86
+ listenHost = next;
87
+ }
88
+ }
89
+ }
90
+ } else if (arg === "--agent-host" || arg === "--ws" || arg === "-a") {
91
+ agentHostParam = value ?? args[++i] ?? "";
41
92
  } else if (arg === "--help") {
42
93
  console.log(`
43
94
  agent-host-protocol-ui - Client-side UI for Agent Host Protocol
@@ -46,10 +97,17 @@ Usage:
46
97
  npx agent-host-protocol-ui [options]
47
98
 
48
99
  Options:
49
- -p, --port <number> Port to listen on (default: 5173)
50
- -h, --host <ws-url> Pre-configure host WebSocket URL
51
- --no-open Do not automatically open the browser
52
- --help Show help
100
+ -b, --bind <address> Hostname/IP to listen on (e.g. 0.0.0.0 or localhost, default: localhost)
101
+ --host [address] Bind to address (default: 0.0.0.0 if flag present without value)
102
+ -p, --port <number> Port to listen on (default: 5173 or process.env.PORT)
103
+ -a, --agent-host <ws-url> Pre-configure agent host WebSocket URL
104
+ --no-open Do not automatically open the browser
105
+ --help Show help
106
+
107
+ Environment variables:
108
+ HOST=<address> Default hostname/IP to listen on (e.g. 0.0.0.0)
109
+ PORT=<number> Default port to listen on
110
+ AGENT_HOST=<ws-url> Default agent host WebSocket URL
53
111
  `);
54
112
  process.exit(0);
55
113
  }
@@ -107,29 +165,47 @@ server.on("error", (err) => {
107
165
  if (err && typeof err === "object" && "code" in err && err.code === "EADDRINUSE") {
108
166
  console.log(`Port ${port} in use, trying ${port + 1}...`);
109
167
  port++;
110
- server.listen(port);
168
+ server.listen(port, listenHost);
111
169
  } else {
112
170
  console.error("Server error:", err);
113
171
  process.exit(1);
114
172
  }
115
173
  });
116
174
 
117
- server.listen(port, () => {
118
- let targetUrl = `http://localhost:${port}`;
119
- if (hostParam) {
120
- targetUrl += `?host=${encodeURIComponent(hostParam)}`;
121
- }
175
+ server.listen(port, listenHost, () => {
176
+ const isWildcard = listenHost === "0.0.0.0" || listenHost === "::";
177
+ const isLocal = listenHost === "localhost" || listenHost === "127.0.0.1" || listenHost === "::1";
178
+ const querySuffix = agentHostParam ? `?host=${encodeURIComponent(agentHostParam)}` : "";
179
+
180
+ const displayLocalUrl = `http://localhost:${port}${querySuffix}`;
181
+ const openUrl = isLocal || isWildcard ? displayLocalUrl : `http://${listenHost}:${port}${querySuffix}`;
182
+ const networkIps = isWildcard ? getNetworkIps() : [];
183
+
122
184
  console.log(`
123
185
  ┌────────────────────────────────────────────────────────┐
124
186
  │ │
125
187
  │ Agent Host Protocol UI │
126
- │ Running at: ${targetUrl.padEnd(41)}│
127
- │ │
188
+ │ │`);
189
+
190
+ if (isWildcard) {
191
+ console.log(`│ > Local: ${displayLocalUrl.padEnd(42)}│`);
192
+ for (const ip of networkIps) {
193
+ const netUrl = `http://${ip}:${port}${querySuffix}`;
194
+ console.log(`│ > Network: ${netUrl.padEnd(42)}│`);
195
+ }
196
+ } else if (isLocal) {
197
+ console.log(`│ > Local: ${displayLocalUrl.padEnd(42)}│`);
198
+ } else {
199
+ const customUrl = `http://${listenHost}:${port}${querySuffix}`;
200
+ console.log(`│ > Host: ${customUrl.padEnd(42)}│`);
201
+ }
202
+
203
+ console.log(`│ │
128
204
  │ Press Ctrl+C to stop │
129
205
  └────────────────────────────────────────────────────────┘
130
206
  `);
131
207
  if (autoOpen) {
132
- openBrowser(targetUrl);
208
+ openBrowser(openUrl);
133
209
  }
134
210
  });
135
211
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-host-protocol-ui",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Client-side web UI for the Agent Host Protocol (AHP) inspired by VS Code Agents view",
5
5
  "author": "Yusuke Tsutsumi <yusuke@tsutsumi.io>",
6
6
  "license": "Apache-2.0",