@elizaos/plugin-ngrok 2.0.0-beta.1 → 2.0.3-beta.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 (38) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +38 -294
  3. package/package.json +24 -7
  4. package/src/__tests__/test-utils.ts +2 -2
  5. package/src/__tests__/unit/environment.test.ts +1 -1
  6. package/dist/__tests__/NgrokTestSuite.d.ts +0 -6
  7. package/dist/__tests__/NgrokTestSuite.d.ts.map +0 -1
  8. package/dist/__tests__/NgrokTestSuite.js +0 -92
  9. package/dist/__tests__/NgrokTestSuite.js.map +0 -1
  10. package/dist/actions/get-tunnel-status.d.ts +0 -4
  11. package/dist/actions/get-tunnel-status.d.ts.map +0 -1
  12. package/dist/actions/get-tunnel-status.js +0 -186
  13. package/dist/actions/get-tunnel-status.js.map +0 -1
  14. package/dist/actions/start-tunnel.d.ts +0 -4
  15. package/dist/actions/start-tunnel.d.ts.map +0 -1
  16. package/dist/actions/start-tunnel.js +0 -221
  17. package/dist/actions/start-tunnel.js.map +0 -1
  18. package/dist/actions/stop-tunnel.d.ts +0 -4
  19. package/dist/actions/stop-tunnel.d.ts.map +0 -1
  20. package/dist/actions/stop-tunnel.js +0 -174
  21. package/dist/actions/stop-tunnel.js.map +0 -1
  22. package/dist/environment.d.ts +0 -12
  23. package/dist/environment.d.ts.map +0 -1
  24. package/dist/environment.js +0 -68
  25. package/dist/environment.js.map +0 -1
  26. package/dist/index.d.ts +0 -13
  27. package/dist/index.d.ts.map +0 -1
  28. package/dist/index.js +0 -29
  29. package/dist/index.js.map +0 -1
  30. package/dist/services/NgrokService.d.ts +0 -30
  31. package/dist/services/NgrokService.d.ts.map +0 -1
  32. package/dist/services/NgrokService.js +0 -333
  33. package/dist/services/NgrokService.js.map +0 -1
  34. package/src/__tests__/e2e/real-ngrok.test.ts +0 -543
  35. package/src/__tests__/unit/actions.test.ts +0 -402
  36. package/src/actions/get-tunnel-status.ts +0 -218
  37. package/src/actions/start-tunnel.ts +0 -255
  38. package/src/actions/stop-tunnel.ts +0 -203
@@ -1,68 +0,0 @@
1
- import { elizaLogger } from '@elizaos/core';
2
- import { z } from 'zod';
3
- export const ngrokEnvSchema = z.object({
4
- NGROK_AUTH_TOKEN: z.string().optional(),
5
- NGROK_REGION: z
6
- .union([z.string(), z.number()])
7
- .optional()
8
- .transform((val) => {
9
- if (val === undefined || val === null) {
10
- return 'us';
11
- }
12
- return String(val);
13
- })
14
- .default('us'),
15
- NGROK_SUBDOMAIN: z.string().optional(),
16
- NGROK_DOMAIN: z.string().optional(),
17
- NGROK_DEFAULT_PORT: z
18
- .union([z.string(), z.number()])
19
- .optional()
20
- .transform((val) => {
21
- if (val === undefined || val === '') {
22
- return 3000;
23
- }
24
- const num = typeof val === 'string' ? parseInt(val, 10) : val;
25
- // If port is 0 or invalid, use default
26
- if (Number.isNaN(num) || num <= 0 || num > 65535) {
27
- return 3000;
28
- }
29
- return num;
30
- })
31
- .default(3000),
32
- });
33
- /**
34
- * Coerce a runtime setting (string | number | boolean | null) to a string suitable
35
- * for schema parsing. Null/undefined return undefined so optional schema fields work.
36
- */
37
- function settingToString(value) {
38
- if (value === null || value === undefined)
39
- return undefined;
40
- return String(value);
41
- }
42
- export async function validateNgrokConfig(runtime) {
43
- try {
44
- elizaLogger.debug('Validating Ngrok configuration with runtime settings');
45
- const config = {
46
- NGROK_AUTH_TOKEN: settingToString(runtime.getSetting('NGROK_AUTH_TOKEN')) ?? process.env.NGROK_AUTH_TOKEN,
47
- NGROK_REGION: settingToString(runtime.getSetting('NGROK_REGION')) ?? process.env.NGROK_REGION,
48
- NGROK_SUBDOMAIN: settingToString(runtime.getSetting('NGROK_SUBDOMAIN')) ?? process.env.NGROK_SUBDOMAIN,
49
- NGROK_DOMAIN: settingToString(runtime.getSetting('NGROK_DOMAIN')) ?? process.env.NGROK_DOMAIN,
50
- NGROK_DEFAULT_PORT: settingToString(runtime.getSetting('NGROK_DEFAULT_PORT')) ??
51
- process.env.NGROK_DEFAULT_PORT ??
52
- process.env.NGROK_TUNNEL_PORT,
53
- };
54
- elizaLogger.debug({ config }, 'Parsing configuration with schema');
55
- const validated = ngrokEnvSchema.parse(config);
56
- elizaLogger.debug('Configuration validated successfully');
57
- return validated;
58
- }
59
- catch (error) {
60
- if (error instanceof z.ZodError) {
61
- const errorMessages = error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join('\n');
62
- elizaLogger.error(`Configuration validation failed: ${errorMessages}`);
63
- throw new Error(`Ngrok configuration validation failed:\n${errorMessages}`);
64
- }
65
- throw error;
66
- }
67
- }
68
- //# sourceMappingURL=environment.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"environment.js","sourceRoot":"","sources":["../src/environment.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts DELETED
@@ -1,13 +0,0 @@
1
- import { type Plugin } from '@elizaos/core';
2
- /**
3
- * Ngrok tunnel plugin.
4
- *
5
- * Implements the `ITunnelService` contract from `@elizaos/plugin-tunnel`.
6
- * Registers `serviceType="tunnel"` only when no other tunnel service has
7
- * already claimed the slot (first-active-wins coordination across
8
- * plugin-tunnel, plugin-elizacloud's CloudTunnelService, and this plugin).
9
- */
10
- export declare const ngrokPlugin: Plugin;
11
- export default ngrokPlugin;
12
- export * from './services/NgrokService';
13
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,MAAM,EAAE,MAAM,eAAe,CAAC;AAKzD;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,EAAE,MAezB,CAAC;AAEF,eAAe,WAAW,CAAC;AAE3B,cAAc,yBAAyB,CAAC"}
package/dist/index.js DELETED
@@ -1,29 +0,0 @@
1
- import { elizaLogger } from '@elizaos/core';
2
- import { tunnelSlotIsFree } from '@elizaos/plugin-tunnel';
3
- import { NgrokTestSuite } from './__tests__/NgrokTestSuite';
4
- import { NgrokService } from './services/NgrokService';
5
- /**
6
- * Ngrok tunnel plugin.
7
- *
8
- * Implements the `ITunnelService` contract from `@elizaos/plugin-tunnel`.
9
- * Registers `serviceType="tunnel"` only when no other tunnel service has
10
- * already claimed the slot (first-active-wins coordination across
11
- * plugin-tunnel, plugin-elizacloud's CloudTunnelService, and this plugin).
12
- */
13
- export const ngrokPlugin = {
14
- name: 'ngrok',
15
- description: 'Ngrok tunnel backend. Coexists with plugin-tunnel via first-active-wins.',
16
- actions: [],
17
- tests: [new NgrokTestSuite()],
18
- init: async (_config, runtime) => {
19
- if (!tunnelSlotIsFree(runtime)) {
20
- elizaLogger.info('[plugin-ngrok] another tunnel service already registered — skipping NgrokService');
21
- return;
22
- }
23
- elizaLogger.info('[plugin-ngrok] registering NgrokService for serviceType="tunnel"');
24
- await runtime.registerService(NgrokService);
25
- },
26
- };
27
- export default ngrokPlugin;
28
- export * from './services/NgrokService';
29
- //# sourceMappingURL=index.js.map
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAe,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEvD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,WAAW,GAAW;IACjC,IAAI,EAAE,OAAO;IACb,WAAW,EAAE,0EAA0E;IACvF,OAAO,EAAE,EAAE;IACX,KAAK,EAAE,CAAC,IAAI,cAAc,EAAE,CAAC;IAC7B,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;QAC/B,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/B,WAAW,CAAC,IAAI,CACd,kFAAkF,CACnF,CAAC;YACF,OAAO;QACT,CAAC;QACD,WAAW,CAAC,IAAI,CAAC,kEAAkE,CAAC,CAAC;QACrF,MAAM,OAAO,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;IAC9C,CAAC;CACF,CAAC;AAEF,eAAe,WAAW,CAAC;AAE3B,cAAc,yBAAyB,CAAC"}
@@ -1,30 +0,0 @@
1
- import { type IAgentRuntime, Service } from '@elizaos/core';
2
- import type { ITunnelService, TunnelStatus } from '@elizaos/plugin-tunnel';
3
- export declare class NgrokService extends Service implements ITunnelService {
4
- static serviceType: string;
5
- readonly capabilityDescription = "Provides secure tunnel functionality using ngrok for exposing local services to the internet";
6
- private static readonly MIN_TUNNEL_INTERVAL;
7
- private ngrokProcess;
8
- private tunnelUrl;
9
- private tunnelPort;
10
- private startedAt;
11
- private lastStartTime;
12
- private tunnelConfig;
13
- constructor(runtime?: IAgentRuntime);
14
- initialize(): Promise<void>;
15
- static start(runtime: IAgentRuntime): Promise<Service>;
16
- start(): Promise<void>;
17
- stop(): Promise<void>;
18
- startTunnel(port?: number): Promise<string | undefined>;
19
- private attemptStartTunnel;
20
- private startTunnelInternal;
21
- stopTunnel(): Promise<void>;
22
- getUrl(): string | null;
23
- isActive(): boolean;
24
- getStatus(): TunnelStatus;
25
- private cleanup;
26
- private checkNgrokInstalled;
27
- private setAuthToken;
28
- private fetchTunnelUrl;
29
- }
30
- //# sourceMappingURL=NgrokService.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"NgrokService.d.ts","sourceRoot":"","sources":["../../src/services/NgrokService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,aAAa,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAgC3E,qBAAa,YAAa,SAAQ,OAAQ,YAAW,cAAc;IACjE,MAAM,CAAC,WAAW,SAAY;IAC9B,QAAQ,CAAC,qBAAqB,kGACmE;IAEjG,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAQ;IAEnD,OAAO,CAAC,YAAY,CAA6B;IACjD,OAAO,CAAC,SAAS,CAAuB;IACxC,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,YAAY,CAAe;gBAEvB,OAAO,CAAC,EAAE,aAAa;IAS7B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;WAsBX,KAAK,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC;IAO/D,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAKrB,WAAW,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;YA4C/C,kBAAkB;YAmClB,mBAAmB;IA2H3B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA2BjC,MAAM,IAAI,MAAM,GAAG,IAAI;IAIvB,QAAQ,IAAI,OAAO;IAInB,SAAS,IAAI,YAAY;IAUzB,OAAO,CAAC,OAAO;YAOD,mBAAmB;YAQnB,YAAY;YAeZ,cAAc;CA6B7B"}
@@ -1,333 +0,0 @@
1
- import { elizaLogger, Service } from '@elizaos/core';
2
- /** Coerce runtime.getSetting() (string | number | boolean | null) to string. */
3
- function settingString(value) {
4
- if (value === null || value === undefined)
5
- return undefined;
6
- return String(value);
7
- }
8
- function errorMessage(error) {
9
- return error instanceof Error ? error.message : String(error);
10
- }
11
- import { spawn } from 'node:child_process';
12
- import * as http from 'node:http';
13
- import { validateNgrokConfig } from '../environment';
14
- export class NgrokService extends Service {
15
- static serviceType = 'tunnel';
16
- capabilityDescription = 'Provides secure tunnel functionality using ngrok for exposing local services to the internet';
17
- static MIN_TUNNEL_INTERVAL = 2000; // 2 seconds minimum between tunnel starts
18
- ngrokProcess = null;
19
- tunnelUrl = null;
20
- tunnelPort = null;
21
- startedAt = null;
22
- lastStartTime = 0;
23
- tunnelConfig;
24
- constructor(runtime) {
25
- super(runtime);
26
- this.tunnelConfig = {
27
- provider: 'ngrok',
28
- authToken: settingString(runtime?.getSetting('NGROK_AUTH_TOKEN')) ?? process.env.NGROK_AUTH_TOKEN,
29
- };
30
- }
31
- async initialize() {
32
- elizaLogger.info('🚇 Initializing Ngrok tunnel service...');
33
- const isInstalled = await this.checkNgrokInstalled();
34
- if (!isInstalled) {
35
- throw new Error('ngrok is not installed. Please install it from https://ngrok.com/download or run: brew install ngrok');
36
- }
37
- const authToken = this.tunnelConfig.authToken ??
38
- settingString(this.runtime.getSetting('NGROK_AUTH_TOKEN')) ??
39
- process.env.NGROK_AUTH_TOKEN;
40
- if (authToken) {
41
- await this.setAuthToken(authToken);
42
- elizaLogger.info('Setting ngrok auth token');
43
- }
44
- else {
45
- elizaLogger.warn('No ngrok auth token found - running in limited mode');
46
- }
47
- }
48
- static async start(runtime) {
49
- const service = new NgrokService(runtime);
50
- await service.start();
51
- return service;
52
- }
53
- // Base Service lifecycle methods
54
- async start() {
55
- elizaLogger.info('NgrokService started');
56
- }
57
- async stop() {
58
- await this.stopTunnel();
59
- }
60
- // ITunnelService implementation
61
- async startTunnel(port) {
62
- if (this.isActive()) {
63
- elizaLogger.warn('Ngrok tunnel is already running');
64
- return this.tunnelUrl || undefined;
65
- }
66
- if (!port) {
67
- elizaLogger.warn('NgrokService.start() called without a port. The service will be active but no tunnel will be started.');
68
- return;
69
- }
70
- // Validate environment
71
- try {
72
- await validateNgrokConfig(this.runtime);
73
- }
74
- catch (error) {
75
- throw new Error(`Ngrok environment validation failed: ${errorMessage(error)}`);
76
- }
77
- // Enforce rate limiting
78
- const now = Date.now();
79
- if (this.lastStartTime && now - this.lastStartTime < NgrokService.MIN_TUNNEL_INTERVAL) {
80
- const waitTime = NgrokService.MIN_TUNNEL_INTERVAL - (now - this.lastStartTime);
81
- elizaLogger.warn(`Rate limiting: waiting ${waitTime}ms before starting tunnel`);
82
- await new Promise((resolve) => setTimeout(resolve, waitTime));
83
- }
84
- this.lastStartTime = Date.now();
85
- elizaLogger.info(`🚀 Starting ngrok tunnel on port ${port}...`);
86
- try {
87
- const tunnelUrl = await this.attemptStartTunnel(port);
88
- this.tunnelUrl = tunnelUrl;
89
- this.tunnelPort = port;
90
- this.startedAt = new Date();
91
- elizaLogger.success(`✅ Ngrok tunnel started: ${tunnelUrl}`);
92
- return tunnelUrl;
93
- }
94
- catch (error) {
95
- elizaLogger.error('Failed to start ngrok tunnel:', errorMessage(error));
96
- throw error;
97
- }
98
- }
99
- async attemptStartTunnel(port) {
100
- let attempts = 0;
101
- const maxAttempts = 3;
102
- const baseDelay = 2000;
103
- while (attempts < maxAttempts) {
104
- try {
105
- return await this.startTunnelInternal(port);
106
- }
107
- catch (error) {
108
- attempts++;
109
- if (errorMessage(error).includes('domain might already be in use')) {
110
- if (attempts < maxAttempts) {
111
- elizaLogger.warn(`Domain conflict detected, retrying in ${baseDelay * attempts}ms (attempt ${attempts}/${maxAttempts})`);
112
- await new Promise((resolve) => setTimeout(resolve, baseDelay * attempts));
113
- // Try to stop any existing process just in case
114
- if (this.ngrokProcess) {
115
- this.ngrokProcess.kill();
116
- this.ngrokProcess = null;
117
- await new Promise((resolve) => setTimeout(resolve, 1000));
118
- }
119
- continue;
120
- }
121
- }
122
- throw error;
123
- }
124
- }
125
- throw new Error(`Failed to start tunnel after ${maxAttempts} attempts`);
126
- }
127
- async startTunnelInternal(port) {
128
- return new Promise((resolve, reject) => {
129
- const args = ['http', port.toString()];
130
- if (this.tunnelConfig.region) {
131
- args.push('--region', this.tunnelConfig.region);
132
- }
133
- // Check for domain configuration
134
- const domain = settingString(this.runtime.getSetting('NGROK_DOMAIN')) ?? process.env.NGROK_DOMAIN;
135
- const useRandomSubdomain = settingString(this.runtime.getSetting('NGROK_USE_RANDOM_SUBDOMAIN')) === 'true';
136
- if (domain && !useRandomSubdomain) {
137
- args.push('--domain', domain);
138
- elizaLogger.info(`Using ngrok domain: ${domain}`);
139
- }
140
- else if (this.tunnelConfig.subdomain && !useRandomSubdomain) {
141
- // Only use subdomain if explicitly configured and not in test mode
142
- // Note: Subdomains require a paid ngrok account
143
- args.push('--subdomain', this.tunnelConfig.subdomain);
144
- elizaLogger.info(`Using configured subdomain: ${this.tunnelConfig.subdomain}`);
145
- }
146
- // For free accounts or when random subdomain is requested,
147
- // don't specify any domain/subdomain - let ngrok generate a random URL
148
- this.ngrokProcess = spawn('ngrok', args, { stdio: ['ignore', 'pipe', 'pipe'] });
149
- let errorOccurred = false;
150
- this.ngrokProcess.on('error', (error) => {
151
- errorOccurred = true;
152
- elizaLogger.error(`Failed to start ngrok: ${error.message}`);
153
- reject(new Error(`Failed to start ngrok: ${error.message}`));
154
- });
155
- this.ngrokProcess.stderr?.on('data', (data) => {
156
- const message = data.toString();
157
- elizaLogger.error('Ngrok error:', message);
158
- if (!errorOccurred) {
159
- errorOccurred = true;
160
- // Kill the process to clean up
161
- if (this.ngrokProcess && !this.ngrokProcess.killed) {
162
- this.ngrokProcess.kill();
163
- }
164
- // Handle specific error cases
165
- if (message.includes('invalid port')) {
166
- reject(new Error('Invalid port specified'));
167
- }
168
- else if (message.includes('address already in use')) {
169
- reject(new Error('Port is already in use'));
170
- }
171
- else if (message.includes('ERR_NGROK_15002') || message.includes('Pay-as-you-go')) {
172
- // Pay-as-you-go account requires domain
173
- if (!domain) {
174
- reject(new Error('Pay-as-you-go ngrok account requires NGROK_DOMAIN to be set. Please set NGROK_DOMAIN=your-domain.ngrok-free.app in your .env file'));
175
- }
176
- else {
177
- reject(new Error('Failed to start tunnel with pay-as-you-go account. Ensure your domain is registered at https://dashboard.ngrok.com/domains'));
178
- }
179
- }
180
- else if (message.includes('failed to start tunnel') ||
181
- message.includes('is already bound to another tunnel') ||
182
- message.includes('tunnel session failed')) {
183
- // This might happen if the domain is already in use
184
- reject(new Error('Failed to start tunnel - domain might already be in use'));
185
- }
186
- else {
187
- reject(new Error(`Ngrok error: ${message}`));
188
- }
189
- }
190
- });
191
- // Give ngrok more time to start and handle multiple retry attempts
192
- let retryCount = 0;
193
- const maxRetries = 3;
194
- const retryDelay = 2000;
195
- const tryFetchUrl = async () => {
196
- if (errorOccurred) {
197
- return; // Don't try to fetch URL if we already have an error
198
- }
199
- try {
200
- const url = await this.fetchTunnelUrl();
201
- if (url) {
202
- this.tunnelUrl = url;
203
- this.tunnelPort = port;
204
- this.startedAt = new Date();
205
- elizaLogger.success(`✅ Ngrok tunnel started: ${url}`);
206
- resolve(url);
207
- }
208
- else if (retryCount < maxRetries) {
209
- retryCount++;
210
- elizaLogger.warn(`Retrying to fetch tunnel URL (attempt ${retryCount}/${maxRetries})...`);
211
- setTimeout(tryFetchUrl, retryDelay);
212
- }
213
- else {
214
- reject(new Error('Failed to get tunnel URL from ngrok after multiple attempts'));
215
- }
216
- }
217
- catch (error) {
218
- if (retryCount < maxRetries && !errorOccurred) {
219
- retryCount++;
220
- elizaLogger.warn(`Retrying to fetch tunnel URL (attempt ${retryCount}/${maxRetries})...`);
221
- setTimeout(tryFetchUrl, retryDelay);
222
- }
223
- else {
224
- reject(error);
225
- }
226
- }
227
- };
228
- setTimeout(tryFetchUrl, 2000);
229
- });
230
- }
231
- async stopTunnel() {
232
- if (!this.ngrokProcess) {
233
- elizaLogger.warn('Ngrok tunnel is not running');
234
- return;
235
- }
236
- elizaLogger.info('🛑 Stopping ngrok tunnel...');
237
- return new Promise((resolve) => {
238
- if (this.ngrokProcess) {
239
- this.ngrokProcess.on('exit', () => {
240
- this.cleanup();
241
- elizaLogger.info('✅ Ngrok tunnel stopped');
242
- resolve();
243
- });
244
- this.ngrokProcess.kill();
245
- setTimeout(() => {
246
- if (this.ngrokProcess && !this.ngrokProcess.killed) {
247
- this.ngrokProcess.kill('SIGKILL');
248
- }
249
- this.cleanup();
250
- resolve();
251
- }, 5000);
252
- }
253
- else {
254
- resolve();
255
- }
256
- });
257
- }
258
- getUrl() {
259
- return this.tunnelUrl;
260
- }
261
- isActive() {
262
- return this.ngrokProcess !== null && !this.ngrokProcess.killed && this.tunnelUrl !== null;
263
- }
264
- getStatus() {
265
- return {
266
- active: this.isActive(),
267
- url: this.tunnelUrl,
268
- port: this.tunnelPort,
269
- startedAt: this.startedAt,
270
- provider: 'ngrok',
271
- };
272
- }
273
- cleanup() {
274
- this.ngrokProcess = null;
275
- this.tunnelUrl = null;
276
- this.tunnelPort = null;
277
- this.startedAt = null;
278
- }
279
- async checkNgrokInstalled() {
280
- return new Promise((resolve) => {
281
- const proc = spawn('which', ['ngrok']);
282
- proc.on('exit', (code) => resolve(code === 0));
283
- proc.on('error', () => resolve(false));
284
- });
285
- }
286
- async setAuthToken(token) {
287
- return new Promise((resolve, reject) => {
288
- const proc = spawn('ngrok', ['config', 'add-authtoken', token]);
289
- proc.on('exit', (code) => {
290
- if (code === 0) {
291
- elizaLogger.info('✅ Ngrok auth token configured');
292
- resolve();
293
- }
294
- else {
295
- reject(new Error('Failed to set ngrok auth token'));
296
- }
297
- });
298
- proc.on('error', reject);
299
- });
300
- }
301
- async fetchTunnelUrl() {
302
- return new Promise((resolve) => {
303
- http
304
- .get('http://localhost:4040/api/tunnels', (res) => {
305
- let data = '';
306
- res.on('data', (chunk) => (data += chunk));
307
- res.on('end', () => {
308
- try {
309
- const tunnels = JSON.parse(data);
310
- const httpsTunnel = tunnels.tunnels?.find((t) => t.proto === 'https');
311
- if (httpsTunnel?.public_url) {
312
- resolve(httpsTunnel.public_url);
313
- }
314
- else {
315
- elizaLogger.warn('No HTTPS tunnel found in ngrok response');
316
- resolve(null);
317
- }
318
- }
319
- catch (error) {
320
- const msg = error instanceof Error ? error.message : String(error);
321
- elizaLogger.error(`Failed to parse ngrok API response: ${msg}`);
322
- resolve(null);
323
- }
324
- });
325
- })
326
- .on('error', (error) => {
327
- elizaLogger.error(`Failed to connect to ngrok API: ${error.message}`);
328
- resolve(null);
329
- });
330
- });
331
- }
332
- }
333
- //# sourceMappingURL=NgrokService.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"NgrokService.js","sourceRoot":"","sources":["../../src/services/NgrokService.ts"],"names":[],"mappings":"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"}