@elizaos/plugin-ngrok 2.0.0-beta.1
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 +325 -0
- package/dist/__tests__/NgrokTestSuite.d.ts +6 -0
- package/dist/__tests__/NgrokTestSuite.d.ts.map +1 -0
- package/dist/__tests__/NgrokTestSuite.js +92 -0
- package/dist/__tests__/NgrokTestSuite.js.map +1 -0
- package/dist/actions/get-tunnel-status.d.ts +4 -0
- package/dist/actions/get-tunnel-status.d.ts.map +1 -0
- package/dist/actions/get-tunnel-status.js +186 -0
- package/dist/actions/get-tunnel-status.js.map +1 -0
- package/dist/actions/start-tunnel.d.ts +4 -0
- package/dist/actions/start-tunnel.d.ts.map +1 -0
- package/dist/actions/start-tunnel.js +221 -0
- package/dist/actions/start-tunnel.js.map +1 -0
- package/dist/actions/stop-tunnel.d.ts +4 -0
- package/dist/actions/stop-tunnel.d.ts.map +1 -0
- package/dist/actions/stop-tunnel.js +174 -0
- package/dist/actions/stop-tunnel.js.map +1 -0
- package/dist/environment.d.ts +12 -0
- package/dist/environment.d.ts.map +1 -0
- package/dist/environment.js +68 -0
- package/dist/environment.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/services/NgrokService.d.ts +30 -0
- package/dist/services/NgrokService.d.ts.map +1 -0
- package/dist/services/NgrokService.js +333 -0
- package/dist/services/NgrokService.js.map +1 -0
- package/package.json +63 -0
- package/src/__tests__/NgrokTestSuite.ts +110 -0
- package/src/__tests__/debug-mock.test.ts +15 -0
- package/src/__tests__/e2e/real-ngrok.test.ts +543 -0
- package/src/__tests__/integration/webhook-scenarios.test.ts +463 -0
- package/src/__tests__/mocks/NgrokServiceMock.ts +76 -0
- package/src/__tests__/ngrok-integration.test.ts +521 -0
- package/src/__tests__/test-config.ts +83 -0
- package/src/__tests__/test-helpers.ts +43 -0
- package/src/__tests__/test-setup.ts +174 -0
- package/src/__tests__/test-utils.ts +155 -0
- package/src/__tests__/unit/actions.test.ts +402 -0
- package/src/__tests__/unit/environment.test.ts +352 -0
- package/src/actions/get-tunnel-status.ts +218 -0
- package/src/actions/start-tunnel.ts +255 -0
- package/src/actions/stop-tunnel.ts +203 -0
- package/src/environment.ts +75 -0
- package/src/index.ts +33 -0
- package/src/services/NgrokService.ts +401 -0
package/README.md
ADDED
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
# @elizaos/plugin-ngrok
|
|
2
|
+
|
|
3
|
+
<img src="images/banner.jpg" alt="Plugin Ngrok Banner" width="100%" />
|
|
4
|
+
|
|
5
|
+
A powerful ngrok tunnel plugin for ElizaOS that enables agents to expose local services to the internet with a production-ready dashboard.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- ๐ **Expose Local Services**: Create secure HTTPS tunnels to your local servers
|
|
10
|
+
- ๐ **Web Dashboard**: Real-time monitoring and management of active tunnels
|
|
11
|
+
- ๐ง **Full API**: RESTful API for programmatic tunnel management
|
|
12
|
+
- ๐งช **100% Test Coverage**: Comprehensive unit, integration, E2E, and Cypress tests
|
|
13
|
+
- ๐ฏ **TypeScript**: Fully typed for excellent developer experience
|
|
14
|
+
- ๐ **Secure**: Built-in auth token support and secure tunnel management
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @elizaos/plugin-ngrok
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
1. **Get your ngrok auth token** (optional but recommended):
|
|
25
|
+
|
|
26
|
+
- Visit [ngrok.com](https://dashboard.ngrok.com/get-started/your-authtoken)
|
|
27
|
+
- Sign up for a free account
|
|
28
|
+
- Copy your auth token
|
|
29
|
+
|
|
30
|
+
2. **Configure your environment**:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# .env file
|
|
34
|
+
NGROK_AUTH_TOKEN=your_auth_token_here # Optional but recommended
|
|
35
|
+
NGROK_REGION=us # Optional: us, eu, ap, au, sa, jp, in
|
|
36
|
+
NGROK_SUBDOMAIN=my-app # Optional: requires paid plan
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
3. **Use in your agent**:
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import ngrokPlugin from '@elizaos/plugin-ngrok';
|
|
43
|
+
|
|
44
|
+
const agent = new Agent({
|
|
45
|
+
plugins: [ngrokPlugin],
|
|
46
|
+
// ... other config
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Web Dashboard
|
|
51
|
+
|
|
52
|
+
The plugin includes a beautiful, production-ready web dashboard for managing your tunnels.
|
|
53
|
+
|
|
54
|
+
### Running the Dashboard
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Start both API server and dashboard
|
|
58
|
+
npm run demo:full
|
|
59
|
+
|
|
60
|
+
# Or run them separately:
|
|
61
|
+
npm run demo:api # Start API server on port 3001
|
|
62
|
+
npm run dev # Start dashboard on port 5173
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Visit http://localhost:5173 to access the dashboard.
|
|
66
|
+
|
|
67
|
+
### Dashboard Features
|
|
68
|
+
|
|
69
|
+
- **Real-time Status**: Monitor active tunnels with live updates
|
|
70
|
+
- **Easy Management**: Start/stop tunnels with a single click
|
|
71
|
+
- **Configuration**: Set port, region, and custom subdomains
|
|
72
|
+
- **Copy URL**: Quick copy button for sharing tunnel URLs
|
|
73
|
+
- **Responsive Design**: Works perfectly on desktop and mobile
|
|
74
|
+
- **Auto-refresh**: Status updates every 5 seconds
|
|
75
|
+
|
|
76
|
+
## Available Actions
|
|
77
|
+
|
|
78
|
+
The plugin provides three main actions:
|
|
79
|
+
|
|
80
|
+
### START_TUNNEL
|
|
81
|
+
|
|
82
|
+
Starts a new ngrok tunnel on the specified port.
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
// Example usage in agent
|
|
86
|
+
'Can you start a tunnel on port 3000?';
|
|
87
|
+
'Open ngrok on port 8080 in the EU region';
|
|
88
|
+
"Create a tunnel with subdomain 'my-app' on port 3000";
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### STOP_TUNNEL
|
|
92
|
+
|
|
93
|
+
Stops the currently active tunnel.
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
'Stop the tunnel';
|
|
97
|
+
'Close ngrok';
|
|
98
|
+
'Shutdown the tunnel';
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### GET_TUNNEL_STATUS
|
|
102
|
+
|
|
103
|
+
Gets the current status of the tunnel.
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
"What's the tunnel status?";
|
|
107
|
+
'Is ngrok running?';
|
|
108
|
+
'Show me the tunnel URL';
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Testing
|
|
112
|
+
|
|
113
|
+
This plugin includes comprehensive test coverage across multiple test types:
|
|
114
|
+
|
|
115
|
+
### Run All Tests
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
# Run all plugin tests (unit + E2E)
|
|
119
|
+
npm test
|
|
120
|
+
|
|
121
|
+
# Run with coverage report
|
|
122
|
+
npm run test:coverage
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Unit Tests
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
# Run unit tests only
|
|
129
|
+
npm run test:unit
|
|
130
|
+
|
|
131
|
+
# Run in watch mode
|
|
132
|
+
npm run test:watch
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Integration Tests
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
# Run integration tests (requires ngrok installed)
|
|
139
|
+
npm run test:integration
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### E2E Tests
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
# Run E2E tests (uses real ngrok API)
|
|
146
|
+
npm run test:e2e
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Cypress Tests
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
# Run Cypress tests headlessly
|
|
153
|
+
npm run test:cypress
|
|
154
|
+
|
|
155
|
+
# Open Cypress interactive mode
|
|
156
|
+
npm run cypress:open
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## API Reference
|
|
160
|
+
|
|
161
|
+
### REST API Endpoints
|
|
162
|
+
|
|
163
|
+
The plugin includes an Express API server for the dashboard:
|
|
164
|
+
|
|
165
|
+
#### GET /api/tunnel/status
|
|
166
|
+
|
|
167
|
+
Returns the current tunnel status.
|
|
168
|
+
|
|
169
|
+
**Response:**
|
|
170
|
+
|
|
171
|
+
```json
|
|
172
|
+
{
|
|
173
|
+
"active": true,
|
|
174
|
+
"url": "https://abc123.ngrok.io",
|
|
175
|
+
"port": 3000,
|
|
176
|
+
"startedAt": "2024-01-01T00:00:00.000Z",
|
|
177
|
+
"provider": "ngrok",
|
|
178
|
+
"uptime": "15 minutes"
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
#### POST /api/tunnel/start
|
|
183
|
+
|
|
184
|
+
Starts a new tunnel.
|
|
185
|
+
|
|
186
|
+
**Request Body:**
|
|
187
|
+
|
|
188
|
+
```json
|
|
189
|
+
{
|
|
190
|
+
"port": 3000,
|
|
191
|
+
"region": "eu", // optional
|
|
192
|
+
"subdomain": "my-app" // optional, requires paid plan
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
#### POST /api/tunnel/stop
|
|
197
|
+
|
|
198
|
+
Stops the active tunnel.
|
|
199
|
+
|
|
200
|
+
### TypeScript Types
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
interface TunnelStatus {
|
|
204
|
+
active: boolean;
|
|
205
|
+
url: string | null;
|
|
206
|
+
port: number | null;
|
|
207
|
+
startedAt: Date | null;
|
|
208
|
+
provider: string;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
interface TunnelConfig {
|
|
212
|
+
provider?: 'ngrok' | 'cloudflare' | 'localtunnel';
|
|
213
|
+
authToken?: string;
|
|
214
|
+
region?: string;
|
|
215
|
+
subdomain?: string;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
interface ITunnelService {
|
|
219
|
+
start(port: number): Promise<string>;
|
|
220
|
+
stop(): Promise<void>;
|
|
221
|
+
getUrl(): string | null;
|
|
222
|
+
isActive(): boolean;
|
|
223
|
+
getStatus(): TunnelStatus;
|
|
224
|
+
}
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
## Development
|
|
228
|
+
|
|
229
|
+
### Project Structure
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
plugin-ngrok/
|
|
233
|
+
โโโ src/
|
|
234
|
+
โ โโโ actions/ # Agent actions
|
|
235
|
+
โ โโโ services/ # NgrokService implementation
|
|
236
|
+
โ โโโ types/ # TypeScript types
|
|
237
|
+
โ โโโ frontend/ # React dashboard
|
|
238
|
+
โ โโโ __tests__/ # Test suites
|
|
239
|
+
โโโ demo/ # Demo applications
|
|
240
|
+
โโโ cypress/ # Cypress E2E tests
|
|
241
|
+
โโโ dist/ # Build output
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Building
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
# Build plugin and dashboard
|
|
248
|
+
npm run build
|
|
249
|
+
|
|
250
|
+
# Build plugin only
|
|
251
|
+
tsup src/index.ts --format esm --dts
|
|
252
|
+
|
|
253
|
+
# Build dashboard only
|
|
254
|
+
vite build
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Development Mode
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
# Watch plugin changes
|
|
261
|
+
npm run dev:plugin
|
|
262
|
+
|
|
263
|
+
# Run dashboard dev server
|
|
264
|
+
npm run dev
|
|
265
|
+
|
|
266
|
+
# Run everything in dev mode
|
|
267
|
+
npm run demo:full
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## Environment Variables
|
|
271
|
+
|
|
272
|
+
| Variable | Description | Default | Required |
|
|
273
|
+
| -------------------- | ------------------------------------------ | ------- | -------------------- |
|
|
274
|
+
| `NGROK_AUTH_TOKEN` | Your ngrok authentication token | - | No (but recommended) |
|
|
275
|
+
| `NGROK_REGION` | Tunnel region (us, eu, ap, au, sa, jp, in) | us | No |
|
|
276
|
+
| `NGROK_SUBDOMAIN` | Custom subdomain (requires paid plan) | - | No |
|
|
277
|
+
| `NGROK_DEFAULT_PORT` | Default port for tunnels | 3000 | No |
|
|
278
|
+
| `API_PORT` | Port for the API server | 3001 | No |
|
|
279
|
+
|
|
280
|
+
## Troubleshooting
|
|
281
|
+
|
|
282
|
+
### Ngrok not installed
|
|
283
|
+
|
|
284
|
+
If you see "ngrok is not installed", install it using:
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
# macOS
|
|
288
|
+
brew install ngrok
|
|
289
|
+
|
|
290
|
+
# Linux
|
|
291
|
+
snap install ngrok
|
|
292
|
+
|
|
293
|
+
# Windows
|
|
294
|
+
choco install ngrok
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
### Auth token issues
|
|
298
|
+
|
|
299
|
+
Without an auth token, tunnels will have limited functionality. Get a free token at [ngrok.com](https://dashboard.ngrok.com/get-started/your-authtoken).
|
|
300
|
+
|
|
301
|
+
### Port already in use
|
|
302
|
+
|
|
303
|
+
Make sure the port you're trying to tunnel is actually running a service and is not blocked by a firewall.
|
|
304
|
+
|
|
305
|
+
## Contributing
|
|
306
|
+
|
|
307
|
+
Contributions are welcome! Please ensure all tests pass and add tests for new features:
|
|
308
|
+
|
|
309
|
+
1. Fork the repository
|
|
310
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
311
|
+
3. Write tests for your changes
|
|
312
|
+
4. Ensure all tests pass (`npm test`)
|
|
313
|
+
5. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
314
|
+
6. Push to the branch (`git push origin feature/amazing-feature`)
|
|
315
|
+
7. Open a Pull Request
|
|
316
|
+
|
|
317
|
+
## License
|
|
318
|
+
|
|
319
|
+
This plugin is part of the ElizaOS project. See the main project for license information.
|
|
320
|
+
|
|
321
|
+
## Support
|
|
322
|
+
|
|
323
|
+
For issues and feature requests, please use the GitHub issue tracker.
|
|
324
|
+
|
|
325
|
+
For questions and discussions, join the ElizaOS community on Discord.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NgrokTestSuite.d.ts","sourceRoot":"","sources":["../../src/__tests__/NgrokTestSuite.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG7D,qBAAa,cAAc;IACzB,IAAI,SAAW;IACf,KAAK,EAAE,QAAQ,EAAE,CAuGf;CACH"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { NgrokService } from '../services/NgrokService';
|
|
2
|
+
export class NgrokTestSuite {
|
|
3
|
+
name = 'ngrok';
|
|
4
|
+
tests = [
|
|
5
|
+
{
|
|
6
|
+
name: 'Initialize Ngrok Service',
|
|
7
|
+
fn: async (runtime) => {
|
|
8
|
+
// Test service initialization
|
|
9
|
+
const service = new NgrokService(runtime);
|
|
10
|
+
// Verify service is initialized
|
|
11
|
+
if (!service) {
|
|
12
|
+
throw new Error('Failed to initialize Ngrok service');
|
|
13
|
+
}
|
|
14
|
+
if (!(service instanceof NgrokService)) {
|
|
15
|
+
throw new Error('Service is not instance of NgrokService');
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
name: 'Start and Stop Tunnel',
|
|
21
|
+
fn: async (runtime) => {
|
|
22
|
+
const service = new NgrokService(runtime);
|
|
23
|
+
// Test starting tunnel
|
|
24
|
+
const url = await service.startTunnel(3000);
|
|
25
|
+
if (!url?.startsWith('https://')) {
|
|
26
|
+
throw new Error('Failed to start tunnel or invalid URL returned');
|
|
27
|
+
}
|
|
28
|
+
// Verify tunnel is active
|
|
29
|
+
if (!service.isActive()) {
|
|
30
|
+
throw new Error('Tunnel should be active after starting');
|
|
31
|
+
}
|
|
32
|
+
// Test getting status
|
|
33
|
+
const status = service.getStatus();
|
|
34
|
+
if (!status.active || status.port !== 3000) {
|
|
35
|
+
throw new Error('Invalid tunnel status');
|
|
36
|
+
}
|
|
37
|
+
// Test stopping tunnel
|
|
38
|
+
await service.stopTunnel();
|
|
39
|
+
// Verify tunnel is stopped
|
|
40
|
+
if (service.isActive()) {
|
|
41
|
+
throw new Error('Tunnel should not be active after stopping');
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
name: 'Service Registration',
|
|
47
|
+
fn: async (runtime) => {
|
|
48
|
+
// Test that service can be registered and retrieved
|
|
49
|
+
const _service = new NgrokService(runtime);
|
|
50
|
+
// In a real test, we would register the service with runtime
|
|
51
|
+
// and then retrieve it to verify registration
|
|
52
|
+
const serviceType = NgrokService.serviceType;
|
|
53
|
+
if (serviceType !== 'tunnel') {
|
|
54
|
+
throw new Error('Service type should be "tunnel"');
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: 'Tunnel Status When Inactive',
|
|
60
|
+
fn: async (runtime) => {
|
|
61
|
+
const service = new NgrokService(runtime);
|
|
62
|
+
// Get status when tunnel is not active
|
|
63
|
+
const status = service.getStatus();
|
|
64
|
+
if (status.active) {
|
|
65
|
+
throw new Error('Tunnel should not be active initially');
|
|
66
|
+
}
|
|
67
|
+
if (status.url !== null || status.port !== null) {
|
|
68
|
+
throw new Error('URL and port should be null when inactive');
|
|
69
|
+
}
|
|
70
|
+
if (status.provider !== 'ngrok') {
|
|
71
|
+
throw new Error('Provider should always be "ngrok"');
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: 'Multiple Start Attempts',
|
|
77
|
+
fn: async (runtime) => {
|
|
78
|
+
const service = new NgrokService(runtime);
|
|
79
|
+
// Start tunnel
|
|
80
|
+
const url1 = await service.startTunnel(3000);
|
|
81
|
+
// Try to start again (should return same URL)
|
|
82
|
+
const url2 = await service.startTunnel(3000);
|
|
83
|
+
if (url1 !== url2) {
|
|
84
|
+
throw new Error('Starting tunnel twice should return the same URL');
|
|
85
|
+
}
|
|
86
|
+
// Clean up
|
|
87
|
+
await service.stopTunnel();
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
];
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=NgrokTestSuite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NgrokTestSuite.js","sourceRoot":"","sources":["../../src/__tests__/NgrokTestSuite.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-tunnel-status.d.ts","sourceRoot":"","sources":["../../src/actions/get-tunnel-status.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,MAAM,EAQZ,MAAM,eAAe,CAAC;AAGvB,eAAO,MAAM,qBAAqB,EAAE,MA2MnC,CAAC;AAEF,eAAe,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { elizaLogger, } from '@elizaos/core';
|
|
2
|
+
import { getTunnelService } from '@elizaos/plugin-tunnel';
|
|
3
|
+
export const getTunnelStatusAction = {
|
|
4
|
+
name: 'GET_TUNNEL_STATUS',
|
|
5
|
+
similes: ['TUNNEL_STATUS', 'CHECK_TUNNEL', 'NGROK_STATUS', 'TUNNEL_INFO'],
|
|
6
|
+
description: 'Get the current status of the ngrok tunnel including URL, port, and uptime information. Supports action chaining by providing tunnel metadata for monitoring workflows, health checks, or conditional tunnel management.',
|
|
7
|
+
validate: async (runtime, _message) => {
|
|
8
|
+
return !!getTunnelService(runtime);
|
|
9
|
+
},
|
|
10
|
+
handler: async (runtime, _message, _state, _options, callback) => {
|
|
11
|
+
try {
|
|
12
|
+
elizaLogger.info('Getting ngrok tunnel status...');
|
|
13
|
+
const tunnelService = getTunnelService(runtime);
|
|
14
|
+
if (!tunnelService) {
|
|
15
|
+
throw new Error('Tunnel service not found');
|
|
16
|
+
}
|
|
17
|
+
const status = tunnelService.getStatus();
|
|
18
|
+
let responseText;
|
|
19
|
+
const response = {
|
|
20
|
+
...status,
|
|
21
|
+
uptime: 'N/A',
|
|
22
|
+
};
|
|
23
|
+
if (status.active) {
|
|
24
|
+
if (status.startedAt) {
|
|
25
|
+
const uptimeMs = Date.now() - new Date(status.startedAt).getTime();
|
|
26
|
+
const minutes = Math.floor(uptimeMs / 60000);
|
|
27
|
+
const hours = Math.floor(minutes / 60);
|
|
28
|
+
if (hours > 0) {
|
|
29
|
+
response.uptime = `${hours} hour${hours > 1 ? 's' : ''}, ${minutes % 60} minute${minutes % 60 !== 1 ? 's' : ''}`;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
response.uptime = `${minutes} minute${minutes !== 1 ? 's' : ''}`;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
responseText = `โ
Ngrok tunnel is active!\n\n๐ Public URL: ${status.url}\n๐ Local Port: ${status.port}\nโฑ๏ธ Uptime: ${response.uptime}\n๐ข Provider: ${status.provider}\n\nYour local service is accessible from the internet.`;
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
responseText =
|
|
39
|
+
'โ No active ngrok tunnel.\n\nTo start a tunnel, say "start ngrok tunnel on port [PORT]"';
|
|
40
|
+
}
|
|
41
|
+
const startedAtIso = status.startedAt ? status.startedAt.toISOString() : null;
|
|
42
|
+
if (callback) {
|
|
43
|
+
await callback({
|
|
44
|
+
text: responseText,
|
|
45
|
+
metadata: {
|
|
46
|
+
action: 'tunnel_status',
|
|
47
|
+
uptime: response.uptime,
|
|
48
|
+
active: status.active,
|
|
49
|
+
url: status.url,
|
|
50
|
+
port: status.port,
|
|
51
|
+
startedAt: startedAtIso,
|
|
52
|
+
provider: status.provider,
|
|
53
|
+
backend: status.backend ?? null,
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
success: true,
|
|
59
|
+
text: responseText,
|
|
60
|
+
values: {
|
|
61
|
+
success: true,
|
|
62
|
+
isActive: status.active,
|
|
63
|
+
tunnelUrl: status.url,
|
|
64
|
+
port: status.port,
|
|
65
|
+
uptime: response.uptime,
|
|
66
|
+
provider: status.provider,
|
|
67
|
+
},
|
|
68
|
+
data: {
|
|
69
|
+
action: 'GET_TUNNEL_STATUS',
|
|
70
|
+
tunnelStatus: {
|
|
71
|
+
active: status.active,
|
|
72
|
+
url: status.url,
|
|
73
|
+
port: status.port,
|
|
74
|
+
startedAt: startedAtIso,
|
|
75
|
+
provider: status.provider,
|
|
76
|
+
backend: status.backend ?? null,
|
|
77
|
+
uptime: response.uptime,
|
|
78
|
+
checkedAt: new Date().toISOString(),
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
85
|
+
const stack = error instanceof Error ? (error.stack ?? null) : null;
|
|
86
|
+
elizaLogger.error(`Failed to get tunnel status: ${message}`);
|
|
87
|
+
if (callback) {
|
|
88
|
+
await callback({
|
|
89
|
+
text: `โ Failed to get tunnel status: ${message}`,
|
|
90
|
+
metadata: {
|
|
91
|
+
error: message,
|
|
92
|
+
action: 'tunnel_status_failed',
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
success: false,
|
|
98
|
+
text: `โ Failed to get tunnel status: ${message}`,
|
|
99
|
+
values: {
|
|
100
|
+
success: false,
|
|
101
|
+
error: message,
|
|
102
|
+
},
|
|
103
|
+
data: {
|
|
104
|
+
action: 'GET_TUNNEL_STATUS',
|
|
105
|
+
errorType: 'status_check_failed',
|
|
106
|
+
errorDetails: stack,
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
examples: [
|
|
112
|
+
[
|
|
113
|
+
{
|
|
114
|
+
name: '{{user}}',
|
|
115
|
+
content: {
|
|
116
|
+
text: 'What is the tunnel status?',
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: '{{agent}}',
|
|
121
|
+
content: {
|
|
122
|
+
text: 'โ
Ngrok tunnel is active!\n\n๐ Public URL: https://abc123.ngrok.io\n๐ Local Port: 3000\nโฑ๏ธ Uptime: 15 minutes\n๐ข Provider: ngrok\n\nYour local service is accessible from the internet.',
|
|
123
|
+
actions: ['GET_TUNNEL_STATUS'],
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
[
|
|
128
|
+
{
|
|
129
|
+
name: '{{user}}',
|
|
130
|
+
content: {
|
|
131
|
+
text: "Check tunnel status and restart it if it's been running too long",
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
name: '{{agent}}',
|
|
136
|
+
content: {
|
|
137
|
+
text: "I'll check the current tunnel status and restart it if needed.",
|
|
138
|
+
thought: 'User wants me to monitor tunnel uptime and restart if necessary - I should check status first, then decide whether to restart based on uptime.',
|
|
139
|
+
actions: ['GET_TUNNEL_STATUS'],
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
name: '{{agent}}',
|
|
144
|
+
content: {
|
|
145
|
+
text: "Tunnel has been running for 2 hours. That seems like a long time - I'll restart it for optimal performance.",
|
|
146
|
+
thought: 'Status shows the tunnel has been up for 2 hours, which is quite long. I should stop and restart it as requested.',
|
|
147
|
+
actions: ['STOP_TUNNEL'],
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
name: '{{agent}}',
|
|
152
|
+
content: {
|
|
153
|
+
text: 'Tunnel stopped. Now starting a fresh tunnel...',
|
|
154
|
+
thought: 'Old tunnel is down, now I can start a new fresh tunnel for optimal performance.',
|
|
155
|
+
actions: ['START_TUNNEL'],
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
[
|
|
160
|
+
{
|
|
161
|
+
name: '{{user}}',
|
|
162
|
+
content: {
|
|
163
|
+
text: 'Get tunnel info and then update our webhook URLs',
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
name: '{{agent}}',
|
|
168
|
+
content: {
|
|
169
|
+
text: "I'll check the current tunnel status and then update the webhook URLs.",
|
|
170
|
+
thought: 'User needs the current tunnel URL for webhook configuration - I should get the status first, then update webhooks with the public URL.',
|
|
171
|
+
actions: ['GET_TUNNEL_STATUS'],
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
name: '{{agent}}',
|
|
176
|
+
content: {
|
|
177
|
+
text: 'Tunnel is active at https://abc123.ngrok.io. Now updating webhook URLs...',
|
|
178
|
+
thought: 'I have the current tunnel URL from the status check. I can now update the webhook configurations with this public URL.',
|
|
179
|
+
actions: ['UPDATE_WEBHOOKS'],
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
],
|
|
183
|
+
],
|
|
184
|
+
};
|
|
185
|
+
export default getTunnelStatusAction;
|
|
186
|
+
//# sourceMappingURL=get-tunnel-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-tunnel-status.js","sourceRoot":"","sources":["../../src/actions/get-tunnel-status.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start-tunnel.d.ts","sourceRoot":"","sources":["../../src/actions/start-tunnel.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,MAAM,EASZ,MAAM,eAAe,CAAC;AAiBvB,eAAO,MAAM,iBAAiB,EAAE,MAiO/B,CAAC;AAEF,eAAe,iBAAiB,CAAC"}
|