memorylens 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/README.md +79 -0
- package/dist/index-BZqWj0_R.d.mts +6 -0
- package/dist/index-BZqWj0_R.d.ts +6 -0
- package/dist/index.d.mts +171 -0
- package/dist/index.d.ts +171 -0
- package/dist/index.js +492 -0
- package/dist/index.mjs +447 -0
- package/dist/integrations/langchain/index.d.mts +9 -0
- package/dist/integrations/langchain/index.d.ts +9 -0
- package/dist/integrations/langchain/index.js +257 -0
- package/dist/integrations/langchain/index.mjs +237 -0
- package/package.json +46 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
// src/tracer.ts
|
|
9
|
+
import { randomUUID } from "crypto";
|
|
10
|
+
|
|
11
|
+
// src/context.ts
|
|
12
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
13
|
+
var contextStorage = new AsyncLocalStorage();
|
|
14
|
+
function getCurrentContext() {
|
|
15
|
+
return contextStorage.getStore();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// src/sampler.ts
|
|
19
|
+
var Sampler = class {
|
|
20
|
+
rate;
|
|
21
|
+
constructor(rate = 1) {
|
|
22
|
+
if (rate < 0 || rate > 1) {
|
|
23
|
+
throw new Error(`Sample rate must be between 0.0 and 1.0, got ${rate}`);
|
|
24
|
+
}
|
|
25
|
+
this.rate = rate;
|
|
26
|
+
}
|
|
27
|
+
shouldSample() {
|
|
28
|
+
if (this.rate === 1) return true;
|
|
29
|
+
if (this.rate === 0) return false;
|
|
30
|
+
return Math.random() < this.rate;
|
|
31
|
+
}
|
|
32
|
+
getRate() {
|
|
33
|
+
return this.rate;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// src/tracer.ts
|
|
38
|
+
var MutableSpan = class {
|
|
39
|
+
traceId;
|
|
40
|
+
spanId;
|
|
41
|
+
operation;
|
|
42
|
+
parentSpanId;
|
|
43
|
+
status = "ok";
|
|
44
|
+
startTime;
|
|
45
|
+
endTime = 0;
|
|
46
|
+
agentId;
|
|
47
|
+
sessionId;
|
|
48
|
+
userId;
|
|
49
|
+
inputContent = null;
|
|
50
|
+
outputContent = null;
|
|
51
|
+
attributes;
|
|
52
|
+
constructor(options) {
|
|
53
|
+
this.traceId = randomUUID().replace(/-/g, "");
|
|
54
|
+
this.spanId = randomUUID().replace(/-/g, "").substring(0, 16);
|
|
55
|
+
this.operation = options.operation;
|
|
56
|
+
this.parentSpanId = options.parentSpanId ?? null;
|
|
57
|
+
const ctx = getCurrentContext();
|
|
58
|
+
this.agentId = options.agentId !== void 0 ? options.agentId : ctx?.agentId ?? null;
|
|
59
|
+
this.sessionId = options.sessionId !== void 0 ? options.sessionId : ctx?.sessionId ?? null;
|
|
60
|
+
this.userId = options.userId !== void 0 ? options.userId : ctx?.userId ?? null;
|
|
61
|
+
this.attributes = { ...options.attributes };
|
|
62
|
+
this.startTime = Date.now();
|
|
63
|
+
}
|
|
64
|
+
setAttribute(key, value) {
|
|
65
|
+
this.attributes[key] = value;
|
|
66
|
+
}
|
|
67
|
+
setContent(input, output) {
|
|
68
|
+
if (input !== void 0) this.inputContent = input;
|
|
69
|
+
if (output !== void 0) this.outputContent = output;
|
|
70
|
+
}
|
|
71
|
+
setStatus(status) {
|
|
72
|
+
this.status = status;
|
|
73
|
+
}
|
|
74
|
+
setError(error) {
|
|
75
|
+
this.status = "error";
|
|
76
|
+
if (error instanceof Error) {
|
|
77
|
+
this.attributes["error.type"] = error.constructor.name;
|
|
78
|
+
this.attributes["error.message"] = error.message;
|
|
79
|
+
} else {
|
|
80
|
+
this.attributes["error.type"] = "Error";
|
|
81
|
+
this.attributes["error.message"] = String(error);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
end() {
|
|
85
|
+
this.endTime = Date.now();
|
|
86
|
+
return {
|
|
87
|
+
spanId: this.spanId,
|
|
88
|
+
traceId: this.traceId,
|
|
89
|
+
parentSpanId: this.parentSpanId,
|
|
90
|
+
operation: this.operation,
|
|
91
|
+
status: this.status,
|
|
92
|
+
startTime: this.startTime,
|
|
93
|
+
endTime: this.endTime,
|
|
94
|
+
durationMs: this.endTime - this.startTime,
|
|
95
|
+
agentId: this.agentId,
|
|
96
|
+
sessionId: this.sessionId,
|
|
97
|
+
userId: this.userId,
|
|
98
|
+
inputContent: this.inputContent,
|
|
99
|
+
outputContent: this.outputContent,
|
|
100
|
+
attributes: { ...this.attributes }
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
var Tracer = class {
|
|
105
|
+
name;
|
|
106
|
+
provider;
|
|
107
|
+
constructor(name, provider) {
|
|
108
|
+
this.name = name;
|
|
109
|
+
this.provider = provider;
|
|
110
|
+
}
|
|
111
|
+
getName() {
|
|
112
|
+
return this.name;
|
|
113
|
+
}
|
|
114
|
+
startSpan(operation, attributes) {
|
|
115
|
+
const ctx = getCurrentContext();
|
|
116
|
+
return new MutableSpan({
|
|
117
|
+
operation,
|
|
118
|
+
agentId: ctx?.agentId ?? null,
|
|
119
|
+
sessionId: ctx?.sessionId ?? null,
|
|
120
|
+
userId: ctx?.userId ?? null,
|
|
121
|
+
attributes
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
endSpan(span) {
|
|
125
|
+
const finished = span.end();
|
|
126
|
+
for (const processor of this.provider.processors) {
|
|
127
|
+
processor.onEnd(finished);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
var TracerProvider = class _TracerProvider {
|
|
132
|
+
static instance = null;
|
|
133
|
+
processors = [];
|
|
134
|
+
sampler = new Sampler(1);
|
|
135
|
+
serviceName = "memorylens";
|
|
136
|
+
static get() {
|
|
137
|
+
if (!_TracerProvider.instance) {
|
|
138
|
+
_TracerProvider.instance = new _TracerProvider();
|
|
139
|
+
}
|
|
140
|
+
return _TracerProvider.instance;
|
|
141
|
+
}
|
|
142
|
+
static reset() {
|
|
143
|
+
if (_TracerProvider.instance) {
|
|
144
|
+
for (const p of _TracerProvider.instance.processors) {
|
|
145
|
+
p.shutdown().catch(() => {
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
_TracerProvider.instance = null;
|
|
150
|
+
}
|
|
151
|
+
addProcessor(processor) {
|
|
152
|
+
this.processors.push(processor);
|
|
153
|
+
}
|
|
154
|
+
getTracer(name) {
|
|
155
|
+
return new Tracer(name, this);
|
|
156
|
+
}
|
|
157
|
+
async shutdown() {
|
|
158
|
+
for (const p of this.processors) {
|
|
159
|
+
await p.shutdown();
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// src/integrations/langchain/instrumentor.ts
|
|
165
|
+
var originals = /* @__PURE__ */ new WeakMap();
|
|
166
|
+
var LangChainInstrumentor = class {
|
|
167
|
+
patched = false;
|
|
168
|
+
instrument(_options) {
|
|
169
|
+
if (this.patched) return;
|
|
170
|
+
let BaseChatMemory;
|
|
171
|
+
try {
|
|
172
|
+
const mod = __require("langchain/memory");
|
|
173
|
+
BaseChatMemory = mod.BaseChatMemory;
|
|
174
|
+
} catch {
|
|
175
|
+
console.warn("[memorylens] langchain/memory not found \u2014 LangChain instrumentation skipped");
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
if (!BaseChatMemory?.prototype) return;
|
|
179
|
+
const proto = BaseChatMemory.prototype;
|
|
180
|
+
const origSaveContext = proto.saveContext;
|
|
181
|
+
const origLoadMemoryVariables = proto.loadMemoryVariables;
|
|
182
|
+
proto.saveContext = async function(...args) {
|
|
183
|
+
const provider = TracerProvider.get();
|
|
184
|
+
const tracer = provider.getTracer("memorylens.langchain");
|
|
185
|
+
const span = tracer.startSpan("memory.write", { "langchain.method": "saveContext" });
|
|
186
|
+
try {
|
|
187
|
+
const result = await origSaveContext.apply(this, args);
|
|
188
|
+
tracer.endSpan(span);
|
|
189
|
+
return result;
|
|
190
|
+
} catch (error) {
|
|
191
|
+
span.setError(error);
|
|
192
|
+
tracer.endSpan(span);
|
|
193
|
+
throw error;
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
proto.loadMemoryVariables = async function(...args) {
|
|
197
|
+
const provider = TracerProvider.get();
|
|
198
|
+
const tracer = provider.getTracer("memorylens.langchain");
|
|
199
|
+
const span = tracer.startSpan("memory.read", {
|
|
200
|
+
"langchain.method": "loadMemoryVariables"
|
|
201
|
+
});
|
|
202
|
+
try {
|
|
203
|
+
const result = await origLoadMemoryVariables.apply(this, args);
|
|
204
|
+
tracer.endSpan(span);
|
|
205
|
+
return result;
|
|
206
|
+
} catch (error) {
|
|
207
|
+
span.setError(error);
|
|
208
|
+
tracer.endSpan(span);
|
|
209
|
+
throw error;
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
originals.set(proto, { saveContext: origSaveContext, loadMemoryVariables: origLoadMemoryVariables });
|
|
213
|
+
this.patched = true;
|
|
214
|
+
}
|
|
215
|
+
uninstrument() {
|
|
216
|
+
if (!this.patched) return;
|
|
217
|
+
let BaseChatMemory;
|
|
218
|
+
try {
|
|
219
|
+
const mod = __require("langchain/memory");
|
|
220
|
+
BaseChatMemory = mod.BaseChatMemory;
|
|
221
|
+
} catch {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (!BaseChatMemory?.prototype) return;
|
|
225
|
+
const proto = BaseChatMemory.prototype;
|
|
226
|
+
const orig = originals.get(proto);
|
|
227
|
+
if (orig) {
|
|
228
|
+
proto.saveContext = orig.saveContext;
|
|
229
|
+
proto.loadMemoryVariables = orig.loadMemoryVariables;
|
|
230
|
+
originals.delete(proto);
|
|
231
|
+
}
|
|
232
|
+
this.patched = false;
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
export {
|
|
236
|
+
LangChainInstrumentor
|
|
237
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "memorylens",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Observability and debugging for AI agent memory systems",
|
|
5
|
+
"main": "./dist/index.cjs",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"require": "./dist/index.cjs"
|
|
13
|
+
},
|
|
14
|
+
"./integrations/langchain": {
|
|
15
|
+
"types": "./dist/integrations/langchain/index.d.ts",
|
|
16
|
+
"import": "./dist/integrations/langchain/index.js",
|
|
17
|
+
"require": "./dist/integrations/langchain/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsup",
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"test:watch": "vitest",
|
|
24
|
+
"lint": "tsc --noEmit"
|
|
25
|
+
},
|
|
26
|
+
"license": "Apache-2.0",
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@opentelemetry/api": "^1.7.0",
|
|
29
|
+
"@opentelemetry/exporter-trace-otlp-http": "^0.48.0",
|
|
30
|
+
"@opentelemetry/sdk-trace-base": "^1.20.0"
|
|
31
|
+
},
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"langchain": ">=0.1.0"
|
|
34
|
+
},
|
|
35
|
+
"peerDependenciesMeta": {
|
|
36
|
+
"langchain": {
|
|
37
|
+
"optional": true
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@types/node": "^25.5.2",
|
|
42
|
+
"tsup": "^8.0.0",
|
|
43
|
+
"typescript": "^5.3.0",
|
|
44
|
+
"vitest": "^1.2.0"
|
|
45
|
+
}
|
|
46
|
+
}
|