@mynitorai/sdk 0.1.1 → 0.1.3
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/index.d.ts +1 -1
- package/dist/index.js +46 -18
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
*/
|
|
5
5
|
export interface MyNitorConfig {
|
|
6
6
|
apiKey: string;
|
|
7
|
-
environment?: string;
|
|
8
7
|
endpoint?: string;
|
|
9
8
|
}
|
|
10
9
|
export declare class MyNitor {
|
|
@@ -17,6 +16,7 @@ export declare class MyNitor {
|
|
|
17
16
|
* Automatically detect and wrap AI libraries like OpenAI
|
|
18
17
|
*/
|
|
19
18
|
instrument(): void;
|
|
19
|
+
private getCallSite;
|
|
20
20
|
private sendEvent;
|
|
21
21
|
private wrapOpenAI;
|
|
22
22
|
}
|
package/dist/index.js
CHANGED
|
@@ -9,8 +9,7 @@ class MyNitor {
|
|
|
9
9
|
constructor(config) {
|
|
10
10
|
this.isInstrumented = false;
|
|
11
11
|
this.config = {
|
|
12
|
-
|
|
13
|
-
endpoint: 'https://www.mynitor.ai/api/v1/events',
|
|
12
|
+
endpoint: 'https://app.mynitor.ai/api/v1/events',
|
|
14
13
|
...config
|
|
15
14
|
};
|
|
16
15
|
}
|
|
@@ -30,9 +29,39 @@ class MyNitor {
|
|
|
30
29
|
this.isInstrumented = true;
|
|
31
30
|
console.log('🚀 MyNitor: Auto-instrumentation active.');
|
|
32
31
|
}
|
|
32
|
+
getCallSite() {
|
|
33
|
+
try {
|
|
34
|
+
const err = new Error();
|
|
35
|
+
const stack = err.stack?.split('\n') || [];
|
|
36
|
+
// Look for the frame that called the LLM method
|
|
37
|
+
// Stack usually: Error -> getCallSite -> wrapOpenAI wrapper -> USER CODE
|
|
38
|
+
// We iterate to find the first frame NOT in MyNitor SDK
|
|
39
|
+
for (const line of stack) {
|
|
40
|
+
if (!line.includes('mynitor') && !line.includes('Error') && line.includes('/')) {
|
|
41
|
+
// Typical format: " at Object.myFunction (/path/to/file.ts:10:5)"
|
|
42
|
+
const match = line.match(/at\s+(?:(.+?)\s+\()?(.*?):(\d+):(\d+)\)?/);
|
|
43
|
+
if (match) {
|
|
44
|
+
const func = match[1] || 'anonymous';
|
|
45
|
+
const fullPath = match[2];
|
|
46
|
+
const filename = fullPath.split('/').pop()?.split('.')[0] || 'unknown';
|
|
47
|
+
return {
|
|
48
|
+
file: fullPath,
|
|
49
|
+
line: parseInt(match[3]),
|
|
50
|
+
functionName: func,
|
|
51
|
+
workflowGuess: `${filename}:${func}`.replace('Object.', '')
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch (e) {
|
|
58
|
+
// fail safe
|
|
59
|
+
}
|
|
60
|
+
return { file: 'unknown', line: 0, functionName: 'unknown', workflowGuess: 'default-workflow' };
|
|
61
|
+
}
|
|
33
62
|
async sendEvent(payload) {
|
|
34
63
|
try {
|
|
35
|
-
// Fire and forget
|
|
64
|
+
// Fire and forget
|
|
36
65
|
fetch(this.config.endpoint, {
|
|
37
66
|
method: 'POST',
|
|
38
67
|
headers: {
|
|
@@ -41,20 +70,14 @@ class MyNitor {
|
|
|
41
70
|
},
|
|
42
71
|
body: JSON.stringify({
|
|
43
72
|
...payload,
|
|
44
|
-
environment: this.config.environment,
|
|
45
73
|
eventVersion: '1.0'
|
|
46
74
|
})
|
|
47
|
-
}).catch(() => {
|
|
48
|
-
/* Silently fail to protect the user's production app */
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
catch (e) {
|
|
52
|
-
/* Silently fail */
|
|
75
|
+
}).catch(() => { });
|
|
53
76
|
}
|
|
77
|
+
catch (e) { }
|
|
54
78
|
}
|
|
55
79
|
wrapOpenAI() {
|
|
56
80
|
try {
|
|
57
|
-
// Detect if OpenAI is installed
|
|
58
81
|
const OpenAI = require('openai');
|
|
59
82
|
if (!OpenAI || !OpenAI.OpenAI)
|
|
60
83
|
return;
|
|
@@ -63,14 +86,19 @@ class MyNitor {
|
|
|
63
86
|
OpenAI.OpenAI.Chat.Completions.prototype.create = async function (...args) {
|
|
64
87
|
const start = Date.now();
|
|
65
88
|
const body = args[0];
|
|
89
|
+
const callsite = self.getCallSite();
|
|
66
90
|
try {
|
|
67
91
|
const result = await originalChatCreate.apply(this, args);
|
|
68
92
|
const end = Date.now();
|
|
69
|
-
// Background capture
|
|
70
93
|
self.sendEvent({
|
|
71
94
|
requestId: result.id || `req_${Date.now()}`,
|
|
72
95
|
model: result.model || body.model,
|
|
73
96
|
provider: 'openai',
|
|
97
|
+
agent: 'default-agent',
|
|
98
|
+
workflow: callsite.workflowGuess,
|
|
99
|
+
file: callsite.file,
|
|
100
|
+
functionName: callsite.functionName,
|
|
101
|
+
lineNumber: callsite.line,
|
|
74
102
|
inputTokens: result.usage?.prompt_tokens || 0,
|
|
75
103
|
outputTokens: result.usage?.completion_tokens || 0,
|
|
76
104
|
latencyMs: end - start,
|
|
@@ -84,8 +112,10 @@ class MyNitor {
|
|
|
84
112
|
requestId: `err_${Date.now()}`,
|
|
85
113
|
model: body?.model || 'unknown',
|
|
86
114
|
provider: 'openai',
|
|
87
|
-
|
|
88
|
-
|
|
115
|
+
agent: 'default-agent',
|
|
116
|
+
workflow: callsite.workflowGuess,
|
|
117
|
+
file: callsite.file,
|
|
118
|
+
functionName: callsite.functionName,
|
|
89
119
|
latencyMs: end - start,
|
|
90
120
|
status: 'error',
|
|
91
121
|
errorType: error?.constructor?.name || 'Error'
|
|
@@ -94,11 +124,9 @@ class MyNitor {
|
|
|
94
124
|
}
|
|
95
125
|
};
|
|
96
126
|
}
|
|
97
|
-
catch (e) {
|
|
98
|
-
// Library not found or version mismatch - skip silently
|
|
99
|
-
}
|
|
127
|
+
catch (e) { }
|
|
100
128
|
}
|
|
101
129
|
}
|
|
102
130
|
exports.MyNitor = MyNitor;
|
|
103
|
-
// Global accessor
|
|
131
|
+
// Global accessor
|
|
104
132
|
exports.init = MyNitor.init;
|