@privateconnect/sdk 0.3.0
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 +174 -0
- package/dist/index.d.ts +203 -0
- package/dist/index.js +309 -0
- package/package.json +33 -0
package/README.md
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# Private Connect SDK
|
|
2
|
+
|
|
3
|
+
TypeScript SDK for Private Connect - programmatic access to services and agent orchestration.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @privateconnect/sdk
|
|
9
|
+
# or
|
|
10
|
+
pnpm add @privateconnect/sdk
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { PrivateConnect, connect } from '@privateconnect/sdk';
|
|
17
|
+
|
|
18
|
+
// Quick connect to a service
|
|
19
|
+
const db = await connect('postgres-prod');
|
|
20
|
+
console.log(db.connectionString); // postgres://localhost:5432/...
|
|
21
|
+
|
|
22
|
+
// Or use the full client
|
|
23
|
+
const pc = new PrivateConnect({
|
|
24
|
+
apiKey: process.env.PRIVATECONNECT_API_KEY
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// List available services
|
|
28
|
+
const services = await pc.services.list();
|
|
29
|
+
|
|
30
|
+
// Connect to a specific service
|
|
31
|
+
const redis = await pc.connect('redis-cache');
|
|
32
|
+
console.log(redis.connectionString); // redis://localhost:6379
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Agent Orchestration
|
|
36
|
+
|
|
37
|
+
The SDK enables multi-agent orchestration - coordinating work across agents running on different machines.
|
|
38
|
+
|
|
39
|
+
### List Agents
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
// Get all agents in your workspace
|
|
43
|
+
const agents = await pc.agents.list();
|
|
44
|
+
|
|
45
|
+
// Get only online agents
|
|
46
|
+
const online = await pc.agents.list({ onlineOnly: true });
|
|
47
|
+
|
|
48
|
+
// Find agents with specific capabilities
|
|
49
|
+
const gpuAgents = await pc.agents.findByCapability('gpu');
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Register Capabilities
|
|
53
|
+
|
|
54
|
+
Tell other agents what you can do:
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
await pc.agents.registerCapabilities([
|
|
58
|
+
{ name: 'database', metadata: { type: 'postgres', version: '15' } },
|
|
59
|
+
{ name: 'gpu', metadata: { model: 'A100', memory: '80GB' } },
|
|
60
|
+
]);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Agent Messaging
|
|
64
|
+
|
|
65
|
+
Coordinate with other agents:
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
// Send a message to a specific agent
|
|
69
|
+
await pc.agents.sendMessage(targetAgentId, {
|
|
70
|
+
action: 'run-migration',
|
|
71
|
+
database: 'users',
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Broadcast to all agents
|
|
75
|
+
await pc.agents.broadcast({
|
|
76
|
+
type: 'deployment-starting',
|
|
77
|
+
service: 'api',
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Get your messages
|
|
81
|
+
const messages = await pc.agents.getMessages({ unreadOnly: true });
|
|
82
|
+
for (const msg of messages) {
|
|
83
|
+
console.log(`From ${msg.from.name}: ${JSON.stringify(msg.payload)}`);
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Orchestration Sessions
|
|
88
|
+
|
|
89
|
+
Create ephemeral sessions for coordinated workflows:
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
// Create a session
|
|
93
|
+
const session = await pc.sessions.create('deploy-v2.1', {
|
|
94
|
+
ttlMinutes: 30,
|
|
95
|
+
metadata: { version: '2.1.0' },
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// ... coordinate agents ...
|
|
99
|
+
|
|
100
|
+
// End the session
|
|
101
|
+
await pc.sessions.end(session.id);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Connection Strings
|
|
105
|
+
|
|
106
|
+
Get properly formatted connection strings for common services:
|
|
107
|
+
|
|
108
|
+
```typescript
|
|
109
|
+
const db = await pc.connect('postgres-prod');
|
|
110
|
+
// db.connectionString = 'postgres://localhost:5432/postgres'
|
|
111
|
+
// db.envVar = 'DATABASE_URL'
|
|
112
|
+
|
|
113
|
+
const cache = await pc.connect('redis-cache');
|
|
114
|
+
// cache.connectionString = 'redis://localhost:6379'
|
|
115
|
+
// cache.envVar = 'REDIS_URL'
|
|
116
|
+
|
|
117
|
+
const api = await pc.connect('internal-api');
|
|
118
|
+
// api.connectionString = 'http://localhost:8080'
|
|
119
|
+
// api.envVar = 'API_URL'
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Environment Variables
|
|
123
|
+
|
|
124
|
+
The SDK can read configuration from environment variables:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
export PRIVATECONNECT_API_KEY=your-api-key
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
// API key automatically read from env
|
|
132
|
+
const connection = await connect('my-service');
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## API Reference
|
|
136
|
+
|
|
137
|
+
### `PrivateConnect`
|
|
138
|
+
|
|
139
|
+
Main client class.
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
const pc = new PrivateConnect({
|
|
143
|
+
apiKey: string, // Required: Your API key
|
|
144
|
+
hubUrl?: string, // Optional: Hub URL (default: https://api.privateconnect.co)
|
|
145
|
+
agentId?: string, // Optional: Agent ID (auto-detected)
|
|
146
|
+
});
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### `pc.services`
|
|
150
|
+
|
|
151
|
+
- `list()` - List all services
|
|
152
|
+
- `get(name)` - Get a service by name
|
|
153
|
+
- `getConnection(name)` - Get connection details for a service
|
|
154
|
+
|
|
155
|
+
### `pc.agents`
|
|
156
|
+
|
|
157
|
+
- `list(options?)` - List all agents
|
|
158
|
+
- `findByCapability(capability)` - Find agents by capability
|
|
159
|
+
- `registerCapabilities(capabilities)` - Register this agent's capabilities
|
|
160
|
+
- `sendMessage(toAgentId, payload, options?)` - Send a message
|
|
161
|
+
- `broadcast(payload, options?)` - Broadcast to all agents
|
|
162
|
+
- `getMessages(options?)` - Get received messages
|
|
163
|
+
- `markRead(messageIds)` - Mark messages as read
|
|
164
|
+
|
|
165
|
+
### `pc.sessions`
|
|
166
|
+
|
|
167
|
+
- `create(name, options?)` - Create an orchestration session
|
|
168
|
+
- `end(sessionId)` - End a session
|
|
169
|
+
- `getActive()` - Get active sessions
|
|
170
|
+
|
|
171
|
+
## License
|
|
172
|
+
|
|
173
|
+
[FSL-1.1-MIT](LICENSE)
|
|
174
|
+
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Private Connect SDK
|
|
3
|
+
*
|
|
4
|
+
* Programmatic access to Private Connect services and agent orchestration.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { PrivateConnect } from '@privateconnect/sdk';
|
|
9
|
+
*
|
|
10
|
+
* const pc = new PrivateConnect({ apiKey: 'your-api-key' });
|
|
11
|
+
*
|
|
12
|
+
* // Connect to a service
|
|
13
|
+
* const db = await pc.connect('postgres-prod');
|
|
14
|
+
* console.log(db.connectionString); // postgres://localhost:5432/...
|
|
15
|
+
*
|
|
16
|
+
* // List all agents
|
|
17
|
+
* const agents = await pc.agents.list();
|
|
18
|
+
*
|
|
19
|
+
* // Send message to another agent
|
|
20
|
+
* await pc.agents.sendMessage(targetAgentId, { action: 'deploy' });
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export interface PrivateConnectConfig {
|
|
24
|
+
/** API key for authentication */
|
|
25
|
+
apiKey: string;
|
|
26
|
+
/** Hub URL (default: https://api.privateconnect.co) */
|
|
27
|
+
hubUrl?: string;
|
|
28
|
+
/** Agent ID (auto-detected from config if not provided) */
|
|
29
|
+
agentId?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface Service {
|
|
32
|
+
id: string;
|
|
33
|
+
name: string;
|
|
34
|
+
targetHost: string;
|
|
35
|
+
targetPort: number;
|
|
36
|
+
tunnelPort?: number;
|
|
37
|
+
protocol: string;
|
|
38
|
+
status: string;
|
|
39
|
+
agentLabel?: string;
|
|
40
|
+
}
|
|
41
|
+
export interface Agent {
|
|
42
|
+
id: string;
|
|
43
|
+
name?: string;
|
|
44
|
+
label: string;
|
|
45
|
+
isOnline: boolean;
|
|
46
|
+
lastSeenAt: string;
|
|
47
|
+
capabilities: string[];
|
|
48
|
+
services: string[];
|
|
49
|
+
}
|
|
50
|
+
export interface Connection {
|
|
51
|
+
service: string;
|
|
52
|
+
host: string;
|
|
53
|
+
port: number;
|
|
54
|
+
connectionString: string;
|
|
55
|
+
envVar: string;
|
|
56
|
+
}
|
|
57
|
+
export interface Message {
|
|
58
|
+
id: string;
|
|
59
|
+
from: {
|
|
60
|
+
id: string;
|
|
61
|
+
name?: string;
|
|
62
|
+
label?: string;
|
|
63
|
+
};
|
|
64
|
+
channel: string;
|
|
65
|
+
type: string;
|
|
66
|
+
payload: Record<string, unknown>;
|
|
67
|
+
createdAt: string;
|
|
68
|
+
isRead: boolean;
|
|
69
|
+
}
|
|
70
|
+
export interface Session {
|
|
71
|
+
id: string;
|
|
72
|
+
name: string;
|
|
73
|
+
createdBy: string;
|
|
74
|
+
createdAt: string;
|
|
75
|
+
expiresAt: string;
|
|
76
|
+
metadata?: Record<string, unknown>;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Agents API for discovery and orchestration
|
|
80
|
+
*/
|
|
81
|
+
export declare class AgentsAPI {
|
|
82
|
+
private client;
|
|
83
|
+
constructor(client: PrivateConnect);
|
|
84
|
+
/**
|
|
85
|
+
* List all agents in the workspace
|
|
86
|
+
*/
|
|
87
|
+
list(options?: {
|
|
88
|
+
onlineOnly?: boolean;
|
|
89
|
+
}): Promise<Agent[]>;
|
|
90
|
+
/**
|
|
91
|
+
* Find agents by capability
|
|
92
|
+
*/
|
|
93
|
+
findByCapability(capability: string): Promise<Agent[]>;
|
|
94
|
+
/**
|
|
95
|
+
* Register capabilities for this agent
|
|
96
|
+
*/
|
|
97
|
+
registerCapabilities(capabilities: Array<{
|
|
98
|
+
name: string;
|
|
99
|
+
metadata?: Record<string, unknown>;
|
|
100
|
+
}>): Promise<void>;
|
|
101
|
+
/**
|
|
102
|
+
* Send a message to another agent
|
|
103
|
+
*/
|
|
104
|
+
sendMessage(toAgentId: string, payload: Record<string, unknown>, options?: {
|
|
105
|
+
channel?: string;
|
|
106
|
+
type?: 'request' | 'response' | 'event';
|
|
107
|
+
}): Promise<{
|
|
108
|
+
messageId: string;
|
|
109
|
+
}>;
|
|
110
|
+
/**
|
|
111
|
+
* Broadcast a message to all online agents
|
|
112
|
+
*/
|
|
113
|
+
broadcast(payload: Record<string, unknown>, options?: {
|
|
114
|
+
channel?: string;
|
|
115
|
+
}): Promise<{
|
|
116
|
+
sent: number;
|
|
117
|
+
}>;
|
|
118
|
+
/**
|
|
119
|
+
* Get messages for this agent
|
|
120
|
+
*/
|
|
121
|
+
getMessages(options?: {
|
|
122
|
+
channel?: string;
|
|
123
|
+
unreadOnly?: boolean;
|
|
124
|
+
limit?: number;
|
|
125
|
+
}): Promise<Message[]>;
|
|
126
|
+
/**
|
|
127
|
+
* Mark messages as read
|
|
128
|
+
*/
|
|
129
|
+
markRead(messageIds: string[]): Promise<void>;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Services API for connecting to and managing services
|
|
133
|
+
*/
|
|
134
|
+
export declare class ServicesAPI {
|
|
135
|
+
private client;
|
|
136
|
+
constructor(client: PrivateConnect);
|
|
137
|
+
/**
|
|
138
|
+
* List all services
|
|
139
|
+
*/
|
|
140
|
+
list(): Promise<Service[]>;
|
|
141
|
+
/**
|
|
142
|
+
* Get a specific service by name
|
|
143
|
+
*/
|
|
144
|
+
get(name: string): Promise<Service | null>;
|
|
145
|
+
/**
|
|
146
|
+
* Get connection details for a service
|
|
147
|
+
*/
|
|
148
|
+
getConnection(serviceName: string): Promise<Connection>;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Sessions API for ephemeral orchestration sessions
|
|
152
|
+
*/
|
|
153
|
+
export declare class SessionsAPI {
|
|
154
|
+
private client;
|
|
155
|
+
private activeSessions;
|
|
156
|
+
constructor(client: PrivateConnect);
|
|
157
|
+
/**
|
|
158
|
+
* Create an orchestration session
|
|
159
|
+
*/
|
|
160
|
+
create(name: string, options?: {
|
|
161
|
+
ttlMinutes?: number;
|
|
162
|
+
metadata?: Record<string, unknown>;
|
|
163
|
+
}): Promise<Session>;
|
|
164
|
+
/**
|
|
165
|
+
* End an orchestration session
|
|
166
|
+
*/
|
|
167
|
+
end(sessionId: string): Promise<void>;
|
|
168
|
+
/**
|
|
169
|
+
* Get active sessions
|
|
170
|
+
*/
|
|
171
|
+
getActive(): Session[];
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Main Private Connect SDK client
|
|
175
|
+
*/
|
|
176
|
+
export declare class PrivateConnect {
|
|
177
|
+
private config;
|
|
178
|
+
/** Agents API for discovery and orchestration */
|
|
179
|
+
agents: AgentsAPI;
|
|
180
|
+
/** Services API for connecting to services */
|
|
181
|
+
services: ServicesAPI;
|
|
182
|
+
/** Sessions API for ephemeral orchestration */
|
|
183
|
+
sessions: SessionsAPI;
|
|
184
|
+
constructor(config: PrivateConnectConfig);
|
|
185
|
+
/**
|
|
186
|
+
* Get the agent ID
|
|
187
|
+
*/
|
|
188
|
+
get agentId(): string | undefined;
|
|
189
|
+
/**
|
|
190
|
+
* Connect to a service and get connection details
|
|
191
|
+
*/
|
|
192
|
+
connect(serviceName: string): Promise<Connection>;
|
|
193
|
+
/**
|
|
194
|
+
* Internal fetch helper
|
|
195
|
+
*/
|
|
196
|
+
fetch(path: string, options?: RequestInit): Promise<Response>;
|
|
197
|
+
/**
|
|
198
|
+
* Try to detect agent ID from local config
|
|
199
|
+
*/
|
|
200
|
+
private detectAgentId;
|
|
201
|
+
}
|
|
202
|
+
export default PrivateConnect;
|
|
203
|
+
export declare function connect(serviceName: string, config?: PrivateConnectConfig): Promise<Connection>;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Private Connect SDK
|
|
4
|
+
*
|
|
5
|
+
* Programmatic access to Private Connect services and agent orchestration.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { PrivateConnect } from '@privateconnect/sdk';
|
|
10
|
+
*
|
|
11
|
+
* const pc = new PrivateConnect({ apiKey: 'your-api-key' });
|
|
12
|
+
*
|
|
13
|
+
* // Connect to a service
|
|
14
|
+
* const db = await pc.connect('postgres-prod');
|
|
15
|
+
* console.log(db.connectionString); // postgres://localhost:5432/...
|
|
16
|
+
*
|
|
17
|
+
* // List all agents
|
|
18
|
+
* const agents = await pc.agents.list();
|
|
19
|
+
*
|
|
20
|
+
* // Send message to another agent
|
|
21
|
+
* await pc.agents.sendMessage(targetAgentId, { action: 'deploy' });
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.PrivateConnect = exports.SessionsAPI = exports.ServicesAPI = exports.AgentsAPI = void 0;
|
|
26
|
+
exports.connect = connect;
|
|
27
|
+
/**
|
|
28
|
+
* Agents API for discovery and orchestration
|
|
29
|
+
*/
|
|
30
|
+
class AgentsAPI {
|
|
31
|
+
constructor(client) {
|
|
32
|
+
this.client = client;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* List all agents in the workspace
|
|
36
|
+
*/
|
|
37
|
+
async list(options) {
|
|
38
|
+
const response = await this.client.fetch('/v1/agents/orchestration');
|
|
39
|
+
const data = await response.json();
|
|
40
|
+
let agents = data.agents || [];
|
|
41
|
+
if (options?.onlineOnly) {
|
|
42
|
+
agents = agents.filter((a) => a.isOnline);
|
|
43
|
+
}
|
|
44
|
+
return agents.map((a) => ({
|
|
45
|
+
id: a.id,
|
|
46
|
+
name: a.name,
|
|
47
|
+
label: a.label,
|
|
48
|
+
isOnline: a.isOnline,
|
|
49
|
+
lastSeenAt: a.lastSeenAt,
|
|
50
|
+
capabilities: a.capabilities?.map((c) => c.name) || [],
|
|
51
|
+
services: a.services?.map((s) => s.name) || [],
|
|
52
|
+
}));
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Find agents by capability
|
|
56
|
+
*/
|
|
57
|
+
async findByCapability(capability) {
|
|
58
|
+
const response = await this.client.fetch(`/v1/agents/by-capability/${encodeURIComponent(capability)}`);
|
|
59
|
+
const data = await response.json();
|
|
60
|
+
return data.agents || [];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Register capabilities for this agent
|
|
64
|
+
*/
|
|
65
|
+
async registerCapabilities(capabilities) {
|
|
66
|
+
await this.client.fetch(`/v1/agents/${this.client.agentId}/capabilities`, {
|
|
67
|
+
method: 'POST',
|
|
68
|
+
body: JSON.stringify({ capabilities }),
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Send a message to another agent
|
|
73
|
+
*/
|
|
74
|
+
async sendMessage(toAgentId, payload, options) {
|
|
75
|
+
const response = await this.client.fetch(`/v1/agents/${this.client.agentId}/messages/send`, {
|
|
76
|
+
method: 'POST',
|
|
77
|
+
body: JSON.stringify({ toAgentId, payload, ...options }),
|
|
78
|
+
});
|
|
79
|
+
return response.json();
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Broadcast a message to all online agents
|
|
83
|
+
*/
|
|
84
|
+
async broadcast(payload, options) {
|
|
85
|
+
const response = await this.client.fetch(`/v1/agents/${this.client.agentId}/messages/broadcast`, {
|
|
86
|
+
method: 'POST',
|
|
87
|
+
body: JSON.stringify({ payload, ...options }),
|
|
88
|
+
});
|
|
89
|
+
return response.json();
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Get messages for this agent
|
|
93
|
+
*/
|
|
94
|
+
async getMessages(options) {
|
|
95
|
+
const params = new URLSearchParams();
|
|
96
|
+
if (options?.channel)
|
|
97
|
+
params.set('channel', options.channel);
|
|
98
|
+
if (options?.unreadOnly !== undefined)
|
|
99
|
+
params.set('unreadOnly', String(options.unreadOnly));
|
|
100
|
+
if (options?.limit)
|
|
101
|
+
params.set('limit', String(options.limit));
|
|
102
|
+
const response = await this.client.fetch(`/v1/agents/${this.client.agentId}/messages?${params}`);
|
|
103
|
+
const data = await response.json();
|
|
104
|
+
return data.messages || [];
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Mark messages as read
|
|
108
|
+
*/
|
|
109
|
+
async markRead(messageIds) {
|
|
110
|
+
await this.client.fetch(`/v1/agents/${this.client.agentId}/messages/read`, {
|
|
111
|
+
method: 'POST',
|
|
112
|
+
body: JSON.stringify({ messageIds }),
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
exports.AgentsAPI = AgentsAPI;
|
|
117
|
+
/**
|
|
118
|
+
* Services API for connecting to and managing services
|
|
119
|
+
*/
|
|
120
|
+
class ServicesAPI {
|
|
121
|
+
constructor(client) {
|
|
122
|
+
this.client = client;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* List all services
|
|
126
|
+
*/
|
|
127
|
+
async list() {
|
|
128
|
+
const response = await this.client.fetch('/v1/services');
|
|
129
|
+
return response.json();
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Get a specific service by name
|
|
133
|
+
*/
|
|
134
|
+
async get(name) {
|
|
135
|
+
const services = await this.list();
|
|
136
|
+
return services.find(s => s.name.toLowerCase() === name.toLowerCase()) || null;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get connection details for a service
|
|
140
|
+
*/
|
|
141
|
+
async getConnection(serviceName) {
|
|
142
|
+
const service = await this.get(serviceName);
|
|
143
|
+
if (!service) {
|
|
144
|
+
throw new Error(`Service "${serviceName}" not found`);
|
|
145
|
+
}
|
|
146
|
+
const port = service.tunnelPort || service.targetPort;
|
|
147
|
+
const host = 'localhost';
|
|
148
|
+
let connectionString = '';
|
|
149
|
+
let envVar = 'SERVICE_URL';
|
|
150
|
+
if (service.targetPort === 5432 || service.protocol === 'postgres') {
|
|
151
|
+
connectionString = `postgres://${host}:${port}/postgres`;
|
|
152
|
+
envVar = 'DATABASE_URL';
|
|
153
|
+
}
|
|
154
|
+
else if (service.targetPort === 3306 || service.protocol === 'mysql') {
|
|
155
|
+
connectionString = `mysql://${host}:${port}`;
|
|
156
|
+
envVar = 'DATABASE_URL';
|
|
157
|
+
}
|
|
158
|
+
else if (service.targetPort === 6379 || service.protocol === 'redis') {
|
|
159
|
+
connectionString = `redis://${host}:${port}`;
|
|
160
|
+
envVar = 'REDIS_URL';
|
|
161
|
+
}
|
|
162
|
+
else if (service.targetPort === 27017 || service.protocol === 'mongodb') {
|
|
163
|
+
connectionString = `mongodb://${host}:${port}`;
|
|
164
|
+
envVar = 'MONGODB_URI';
|
|
165
|
+
}
|
|
166
|
+
else if (service.protocol === 'http' || service.protocol === 'https') {
|
|
167
|
+
connectionString = `http://${host}:${port}`;
|
|
168
|
+
envVar = 'API_URL';
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
connectionString = `tcp://${host}:${port}`;
|
|
172
|
+
envVar = `${serviceName.toUpperCase().replace(/-/g, '_')}_URL`;
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
service: serviceName,
|
|
176
|
+
host,
|
|
177
|
+
port,
|
|
178
|
+
connectionString,
|
|
179
|
+
envVar,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
exports.ServicesAPI = ServicesAPI;
|
|
184
|
+
/**
|
|
185
|
+
* Sessions API for ephemeral orchestration sessions
|
|
186
|
+
*/
|
|
187
|
+
class SessionsAPI {
|
|
188
|
+
constructor(client) {
|
|
189
|
+
this.client = client;
|
|
190
|
+
this.activeSessions = new Map();
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Create an orchestration session
|
|
194
|
+
*/
|
|
195
|
+
async create(name, options) {
|
|
196
|
+
const ttlMinutes = options?.ttlMinutes || 60;
|
|
197
|
+
const sessionId = `${this.client.agentId}-${Date.now()}-${Math.random().toString(36).substring(2, 8)}`;
|
|
198
|
+
const expiresAt = new Date(Date.now() + ttlMinutes * 60 * 1000);
|
|
199
|
+
const session = {
|
|
200
|
+
id: sessionId,
|
|
201
|
+
name,
|
|
202
|
+
createdBy: this.client.agentId,
|
|
203
|
+
createdAt: new Date().toISOString(),
|
|
204
|
+
expiresAt: expiresAt.toISOString(),
|
|
205
|
+
metadata: options?.metadata,
|
|
206
|
+
};
|
|
207
|
+
this.activeSessions.set(sessionId, session);
|
|
208
|
+
// Broadcast session creation
|
|
209
|
+
await this.client.agents.broadcast({ type: 'session:created', session }, { channel: 'orchestration' });
|
|
210
|
+
return session;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* End an orchestration session
|
|
214
|
+
*/
|
|
215
|
+
async end(sessionId) {
|
|
216
|
+
this.activeSessions.delete(sessionId);
|
|
217
|
+
// Broadcast session end
|
|
218
|
+
await this.client.agents.broadcast({
|
|
219
|
+
type: 'session:ended',
|
|
220
|
+
sessionId,
|
|
221
|
+
endedBy: this.client.agentId,
|
|
222
|
+
endedAt: new Date().toISOString(),
|
|
223
|
+
}, { channel: 'orchestration' });
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Get active sessions
|
|
227
|
+
*/
|
|
228
|
+
getActive() {
|
|
229
|
+
const now = new Date();
|
|
230
|
+
const active = [];
|
|
231
|
+
for (const [id, session] of this.activeSessions) {
|
|
232
|
+
if (new Date(session.expiresAt) > now) {
|
|
233
|
+
active.push(session);
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
this.activeSessions.delete(id);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return active;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
exports.SessionsAPI = SessionsAPI;
|
|
243
|
+
/**
|
|
244
|
+
* Main Private Connect SDK client
|
|
245
|
+
*/
|
|
246
|
+
class PrivateConnect {
|
|
247
|
+
constructor(config) {
|
|
248
|
+
this.config = {
|
|
249
|
+
apiKey: config.apiKey,
|
|
250
|
+
hubUrl: config.hubUrl || 'https://api.privateconnect.co',
|
|
251
|
+
agentId: config.agentId || this.detectAgentId(),
|
|
252
|
+
};
|
|
253
|
+
this.agents = new AgentsAPI(this);
|
|
254
|
+
this.services = new ServicesAPI(this);
|
|
255
|
+
this.sessions = new SessionsAPI(this);
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Get the agent ID
|
|
259
|
+
*/
|
|
260
|
+
get agentId() {
|
|
261
|
+
return this.config.agentId;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Connect to a service and get connection details
|
|
265
|
+
*/
|
|
266
|
+
async connect(serviceName) {
|
|
267
|
+
return this.services.getConnection(serviceName);
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Internal fetch helper
|
|
271
|
+
*/
|
|
272
|
+
async fetch(path, options) {
|
|
273
|
+
const url = `${this.config.hubUrl}${path}`;
|
|
274
|
+
const response = await fetch(url, {
|
|
275
|
+
...options,
|
|
276
|
+
headers: {
|
|
277
|
+
'x-api-key': this.config.apiKey,
|
|
278
|
+
'Content-Type': 'application/json',
|
|
279
|
+
...options?.headers,
|
|
280
|
+
},
|
|
281
|
+
});
|
|
282
|
+
if (!response.ok) {
|
|
283
|
+
const error = await response.json().catch(() => ({ message: 'Unknown error' }));
|
|
284
|
+
throw new Error(error.message || `Request failed: ${response.status}`);
|
|
285
|
+
}
|
|
286
|
+
return response;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Try to detect agent ID from local config
|
|
290
|
+
*/
|
|
291
|
+
detectAgentId() {
|
|
292
|
+
// In a real implementation, this would read from ~/.connect/config.json
|
|
293
|
+
// For now, generate a default ID
|
|
294
|
+
return `sdk-${Date.now()}`;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
exports.PrivateConnect = PrivateConnect;
|
|
298
|
+
// Default export
|
|
299
|
+
exports.default = PrivateConnect;
|
|
300
|
+
// Convenience function
|
|
301
|
+
async function connect(serviceName, config) {
|
|
302
|
+
const apiKey = config?.apiKey || process.env.PRIVATECONNECT_API_KEY;
|
|
303
|
+
if (!apiKey) {
|
|
304
|
+
throw new Error('API key required. Set PRIVATECONNECT_API_KEY or pass config.apiKey');
|
|
305
|
+
}
|
|
306
|
+
const client = new PrivateConnect({ ...config, apiKey });
|
|
307
|
+
return client.connect(serviceName);
|
|
308
|
+
}
|
|
309
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FxQkc7OztBQTBYSCwwQkFRQztBQXZVRDs7R0FFRztBQUNILE1BQWEsU0FBUztJQUNwQixZQUFvQixNQUFzQjtRQUF0QixXQUFNLEdBQU4sTUFBTSxDQUFnQjtJQUFHLENBQUM7SUFFOUM7O09BRUc7SUFDSCxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQWtDO1FBQzNDLE1BQU0sUUFBUSxHQUFHLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsMEJBQTBCLENBQUMsQ0FBQztRQUNyRSxNQUFNLElBQUksR0FBRyxNQUFNLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNuQyxJQUFJLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxJQUFJLEVBQUUsQ0FBQztRQUUvQixJQUFJLE9BQU8sRUFBRSxVQUFVLEVBQUUsQ0FBQztZQUN4QixNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQU0sRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ2pELENBQUM7UUFFRCxPQUFPLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFNLEVBQUUsRUFBRSxDQUFDLENBQUM7WUFDN0IsRUFBRSxFQUFFLENBQUMsQ0FBQyxFQUFFO1lBQ1IsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJO1lBQ1osS0FBSyxFQUFFLENBQUMsQ0FBQyxLQUFLO1lBQ2QsUUFBUSxFQUFFLENBQUMsQ0FBQyxRQUFRO1lBQ3BCLFVBQVUsRUFBRSxDQUFDLENBQUMsVUFBVTtZQUN4QixZQUFZLEVBQUUsQ0FBQyxDQUFDLFlBQVksRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFNLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFO1lBQzNELFFB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QUFjLENBQUMsRUFBRSxHQUFHLE1BQU0sRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDO0lBQ3pELE9BQU8sTUFBTSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztBQUNyQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBQcml2YXRlIENvbm5lY3QgU0RLXG4gKiBcbiAqIFByb2dyYW1tYXRpYyBhY2Nlc3MgdG8gUHJpdmF0ZSBDb25uZWN0IHNlcnZpY2VzIGFuZCBhZ2VudCBvcmNoZXN0cmF0aW9uLlxuICogXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogaW1wb3J0IHsgUHJpdmF0ZUNvbm5lY3QgfSBmcm9tICdAcHJpdmF0ZWNvbm5lY3Qvc2RrJztcbiAqIFxuICogY29uc3QgcGMgPSBuZXcgUHJpdmF0ZUNvbm5lY3QoeyBhcGlLZXk6ICd5b3VyLWFwaS1rZXknIH0pO1xuICogXG4gKiAvLyBDb25uZWN0IHRvIGEgc2VydmljZVxuICogY29uc3QgZGIgPSBhd2FpdCBwYy5jb25uZWN0KCdwb3N0Z3Jlcy1wcm9kJyk7XG4gKiBjb25zb2xlLmxvZyhkYi5jb25uZWN0aW9uU3RyaW5nKTsgLy8gcG9zdGdyZXM6Ly9sb2NhbGhvc3Q6NTQzMi8uLi5cbiAqIFxuICogLy8gTGlzdCBhbGwgYWdlbnRzXG4gKiBjb25zdCBhZ2VudHMgPSBhd2FpdCBwYy5hZ2VudHMubGlzdCgpO1xuICogXG4gKiAvLyBTZW5kIG1lc3NhZ2UgdG8gYW5vdGhlciBhZ2VudFxuICogYXdhaXQgcGMuYWdlbnRzLnNlbmRNZXNzYWdlKHRhcmdldEFnZW50SWQsIHsgYWN0aW9uOiAnZGVwbG95JyB9KTtcbiAqIGBgYFxuICovXG5cbmV4cG9ydCBpbnRlcmZhY2UgUHJpdmF0ZUNvbm5lY3RDb25maWcge1xuICAvKiogQVBJIGtleSBmb3IgYXV0aGVudGljYXRpb24gKi9cbiAgYXBpS2V5OiBzdHJpbmc7XG4gIC8qKiBIdWIgVVJMIChkZWZhdWx0OiBodHRwczovL2FwaS5wcml2YXRlY29ubmVjdC5jbykgKi9cbiAgaHViVXJsPzogc3RyaW5nO1xuICAvKiogQWdlbnQgSUQgKGF1dG8tZGV0ZWN0ZWQgZnJvbSBjb25maWcgaWYgbm90IHByb3ZpZGVkKSAqL1xuICBhZ2VudElkPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNlcnZpY2Uge1xuICBpZDogc3RyaW5nO1xuICBuYW1lOiBzdHJpbmc7XG4gIHRhcmdldEhvc3Q6IHN0cmluZztcbiAgdGFyZ2V0UG9ydDogbnVtYmVyO1xuICB0dW5uZWxQb3J0PzogbnVtYmVyO1xuICBwcm90b2NvbDogc3RyaW5nO1xuICBzdGF0dXM6IHN0cmluZztcbiAgYWdlbnRMYWJlbD86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBZ2VudCB7XG4gIGlkOiBzdHJpbmc7XG4gIG5hbWU/OiBzdHJpbmc7XG4gIGxhYmVsOiBzdHJpbmc7XG4gIGlzT25saW5lOiBib29sZWFuO1xuICBsYXN0U2VlbkF0OiBzdHJpbmc7XG4gIGNhcGFiaWxpdGllczogc3RyaW5nW107XG4gIHNlcnZpY2VzOiBzdHJpbmdbXTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb25uZWN0aW9uIHtcbiAgc2VydmljZTogc3RyaW5nO1xuICBob3N0OiBzdHJpbmc7XG4gIHBvcnQ6IG51bWJlcjtcbiAgY29ubmVjdGlvblN0cmluZzogc3RyaW5nO1xuICBlbnZWYXI6IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBNZXNzYWdlIHtcbiAgaWQ6IHN0cmluZztcbiAgZnJvbTogeyBpZDogc3RyaW5nOyBuYW1lPzogc3RyaW5nOyBsYWJlbD86IHN0cmluZyB9O1xuICBjaGFubmVsOiBzdHJpbmc7XG4gIHR5cGU6IHN0cmluZztcbiAgcGF5bG9hZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIGNyZWF0ZWRBdDogc3RyaW5nO1xuICBpc1JlYWQ6IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2Vzc2lvbiB7XG4gIGlkOiBzdHJpbmc7XG4gIG5hbWU6IHN0cmluZztcbiAgY3JlYXRlZEJ5OiBzdHJpbmc7XG4gIGNyZWF0ZWRBdDogc3RyaW5nO1xuICBleHBpcmVzQXQ6IHN0cmluZztcbiAgbWV0YWRhdGE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbn1cblxuLyoqXG4gKiBBZ2VudHMgQVBJIGZvciBkaXNjb3ZlcnkgYW5kIG9yY2hlc3RyYXRpb25cbiAqL1xuZXhwb3J0IGNsYXNzIEFnZW50c0FQSSB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgY2xpZW50OiBQcml2YXRlQ29ubmVjdCkge31cblxuICAvKipcbiAgICogTGlzdCBhbGwgYWdlbnRzIGluIHRoZSB3b3Jrc3BhY2VcbiAgICovXG4gIGFzeW5jIGxpc3Qob3B0aW9ucz86IHsgb25saW5lT25seT86IGJvb2xlYW4gfSk6IFByb21pc2U8QWdlbnRbXT4ge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5jbGllbnQuZmV0Y2goJy92MS9hZ2VudHMvb3JjaGVzdHJhdGlvbicpO1xuICAgIGNvbnN0IGRhdGEgPSBhd2FpdCByZXNwb25zZS5qc29uKCk7XG4gICAgbGV0IGFnZW50cyA9IGRhdGEuYWdlbnRzIHx8IFtdO1xuICAgIFxuICAgIGlmIChvcHRpb25zPy5vbmxpbmVPbmx5KSB7XG4gICAgICBhZ2VudHMgPSBhZ2VudHMuZmlsdGVyKChhOiBhbnkpID0+IGEuaXNPbmxpbmUpO1xuICAgIH1cbiAgICBcbiAgICByZXR1cm4gYWdlbnRzLm1hcCgoYTogYW55KSA9PiAoe1xuICAgICAgaWQ6IGEuaWQsXG4gICAgICBuYW1lOiBhLm5hbWUsXG4gICAgICBsYWJlbDogYS5sYWJlbCxcbiAgICAgIGlzT25saW5lOiBhLmlzT25saW5lLFxuICAgICAgbGFzdFNlZW5BdDogYS5sYXN0U2VlbkF0LFxuICAgICAgY2FwYWJpbGl0aWVzOiBhLmNhcGFiaWxpdGllcz8ubWFwKChjOiBhbnkpID0+IGMubmFtZSkgfHwgW10sXG4gICAgICBzZXJ2aWNlczogYS5zZXJ2aWNlcz8ubWFwKChzOiBhbnkpID0+IHMubmFtZSkgfHwgW10sXG4gICAgfSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEZpbmQgYWdlbnRzIGJ5IGNhcGFiaWxpdHlcbiAgICovXG4gIGFzeW5jIGZpbmRCeUNhcGFiaWxpdHkoY2FwYWJpbGl0eTogc3RyaW5nKTogUHJvbWlzZTxBZ2VudFtdPiB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmNsaWVudC5mZXRjaChgL3YxL2FnZW50cy9ieS1jYXBhYmlsaXR5LyR7ZW5jb2RlVVJJQ29tcG9uZW50KGNhcGFiaWxpdHkpfWApO1xuICAgIGNvbnN0IGRhdGEgPSBhd2FpdCByZXNwb25zZS5qc29uKCk7XG4gICAgcmV0dXJuIGRhdGEuYWdlbnRzIHx8IFtdO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVyIGNhcGFiaWxpdGllcyBmb3IgdGhpcyBhZ2VudFxuICAgKi9cbiAgYXN5bmMgcmVnaXN0ZXJDYXBhYmlsaXRpZXMoY2FwYWJpbGl0aWVzOiBBcnJheTx7IG5hbWU6IHN0cmluZzsgbWV0YWRhdGE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB9Pik6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuY2xpZW50LmZldGNoKGAvdjEvYWdlbnRzLyR7dGhpcy5jbGllbnQuYWdlbnRJZH0vY2FwYWJpbGl0aWVzYCwge1xuICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7IGNhcGFiaWxpdGllcyB9KSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZW5kIGEgbWVzc2FnZSB0byBhbm90aGVyIGFnZW50XG4gICAqL1xuICBhc3luYyBzZW5kTWVzc2FnZShcbiAgICB0b0FnZW50SWQ6IHN0cmluZyxcbiAgICBwYXlsb2FkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgICBvcHRpb25zPzogeyBjaGFubmVsPzogc3RyaW5nOyB0eXBlPzogJ3JlcXVlc3QnIHwgJ3Jlc3BvbnNlJyB8ICdldmVudCcgfVxuICApOiBQcm9taXNlPHsgbWVzc2FnZUlkOiBzdHJpbmcgfT4ge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5jbGllbnQuZmV0Y2goYC92MS9hZ2VudHMvJHt0aGlzLmNsaWVudC5hZ2VudElkfS9tZXNzYWdlcy9zZW5kYCwge1xuICAgICAgbWV0aG9kOiAnUE9TVCcsXG4gICAgICBib2R5OiBKU09OLnN0cmluZ2lmeSh7IHRvQWdlbnRJZCwgcGF5bG9hZCwgLi4ub3B0aW9ucyB9KSxcbiAgICB9KTtcbiAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpO1xuICB9XG5cbiAgLyoqXG4gICAqIEJyb2FkY2FzdCBhIG1lc3NhZ2UgdG8gYWxsIG9ubGluZSBhZ2VudHNcbiAgICovXG4gIGFzeW5jIGJyb2FkY2FzdChcbiAgICBwYXlsb2FkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgICBvcHRpb25zPzogeyBjaGFubmVsPzogc3RyaW5nIH1cbiAgKTogUHJvbWlzZTx7IHNlbnQ6IG51bWJlciB9PiB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCB0aGlzLmNsaWVudC5mZXRjaChgL3YxL2FnZW50cy8ke3RoaXMuY2xpZW50LmFnZW50SWR9L21lc3NhZ2VzL2Jyb2FkY2FzdGAsIHtcbiAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoeyBwYXlsb2FkLCAuLi5vcHRpb25zIH0pLFxuICAgIH0pO1xuICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IG1lc3NhZ2VzIGZvciB0aGlzIGFnZW50XG4gICAqL1xuICBhc3luYyBnZXRNZXNzYWdlcyhvcHRpb25zPzogeyBjaGFubmVsPzogc3RyaW5nOyB1bnJlYWRPbmx5PzogYm9vbGVhbjsgbGltaXQ/OiBudW1iZXIgfSk6IFByb21pc2U8TWVzc2FnZVtdPiB7XG4gICAgY29uc3QgcGFyYW1zID0gbmV3IFVSTFNlYXJjaFBhcmFtcygpO1xuICAgIGlmIChvcHRpb25zPy5jaGFubmVsKSBwYXJhbXMuc2V0KCdjaGFubmVsJywgb3B0aW9ucy5jaGFubmVsKTtcbiAgICBpZiAob3B0aW9ucz8udW5yZWFkT25seSAhPT0gdW5kZWZpbmVkKSBwYXJhbXMuc2V0KCd1bnJlYWRPbmx5JywgU3RyaW5nKG9wdGlvbnMudW5yZWFkT25seSkpO1xuICAgIGlmIChvcHRpb25zPy5saW1pdCkgcGFyYW1zLnNldCgnbGltaXQnLCBTdHJpbmcob3B0aW9ucy5saW1pdCkpO1xuICAgIFxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5jbGllbnQuZmV0Y2goYC92MS9hZ2VudHMvJHt0aGlzLmNsaWVudC5hZ2VudElkfS9tZXNzYWdlcz8ke3BhcmFtc31gKTtcbiAgICBjb25zdCBkYXRhID0gYXdhaXQgcmVzcG9uc2UuanNvbigpO1xuICAgIHJldHVybiBkYXRhLm1lc3NhZ2VzIHx8IFtdO1xuICB9XG5cbiAgLyoqXG4gICAqIE1hcmsgbWVzc2FnZXMgYXMgcmVhZFxuICAgKi9cbiAgYXN5bmMgbWFya1JlYWQobWVzc2FnZUlkczogc3RyaW5nW10pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLmNsaWVudC5mZXRjaChgL3YxL2FnZW50cy8ke3RoaXMuY2xpZW50LmFnZW50SWR9L21lc3NhZ2VzL3JlYWRgLCB7XG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHsgbWVzc2FnZUlkcyB9KSxcbiAgICB9KTtcbiAgfVxufVxuXG4vKipcbiAqIFNlcnZpY2VzIEFQSSBmb3IgY29ubmVjdGluZyB0byBhbmQgbWFuYWdpbmcgc2VydmljZXNcbiAqL1xuZXhwb3J0IGNsYXNzIFNlcnZpY2VzQVBJIHtcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBjbGllbnQ6IFByaXZhdGVDb25uZWN0KSB7fVxuXG4gIC8qKlxuICAgKiBMaXN0IGFsbCBzZXJ2aWNlc1xuICAgKi9cbiAgYXN5bmMgbGlzdCgpOiBQcm9taXNlPFNlcnZpY2VbXT4ge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5jbGllbnQuZmV0Y2goJy92MS9zZXJ2aWNlcycpO1xuICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGEgc3BlY2lmaWMgc2VydmljZSBieSBuYW1lXG4gICAqL1xuICBhc3luYyBnZXQobmFtZTogc3RyaW5nKTogUHJvbWlzZTxTZXJ2aWNlIHwgbnVsbD4ge1xuICAgIGNvbnN0IHNlcnZpY2VzID0gYXdhaXQgdGhpcy5saXN0KCk7XG4gICAgcmV0dXJuIHNlcnZpY2VzLmZpbmQocyA9PiBzLm5hbWUudG9Mb3dlckNhc2UoKSA9PT0gbmFtZS50b0xvd2VyQ2FzZSgpKSB8fCBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBjb25uZWN0aW9uIGRldGFpbHMgZm9yIGEgc2VydmljZVxuICAgKi9cbiAgYXN5bmMgZ2V0Q29ubmVjdGlvbihzZXJ2aWNlTmFtZTogc3RyaW5nKTogUHJvbWlzZTxDb25uZWN0aW9uPiB7XG4gICAgY29uc3Qgc2VydmljZSA9IGF3YWl0IHRoaXMuZ2V0KHNlcnZpY2VOYW1lKTtcbiAgICBpZiAoIXNlcnZpY2UpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgU2VydmljZSBcIiR7c2VydmljZU5hbWV9XCIgbm90IGZvdW5kYCk7XG4gICAgfVxuXG4gICAgY29uc3QgcG9ydCA9IHNlcnZpY2UudHVubmVsUG9ydCB8fCBzZXJ2aWNlLnRhcmdldFBvcnQ7XG4gICAgY29uc3QgaG9zdCA9ICdsb2NhbGhvc3QnO1xuICAgIFxuICAgIGxldCBjb25uZWN0aW9uU3RyaW5nID0gJyc7XG4gICAgbGV0IGVudlZhciA9ICdTRVJWSUNFX1VSTCc7XG4gICAgXG4gICAgaWYgKHNlcnZpY2UudGFyZ2V0UG9ydCA9PT0gNTQzMiB8fCBzZXJ2aWNlLnByb3RvY29sID09PSAncG9zdGdyZXMnKSB7XG4gICAgICBjb25uZWN0aW9uU3RyaW5nID0gYHBvc3RncmVzOi8vJHtob3N0fToke3BvcnR9L3Bvc3RncmVzYDtcbiAgICAgIGVudlZhciA9ICdEQVRBQkFTRV9VUkwnO1xuICAgIH0gZWxzZSBpZiAoc2VydmljZS50YXJnZXRQb3J0ID09PSAzMzA2IHx8IHNlcnZpY2UucHJvdG9jb2wgPT09ICdteXNxbCcpIHtcbiAgICAgIGNvbm5lY3Rpb25TdHJpbmcgPSBgbXlzcWw6Ly8ke2hvc3R9OiR7cG9ydH1gO1xuICAgICAgZW52VmFyID0gJ0RBVEFCQVNFX1VSTCc7XG4gICAgfSBlbHNlIGlmIChzZXJ2aWNlLnRhcmdldFBvcnQgPT09IDYzNzkgfHwgc2VydmljZS5wcm90b2NvbCA9PT0gJ3JlZGlzJykge1xuICAgICAgY29ubmVjdGlvblN0cmluZyA9IGByZWRpczovLyR7aG9zdH06JHtwb3J0fWA7XG4gICAgICBlbnZWYXIgPSAnUkVESVNfVVJMJztcbiAgICB9IGVsc2UgaWYgKHNlcnZpY2UudGFyZ2V0UG9ydCA9PT0gMjcwMTcgfHwgc2VydmljZS5wcm90b2NvbCA9PT0gJ21vbmdvZGInKSB7XG4gICAgICBjb25uZWN0aW9uU3RyaW5nID0gYG1vbmdvZGI6Ly8ke2hvc3R9OiR7cG9ydH1gO1xuICAgICAgZW52VmFyID0gJ01PTkdPREJfVVJJJztcbiAgICB9IGVsc2UgaWYgKHNlcnZpY2UucHJvdG9jb2wgPT09ICdodHRwJyB8fCBzZXJ2aWNlLnByb3RvY29sID09PSAnaHR0cHMnKSB7XG4gICAgICBjb25uZWN0aW9uU3RyaW5nID0gYGh0dHA6Ly8ke2hvc3R9OiR7cG9ydH1gO1xuICAgICAgZW52VmFyID0gJ0FQSV9VUkwnO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25uZWN0aW9uU3RyaW5nID0gYHRjcDovLyR7aG9zdH06JHtwb3J0fWA7XG4gICAgICBlbnZWYXIgPSBgJHtzZXJ2aWNlTmFtZS50b1VwcGVyQ2FzZSgpLnJlcGxhY2UoLy0vZywgJ18nKX1fVVJMYDtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgc2VydmljZTogc2VydmljZU5hbWUsXG4gICAgICBob3N0LFxuICAgICAgcG9ydCxcbiAgICAgIGNvbm5lY3Rpb25TdHJpbmcsXG4gICAgICBlbnZWYXIsXG4gICAgfTtcbiAgfVxufVxuXG4vKipcbiAqIFNlc3Npb25zIEFQSSBmb3IgZXBoZW1lcmFsIG9yY2hlc3RyYXRpb24gc2Vzc2lvbnNcbiAqL1xuZXhwb3J0IGNsYXNzIFNlc3Npb25zQVBJIHtcbiAgcHJpdmF0ZSBhY3RpdmVTZXNzaW9ucyA9IG5ldyBNYXA8c3RyaW5nLCBTZXNzaW9uPigpO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgY2xpZW50OiBQcml2YXRlQ29ubmVjdCkge31cblxuICAvKipcbiAgICogQ3JlYXRlIGFuIG9yY2hlc3RyYXRpb24gc2Vzc2lvblxuICAgKi9cbiAgYXN5bmMgY3JlYXRlKG5hbWU6IHN0cmluZywgb3B0aW9ucz86IHsgdHRsTWludXRlcz86IG51bWJlcjsgbWV0YWRhdGE/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB9KTogUHJvbWlzZTxTZXNzaW9uPiB7XG4gICAgY29uc3QgdHRsTWludXRlcyA9IG9wdGlvbnM/LnR0bE1pbnV0ZXMgfHwgNjA7XG4gICAgY29uc3Qgc2Vzc2lvbklkID0gYCR7dGhpcy5jbGllbnQuYWdlbnRJZH0tJHtEYXRlLm5vdygpfS0ke01hdGgucmFuZG9tKCkudG9TdHJpbmcoMzYpLnN1YnN0cmluZygyLCA4KX1gO1xuICAgIGNvbnN0IGV4cGlyZXNBdCA9IG5ldyBEYXRlKERhdGUubm93KCkgKyB0dGxNaW51dGVzICogNjAgKiAxMDAwKTtcblxuICAgIGNvbnN0IHNlc3Npb246IFNlc3Npb24gPSB7XG4gICAgICBpZDogc2Vzc2lvbklkLFxuICAgICAgbmFtZSxcbiAgICAgIGNyZWF0ZWRCeTogdGhpcy5jbGllbnQuYWdlbnRJZCEsXG4gICAgICBjcmVhdGVkQXQ6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgIGV4cGlyZXNBdDogZXhwaXJlc0F0LnRvSVNPU3RyaW5nKCksXG4gICAgICBtZXRhZGF0YTogb3B0aW9ucz8ubWV0YWRhdGEsXG4gICAgfTtcblxuICAgIHRoaXMuYWN0aXZlU2Vzc2lvbnMuc2V0KHNlc3Npb25JZCwgc2Vzc2lvbik7XG5cbiAgICAvLyBCcm9hZGNhc3Qgc2Vzc2lvbiBjcmVhdGlvblxuICAgIGF3YWl0IHRoaXMuY2xpZW50LmFnZW50cy5icm9hZGNhc3QoXG4gICAgICB7IHR5cGU6ICdzZXNzaW9uOmNyZWF0ZWQnLCBzZXNzaW9uIH0sXG4gICAgICB7IGNoYW5uZWw6ICdvcmNoZXN0cmF0aW9uJyB9XG4gICAgKTtcblxuICAgIHJldHVybiBzZXNzaW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIEVuZCBhbiBvcmNoZXN0cmF0aW9uIHNlc3Npb25cbiAgICovXG4gIGFzeW5jIGVuZChzZXNzaW9uSWQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuYWN0aXZlU2Vzc2lvbnMuZGVsZXRlKHNlc3Npb25JZCk7XG5cbiAgICAvLyBCcm9hZGNhc3Qgc2Vzc2lvbiBlbmRcbiAgICBhd2FpdCB0aGlzLmNsaWVudC5hZ2VudHMuYnJvYWRjYXN0KFxuICAgICAge1xuICAgICAgICB0eXBlOiAnc2Vzc2lvbjplbmRlZCcsXG4gICAgICAgIHNlc3Npb25JZCxcbiAgICAgICAgZW5kZWRCeTogdGhpcy5jbGllbnQuYWdlbnRJZCxcbiAgICAgICAgZW5kZWRBdDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLFxuICAgICAgfSxcbiAgICAgIHsgY2hhbm5lbDogJ29yY2hlc3RyYXRpb24nIH1cbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhY3RpdmUgc2Vzc2lvbnNcbiAgICovXG4gIGdldEFjdGl2ZSgpOiBTZXNzaW9uW10ge1xuICAgIGNvbnN0IG5vdyA9IG5ldyBEYXRlKCk7XG4gICAgY29uc3QgYWN0aXZlOiBTZXNzaW9uW10gPSBbXTtcbiAgICBcbiAgICBmb3IgKGNvbnN0IFtpZCwgc2Vzc2lvbl0gb2YgdGhpcy5hY3RpdmVTZXNzaW9ucykge1xuICAgICAgaWYgKG5ldyBEYXRlKHNlc3Npb24uZXhwaXJlc0F0KSA+IG5vdykge1xuICAgICAgICBhY3RpdmUucHVzaChzZXNzaW9uKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuYWN0aXZlU2Vzc2lvbnMuZGVsZXRlKGlkKTtcbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIGFjdGl2ZTtcbiAgfVxufVxuXG4vKipcbiAqIE1haW4gUHJpdmF0ZSBDb25uZWN0IFNESyBjbGllbnRcbiAqL1xuZXhwb3J0IGNsYXNzIFByaXZhdGVDb25uZWN0IHtcbiAgcHJpdmF0ZSBjb25maWc6IFJlcXVpcmVkPFByaXZhdGVDb25uZWN0Q29uZmlnPjtcbiAgXG4gIC8qKiBBZ2VudHMgQVBJIGZvciBkaXNjb3ZlcnkgYW5kIG9yY2hlc3RyYXRpb24gKi9cbiAgcHVibGljIGFnZW50czogQWdlbnRzQVBJO1xuICBcbiAgLyoqIFNlcnZpY2VzIEFQSSBmb3IgY29ubmVjdGluZyB0byBzZXJ2aWNlcyAqL1xuICBwdWJsaWMgc2VydmljZXM6IFNlcnZpY2VzQVBJO1xuICBcbiAgLyoqIFNlc3Npb25zIEFQSSBmb3IgZXBoZW1lcmFsIG9yY2hlc3RyYXRpb24gKi9cbiAgcHVibGljIHNlc3Npb25zOiBTZXNzaW9uc0FQSTtcblxuICBjb25zdHJ1Y3Rvcihjb25maWc6IFByaXZhdGVDb25uZWN0Q29uZmlnKSB7XG4gICAgdGhpcy5jb25maWcgPSB7XG4gICAgICBhcGlLZXk6IGNvbmZpZy5hcGlLZXksXG4gICAgICBodWJVcmw6IGNvbmZpZy5odWJVcmwgfHwgJ2h0dHBzOi8vYXBpLnByaXZhdGVjb25uZWN0LmNvJyxcbiAgICAgIGFnZW50SWQ6IGNvbmZpZy5hZ2VudElkIHx8IHRoaXMuZGV0ZWN0QWdlbnRJZCgpLFxuICAgIH07XG5cbiAgICB0aGlzLmFnZW50cyA9IG5ldyBBZ2VudHNBUEkodGhpcyk7XG4gICAgdGhpcy5zZXJ2aWNlcyA9IG5ldyBTZXJ2aWNlc0FQSSh0aGlzKTtcbiAgICB0aGlzLnNlc3Npb25zID0gbmV3IFNlc3Npb25zQVBJKHRoaXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgYWdlbnQgSURcbiAgICovXG4gIGdldCBhZ2VudElkKCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuY29uZmlnLmFnZW50SWQ7XG4gIH1cblxuICAvKipcbiAgICogQ29ubmVjdCB0byBhIHNlcnZpY2UgYW5kIGdldCBjb25uZWN0aW9uIGRldGFpbHNcbiAgICovXG4gIGFzeW5jIGNvbm5lY3Qoc2VydmljZU5hbWU6IHN0cmluZyk6IFByb21pc2U8Q29ubmVjdGlvbj4ge1xuICAgIHJldHVybiB0aGlzLnNlcnZpY2VzLmdldENvbm5lY3Rpb24oc2VydmljZU5hbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEludGVybmFsIGZldGNoIGhlbHBlclxuICAgKi9cbiAgYXN5bmMgZmV0Y2gocGF0aDogc3RyaW5nLCBvcHRpb25zPzogUmVxdWVzdEluaXQpOiBQcm9taXNlPFJlc3BvbnNlPiB7XG4gICAgY29uc3QgdXJsID0gYCR7dGhpcy5jb25maWcuaHViVXJsfSR7cGF0aH1gO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godXJsLCB7XG4gICAgICAuLi5vcHRpb25zLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICAneC1hcGkta2V5JzogdGhpcy5jb25maWcuYXBpS2V5LFxuICAgICAgICAnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL2pzb24nLFxuICAgICAgICAuLi5vcHRpb25zPy5oZWFkZXJzLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgIGNvbnN0IGVycm9yID0gYXdhaXQgcmVzcG9uc2UuanNvbigpLmNhdGNoKCgpID0+ICh7IG1lc3NhZ2U6ICdVbmtub3duIGVycm9yJyB9KSk7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3IubWVzc2FnZSB8fCBgUmVxdWVzdCBmYWlsZWQ6ICR7cmVzcG9uc2Uuc3RhdHVzfWApO1xuICAgIH1cblxuICAgIHJldHVybiByZXNwb25zZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUcnkgdG8gZGV0ZWN0IGFnZW50IElEIGZyb20gbG9jYWwgY29uZmlnXG4gICAqL1xuICBwcml2YXRlIGRldGVjdEFnZW50SWQoKTogc3RyaW5nIHtcbiAgICAvLyBJbiBhIHJlYWwgaW1wbGVtZW50YXRpb24sIHRoaXMgd291bGQgcmVhZCBmcm9tIH4vLmNvbm5lY3QvY29uZmlnLmpzb25cbiAgICAvLyBGb3Igbm93LCBnZW5lcmF0ZSBhIGRlZmF1bHQgSURcbiAgICByZXR1cm4gYHNkay0ke0RhdGUubm93KCl9YDtcbiAgfVxufVxuXG4vLyBEZWZhdWx0IGV4cG9ydFxuZXhwb3J0IGRlZmF1bHQgUHJpdmF0ZUNvbm5lY3Q7XG5cbi8vIENvbnZlbmllbmNlIGZ1bmN0aW9uXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY29ubmVjdChzZXJ2aWNlTmFtZTogc3RyaW5nLCBjb25maWc/OiBQcml2YXRlQ29ubmVjdENvbmZpZyk6IFByb21pc2U8Q29ubmVjdGlvbj4ge1xuICBjb25zdCBhcGlLZXkgPSBjb25maWc/LmFwaUtleSB8fCBwcm9jZXNzLmVudi5QUklWQVRFQ09OTkVDVF9BUElfS0VZO1xuICBpZiAoIWFwaUtleSkge1xuICAgIHRocm93IG5ldyBFcnJvcignQVBJIGtleSByZXF1aXJlZC4gU2V0IFBSSVZBVEVDT05ORUNUX0FQSV9LRVkgb3IgcGFzcyBjb25maWcuYXBpS2V5Jyk7XG4gIH1cbiAgXG4gIGNvbnN0IGNsaWVudCA9IG5ldyBQcml2YXRlQ29ubmVjdCh7IC4uLmNvbmZpZywgYXBpS2V5IH0pO1xuICByZXR1cm4gY2xpZW50LmNvbm5lY3Qoc2VydmljZU5hbWUpO1xufVxuXG4iXX0=
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@privateconnect/sdk",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "TypeScript SDK for Private Connect - programmatic access to services and agent orchestration",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"dev": "tsc -w",
|
|
13
|
+
"clean": "rm -rf dist"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"private-connect",
|
|
17
|
+
"tunnel",
|
|
18
|
+
"networking",
|
|
19
|
+
"orchestration",
|
|
20
|
+
"agent"
|
|
21
|
+
],
|
|
22
|
+
"license": "FSL-1.1-MIT",
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "https://github.com/treadiehq/private-connect.git",
|
|
26
|
+
"directory": "packages/sdk"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/node": "^20.0.0",
|
|
30
|
+
"typescript": "^5.0.0"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|