@liveport/agent-sdk 0.1.1 → 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.
@@ -1,175 +0,0 @@
1
- /**
2
- * AI Agent Workflow Example
3
- *
4
- * This example demonstrates how an AI agent might use the SDK
5
- * to interact with a developer's local application.
6
- */
7
-
8
- import { LivePortAgent, ApiError } from "@liveport/agent-sdk";
9
-
10
- interface TestResult {
11
- endpoint: string;
12
- status: "pass" | "fail";
13
- responseTime: number;
14
- statusCode?: number;
15
- error?: string;
16
- }
17
-
18
- class AIAgentTester {
19
- private agent: LivePortAgent;
20
- private results: TestResult[] = [];
21
-
22
- constructor(bridgeKey: string) {
23
- this.agent = new LivePortAgent({
24
- key: bridgeKey,
25
- timeout: 120000, // 2 minute timeout for tunnel
26
- });
27
- }
28
-
29
- async run(): Promise<void> {
30
- console.log("šŸ¤– AI Agent Test Runner Starting...\n");
31
-
32
- try {
33
- // Step 1: Wait for tunnel
34
- console.log("ā³ Waiting for developer to start tunnel...");
35
- const tunnel = await this.agent.waitForTunnel({
36
- timeout: 120000,
37
- });
38
-
39
- console.log(`āœ“ Tunnel established: ${tunnel.url}`);
40
- console.log(` Port: ${tunnel.localPort}`);
41
- console.log(` Expires: ${tunnel.expiresAt.toLocaleString()}\n`);
42
-
43
- // Step 2: Discover available endpoints
44
- console.log("šŸ” Discovering API endpoints...");
45
- const baseUrl = tunnel.url;
46
-
47
- // Test common endpoints
48
- const endpoints = [
49
- "/",
50
- "/api/health",
51
- "/api/users",
52
- "/api/products",
53
- "/api/auth/login",
54
- ];
55
-
56
- // Step 3: Test each endpoint
57
- for (const endpoint of endpoints) {
58
- await this.testEndpoint(baseUrl, endpoint);
59
- }
60
-
61
- // Step 4: Report results
62
- this.printResults();
63
-
64
- // Step 5: Analyze and provide recommendations
65
- this.analyzeResults();
66
- } catch (error) {
67
- if (error instanceof ApiError) {
68
- console.error(`āŒ API Error [${error.code}]: ${error.message}`);
69
- } else {
70
- console.error("āŒ Error:", error);
71
- }
72
- } finally {
73
- await this.agent.disconnect();
74
- }
75
- }
76
-
77
- private async testEndpoint(
78
- baseUrl: string,
79
- endpoint: string
80
- ): Promise<void> {
81
- const start = Date.now();
82
-
83
- try {
84
- const response = await fetch(`${baseUrl}${endpoint}`, {
85
- signal: AbortSignal.timeout(5000), // 5 second timeout per request
86
- });
87
-
88
- const responseTime = Date.now() - start;
89
-
90
- this.results.push({
91
- endpoint,
92
- status: response.ok ? "pass" : "fail",
93
- responseTime,
94
- statusCode: response.status,
95
- });
96
-
97
- const emoji = response.ok ? "āœ“" : "āœ—";
98
- console.log(
99
- ` ${emoji} ${endpoint.padEnd(20)} [${response.status}] ${responseTime}ms`
100
- );
101
- } catch (error) {
102
- const responseTime = Date.now() - start;
103
-
104
- this.results.push({
105
- endpoint,
106
- status: "fail",
107
- responseTime,
108
- error: error instanceof Error ? error.message : "Unknown error",
109
- });
110
-
111
- console.log(` āœ— ${endpoint.padEnd(20)} [ERROR] ${error}`);
112
- }
113
- }
114
-
115
- private printResults(): void {
116
- console.log("\nšŸ“Š Test Results Summary");
117
- console.log("=" .repeat(50));
118
-
119
- const passed = this.results.filter((r) => r.status === "pass").length;
120
- const failed = this.results.filter((r) => r.status === "fail").length;
121
- const avgTime =
122
- this.results.reduce((sum, r) => sum + r.responseTime, 0) /
123
- this.results.length;
124
-
125
- console.log(`Total Endpoints: ${this.results.length}`);
126
- console.log(`Passed: ${passed}`);
127
- console.log(`Failed: ${failed}`);
128
- console.log(`Average Response Time: ${avgTime.toFixed(0)}ms`);
129
- }
130
-
131
- private analyzeResults(): void {
132
- console.log("\nšŸ’” AI Analysis & Recommendations");
133
- console.log("=" .repeat(50));
134
-
135
- const slowEndpoints = this.results.filter((r) => r.responseTime > 1000);
136
- if (slowEndpoints.length > 0) {
137
- console.log("\nāš ļø Slow Endpoints (>1000ms):");
138
- slowEndpoints.forEach((r) => {
139
- console.log(` - ${r.endpoint}: ${r.responseTime}ms`);
140
- });
141
- console.log(" šŸ’” Consider optimizing database queries or adding caching");
142
- }
143
-
144
- const failedEndpoints = this.results.filter((r) => r.status === "fail");
145
- if (failedEndpoints.length > 0) {
146
- console.log("\nāŒ Failed Endpoints:");
147
- failedEndpoints.forEach((r) => {
148
- console.log(` - ${r.endpoint}: ${r.statusCode || r.error}`);
149
- });
150
- console.log(" šŸ’” Review error handling and endpoint implementations");
151
- }
152
-
153
- const avgTime =
154
- this.results.reduce((sum, r) => sum + r.responseTime, 0) /
155
- this.results.length;
156
- if (avgTime < 100) {
157
- console.log("\n✨ Great performance! All endpoints responding quickly.");
158
- }
159
- }
160
- }
161
-
162
- // Run the AI agent
163
- async function main() {
164
- const bridgeKey = process.env.LIVEPORT_KEY;
165
-
166
- if (!bridgeKey) {
167
- console.error("Error: LIVEPORT_KEY environment variable not set");
168
- process.exit(1);
169
- }
170
-
171
- const tester = new AIAgentTester(bridgeKey);
172
- await tester.run();
173
- }
174
-
175
- main();
@@ -1,84 +0,0 @@
1
- /**
2
- * Multiple Tunnels Example
3
- *
4
- * This example shows how to work with multiple tunnels
5
- * when testing microservices or multi-service architectures.
6
- */
7
-
8
- import { LivePortAgent } from "@liveport/agent-sdk";
9
-
10
- async function main() {
11
- const agent = new LivePortAgent({
12
- key: process.env.LIVEPORT_KEY!,
13
- });
14
-
15
- console.log("šŸ” Checking for available tunnels...\n");
16
-
17
- try {
18
- // List all active tunnels for this bridge key
19
- const tunnels = await agent.listTunnels();
20
-
21
- if (tunnels.length === 0) {
22
- console.log("No tunnels available.");
23
- console.log("Start one or more tunnels with:");
24
- console.log(" liveport connect 3000 # API server");
25
- console.log(" liveport connect 3001 # Web server");
26
- console.log(" liveport connect 5432 # Database");
27
- return;
28
- }
29
-
30
- console.log(`Found ${tunnels.length} active tunnel(s):\n`);
31
-
32
- // Display tunnel information
33
- for (const tunnel of tunnels) {
34
- console.log(`šŸ“ ${tunnel.subdomain}`);
35
- console.log(` URL: ${tunnel.url}`);
36
- console.log(` Local Port: ${tunnel.localPort}`);
37
- console.log(` Created: ${tunnel.createdAt.toLocaleString()}`);
38
- console.log(` Expires: ${tunnel.expiresAt.toLocaleString()}`);
39
- console.log();
40
- }
41
-
42
- // Example: Test each tunnel
43
- console.log("Testing each tunnel...\n");
44
-
45
- for (const tunnel of tunnels) {
46
- try {
47
- const response = await fetch(tunnel.url, {
48
- signal: AbortSignal.timeout(5000),
49
- });
50
-
51
- console.log(
52
- `āœ“ ${tunnel.subdomain.padEnd(30)} [${response.status}] ${response.statusText}`
53
- );
54
- } catch (error) {
55
- console.log(`āœ— ${tunnel.subdomain.padEnd(30)} [ERROR] ${error}`);
56
- }
57
- }
58
-
59
- // Example: Find specific service by port
60
- const apiTunnel = tunnels.find((t) => t.localPort === 3000);
61
- if (apiTunnel) {
62
- console.log(`\nšŸŽÆ Found API server at ${apiTunnel.url}`);
63
-
64
- // Run API-specific tests
65
- const health = await fetch(`${apiTunnel.url}/health`);
66
- console.log(` Health check: ${health.status}`);
67
- }
68
-
69
- const webTunnel = tunnels.find((t) => t.localPort === 3001);
70
- if (webTunnel) {
71
- console.log(`\nšŸŽÆ Found web server at ${webTunnel.url}`);
72
-
73
- // Run web-specific tests
74
- const homepage = await fetch(webTunnel.url);
75
- console.log(` Homepage: ${homepage.status}`);
76
- }
77
- } catch (error) {
78
- console.error("Error:", error);
79
- } finally {
80
- await agent.disconnect();
81
- }
82
- }
83
-
84
- main();
@@ -1,148 +0,0 @@
1
- /**
2
- * Error Handling Example
3
- *
4
- * This example demonstrates proper error handling patterns
5
- * when using the LivePort Agent SDK.
6
- */
7
-
8
- import {
9
- LivePortAgent,
10
- TunnelTimeoutError,
11
- ApiError,
12
- } from "@liveport/agent-sdk";
13
-
14
- async function robustTunnelAccess() {
15
- const agent = new LivePortAgent({
16
- key: process.env.LIVEPORT_KEY!,
17
- timeout: 30000,
18
- });
19
-
20
- try {
21
- console.log("ā³ Waiting for tunnel...");
22
-
23
- const tunnel = await agent.waitForTunnel({
24
- timeout: 30000,
25
- pollInterval: 2000,
26
- });
27
-
28
- console.log(`āœ“ Connected to ${tunnel.url}`);
29
-
30
- // Your application logic here
31
- await runTests(tunnel.url);
32
- } catch (error) {
33
- // Handle specific error types
34
- if (error instanceof TunnelTimeoutError) {
35
- console.error("\nāŒ Tunnel Timeout");
36
- console.error(" No tunnel became available within the timeout period.");
37
- console.error("\nšŸ’” Make sure to:");
38
- console.error(" 1. Start your local server (e.g., npm run dev)");
39
- console.error(" 2. Run: liveport connect <port>");
40
- console.error(" 3. Wait for tunnel URL to appear");
41
- console.error(" 4. Then run this script again");
42
- process.exit(1);
43
- } else if (error instanceof ApiError) {
44
- console.error(`\nāŒ API Error [${error.code}]`);
45
- console.error(` ${error.message}`);
46
- console.error(` Status: ${error.statusCode}`);
47
-
48
- // Handle specific error codes
49
- switch (error.code) {
50
- case "INVALID_KEY":
51
- console.error("\nšŸ’” Your bridge key is invalid or expired.");
52
- console.error(" Get a new key at: https://liveport.dev/keys");
53
- break;
54
-
55
- case "EXPIRED_KEY":
56
- console.error("\nšŸ’” Your bridge key has expired.");
57
- console.error(" Create a new key at: https://liveport.dev/keys");
58
- break;
59
-
60
- case "REVOKED_KEY":
61
- console.error("\nšŸ’” Your bridge key has been revoked.");
62
- console.error(" Create a new key at: https://liveport.dev/keys");
63
- break;
64
-
65
- case "USAGE_LIMIT_EXCEEDED":
66
- console.error("\nšŸ’” Your bridge key has exceeded its usage limit.");
67
- console.error(" Create a new key or increase the limit at:");
68
- console.error(" https://liveport.dev/keys");
69
- break;
70
-
71
- case "RATE_LIMIT_EXCEEDED":
72
- console.error("\nšŸ’” Too many requests. Please wait and try again.");
73
- break;
74
-
75
- default:
76
- console.error("\nšŸ’” Please check your configuration and try again.");
77
- }
78
-
79
- process.exit(1);
80
- } else if (error instanceof Error) {
81
- console.error("\nāŒ Unexpected Error");
82
- console.error(` ${error.message}`);
83
- console.error("\nšŸ’” Please report this issue at:");
84
- console.error(" https://github.com/dundas/liveport/issues");
85
- process.exit(1);
86
- } else {
87
- console.error("\nāŒ Unknown Error");
88
- console.error(error);
89
- process.exit(1);
90
- }
91
- } finally {
92
- // Always clean up
93
- await agent.disconnect();
94
- }
95
- }
96
-
97
- async function runTests(tunnelUrl: string) {
98
- console.log("\n🧪 Running tests...");
99
-
100
- try {
101
- // Example test with retry logic
102
- const response = await fetchWithRetry(`${tunnelUrl}/api/health`, {
103
- maxRetries: 3,
104
- retryDelay: 1000,
105
- });
106
-
107
- if (!response.ok) {
108
- throw new Error(`Health check failed: ${response.status}`);
109
- }
110
-
111
- console.log("āœ“ Health check passed");
112
-
113
- // More tests...
114
- console.log("āœ“ All tests passed!");
115
- } catch (error) {
116
- console.error("āœ— Tests failed:", error);
117
- throw error;
118
- }
119
- }
120
-
121
- async function fetchWithRetry(
122
- url: string,
123
- options: { maxRetries?: number; retryDelay?: number } = {}
124
- ): Promise<Response> {
125
- const { maxRetries = 3, retryDelay = 1000 } = options;
126
-
127
- for (let i = 0; i <= maxRetries; i++) {
128
- try {
129
- const response = await fetch(url, {
130
- signal: AbortSignal.timeout(5000),
131
- });
132
-
133
- return response;
134
- } catch (error) {
135
- if (i === maxRetries) {
136
- throw error;
137
- }
138
-
139
- console.log(` Retry ${i + 1}/${maxRetries} after ${retryDelay}ms...`);
140
- await new Promise((resolve) => setTimeout(resolve, retryDelay));
141
- }
142
- }
143
-
144
- throw new Error("Max retries exceeded");
145
- }
146
-
147
- // Run with proper error handling
148
- robustTunnelAccess();
@@ -1,172 +0,0 @@
1
- # LivePort Agent SDK Examples
2
-
3
- This directory contains practical examples demonstrating different use cases for the LivePort Agent SDK.
4
-
5
- ## Running the Examples
6
-
7
- 1. **Install dependencies:**
8
- ```bash
9
- pnpm install
10
- ```
11
-
12
- 2. **Set your bridge key:**
13
- ```bash
14
- export LIVEPORT_KEY=lpk_your_bridge_key_here
15
- ```
16
-
17
- 3. **Start a local tunnel:**
18
- ```bash
19
- # In a separate terminal
20
- liveport connect 3000
21
- ```
22
-
23
- 4. **Run an example:**
24
- ```bash
25
- npx tsx examples/01-basic-usage.ts
26
- ```
27
-
28
- ## Examples Overview
29
-
30
- ### `01-basic-usage.ts`
31
- **Simplest example** showing how to wait for a tunnel and make a request.
32
-
33
- **Use case:** Quick start, proof of concept
34
-
35
- **Key concepts:**
36
- - Creating an agent instance
37
- - Waiting for tunnel
38
- - Making HTTP requests
39
- - Basic error handling
40
-
41
- ---
42
-
43
- ### `02-testing-integration.ts`
44
- **Testing framework integration** using Vitest (works with Jest too).
45
-
46
- **Use case:** Automated testing, CI/CD pipelines
47
-
48
- **Key concepts:**
49
- - beforeAll/afterAll hooks
50
- - Multiple test cases
51
- - Sharing tunnel across tests
52
- - Timeout configuration
53
-
54
- ---
55
-
56
- ### `03-ai-agent-workflow.ts`
57
- **Complete AI agent workflow** that discovers, tests, and analyzes endpoints.
58
-
59
- **Use case:** AI-powered testing, endpoint discovery, performance analysis
60
-
61
- **Key concepts:**
62
- - Endpoint discovery
63
- - Performance measurement
64
- - Result analysis
65
- - AI recommendations
66
-
67
- ---
68
-
69
- ### `04-multiple-tunnels.ts`
70
- **Working with multiple tunnels** for microservices testing.
71
-
72
- **Use case:** Multi-service architectures, microservices
73
-
74
- **Key concepts:**
75
- - Listing all tunnels
76
- - Finding tunnels by port
77
- - Testing multiple services
78
- - Service-specific logic
79
-
80
- ---
81
-
82
- ### `05-error-handling.ts`
83
- **Comprehensive error handling** patterns and best practices.
84
-
85
- **Use case:** Production applications, robust error handling
86
-
87
- **Key concepts:**
88
- - Specific error types
89
- - User-friendly error messages
90
- - Retry logic
91
- - Cleanup and recovery
92
-
93
- ---
94
-
95
- ## Common Patterns
96
-
97
- ### Pattern 1: Wait with Timeout
98
-
99
- ```typescript
100
- const agent = new LivePortAgent({ key: "lpk_..." });
101
-
102
- try {
103
- const tunnel = await agent.waitForTunnel({ timeout: 60000 });
104
- // Use tunnel.url
105
- } catch (error) {
106
- if (error instanceof TunnelTimeoutError) {
107
- console.log("No tunnel available");
108
- }
109
- }
110
- ```
111
-
112
- ### Pattern 2: Test Suite Integration
113
-
114
- ```typescript
115
- let tunnelUrl: string;
116
-
117
- beforeAll(async () => {
118
- const agent = new LivePortAgent({ key: process.env.LIVEPORT_KEY! });
119
- const tunnel = await agent.waitForTunnel();
120
- tunnelUrl = tunnel.url;
121
- });
122
-
123
- test("API test", async () => {
124
- const response = await fetch(`${tunnelUrl}/api/endpoint`);
125
- // assertions...
126
- });
127
- ```
128
-
129
- ### Pattern 3: Multiple Services
130
-
131
- ```typescript
132
- const agent = new LivePortAgent({ key: "lpk_..." });
133
- const tunnels = await agent.listTunnels();
134
-
135
- const apiTunnel = tunnels.find(t => t.localPort === 3000);
136
- const webTunnel = tunnels.find(t => t.localPort === 3001);
137
-
138
- // Test API
139
- await fetch(`${apiTunnel.url}/health`);
140
-
141
- // Test Web
142
- await fetch(`${webTunnel.url}/`);
143
- ```
144
-
145
- ## Tips
146
-
147
- 1. **Always set a timeout** - Use reasonable timeouts to avoid hanging indefinitely
148
- 2. **Handle errors gracefully** - Provide helpful error messages for users
149
- 3. **Clean up resources** - Always call `agent.disconnect()` in finally blocks
150
- 4. **Use environment variables** - Never hardcode bridge keys
151
- 5. **Add retry logic** - Network requests can fail, especially in CI/CD
152
-
153
- ## Environment Variables
154
-
155
- All examples support these environment variables:
156
-
157
- - `LIVEPORT_KEY` - Your bridge key (required)
158
- - `LIVEPORT_API_URL` - Custom API URL (optional)
159
-
160
- ## Next Steps
161
-
162
- After trying these examples, check out:
163
-
164
- - [API Documentation](../README.md)
165
- - [CLI Documentation](../../cli/README.md)
166
- - [Dashboard](https://liveport.dev/dashboard)
167
-
168
- ## Need Help?
169
-
170
- - šŸ“š [Full Documentation](https://liveport.dev/docs)
171
- - šŸ› [Report Issues](https://github.com/dundas/liveport/issues)
172
- - šŸ’¬ [Community Support](https://liveport.dev/support)