@lmnr-ai/lmnr 0.2.0 → 0.2.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lmnr-ai/lmnr",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "TypeScript SDK for Laminar AI",
5
5
  "main": "src/index.ts",
6
6
  "repository": {
@@ -20,14 +20,17 @@
20
20
  },
21
21
  "homepage": "https://github.com/lmnr-ai/ts-sdk#readme",
22
22
  "dependencies": {
23
+ "@types/ws": "^8.5.10",
23
24
  "browser-or-node": "^3.0.0",
24
25
  "ts-node": "^10.9.2",
25
26
  "tsup": "^8.1.0",
26
27
  "typescript": "^5.5.2",
27
- "websocket": "^1.0.35"
28
+ "uuid": "^10.0.0",
29
+ "ws": "^8.18.0"
28
30
  },
29
31
  "devDependencies": {
30
- "@types/websocket": "^1.0.10"
32
+ "@types/uuid": "^10.0.0",
33
+ "bufferutil": "^4.0.8"
31
34
  },
32
35
  "scripts": {
33
36
  "build": "tsup",
package/src/index.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { NodeInput, EndpointRunResponse, EndpointRunRequest, NodeWebSocketMessage, ToolCall } from './types';
1
+ import { NodeInput, EndpointRunResponse, EndpointRunRequest, NodeWebSocketMessage, ToolCall, WebSocketError } from './types';
2
2
  import { isBrowser, isNode } from 'browser-or-node';
3
+ import { WebSocket } from 'ws';
3
4
 
4
5
  export { NodeInput, EndpointRunResponse, EndpointRunRequest, ChatMessage } from './types';
5
-
6
- class WebSocketError extends Error {}
6
+ export { RemoteDebugger as LaminarRemoteDebugger } from './remote_debugger';
7
7
 
8
8
  export class Laminar {
9
9
  private readonly projectApiKey: string;
@@ -69,54 +69,42 @@ export class Laminar {
69
69
  metadata = {},
70
70
  tools = [],
71
71
  }: EndpointRunRequest): Promise<EndpointRunResponse> {
72
- const WebSocketClient = require('websocket').client;
73
- const socket = new WebSocketClient();
72
+ const socket = new WebSocket(this.ws_url, [], {headers: {'Authorization': `Bearer ${this.projectApiKey}`}});
74
73
  let response: EndpointRunResponse | null = null;
75
-
76
- socket.on('connectFailed', (error: any) => {
77
- console.log('Connect Error: ' + error.toString());
78
- });
79
74
 
80
- socket.on('connect', (connection: any) => {
81
- connection.send(JSON.stringify({
75
+ socket.on('open', () => {
76
+ socket.send(JSON.stringify({
82
77
  inputs,
83
78
  endpoint,
84
79
  env,
85
80
  metadata,
86
81
  tools,
87
82
  }));
88
- connection.on('message', (data: NodeWebSocketMessage) => {
83
+ });
84
+ socket.on('message', (data: NodeWebSocketMessage) => {
85
+ try {
86
+ const toolCall = JSON.parse(data.toString()) as ToolCall;
87
+ const matchingTool = tools.find(tool => tool.name === toolCall.function.name);
88
+ if (!matchingTool) {
89
+ throw new WebSocketError(
90
+ `Tool ${toolCall.function.name} not found. Registered tools: ${tools.map(tool => tool.name).join(', ')}`
91
+ );
92
+ }
93
+ let args = {}
89
94
  try {
90
- const toolCall = JSON.parse(data["utf8Data"]!) as ToolCall;
91
- const matchingTool = tools.find(tool => tool.name === toolCall.function.name);
92
- if (!matchingTool) {
93
- throw new WebSocketError(
94
- `Tool ${toolCall.function.name} not found. Registered tools: ${tools.map(tool => tool.name).join(', ')}`
95
- );
96
- }
97
- let args = {}
98
- try {
99
- args = JSON.parse(toolCall.function.arguments);
100
- } catch (e) {}
101
- const result = matchingTool(args);
102
- connection.send(JSON.stringify(result));
103
- } catch (e) {
104
- if (e instanceof WebSocketError) {
105
- throw e;
106
- }
107
- response = JSON.parse(data["utf8Data"]!) as EndpointRunResponse;
108
- connection.close();
95
+ args = JSON.parse(toolCall.function.arguments);
96
+ } catch (e) {}
97
+ const result = matchingTool(args);
98
+ socket.send(JSON.stringify(result));
99
+ } catch (e) {
100
+ if (e instanceof WebSocketError) {
101
+ throw e;
109
102
  }
110
- });
103
+ response = JSON.parse(data.toString()) as EndpointRunResponse;
104
+ socket.close();
105
+ }
111
106
  });
112
107
 
113
- socket.connect(
114
- this.ws_url,
115
- '', // protocols. If specified, server tries to match one of these, and fails
116
- null, // origin. Makes more sense in a browser context
117
- {'Authorization': `Bearer ${this.projectApiKey}`}
118
- );
119
-
120
108
  // TODO: Implement a better way to wait for the response
121
109
  while (!response) {
122
110
  await new Promise((resolve) => setTimeout(resolve, 1000));
@@ -0,0 +1,81 @@
1
+ import { NodeWebSocketMessage, RegisterDebuggerRequest, Tool, ToolCall, WebSocketError } from "./types";
2
+ import { v4 as uuidv4 } from 'uuid';
3
+ import { WebSocket } from 'ws';
4
+
5
+
6
+ export class RemoteDebugger {
7
+ private readonly projectApiKey: string;
8
+ private readonly url: string = 'wss://api.lmnr.ai/v2/endpoint/ws';
9
+ private readonly tools: Tool[];
10
+ private sessionId: string | null = null;
11
+ private socket;
12
+
13
+ constructor(projectApiKey: string, tools: Tool[]) {
14
+ this.projectApiKey = projectApiKey;
15
+ this.tools = tools;
16
+ this.socket = new WebSocket(this.url, [], {headers: {'Authorization': `Bearer ${this.projectApiKey}`}});
17
+ }
18
+
19
+ public async start(): Promise<string> {
20
+ this.sessionId = this.generateSessionId();
21
+ console.log(this.formatSessionId());
22
+
23
+ this.socket.on('open', () => {
24
+ this.socket.send(JSON.stringify({
25
+ debuggerSessionId: this.sessionId
26
+ } as RegisterDebuggerRequest));
27
+ });
28
+
29
+ this.socket.on('message', (data: NodeWebSocketMessage) => {
30
+ try {
31
+ const toolCall = JSON.parse(data.toString()) as ToolCall;
32
+ const matchingTool = this.tools.find(tool => tool.name === toolCall.function.name);
33
+ if (!matchingTool) {
34
+ console.error(
35
+ `Tool ${toolCall.function.name} not found. Registered tools: ${this.tools.map(tool => tool.name).join(', ')}`
36
+ );
37
+ return;
38
+ }
39
+ let args = {}
40
+ try {
41
+ args = JSON.parse(toolCall.function.arguments);
42
+ } catch (e) {}
43
+ const result = matchingTool(args);
44
+ this.socket.send(JSON.stringify(result));
45
+ } catch (e) {
46
+ this.socket.send(JSON.stringify({
47
+ deregister: true,
48
+ debuggerSessionId: this.sessionId
49
+ } as RegisterDebuggerRequest));
50
+ this.socket.close();
51
+ }
52
+ });
53
+
54
+ return this.sessionId;
55
+ }
56
+
57
+ public stop() {
58
+ this.socket.send(JSON.stringify({
59
+ deregister: true,
60
+ debuggerSessionId: this.sessionId
61
+ } as RegisterDebuggerRequest));
62
+ this.socket.close();
63
+ }
64
+
65
+ public getSessionId(): string | null {
66
+ return this.sessionId;
67
+ }
68
+
69
+ private generateSessionId(): string {
70
+ return uuidv4();
71
+ }
72
+
73
+ private formatSessionId(): string {
74
+ return `
75
+ ========================================
76
+ Debugger Session ID:
77
+ ${this.sessionId}
78
+ ========================================
79
+ `
80
+ }
81
+ }
package/src/types.ts CHANGED
@@ -5,12 +5,14 @@ export type ChatMessage = {
5
5
 
6
6
  export type NodeInput = ChatMessage[] | string;
7
7
 
8
+ export type Tool = (...args: any) => NodeInput | Promise<NodeInput>;
9
+
8
10
  export type EndpointRunRequest = {
9
11
  inputs: Record<string, NodeInput>;
10
12
  endpoint: string;
11
13
  env?: Record<string, string>;
12
14
  metadata?: Record<string, string>;
13
- tools?: ((params: Record<string, any>) => NodeInput | Promise<NodeInput>)[];
15
+ tools?: Tool[];
14
16
  }
15
17
 
16
18
  export type EndpointRunResponse = {
@@ -34,4 +36,13 @@ export type NodeWebSocketMessage = {
34
36
  utf8Data?: string;
35
37
  }
36
38
 
37
- const bar = ({a }: {a: string}): string => a;
39
+ export type RegisterDebuggerRequest = {
40
+ debuggerSessionId: string;
41
+ }
42
+
43
+ export type DeregisterDebuggerRequest = {
44
+ deregister: true;
45
+ debuggerSessionId: string;
46
+ }
47
+
48
+ export class WebSocketError extends Error {}