@sena-ai/platform-connector 0.1.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/dist/connector.d.ts +22 -0
- package/dist/connector.d.ts.map +1 -0
- package/dist/connector.js +163 -0
- package/dist/connector.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/transports/sse.d.ts +6 -0
- package/dist/transports/sse.d.ts.map +1 -0
- package/dist/transports/sse.js +52 -0
- package/dist/transports/sse.js.map +1 -0
- package/dist/transports/types.d.ts +16 -0
- package/dist/transports/types.d.ts.map +1 -0
- package/dist/transports/types.js +2 -0
- package/dist/transports/types.js.map +1 -0
- package/dist/transports/websocket.d.ts +6 -0
- package/dist/transports/websocket.d.ts.map +1 -0
- package/dist/transports/websocket.js +66 -0
- package/dist/transports/websocket.js.map +1 -0
- package/package.json +29 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Connector } from '@sena-ai/core';
|
|
2
|
+
export type TransportType = 'sse' | 'websocket' | 'auto';
|
|
3
|
+
export type PlatformConnectorOptions = {
|
|
4
|
+
/** Platform server URL (e.g. https://platform.example.com) */
|
|
5
|
+
platformUrl: string;
|
|
6
|
+
/** connect_key -- platform-issued authentication key */
|
|
7
|
+
connectKey: string;
|
|
8
|
+
/** Thinking message (optional) */
|
|
9
|
+
thinkingMessage?: string;
|
|
10
|
+
/** Transport type: 'sse' (default), 'websocket', or 'auto' */
|
|
11
|
+
transport?: TransportType;
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Platform Connector: connects to the platform via SSE or WebSocket.
|
|
15
|
+
*
|
|
16
|
+
* - Receives Slack events from the platform relay
|
|
17
|
+
* - Calls Slack API via the platform's HTTP proxy
|
|
18
|
+
*
|
|
19
|
+
* No Slack tokens needed locally (zero token exposure principle).
|
|
20
|
+
*/
|
|
21
|
+
export declare function platformConnector(options: PlatformConnectorOptions): Connector;
|
|
22
|
+
//# sourceMappingURL=connector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connector.d.ts","sourceRoot":"","sources":["../src/connector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EAMV,MAAM,eAAe,CAAA;AAKtB,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,WAAW,GAAG,MAAM,CAAA;AAExD,MAAM,MAAM,wBAAwB,GAAG;IACrC,8DAA8D;IAC9D,WAAW,EAAE,MAAM,CAAA;IACnB,wDAAwD;IACxD,UAAU,EAAE,MAAM,CAAA;IAClB,kCAAkC;IAClC,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,aAAa,CAAA;CAC1B,CAAA;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,SAAS,CA8K9E"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { createSSETransport } from './transports/sse.js';
|
|
2
|
+
import { createWebSocketTransport } from './transports/websocket.js';
|
|
3
|
+
/**
|
|
4
|
+
* Platform Connector: connects to the platform via SSE or WebSocket.
|
|
5
|
+
*
|
|
6
|
+
* - Receives Slack events from the platform relay
|
|
7
|
+
* - Calls Slack API via the platform's HTTP proxy
|
|
8
|
+
*
|
|
9
|
+
* No Slack tokens needed locally (zero token exposure principle).
|
|
10
|
+
*/
|
|
11
|
+
export function platformConnector(options) {
|
|
12
|
+
const { platformUrl, connectKey, thinkingMessage } = options;
|
|
13
|
+
const transportType = options.transport ?? 'sse';
|
|
14
|
+
const baseUrl = platformUrl.replace(/\/$/, '');
|
|
15
|
+
let transport = null;
|
|
16
|
+
let engine = null;
|
|
17
|
+
/**
|
|
18
|
+
* Call Slack API via platform proxy.
|
|
19
|
+
*/
|
|
20
|
+
async function callSlackApi(method, params) {
|
|
21
|
+
const res = await fetch(`${baseUrl}/relay/api`, {
|
|
22
|
+
method: 'POST',
|
|
23
|
+
headers: {
|
|
24
|
+
'Content-Type': 'application/json',
|
|
25
|
+
'x-connect-key': connectKey,
|
|
26
|
+
},
|
|
27
|
+
body: JSON.stringify({ method, params }),
|
|
28
|
+
});
|
|
29
|
+
return (await res.json());
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Convert Slack event to InboundEvent.
|
|
33
|
+
* Ignores bot messages and messages with subtypes.
|
|
34
|
+
*/
|
|
35
|
+
function toInboundEvent(slackEvent) {
|
|
36
|
+
const event = slackEvent.event;
|
|
37
|
+
if (!event)
|
|
38
|
+
return null;
|
|
39
|
+
const type = event.type;
|
|
40
|
+
const subtype = event.subtype;
|
|
41
|
+
const botId = event.bot_id;
|
|
42
|
+
// Ignore bot's own messages
|
|
43
|
+
if (botId)
|
|
44
|
+
return null;
|
|
45
|
+
// Ignore message subtypes (join, leave, etc.)
|
|
46
|
+
if (type === 'message' && subtype)
|
|
47
|
+
return null;
|
|
48
|
+
const channel = event.channel;
|
|
49
|
+
const threadTs = event.thread_ts || event.ts;
|
|
50
|
+
const text = event.text || '';
|
|
51
|
+
const user = event.user || 'unknown';
|
|
52
|
+
// Handle both app_mention and message
|
|
53
|
+
if (type !== 'app_mention' && type !== 'message')
|
|
54
|
+
return null;
|
|
55
|
+
return {
|
|
56
|
+
connector: 'platform',
|
|
57
|
+
conversationId: `${channel}:${threadTs}`,
|
|
58
|
+
userId: user,
|
|
59
|
+
userName: user,
|
|
60
|
+
text,
|
|
61
|
+
raw: slackEvent,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function createTransport() {
|
|
65
|
+
const streamUrl = `${baseUrl}/relay/stream?connect_key=${encodeURIComponent(connectKey)}`;
|
|
66
|
+
if (transportType === 'websocket') {
|
|
67
|
+
return createWebSocketTransport(streamUrl);
|
|
68
|
+
}
|
|
69
|
+
if (transportType === 'auto') {
|
|
70
|
+
// Auto-detect: try WebSocket first, fall back to SSE
|
|
71
|
+
// For now, default to SSE as it's more widely supported
|
|
72
|
+
return createSSETransport(streamUrl);
|
|
73
|
+
}
|
|
74
|
+
return createSSETransport(streamUrl);
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
name: 'platform',
|
|
78
|
+
registerRoutes(_server, turnEngine) {
|
|
79
|
+
engine = turnEngine;
|
|
80
|
+
transport = createTransport();
|
|
81
|
+
transport.on('connected', (data) => {
|
|
82
|
+
const parsed = JSON.parse(data);
|
|
83
|
+
console.log(`[platform] connected to platform (botId: ${parsed.botId})`);
|
|
84
|
+
});
|
|
85
|
+
transport.on('slack_event', (data) => {
|
|
86
|
+
const slackEvent = JSON.parse(data);
|
|
87
|
+
const inbound = toInboundEvent(slackEvent);
|
|
88
|
+
if (inbound) {
|
|
89
|
+
engine?.submitTurn(inbound).catch((err) => {
|
|
90
|
+
console.error('[platform] submitTurn error:', err);
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
transport.on('ping', () => {
|
|
95
|
+
// Keepalive -- no action needed
|
|
96
|
+
});
|
|
97
|
+
transport.onError((err) => {
|
|
98
|
+
console.error('[platform] transport error, will auto-reconnect:', err);
|
|
99
|
+
});
|
|
100
|
+
transport.connect();
|
|
101
|
+
},
|
|
102
|
+
createOutput(context) {
|
|
103
|
+
const [channel, threadTs] = context.conversationId.split(':');
|
|
104
|
+
let thinkingTs = null;
|
|
105
|
+
return {
|
|
106
|
+
async showProgress(_text) {
|
|
107
|
+
if (thinkingMessage && !thinkingTs) {
|
|
108
|
+
const res = await callSlackApi('chat.postMessage', {
|
|
109
|
+
channel,
|
|
110
|
+
thread_ts: threadTs,
|
|
111
|
+
text: thinkingMessage,
|
|
112
|
+
});
|
|
113
|
+
thinkingTs = res.ts;
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
async sendResult(text) {
|
|
117
|
+
if (thinkingTs) {
|
|
118
|
+
await callSlackApi('chat.update', {
|
|
119
|
+
channel,
|
|
120
|
+
ts: thinkingTs,
|
|
121
|
+
text,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
await callSlackApi('chat.postMessage', {
|
|
126
|
+
channel,
|
|
127
|
+
thread_ts: threadTs,
|
|
128
|
+
text,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
async sendError(message) {
|
|
133
|
+
const errorText = `\u26a0\ufe0f ${message}`;
|
|
134
|
+
if (thinkingTs) {
|
|
135
|
+
await callSlackApi('chat.update', {
|
|
136
|
+
channel,
|
|
137
|
+
ts: thinkingTs,
|
|
138
|
+
text: errorText,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
await callSlackApi('chat.postMessage', {
|
|
143
|
+
channel,
|
|
144
|
+
thread_ts: threadTs,
|
|
145
|
+
text: errorText,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
async dispose() {
|
|
150
|
+
// Cleanup -- sendResult already handled thinking message update
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
},
|
|
154
|
+
async stop() {
|
|
155
|
+
if (transport) {
|
|
156
|
+
transport.close();
|
|
157
|
+
transport = null;
|
|
158
|
+
console.log('[platform] transport connection closed');
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
//# sourceMappingURL=connector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connector.js","sourceRoot":"","sources":["../src/connector.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAClD,YAAY,EAAE,wBAAwB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAC7E,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse.d.ts","sourceRoot":"","sources":["../../src/transports/sse.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAE3C;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAoDzD"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { EventSource } from 'eventsource';
|
|
2
|
+
/**
|
|
3
|
+
* SSE transport using EventSource (for Node.js / SSE-based relay).
|
|
4
|
+
*/
|
|
5
|
+
export function createSSETransport(url) {
|
|
6
|
+
let eventSource = null;
|
|
7
|
+
const listeners = new Map();
|
|
8
|
+
let errorHandler = null;
|
|
9
|
+
return {
|
|
10
|
+
connect() {
|
|
11
|
+
eventSource = new EventSource(url);
|
|
12
|
+
for (const [event, handlers] of listeners) {
|
|
13
|
+
for (const handler of handlers) {
|
|
14
|
+
eventSource.addEventListener(event, (e) => {
|
|
15
|
+
handler(e.data);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
eventSource.onerror = (err) => {
|
|
20
|
+
if (errorHandler)
|
|
21
|
+
errorHandler(err);
|
|
22
|
+
};
|
|
23
|
+
},
|
|
24
|
+
on(event, handler) {
|
|
25
|
+
let handlers = listeners.get(event);
|
|
26
|
+
if (!handlers) {
|
|
27
|
+
handlers = [];
|
|
28
|
+
listeners.set(event, handlers);
|
|
29
|
+
}
|
|
30
|
+
handlers.push(handler);
|
|
31
|
+
// If already connected, add listener immediately
|
|
32
|
+
if (eventSource) {
|
|
33
|
+
eventSource.addEventListener(event, (e) => {
|
|
34
|
+
handler(e.data);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
onError(handler) {
|
|
39
|
+
errorHandler = handler;
|
|
40
|
+
if (eventSource) {
|
|
41
|
+
eventSource.onerror = handler;
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
close() {
|
|
45
|
+
if (eventSource) {
|
|
46
|
+
eventSource.close();
|
|
47
|
+
eventSource = null;
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=sse.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse.js","sourceRoot":"","sources":["../../src/transports/sse.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAGzC;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,IAAI,WAAW,GAAuB,IAAI,CAAA;IAC1C,MAAM,SAAS,GAAG,IAAI,GAAG,EAAyC,CAAA;IAClE,IAAI,YAAY,GAAsC,IAAI,CAAA;IAE1D,OAAO;QACL,OAAO;YACL,WAAW,GAAG,IAAI,WAAW,CAAC,GAAG,CAAC,CAAA;YAElC,KAAK,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,SAAS,EAAE,CAAC;gBAC1C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;oBAC/B,WAAW,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC,CAAe,EAAE,EAAE;wBACtD,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;oBACjB,CAAC,CAAC,CAAA;gBACJ,CAAC;YACH,CAAC;YAED,WAAW,CAAC,OAAO,GAAG,CAAC,GAAG,EAAE,EAAE;gBAC5B,IAAI,YAAY;oBAAE,YAAY,CAAC,GAAG,CAAC,CAAA;YACrC,CAAC,CAAA;QACH,CAAC;QAED,EAAE,CAAC,KAAa,EAAE,OAA+B;YAC/C,IAAI,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;YACnC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,QAAQ,GAAG,EAAE,CAAA;gBACb,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;YAChC,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YAEtB,iDAAiD;YACjD,IAAI,WAAW,EAAE,CAAC;gBAChB,WAAW,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC,CAAe,EAAE,EAAE;oBACtD,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;gBACjB,CAAC,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;QAED,OAAO,CAAC,OAAiC;YACvC,YAAY,GAAG,OAAO,CAAA;YACtB,IAAI,WAAW,EAAE,CAAC;gBAChB,WAAW,CAAC,OAAO,GAAG,OAAO,CAAA;YAC/B,CAAC;QACH,CAAC;QAED,KAAK;YACH,IAAI,WAAW,EAAE,CAAC;gBAChB,WAAW,CAAC,KAAK,EAAE,CAAA;gBACnB,WAAW,GAAG,IAAI,CAAA;YACpB,CAAC;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transport interface for platform connector.
|
|
3
|
+
* Abstracts SSE (Node.js) and WebSocket (CF Workers) connections.
|
|
4
|
+
*/
|
|
5
|
+
export interface Transport {
|
|
6
|
+
/** Connect to the platform relay. */
|
|
7
|
+
connect(): void;
|
|
8
|
+
/** Register an event listener. */
|
|
9
|
+
on(event: string, handler: (data: string) => void): void;
|
|
10
|
+
/** Register an error handler. */
|
|
11
|
+
onError(handler: (error: unknown) => void): void;
|
|
12
|
+
/** Close the connection. */
|
|
13
|
+
close(): void;
|
|
14
|
+
}
|
|
15
|
+
export type TransportFactory = (url: string) => Transport;
|
|
16
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/transports/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,qCAAqC;IACrC,OAAO,IAAI,IAAI,CAAA;IACf,kCAAkC;IAClC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAA;IACxD,iCAAiC;IACjC,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,IAAI,CAAA;IAChD,4BAA4B;IAC5B,KAAK,IAAI,IAAI,CAAA;CACd;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,SAAS,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/transports/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../../src/transports/websocket.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAE3C;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAyE/D"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocket transport (for CF Workers / Durable Objects-based relay).
|
|
3
|
+
*/
|
|
4
|
+
export function createWebSocketTransport(url) {
|
|
5
|
+
let ws = null;
|
|
6
|
+
const listeners = new Map();
|
|
7
|
+
let errorHandler = null;
|
|
8
|
+
function dispatchMessage(raw) {
|
|
9
|
+
try {
|
|
10
|
+
const msg = JSON.parse(raw);
|
|
11
|
+
const handlers = listeners.get(msg.type);
|
|
12
|
+
if (handlers) {
|
|
13
|
+
const dataStr = typeof msg.data === 'string'
|
|
14
|
+
? msg.data
|
|
15
|
+
: JSON.stringify(msg.data);
|
|
16
|
+
for (const handler of handlers) {
|
|
17
|
+
handler(dataStr);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// Ignore unparseable messages
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
connect() {
|
|
27
|
+
// Convert http(s) to ws(s)
|
|
28
|
+
const wsUrl = url.replace(/^http/, 'ws');
|
|
29
|
+
ws = new WebSocket(wsUrl);
|
|
30
|
+
ws.onmessage = (event) => {
|
|
31
|
+
const data = typeof event.data === 'string'
|
|
32
|
+
? event.data
|
|
33
|
+
: String(event.data);
|
|
34
|
+
dispatchMessage(data);
|
|
35
|
+
};
|
|
36
|
+
ws.onerror = (event) => {
|
|
37
|
+
if (errorHandler)
|
|
38
|
+
errorHandler(event);
|
|
39
|
+
};
|
|
40
|
+
ws.onclose = () => {
|
|
41
|
+
// Could implement auto-reconnect here
|
|
42
|
+
};
|
|
43
|
+
},
|
|
44
|
+
on(event, handler) {
|
|
45
|
+
let handlers = listeners.get(event);
|
|
46
|
+
if (!handlers) {
|
|
47
|
+
handlers = [];
|
|
48
|
+
listeners.set(event, handlers);
|
|
49
|
+
}
|
|
50
|
+
handlers.push(handler);
|
|
51
|
+
},
|
|
52
|
+
onError(handler) {
|
|
53
|
+
errorHandler = handler;
|
|
54
|
+
if (ws) {
|
|
55
|
+
ws.onerror = handler;
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
close() {
|
|
59
|
+
if (ws) {
|
|
60
|
+
ws.close();
|
|
61
|
+
ws = null;
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=websocket.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket.js","sourceRoot":"","sources":["../../src/transports/websocket.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,UAAU,wBAAwB,CAAC,GAAW;IAClD,IAAI,EAAE,GAAqB,IAAI,CAAA;IAC/B,MAAM,SAAS,GAAG,IAAI,GAAG,EAAyC,CAAA;IAClE,IAAI,YAAY,GAAsC,IAAI,CAAA;IAE1D,SAAS,eAAe,CAAC,GAAW;QAClC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAIzB,CAAA;YACD,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;YACxC,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,OAAO,GACX,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;oBAC1B,CAAC,CAAC,GAAG,CAAC,IAAI;oBACV,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;gBAC9B,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;oBAC/B,OAAO,CAAC,OAAO,CAAC,CAAA;gBAClB,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,8BAA8B;QAChC,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO;YACL,2BAA2B;YAC3B,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;YACxC,EAAE,GAAG,IAAI,SAAS,CAAC,KAAK,CAAC,CAAA;YAEzB,EAAE,CAAC,SAAS,GAAG,CAAC,KAAmB,EAAE,EAAE;gBACrC,MAAM,IAAI,GACR,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;oBAC5B,CAAC,CAAC,KAAK,CAAC,IAAI;oBACZ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;gBACxB,eAAe,CAAC,IAAI,CAAC,CAAA;YACvB,CAAC,CAAA;YAED,EAAE,CAAC,OAAO,GAAG,CAAC,KAAK,EAAE,EAAE;gBACrB,IAAI,YAAY;oBAAE,YAAY,CAAC,KAAK,CAAC,CAAA;YACvC,CAAC,CAAA;YAED,EAAE,CAAC,OAAO,GAAG,GAAG,EAAE;gBAChB,sCAAsC;YACxC,CAAC,CAAA;QACH,CAAC;QAED,EAAE,CAAC,KAAa,EAAE,OAA+B;YAC/C,IAAI,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;YACnC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,QAAQ,GAAG,EAAE,CAAA;gBACb,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;YAChC,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACxB,CAAC;QAED,OAAO,CAAC,OAAiC;YACvC,YAAY,GAAG,OAAO,CAAA;YACtB,IAAI,EAAE,EAAE,CAAC;gBACP,EAAE,CAAC,OAAO,GAAG,OAAO,CAAA;YACtB,CAAC;QACH,CAAC;QAED,KAAK;YACH,IAAI,EAAE,EAAE,CAAC;gBACP,EAAE,CAAC,KAAK,EAAE,CAAA;gBACV,EAAE,GAAG,IAAI,CAAA;YACX,CAAC;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sena-ai/platform-connector",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"import": "./dist/index.js",
|
|
9
|
+
"default": "./dist/index.js"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist"
|
|
14
|
+
],
|
|
15
|
+
"dependencies": {
|
|
16
|
+
"eventsource": "^3.0.0"
|
|
17
|
+
},
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"@sena-ai/core": ">=1.0.0"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"typescript": "^5.8.0",
|
|
23
|
+
"@sena-ai/core": "1.0.23"
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsc -b",
|
|
27
|
+
"typecheck": "tsc --noEmit"
|
|
28
|
+
}
|
|
29
|
+
}
|