@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 +6 -3
- package/src/index.ts +27 -39
- package/src/remote_debugger.ts +81 -0
- package/src/types.ts +13 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lmnr-ai/lmnr",
|
|
3
|
-
"version": "0.2.
|
|
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
|
-
"
|
|
28
|
+
"uuid": "^10.0.0",
|
|
29
|
+
"ws": "^8.18.0"
|
|
28
30
|
},
|
|
29
31
|
"devDependencies": {
|
|
30
|
-
"@types/
|
|
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
|
|
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('
|
|
81
|
-
|
|
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
|
-
|
|
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
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
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?:
|
|
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
|
-
|
|
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 {}
|