@prefactor/langchain 0.1.1 → 0.2.1
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 +10 -2
- package/dist/index.cjs +104 -47
- package/dist/index.cjs.map +5 -5
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +111 -52
- package/dist/index.js.map +5 -5
- package/dist/init.d.ts +19 -3
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +85 -31
- package/dist/init.js.map +1 -1
- package/dist/middleware.d.ts +4 -2
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +33 -20
- package/dist/middleware.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ npm install @prefactor/langchain
|
|
|
10
10
|
bun add @prefactor/langchain
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Note: This package requires `@prefactor/core` as a peer dependency, which will be installed automatically.
|
|
14
14
|
|
|
15
15
|
## Peer Dependencies
|
|
16
16
|
|
|
@@ -78,6 +78,7 @@ For convenience, common types are re-exported:
|
|
|
78
78
|
```typescript
|
|
79
79
|
import {
|
|
80
80
|
type Config,
|
|
81
|
+
type CoreRuntime,
|
|
81
82
|
type HttpTransportConfig,
|
|
82
83
|
type Span,
|
|
83
84
|
SpanStatus,
|
|
@@ -93,6 +94,11 @@ import {
|
|
|
93
94
|
- `PREFACTOR_API_URL`: API endpoint for HTTP transport
|
|
94
95
|
- `PREFACTOR_API_TOKEN`: Authentication token
|
|
95
96
|
- `PREFACTOR_SAMPLE_RATE`: Sampling rate 0.0-1.0 (default: `1.0`)
|
|
97
|
+
- `PREFACTOR_CAPTURE_INPUTS`: Capture span inputs (default: `true`)
|
|
98
|
+
- `PREFACTOR_CAPTURE_OUTPUTS`: Capture span outputs (default: `true`)
|
|
99
|
+
- `PREFACTOR_MAX_INPUT_LENGTH`: Max input string length (default: `10000`)
|
|
100
|
+
- `PREFACTOR_MAX_OUTPUT_LENGTH`: Max output string length (default: `10000`)
|
|
101
|
+
- `PREFACTOR_LOG_LEVEL`: `"debug"` | `"info"` | `"warn"` | `"error"` (default: `"info")`
|
|
96
102
|
|
|
97
103
|
### Programmatic Configuration
|
|
98
104
|
|
|
@@ -109,7 +115,9 @@ const middleware = init({
|
|
|
109
115
|
apiUrl: 'https://api.prefactor.ai',
|
|
110
116
|
apiToken: process.env.PREFACTOR_API_TOKEN!,
|
|
111
117
|
agentId: 'my-agent',
|
|
112
|
-
|
|
118
|
+
agentIdentifier: '1.0.0',
|
|
119
|
+
agentName: 'My Agent',
|
|
120
|
+
agentDescription: 'An agent description',
|
|
113
121
|
},
|
|
114
122
|
});
|
|
115
123
|
```
|
package/dist/index.cjs
CHANGED
|
@@ -29,6 +29,7 @@ var __export = (target, all) => {
|
|
|
29
29
|
// packages/langchain/src/index.ts
|
|
30
30
|
var exports_src = {};
|
|
31
31
|
__export(exports_src, {
|
|
32
|
+
withSpan: () => withSpan,
|
|
32
33
|
shutdown: () => shutdown,
|
|
33
34
|
init: () => init,
|
|
34
35
|
getTracer: () => getTracer,
|
|
@@ -42,7 +43,6 @@ var import_core3 = require("@prefactor/core");
|
|
|
42
43
|
|
|
43
44
|
// packages/langchain/src/init.ts
|
|
44
45
|
var import_core2 = require("@prefactor/core");
|
|
45
|
-
var import_pfid = require("@prefactor/pfid");
|
|
46
46
|
var import_langchain = require("langchain");
|
|
47
47
|
|
|
48
48
|
// packages/langchain/src/middleware.ts
|
|
@@ -84,22 +84,24 @@ function extractTokenUsage(response) {
|
|
|
84
84
|
// packages/langchain/src/middleware.ts
|
|
85
85
|
class PrefactorMiddleware {
|
|
86
86
|
tracer;
|
|
87
|
+
agentManager;
|
|
88
|
+
agentInfo;
|
|
87
89
|
rootSpan = null;
|
|
88
|
-
constructor(tracer) {
|
|
90
|
+
constructor(tracer, agentManager, agentInfo) {
|
|
89
91
|
this.tracer = tracer;
|
|
92
|
+
this.agentManager = agentManager;
|
|
93
|
+
this.agentInfo = agentInfo;
|
|
90
94
|
}
|
|
91
95
|
async beforeAgent(state) {
|
|
92
|
-
const parentSpan = import_core.SpanContext.getCurrent();
|
|
93
96
|
const messages = state?.messages ?? [];
|
|
94
|
-
this.
|
|
97
|
+
this.agentManager.startInstance(this.agentInfo);
|
|
95
98
|
const span = this.tracer.startSpan({
|
|
96
|
-
name: "agent",
|
|
99
|
+
name: "langchain:agent",
|
|
97
100
|
spanType: import_core.SpanType.AGENT,
|
|
98
|
-
inputs: { messages: messages.slice(-3)
|
|
99
|
-
parentSpanId: parentSpan?.spanId,
|
|
100
|
-
traceId: parentSpan?.traceId
|
|
101
|
+
inputs: { messages: import_core.serializeValue(messages.slice(-3)) }
|
|
101
102
|
});
|
|
102
103
|
this.rootSpan = span;
|
|
104
|
+
import_core.SpanContext.enter(span);
|
|
103
105
|
}
|
|
104
106
|
async afterAgent(state) {
|
|
105
107
|
if (!this.rootSpan) {
|
|
@@ -107,20 +109,17 @@ class PrefactorMiddleware {
|
|
|
107
109
|
}
|
|
108
110
|
const messages = state?.messages ?? [];
|
|
109
111
|
this.tracer.endSpan(this.rootSpan, {
|
|
110
|
-
outputs: { messages: messages.slice(-3)
|
|
112
|
+
outputs: { messages: import_core.serializeValue(messages.slice(-3)) }
|
|
111
113
|
});
|
|
112
|
-
this.
|
|
113
|
-
import_core.SpanContext.
|
|
114
|
+
this.agentManager.finishInstance();
|
|
115
|
+
import_core.SpanContext.exit();
|
|
114
116
|
this.rootSpan = null;
|
|
115
117
|
}
|
|
116
118
|
async wrapModelCall(request, handler) {
|
|
117
|
-
const parentSpan = import_core.SpanContext.getCurrent();
|
|
118
119
|
const span = this.tracer.startSpan({
|
|
119
120
|
name: this.extractModelName(request),
|
|
120
121
|
spanType: import_core.SpanType.LLM,
|
|
121
|
-
inputs: this.extractModelInputs(request)
|
|
122
|
-
parentSpanId: parentSpan?.spanId,
|
|
123
|
-
traceId: parentSpan?.traceId
|
|
122
|
+
inputs: this.extractModelInputs(request)
|
|
124
123
|
});
|
|
125
124
|
try {
|
|
126
125
|
const response = await import_core.SpanContext.runAsync(span, async () => {
|
|
@@ -136,13 +135,10 @@ class PrefactorMiddleware {
|
|
|
136
135
|
}
|
|
137
136
|
}
|
|
138
137
|
async wrapToolCall(request, handler) {
|
|
139
|
-
const parentSpan = import_core.SpanContext.getCurrent();
|
|
140
138
|
const span = this.tracer.startSpan({
|
|
141
139
|
name: this.extractToolName(request),
|
|
142
140
|
spanType: import_core.SpanType.TOOL,
|
|
143
|
-
inputs: this.extractToolInputs(request)
|
|
144
|
-
parentSpanId: parentSpan?.spanId,
|
|
145
|
-
traceId: parentSpan?.traceId
|
|
141
|
+
inputs: this.extractToolInputs(request)
|
|
146
142
|
});
|
|
147
143
|
try {
|
|
148
144
|
const response = await import_core.SpanContext.runAsync(span, async () => {
|
|
@@ -158,15 +154,31 @@ class PrefactorMiddleware {
|
|
|
158
154
|
}
|
|
159
155
|
}
|
|
160
156
|
extractModelName(request) {
|
|
161
|
-
|
|
157
|
+
const candidate = request?.model ?? request?.modelName;
|
|
158
|
+
if (typeof candidate === "string") {
|
|
159
|
+
return candidate;
|
|
160
|
+
}
|
|
161
|
+
if (candidate && typeof candidate === "object") {
|
|
162
|
+
const modelObject = candidate;
|
|
163
|
+
if (Array.isArray(modelObject.id) && modelObject.id.every((item) => typeof item === "string")) {
|
|
164
|
+
return modelObject.id.join(".");
|
|
165
|
+
}
|
|
166
|
+
if (typeof modelObject.modelName === "string") {
|
|
167
|
+
return modelObject.modelName;
|
|
168
|
+
}
|
|
169
|
+
if (typeof modelObject.name === "string") {
|
|
170
|
+
return modelObject.name;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return "unknown";
|
|
162
174
|
}
|
|
163
175
|
extractModelInputs(request) {
|
|
164
176
|
const messages = request?.messages ?? [];
|
|
165
|
-
return { messages: messages.slice(-3)
|
|
177
|
+
return { messages: import_core.serializeValue(messages.slice(-3)) };
|
|
166
178
|
}
|
|
167
179
|
extractModelOutputs(response) {
|
|
168
180
|
const content = response?.content ?? response?.text ?? "";
|
|
169
|
-
return { content:
|
|
181
|
+
return { content: import_core.serializeValue(content) };
|
|
170
182
|
}
|
|
171
183
|
extractToolName(request) {
|
|
172
184
|
return request?.name ?? request?.tool ?? "unknown";
|
|
@@ -181,36 +193,67 @@ class PrefactorMiddleware {
|
|
|
181
193
|
|
|
182
194
|
// packages/langchain/src/init.ts
|
|
183
195
|
var logger = import_core2.getLogger("init");
|
|
196
|
+
var DEFAULT_LANGCHAIN_AGENT_SCHEMA = {
|
|
197
|
+
external_identifier: "prefactor",
|
|
198
|
+
span_schemas: {
|
|
199
|
+
agent: { type: "object", additionalProperties: true },
|
|
200
|
+
llm: { type: "object", additionalProperties: true },
|
|
201
|
+
tool: { type: "object", additionalProperties: true },
|
|
202
|
+
chain: { type: "object", additionalProperties: true }
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
var globalCore = null;
|
|
184
206
|
var globalTracer = null;
|
|
185
207
|
var globalMiddleware = null;
|
|
186
208
|
function init(config) {
|
|
187
209
|
import_core2.configureLogging();
|
|
188
|
-
|
|
189
|
-
|
|
210
|
+
let configWithHttp = config;
|
|
211
|
+
const transportType = config?.transportType ?? process.env.PREFACTOR_TRANSPORT ?? "http";
|
|
212
|
+
if (transportType === "http" && !config?.httpConfig) {
|
|
213
|
+
const apiUrl = process.env.PREFACTOR_API_URL;
|
|
214
|
+
const apiToken = process.env.PREFACTOR_API_TOKEN;
|
|
215
|
+
if (!apiUrl || !apiToken) {
|
|
216
|
+
throw new Error("HTTP transport requires PREFACTOR_API_URL and PREFACTOR_API_TOKEN environment variables, " + "or httpConfig to be provided in configuration");
|
|
217
|
+
}
|
|
218
|
+
configWithHttp = {
|
|
219
|
+
...config,
|
|
220
|
+
transportType: "http",
|
|
221
|
+
httpConfig: {
|
|
222
|
+
apiUrl,
|
|
223
|
+
apiToken,
|
|
224
|
+
agentId: process.env.PREFACTOR_AGENT_ID,
|
|
225
|
+
agentName: process.env.PREFACTOR_AGENT_NAME,
|
|
226
|
+
agentIdentifier: process.env.PREFACTOR_AGENT_IDENTIFIER || "1.0.0",
|
|
227
|
+
agentSchema: DEFAULT_LANGCHAIN_AGENT_SCHEMA
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
} else if (transportType === "http" && config?.httpConfig && !config.httpConfig.agentSchema) {
|
|
231
|
+
configWithHttp = {
|
|
232
|
+
...config,
|
|
233
|
+
httpConfig: {
|
|
234
|
+
...config.httpConfig,
|
|
235
|
+
agentSchema: DEFAULT_LANGCHAIN_AGENT_SCHEMA
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
const finalConfig = import_core2.createConfig(configWithHttp);
|
|
190
240
|
if (globalMiddleware !== null) {
|
|
191
241
|
return globalMiddleware;
|
|
192
242
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
const httpConfig = import_core2.HttpTransportConfigSchema.parse(finalConfig.httpConfig);
|
|
201
|
-
transport = new import_core2.HttpTransport(httpConfig);
|
|
202
|
-
}
|
|
203
|
-
let partition;
|
|
204
|
-
if (finalConfig.httpConfig?.agentId) {
|
|
205
|
-
try {
|
|
206
|
-
partition = import_pfid.extractPartition(finalConfig.httpConfig.agentId);
|
|
207
|
-
logger.debug("Extracted partition from agent_id", { partition });
|
|
208
|
-
} catch (error) {
|
|
209
|
-
logger.warn("Failed to extract partition from agent_id, using random partition", { error });
|
|
210
|
-
}
|
|
243
|
+
const core = import_core2.createCore(finalConfig);
|
|
244
|
+
globalCore = core;
|
|
245
|
+
globalTracer = core.tracer;
|
|
246
|
+
const httpConfig = finalConfig.httpConfig;
|
|
247
|
+
if (httpConfig?.agentSchema) {
|
|
248
|
+
core.agentManager.registerSchema(httpConfig.agentSchema);
|
|
211
249
|
}
|
|
212
|
-
|
|
213
|
-
|
|
250
|
+
const agentInfo = finalConfig.httpConfig ? {
|
|
251
|
+
agentId: finalConfig.httpConfig.agentId,
|
|
252
|
+
agentIdentifier: finalConfig.httpConfig.agentIdentifier,
|
|
253
|
+
agentName: finalConfig.httpConfig.agentName,
|
|
254
|
+
agentDescription: finalConfig.httpConfig.agentDescription
|
|
255
|
+
} : undefined;
|
|
256
|
+
const prefactorMiddleware = new PrefactorMiddleware(core.tracer, core.agentManager, agentInfo);
|
|
214
257
|
const middleware = import_langchain.createMiddleware({
|
|
215
258
|
name: "prefactor",
|
|
216
259
|
wrapModelCall: async (request, handler) => {
|
|
@@ -235,11 +278,25 @@ function getTracer() {
|
|
|
235
278
|
}
|
|
236
279
|
return globalTracer;
|
|
237
280
|
}
|
|
281
|
+
async function withSpan(options, fn) {
|
|
282
|
+
const tracer = getTracer();
|
|
283
|
+
const span = tracer.startSpan(options);
|
|
284
|
+
try {
|
|
285
|
+
const result = await import_core2.SpanContext.runAsync(span, async () => await fn());
|
|
286
|
+
tracer.endSpan(span);
|
|
287
|
+
return result;
|
|
288
|
+
} catch (error) {
|
|
289
|
+
const normalizedError = error instanceof Error ? error : new Error(String(error));
|
|
290
|
+
tracer.endSpan(span, { error: normalizedError });
|
|
291
|
+
throw error;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
238
294
|
async function shutdown() {
|
|
239
|
-
if (
|
|
295
|
+
if (globalCore) {
|
|
240
296
|
logger.info("Shutting down Prefactor SDK");
|
|
241
|
-
await
|
|
297
|
+
await globalCore.shutdown();
|
|
242
298
|
}
|
|
299
|
+
globalCore = null;
|
|
243
300
|
globalTracer = null;
|
|
244
301
|
globalMiddleware = null;
|
|
245
302
|
}
|
|
@@ -249,4 +306,4 @@ process.on("beforeExit", () => {
|
|
|
249
306
|
});
|
|
250
307
|
});
|
|
251
308
|
|
|
252
|
-
//# debugId=
|
|
309
|
+
//# debugId=534355E26FF7C82564756E2164756E21
|
package/dist/index.cjs.map
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts", "../src/init.ts", "../src/middleware.ts", "../src/metadata-extractor.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"// Main entry points\n\n// Convenience re-exports from core\nexport {\n type Config,\n type HttpTransportConfig,\n type Span,\n SpanStatus,\n SpanType,\n} from '@prefactor/core';\nexport { getTracer, init, shutdown } from './init.js';\nexport { extractTokenUsage } from './metadata-extractor.js';\n// Middleware\nexport { PrefactorMiddleware } from './middleware.js';\n",
|
|
6
|
-
"import {\n type Config,\n
|
|
7
|
-
"import {
|
|
5
|
+
"// Main entry points\n\n// Convenience re-exports from core\nexport {\n type Config,\n type CoreRuntime,\n type HttpTransportConfig,\n type Span,\n SpanStatus,\n SpanType,\n} from '@prefactor/core';\nexport { getTracer, init, shutdown, withSpan } from './init.js';\nexport { extractTokenUsage } from './metadata-extractor.js';\n// Middleware\nexport { PrefactorMiddleware } from './middleware.js';\n",
|
|
6
|
+
"import {\n type Config,\n type CoreRuntime,\n configureLogging,\n createConfig,\n createCore,\n getLogger,\n SpanContext,\n type Tracer,\n} from '@prefactor/core';\nimport { type AgentMiddleware, createMiddleware } from 'langchain';\nimport { PrefactorMiddleware } from './middleware.js';\n\nconst logger = getLogger('init');\n\nconst DEFAULT_LANGCHAIN_AGENT_SCHEMA = {\n external_identifier: 'prefactor',\n span_schemas: {\n agent: { type: 'object', additionalProperties: true },\n llm: { type: 'object', additionalProperties: true },\n tool: { type: 'object', additionalProperties: true },\n chain: { type: 'object', additionalProperties: true },\n },\n} as const;\n\nlet globalCore: CoreRuntime | null = null;\nlet globalTracer: Tracer | null = null;\nlet globalMiddleware: AgentMiddleware | null = null;\n\nexport type ManualSpanOptions = {\n name: string;\n spanType: string;\n inputs: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n};\n\n/**\n * Initialize the Prefactor SDK and return middleware for LangChain.js\n *\n * This is the main entry point for the SDK. Call this function to create a middleware\n * instance that you can pass to your LangChain.js agents.\n *\n * @param config - Optional configuration object\n * @returns PrefactorMiddleware instance to use with LangChain.js agents\n *\n * @example\n * ```typescript\n * import { init } from '@prefactor/langchain';\n * import { createAgent } from 'langchain';\n *\n * // Initialize with HTTP transport\n * const middleware = init({\n * transportType: 'http',\n * httpConfig: {\n * apiUrl: 'https://api.prefactor.ai',\n * apiToken: process.env.PREFACTOR_API_TOKEN!,\n * agentIdentifier: 'my-langchain-agent',\n * },\n * });\n *\n * // Or configure HTTP transport\n * const middleware = init({\n * transportType: 'http',\n * httpConfig: {\n * apiUrl: 'https://api.prefactor.ai',\n * apiToken: process.env.PREFACTOR_API_TOKEN!,\n * agentIdentifier: 'my-langchain-agent', // Required\n * agentId: 'legacy-agent-id', // Optional legacy identifier\n * }\n * });\n *\n * const agent = createAgent({\n * model: 'claude-sonnet-4-5-20250929',\n * tools: [myTool],\n * middleware: [middleware],\n * });\n * ```\n */\nexport function init(config?: Partial<Config>): AgentMiddleware {\n configureLogging();\n\n let configWithHttp = config;\n const transportType = config?.transportType ?? process.env.PREFACTOR_TRANSPORT ?? 'http';\n\n if (transportType === 'http' && !config?.httpConfig) {\n const apiUrl = process.env.PREFACTOR_API_URL;\n const apiToken = process.env.PREFACTOR_API_TOKEN;\n\n if (!apiUrl || !apiToken) {\n throw new Error(\n 'HTTP transport requires PREFACTOR_API_URL and PREFACTOR_API_TOKEN environment variables, ' +\n 'or httpConfig to be provided in configuration'\n );\n }\n\n configWithHttp = {\n ...config,\n transportType: 'http',\n httpConfig: {\n apiUrl,\n apiToken,\n agentId: process.env.PREFACTOR_AGENT_ID,\n agentName: process.env.PREFACTOR_AGENT_NAME,\n agentIdentifier: process.env.PREFACTOR_AGENT_IDENTIFIER || '1.0.0',\n agentSchema: DEFAULT_LANGCHAIN_AGENT_SCHEMA,\n },\n };\n } else if (transportType === 'http' && config?.httpConfig && !config.httpConfig.agentSchema) {\n configWithHttp = {\n ...config,\n httpConfig: {\n ...config.httpConfig,\n agentSchema: DEFAULT_LANGCHAIN_AGENT_SCHEMA,\n },\n };\n }\n\n const finalConfig = createConfig(configWithHttp);\n\n if (globalMiddleware !== null) {\n return globalMiddleware;\n }\n\n const core = createCore(finalConfig);\n globalCore = core;\n globalTracer = core.tracer;\n\n const httpConfig = finalConfig.httpConfig;\n if (httpConfig?.agentSchema) {\n core.agentManager.registerSchema(httpConfig.agentSchema);\n }\n\n const agentInfo = finalConfig.httpConfig\n ? {\n agentId: finalConfig.httpConfig.agentId,\n agentIdentifier: finalConfig.httpConfig.agentIdentifier,\n agentName: finalConfig.httpConfig.agentName,\n agentDescription: finalConfig.httpConfig.agentDescription,\n }\n : undefined;\n\n const prefactorMiddleware = new PrefactorMiddleware(core.tracer, core.agentManager, agentInfo);\n\n const middleware = createMiddleware({\n name: 'prefactor',\n // biome-ignore lint/suspicious/noExplicitAny: LangChain middleware hooks use dynamic types\n wrapModelCall: async (request: any, handler: any) => {\n return prefactorMiddleware.wrapModelCall(request, handler);\n },\n // biome-ignore lint/suspicious/noExplicitAny: LangChain middleware hooks use dynamic types\n wrapToolCall: async (request: any, handler: any) => {\n return prefactorMiddleware.wrapToolCall(request, handler);\n },\n // biome-ignore lint/suspicious/noExplicitAny: LangChain middleware hooks use dynamic types\n beforeAgent: async (state: any) => {\n await prefactorMiddleware.beforeAgent(state);\n },\n // biome-ignore lint/suspicious/noExplicitAny: LangChain middleware hooks use dynamic types\n afterAgent: async (state: any) => {\n await prefactorMiddleware.afterAgent(state);\n },\n });\n\n globalMiddleware = middleware;\n return middleware;\n}\n\n/**\n * Get the current tracer instance.\n *\n * If no tracer has been created yet, this will call init() with default configuration.\n *\n * @returns Tracer instance\n *\n * @example\n * ```typescript\n * import { getTracer } from '@prefactor/langchain';\n *\n * const tracer = getTracer();\n * const span = tracer.startSpan({\n * name: 'custom-operation',\n * spanType: SpanType.TOOL,\n * inputs: { data: 'example' }\n * });\n * ```\n */\nexport function getTracer(): Tracer {\n if (!globalTracer) {\n init();\n }\n // Safe because init() always sets globalTracer\n return globalTracer as Tracer;\n}\n\nexport async function withSpan<T>(\n options: ManualSpanOptions,\n fn: () => Promise<T> | T\n): Promise<T> {\n const tracer = getTracer();\n const span = tracer.startSpan(options);\n\n try {\n const result = await SpanContext.runAsync(span, async () => await fn());\n tracer.endSpan(span);\n return result;\n } catch (error) {\n const normalizedError = error instanceof Error ? error : new Error(String(error));\n tracer.endSpan(span, { error: normalizedError });\n throw error;\n }\n}\n\n/**\n * Shutdown the SDK and flush any pending spans.\n *\n * Call this before your application exits to ensure all spans are sent to the transport.\n * This is especially important for HTTP transport which has a queue of pending requests.\n *\n * @returns Promise that resolves when shutdown is complete\n *\n * @example\n * ```typescript\n * import { shutdown } from '@prefactor/langchain';\n *\n * process.on('SIGTERM', async () => {\n * await shutdown();\n * process.exit(0);\n * });\n * ```\n */\nexport async function shutdown(): Promise<void> {\n if (globalCore) {\n logger.info('Shutting down Prefactor SDK');\n await globalCore.shutdown();\n }\n globalCore = null;\n globalTracer = null;\n globalMiddleware = null;\n}\n\n// Automatic shutdown on process exit\nprocess.on('beforeExit', () => {\n shutdown().catch((error) => {\n console.error('Error during Prefactor SDK shutdown:', error);\n });\n});\n",
|
|
7
|
+
"import {\n type AgentInstanceManager,\n SpanContext,\n SpanType,\n serializeValue,\n type Tracer,\n} from '@prefactor/core';\nimport { extractTokenUsage } from './metadata-extractor.js';\n\n/**\n * Prefactor middleware for LangChain.js agents.\n *\n * This middleware automatically traces LLM calls, tool executions, and agent workflows.\n * It integrates with LangChain.js middleware API to provide transparent instrumentation.\n *\n * Features:\n * - Automatic parent-child span relationships via context propagation\n * - Token usage extraction for LLM calls\n * - Error tracking and debugging\n * - Zero-overhead instrumentation (graceful failure)\n *\n * @example\n * ```typescript\n * import { init } from '@prefactor/langchain';\n * import { createReactAgent } from '@langchain/langgraph/prebuilt';\n *\n * const middleware = init();\n * const agent = createReactAgent({\n * llm: model,\n * tools: [myTool],\n * middleware: [middleware],\n * });\n * ```\n */\nexport class PrefactorMiddleware {\n private rootSpan: ReturnType<Tracer['startSpan']> | null = null;\n\n constructor(\n private tracer: Tracer,\n private agentManager: AgentInstanceManager,\n private agentInfo?: Parameters<AgentInstanceManager['startInstance']>[0]\n ) {}\n\n /**\n * Called before agent execution starts\n *\n * @param state - Agent state containing messages\n */\n // biome-ignore lint/suspicious/noExplicitAny: LangChain state can be any structure\n async beforeAgent(state: any): Promise<void> {\n const messages = state?.messages ?? [];\n\n this.agentManager.startInstance(this.agentInfo);\n\n const span = this.tracer.startSpan({\n name: 'langchain:agent',\n spanType: SpanType.AGENT,\n inputs: { messages: serializeValue(messages.slice(-3)) },\n });\n\n this.rootSpan = span;\n SpanContext.enter(span);\n }\n\n /**\n * Called after agent execution completes\n *\n * @param state - Agent state containing messages\n */\n // biome-ignore lint/suspicious/noExplicitAny: LangChain state can be any structure\n async afterAgent(state: any): Promise<void> {\n if (!this.rootSpan) {\n return;\n }\n\n const messages = state?.messages ?? [];\n this.tracer.endSpan(this.rootSpan, {\n outputs: { messages: serializeValue(messages.slice(-3)) },\n });\n\n this.agentManager.finishInstance();\n SpanContext.exit();\n this.rootSpan = null;\n }\n\n /**\n * Wrap a model call to trace LLM invocations\n *\n * @param request - Model invocation request\n * @param handler - The actual model call function\n * @returns Promise resolving to the model response\n */\n // biome-ignore lint/suspicious/noExplicitAny: LangChain request/handler types are dynamic\n async wrapModelCall<T>(request: any, handler: (req: any) => Promise<T>): Promise<T> {\n const span = this.tracer.startSpan({\n name: this.extractModelName(request),\n spanType: SpanType.LLM,\n inputs: this.extractModelInputs(request),\n });\n\n try {\n // CRITICAL: Wrap handler in context so child operations see this span\n const response = await SpanContext.runAsync(span, async () => {\n return handler(request);\n });\n\n const outputs = this.extractModelOutputs(response);\n const tokenUsage = extractTokenUsage(response);\n\n this.tracer.endSpan(span, { outputs, tokenUsage: tokenUsage ?? undefined });\n return response;\n } catch (error) {\n this.tracer.endSpan(span, { error: error as Error });\n throw error;\n }\n }\n\n /**\n * Wrap a tool call to trace tool executions\n *\n * @param request - Tool invocation request\n * @param handler - The actual tool call function\n * @returns Promise resolving to the tool response\n */\n // biome-ignore lint/suspicious/noExplicitAny: LangChain request/handler types are dynamic\n async wrapToolCall<T>(request: any, handler: (req: any) => Promise<T>): Promise<T> {\n const span = this.tracer.startSpan({\n name: this.extractToolName(request),\n spanType: SpanType.TOOL,\n inputs: this.extractToolInputs(request),\n });\n\n try {\n // CRITICAL: Wrap handler in context so child operations see this span\n const response = await SpanContext.runAsync(span, async () => {\n return handler(request);\n });\n\n this.tracer.endSpan(span, {\n outputs: this.extractToolOutputs(response),\n });\n return response;\n } catch (error) {\n this.tracer.endSpan(span, { error: error as Error });\n throw error;\n }\n }\n\n /**\n * Extract model name from request\n */\n // biome-ignore lint/suspicious/noExplicitAny: LangChain request structure is dynamic\n private extractModelName(request: any): string {\n const candidate = request?.model ?? request?.modelName;\n\n if (typeof candidate === 'string') {\n return candidate;\n }\n\n if (candidate && typeof candidate === 'object') {\n const modelObject = candidate as Record<string, unknown>;\n if (\n Array.isArray(modelObject.id) &&\n modelObject.id.every((item) => typeof item === 'string')\n ) {\n return (modelObject.id as string[]).join('.');\n }\n\n if (typeof modelObject.modelName === 'string') {\n return modelObject.modelName;\n }\n\n if (typeof modelObject.name === 'string') {\n return modelObject.name;\n }\n }\n\n return 'unknown';\n }\n\n /**\n * Extract model inputs from request\n */\n // biome-ignore lint/suspicious/noExplicitAny: LangChain request structure is dynamic\n private extractModelInputs(request: any): Record<string, unknown> {\n const messages = request?.messages ?? [];\n return { messages: serializeValue(messages.slice(-3)) };\n }\n\n /**\n * Extract model outputs from response\n */\n // biome-ignore lint/suspicious/noExplicitAny: LangChain response structure is dynamic\n private extractModelOutputs(response: any): Record<string, unknown> {\n const content = response?.content ?? response?.text ?? '';\n return { content: serializeValue(content) };\n }\n\n /**\n * Extract tool name from request\n */\n // biome-ignore lint/suspicious/noExplicitAny: LangChain request structure is dynamic\n private extractToolName(request: any): string {\n return request?.name ?? request?.tool ?? 'unknown';\n }\n\n /**\n * Extract tool inputs from request\n */\n // biome-ignore lint/suspicious/noExplicitAny: LangChain request structure is dynamic\n private extractToolInputs(request: any): Record<string, unknown> {\n return { input: request?.input ?? request?.args ?? {} };\n }\n\n /**\n * Extract tool outputs from response\n */\n // biome-ignore lint/suspicious/noExplicitAny: LangChain response structure is dynamic\n private extractToolOutputs(response: any): Record<string, unknown> {\n return { output: response?.output ?? response };\n }\n}\n",
|
|
8
8
|
"import type { TokenUsage } from '@prefactor/core';\n\n/**\n * Extract token usage information from LLM responses.\n *\n * Handles multiple response formats from different LLM providers and LangChain versions.\n *\n * @param response - The LLM response object\n * @returns TokenUsage object or null if no usage data found\n *\n * @example\n * ```typescript\n * const response = await model.invoke(messages);\n * const tokenUsage = extractTokenUsage(response);\n * if (tokenUsage) {\n * console.log(`Tokens used: ${tokenUsage.totalTokens}`);\n * }\n * ```\n */\n// biome-ignore lint/suspicious/noExplicitAny: LLM response structure varies by provider\nexport function extractTokenUsage(response: any): TokenUsage | null {\n try {\n // Try token_usage field (common format)\n const tokenUsage = response?.token_usage ?? response?.usage;\n if (tokenUsage) {\n return {\n promptTokens: tokenUsage.prompt_tokens ?? 0,\n completionTokens: tokenUsage.completion_tokens ?? 0,\n totalTokens: tokenUsage.total_tokens ?? 0,\n };\n }\n\n // Try usage_metadata field (LangChain format)\n const usageMetadata = response?.usage_metadata;\n if (usageMetadata) {\n return {\n promptTokens: usageMetadata.input_tokens ?? 0,\n completionTokens: usageMetadata.output_tokens ?? 0,\n totalTokens: usageMetadata.total_tokens ?? 0,\n };\n }\n\n // Try response_metadata.token_usage (nested format)\n const responseMetadata = response?.response_metadata;\n if (responseMetadata?.token_usage) {\n return {\n promptTokens: responseMetadata.token_usage.prompt_tokens ?? 0,\n completionTokens: responseMetadata.token_usage.completion_tokens ?? 0,\n totalTokens: responseMetadata.token_usage.total_tokens ?? 0,\n };\n }\n\n return null;\n } catch {\n return null;\n }\n}\n"
|
|
9
9
|
],
|
|
10
|
-
"mappings": "
|
|
11
|
-
"debugId": "
|
|
10
|
+
"mappings": "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",
|
|
11
|
+
"debugId": "534355E26FF7C82564756E2164756E21",
|
|
12
12
|
"names": []
|
|
13
13
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { type Config, type HttpTransportConfig, type Span, SpanStatus, SpanType, } from '@prefactor/core';
|
|
2
|
-
export { getTracer, init, shutdown } from './init.js';
|
|
1
|
+
export { type Config, type CoreRuntime, type HttpTransportConfig, type Span, SpanStatus, SpanType, } from '@prefactor/core';
|
|
2
|
+
export { getTracer, init, shutdown, withSpan } from './init.js';
|
|
3
3
|
export { extractTokenUsage } from './metadata-extractor.js';
|
|
4
4
|
export { PrefactorMiddleware } from './middleware.js';
|
|
5
5
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,MAAM,EACX,KAAK,mBAAmB,EACxB,KAAK,IAAI,EACT,UAAU,EACV,QAAQ,GACT,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,MAAM,EACX,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,IAAI,EACT,UAAU,EACV,QAAQ,GACT,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -8,17 +8,18 @@ import {
|
|
|
8
8
|
import {
|
|
9
9
|
configureLogging,
|
|
10
10
|
createConfig,
|
|
11
|
+
createCore,
|
|
11
12
|
getLogger,
|
|
12
|
-
|
|
13
|
-
HttpTransportConfigSchema,
|
|
14
|
-
StdioTransport,
|
|
15
|
-
Tracer
|
|
13
|
+
SpanContext as SpanContext2
|
|
16
14
|
} from "@prefactor/core";
|
|
17
|
-
import { extractPartition } from "@prefactor/pfid";
|
|
18
15
|
import { createMiddleware } from "langchain";
|
|
19
16
|
|
|
20
17
|
// packages/langchain/src/middleware.ts
|
|
21
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
SpanContext,
|
|
20
|
+
SpanType,
|
|
21
|
+
serializeValue
|
|
22
|
+
} from "@prefactor/core";
|
|
22
23
|
|
|
23
24
|
// packages/langchain/src/metadata-extractor.ts
|
|
24
25
|
function extractTokenUsage(response) {
|
|
@@ -56,22 +57,24 @@ function extractTokenUsage(response) {
|
|
|
56
57
|
// packages/langchain/src/middleware.ts
|
|
57
58
|
class PrefactorMiddleware {
|
|
58
59
|
tracer;
|
|
60
|
+
agentManager;
|
|
61
|
+
agentInfo;
|
|
59
62
|
rootSpan = null;
|
|
60
|
-
constructor(tracer) {
|
|
63
|
+
constructor(tracer, agentManager, agentInfo) {
|
|
61
64
|
this.tracer = tracer;
|
|
65
|
+
this.agentManager = agentManager;
|
|
66
|
+
this.agentInfo = agentInfo;
|
|
62
67
|
}
|
|
63
68
|
async beforeAgent(state) {
|
|
64
|
-
const parentSpan = SpanContext.getCurrent();
|
|
65
69
|
const messages = state?.messages ?? [];
|
|
66
|
-
this.
|
|
70
|
+
this.agentManager.startInstance(this.agentInfo);
|
|
67
71
|
const span = this.tracer.startSpan({
|
|
68
|
-
name: "agent",
|
|
72
|
+
name: "langchain:agent",
|
|
69
73
|
spanType: SpanType.AGENT,
|
|
70
|
-
inputs: { messages: messages.slice(-3)
|
|
71
|
-
parentSpanId: parentSpan?.spanId,
|
|
72
|
-
traceId: parentSpan?.traceId
|
|
74
|
+
inputs: { messages: serializeValue(messages.slice(-3)) }
|
|
73
75
|
});
|
|
74
76
|
this.rootSpan = span;
|
|
77
|
+
SpanContext.enter(span);
|
|
75
78
|
}
|
|
76
79
|
async afterAgent(state) {
|
|
77
80
|
if (!this.rootSpan) {
|
|
@@ -79,20 +82,17 @@ class PrefactorMiddleware {
|
|
|
79
82
|
}
|
|
80
83
|
const messages = state?.messages ?? [];
|
|
81
84
|
this.tracer.endSpan(this.rootSpan, {
|
|
82
|
-
outputs: { messages: messages.slice(-3)
|
|
85
|
+
outputs: { messages: serializeValue(messages.slice(-3)) }
|
|
83
86
|
});
|
|
84
|
-
this.
|
|
85
|
-
SpanContext.
|
|
87
|
+
this.agentManager.finishInstance();
|
|
88
|
+
SpanContext.exit();
|
|
86
89
|
this.rootSpan = null;
|
|
87
90
|
}
|
|
88
91
|
async wrapModelCall(request, handler) {
|
|
89
|
-
const parentSpan = SpanContext.getCurrent();
|
|
90
92
|
const span = this.tracer.startSpan({
|
|
91
93
|
name: this.extractModelName(request),
|
|
92
94
|
spanType: SpanType.LLM,
|
|
93
|
-
inputs: this.extractModelInputs(request)
|
|
94
|
-
parentSpanId: parentSpan?.spanId,
|
|
95
|
-
traceId: parentSpan?.traceId
|
|
95
|
+
inputs: this.extractModelInputs(request)
|
|
96
96
|
});
|
|
97
97
|
try {
|
|
98
98
|
const response = await SpanContext.runAsync(span, async () => {
|
|
@@ -108,13 +108,10 @@ class PrefactorMiddleware {
|
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
110
|
async wrapToolCall(request, handler) {
|
|
111
|
-
const parentSpan = SpanContext.getCurrent();
|
|
112
111
|
const span = this.tracer.startSpan({
|
|
113
112
|
name: this.extractToolName(request),
|
|
114
113
|
spanType: SpanType.TOOL,
|
|
115
|
-
inputs: this.extractToolInputs(request)
|
|
116
|
-
parentSpanId: parentSpan?.spanId,
|
|
117
|
-
traceId: parentSpan?.traceId
|
|
114
|
+
inputs: this.extractToolInputs(request)
|
|
118
115
|
});
|
|
119
116
|
try {
|
|
120
117
|
const response = await SpanContext.runAsync(span, async () => {
|
|
@@ -130,15 +127,31 @@ class PrefactorMiddleware {
|
|
|
130
127
|
}
|
|
131
128
|
}
|
|
132
129
|
extractModelName(request) {
|
|
133
|
-
|
|
130
|
+
const candidate = request?.model ?? request?.modelName;
|
|
131
|
+
if (typeof candidate === "string") {
|
|
132
|
+
return candidate;
|
|
133
|
+
}
|
|
134
|
+
if (candidate && typeof candidate === "object") {
|
|
135
|
+
const modelObject = candidate;
|
|
136
|
+
if (Array.isArray(modelObject.id) && modelObject.id.every((item) => typeof item === "string")) {
|
|
137
|
+
return modelObject.id.join(".");
|
|
138
|
+
}
|
|
139
|
+
if (typeof modelObject.modelName === "string") {
|
|
140
|
+
return modelObject.modelName;
|
|
141
|
+
}
|
|
142
|
+
if (typeof modelObject.name === "string") {
|
|
143
|
+
return modelObject.name;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return "unknown";
|
|
134
147
|
}
|
|
135
148
|
extractModelInputs(request) {
|
|
136
149
|
const messages = request?.messages ?? [];
|
|
137
|
-
return { messages: messages.slice(-3)
|
|
150
|
+
return { messages: serializeValue(messages.slice(-3)) };
|
|
138
151
|
}
|
|
139
152
|
extractModelOutputs(response) {
|
|
140
153
|
const content = response?.content ?? response?.text ?? "";
|
|
141
|
-
return { content:
|
|
154
|
+
return { content: serializeValue(content) };
|
|
142
155
|
}
|
|
143
156
|
extractToolName(request) {
|
|
144
157
|
return request?.name ?? request?.tool ?? "unknown";
|
|
@@ -153,36 +166,67 @@ class PrefactorMiddleware {
|
|
|
153
166
|
|
|
154
167
|
// packages/langchain/src/init.ts
|
|
155
168
|
var logger = getLogger("init");
|
|
169
|
+
var DEFAULT_LANGCHAIN_AGENT_SCHEMA = {
|
|
170
|
+
external_identifier: "prefactor",
|
|
171
|
+
span_schemas: {
|
|
172
|
+
agent: { type: "object", additionalProperties: true },
|
|
173
|
+
llm: { type: "object", additionalProperties: true },
|
|
174
|
+
tool: { type: "object", additionalProperties: true },
|
|
175
|
+
chain: { type: "object", additionalProperties: true }
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
var globalCore = null;
|
|
156
179
|
var globalTracer = null;
|
|
157
180
|
var globalMiddleware = null;
|
|
158
181
|
function init(config) {
|
|
159
182
|
configureLogging();
|
|
160
|
-
|
|
161
|
-
|
|
183
|
+
let configWithHttp = config;
|
|
184
|
+
const transportType = config?.transportType ?? process.env.PREFACTOR_TRANSPORT ?? "http";
|
|
185
|
+
if (transportType === "http" && !config?.httpConfig) {
|
|
186
|
+
const apiUrl = process.env.PREFACTOR_API_URL;
|
|
187
|
+
const apiToken = process.env.PREFACTOR_API_TOKEN;
|
|
188
|
+
if (!apiUrl || !apiToken) {
|
|
189
|
+
throw new Error("HTTP transport requires PREFACTOR_API_URL and PREFACTOR_API_TOKEN environment variables, " + "or httpConfig to be provided in configuration");
|
|
190
|
+
}
|
|
191
|
+
configWithHttp = {
|
|
192
|
+
...config,
|
|
193
|
+
transportType: "http",
|
|
194
|
+
httpConfig: {
|
|
195
|
+
apiUrl,
|
|
196
|
+
apiToken,
|
|
197
|
+
agentId: process.env.PREFACTOR_AGENT_ID,
|
|
198
|
+
agentName: process.env.PREFACTOR_AGENT_NAME,
|
|
199
|
+
agentIdentifier: process.env.PREFACTOR_AGENT_IDENTIFIER || "1.0.0",
|
|
200
|
+
agentSchema: DEFAULT_LANGCHAIN_AGENT_SCHEMA
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
} else if (transportType === "http" && config?.httpConfig && !config.httpConfig.agentSchema) {
|
|
204
|
+
configWithHttp = {
|
|
205
|
+
...config,
|
|
206
|
+
httpConfig: {
|
|
207
|
+
...config.httpConfig,
|
|
208
|
+
agentSchema: DEFAULT_LANGCHAIN_AGENT_SCHEMA
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
const finalConfig = createConfig(configWithHttp);
|
|
162
213
|
if (globalMiddleware !== null) {
|
|
163
214
|
return globalMiddleware;
|
|
164
215
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
}
|
|
172
|
-
const httpConfig = HttpTransportConfigSchema.parse(finalConfig.httpConfig);
|
|
173
|
-
transport = new HttpTransport(httpConfig);
|
|
174
|
-
}
|
|
175
|
-
let partition;
|
|
176
|
-
if (finalConfig.httpConfig?.agentId) {
|
|
177
|
-
try {
|
|
178
|
-
partition = extractPartition(finalConfig.httpConfig.agentId);
|
|
179
|
-
logger.debug("Extracted partition from agent_id", { partition });
|
|
180
|
-
} catch (error) {
|
|
181
|
-
logger.warn("Failed to extract partition from agent_id, using random partition", { error });
|
|
182
|
-
}
|
|
216
|
+
const core = createCore(finalConfig);
|
|
217
|
+
globalCore = core;
|
|
218
|
+
globalTracer = core.tracer;
|
|
219
|
+
const httpConfig = finalConfig.httpConfig;
|
|
220
|
+
if (httpConfig?.agentSchema) {
|
|
221
|
+
core.agentManager.registerSchema(httpConfig.agentSchema);
|
|
183
222
|
}
|
|
184
|
-
|
|
185
|
-
|
|
223
|
+
const agentInfo = finalConfig.httpConfig ? {
|
|
224
|
+
agentId: finalConfig.httpConfig.agentId,
|
|
225
|
+
agentIdentifier: finalConfig.httpConfig.agentIdentifier,
|
|
226
|
+
agentName: finalConfig.httpConfig.agentName,
|
|
227
|
+
agentDescription: finalConfig.httpConfig.agentDescription
|
|
228
|
+
} : undefined;
|
|
229
|
+
const prefactorMiddleware = new PrefactorMiddleware(core.tracer, core.agentManager, agentInfo);
|
|
186
230
|
const middleware = createMiddleware({
|
|
187
231
|
name: "prefactor",
|
|
188
232
|
wrapModelCall: async (request, handler) => {
|
|
@@ -207,11 +251,25 @@ function getTracer() {
|
|
|
207
251
|
}
|
|
208
252
|
return globalTracer;
|
|
209
253
|
}
|
|
254
|
+
async function withSpan(options, fn) {
|
|
255
|
+
const tracer = getTracer();
|
|
256
|
+
const span = tracer.startSpan(options);
|
|
257
|
+
try {
|
|
258
|
+
const result = await SpanContext2.runAsync(span, async () => await fn());
|
|
259
|
+
tracer.endSpan(span);
|
|
260
|
+
return result;
|
|
261
|
+
} catch (error) {
|
|
262
|
+
const normalizedError = error instanceof Error ? error : new Error(String(error));
|
|
263
|
+
tracer.endSpan(span, { error: normalizedError });
|
|
264
|
+
throw error;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
210
267
|
async function shutdown() {
|
|
211
|
-
if (
|
|
268
|
+
if (globalCore) {
|
|
212
269
|
logger.info("Shutting down Prefactor SDK");
|
|
213
|
-
await
|
|
270
|
+
await globalCore.shutdown();
|
|
214
271
|
}
|
|
272
|
+
globalCore = null;
|
|
215
273
|
globalTracer = null;
|
|
216
274
|
globalMiddleware = null;
|
|
217
275
|
}
|
|
@@ -221,6 +279,7 @@ process.on("beforeExit", () => {
|
|
|
221
279
|
});
|
|
222
280
|
});
|
|
223
281
|
export {
|
|
282
|
+
withSpan,
|
|
224
283
|
shutdown,
|
|
225
284
|
init,
|
|
226
285
|
getTracer,
|
|
@@ -230,4 +289,4 @@ export {
|
|
|
230
289
|
PrefactorMiddleware
|
|
231
290
|
};
|
|
232
291
|
|
|
233
|
-
//# debugId=
|
|
292
|
+
//# debugId=EBAE04F79C70EA8764756E2164756E21
|
package/dist/index.js.map
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/index.ts", "../src/init.ts", "../src/middleware.ts", "../src/metadata-extractor.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"// Main entry points\n\n// Convenience re-exports from core\nexport {\n type Config,\n type HttpTransportConfig,\n type Span,\n SpanStatus,\n SpanType,\n} from '@prefactor/core';\nexport { getTracer, init, shutdown } from './init.js';\nexport { extractTokenUsage } from './metadata-extractor.js';\n// Middleware\nexport { PrefactorMiddleware } from './middleware.js';\n",
|
|
6
|
-
"import {\n type Config,\n
|
|
7
|
-
"import {
|
|
5
|
+
"// Main entry points\n\n// Convenience re-exports from core\nexport {\n type Config,\n type CoreRuntime,\n type HttpTransportConfig,\n type Span,\n SpanStatus,\n SpanType,\n} from '@prefactor/core';\nexport { getTracer, init, shutdown, withSpan } from './init.js';\nexport { extractTokenUsage } from './metadata-extractor.js';\n// Middleware\nexport { PrefactorMiddleware } from './middleware.js';\n",
|
|
6
|
+
"import {\n type Config,\n type CoreRuntime,\n configureLogging,\n createConfig,\n createCore,\n getLogger,\n SpanContext,\n type Tracer,\n} from '@prefactor/core';\nimport { type AgentMiddleware, createMiddleware } from 'langchain';\nimport { PrefactorMiddleware } from './middleware.js';\n\nconst logger = getLogger('init');\n\nconst DEFAULT_LANGCHAIN_AGENT_SCHEMA = {\n external_identifier: 'prefactor',\n span_schemas: {\n agent: { type: 'object', additionalProperties: true },\n llm: { type: 'object', additionalProperties: true },\n tool: { type: 'object', additionalProperties: true },\n chain: { type: 'object', additionalProperties: true },\n },\n} as const;\n\nlet globalCore: CoreRuntime | null = null;\nlet globalTracer: Tracer | null = null;\nlet globalMiddleware: AgentMiddleware | null = null;\n\nexport type ManualSpanOptions = {\n name: string;\n spanType: string;\n inputs: Record<string, unknown>;\n metadata?: Record<string, unknown>;\n};\n\n/**\n * Initialize the Prefactor SDK and return middleware for LangChain.js\n *\n * This is the main entry point for the SDK. Call this function to create a middleware\n * instance that you can pass to your LangChain.js agents.\n *\n * @param config - Optional configuration object\n * @returns PrefactorMiddleware instance to use with LangChain.js agents\n *\n * @example\n * ```typescript\n * import { init } from '@prefactor/langchain';\n * import { createAgent } from 'langchain';\n *\n * // Initialize with HTTP transport\n * const middleware = init({\n * transportType: 'http',\n * httpConfig: {\n * apiUrl: 'https://api.prefactor.ai',\n * apiToken: process.env.PREFACTOR_API_TOKEN!,\n * agentIdentifier: 'my-langchain-agent',\n * },\n * });\n *\n * // Or configure HTTP transport\n * const middleware = init({\n * transportType: 'http',\n * httpConfig: {\n * apiUrl: 'https://api.prefactor.ai',\n * apiToken: process.env.PREFACTOR_API_TOKEN!,\n * agentIdentifier: 'my-langchain-agent', // Required\n * agentId: 'legacy-agent-id', // Optional legacy identifier\n * }\n * });\n *\n * const agent = createAgent({\n * model: 'claude-sonnet-4-5-20250929',\n * tools: [myTool],\n * middleware: [middleware],\n * });\n * ```\n */\nexport function init(config?: Partial<Config>): AgentMiddleware {\n configureLogging();\n\n let configWithHttp = config;\n const transportType = config?.transportType ?? process.env.PREFACTOR_TRANSPORT ?? 'http';\n\n if (transportType === 'http' && !config?.httpConfig) {\n const apiUrl = process.env.PREFACTOR_API_URL;\n const apiToken = process.env.PREFACTOR_API_TOKEN;\n\n if (!apiUrl || !apiToken) {\n throw new Error(\n 'HTTP transport requires PREFACTOR_API_URL and PREFACTOR_API_TOKEN environment variables, ' +\n 'or httpConfig to be provided in configuration'\n );\n }\n\n configWithHttp = {\n ...config,\n transportType: 'http',\n httpConfig: {\n apiUrl,\n apiToken,\n agentId: process.env.PREFACTOR_AGENT_ID,\n agentName: process.env.PREFACTOR_AGENT_NAME,\n agentIdentifier: process.env.PREFACTOR_AGENT_IDENTIFIER || '1.0.0',\n agentSchema: DEFAULT_LANGCHAIN_AGENT_SCHEMA,\n },\n };\n } else if (transportType === 'http' && config?.httpConfig && !config.httpConfig.agentSchema) {\n configWithHttp = {\n ...config,\n httpConfig: {\n ...config.httpConfig,\n agentSchema: DEFAULT_LANGCHAIN_AGENT_SCHEMA,\n },\n };\n }\n\n const finalConfig = createConfig(configWithHttp);\n\n if (globalMiddleware !== null) {\n return globalMiddleware;\n }\n\n const core = createCore(finalConfig);\n globalCore = core;\n globalTracer = core.tracer;\n\n const httpConfig = finalConfig.httpConfig;\n if (httpConfig?.agentSchema) {\n core.agentManager.registerSchema(httpConfig.agentSchema);\n }\n\n const agentInfo = finalConfig.httpConfig\n ? {\n agentId: finalConfig.httpConfig.agentId,\n agentIdentifier: finalConfig.httpConfig.agentIdentifier,\n agentName: finalConfig.httpConfig.agentName,\n agentDescription: finalConfig.httpConfig.agentDescription,\n }\n : undefined;\n\n const prefactorMiddleware = new PrefactorMiddleware(core.tracer, core.agentManager, agentInfo);\n\n const middleware = createMiddleware({\n name: 'prefactor',\n // biome-ignore lint/suspicious/noExplicitAny: LangChain middleware hooks use dynamic types\n wrapModelCall: async (request: any, handler: any) => {\n return prefactorMiddleware.wrapModelCall(request, handler);\n },\n // biome-ignore lint/suspicious/noExplicitAny: LangChain middleware hooks use dynamic types\n wrapToolCall: async (request: any, handler: any) => {\n return prefactorMiddleware.wrapToolCall(request, handler);\n },\n // biome-ignore lint/suspicious/noExplicitAny: LangChain middleware hooks use dynamic types\n beforeAgent: async (state: any) => {\n await prefactorMiddleware.beforeAgent(state);\n },\n // biome-ignore lint/suspicious/noExplicitAny: LangChain middleware hooks use dynamic types\n afterAgent: async (state: any) => {\n await prefactorMiddleware.afterAgent(state);\n },\n });\n\n globalMiddleware = middleware;\n return middleware;\n}\n\n/**\n * Get the current tracer instance.\n *\n * If no tracer has been created yet, this will call init() with default configuration.\n *\n * @returns Tracer instance\n *\n * @example\n * ```typescript\n * import { getTracer } from '@prefactor/langchain';\n *\n * const tracer = getTracer();\n * const span = tracer.startSpan({\n * name: 'custom-operation',\n * spanType: SpanType.TOOL,\n * inputs: { data: 'example' }\n * });\n * ```\n */\nexport function getTracer(): Tracer {\n if (!globalTracer) {\n init();\n }\n // Safe because init() always sets globalTracer\n return globalTracer as Tracer;\n}\n\nexport async function withSpan<T>(\n options: ManualSpanOptions,\n fn: () => Promise<T> | T\n): Promise<T> {\n const tracer = getTracer();\n const span = tracer.startSpan(options);\n\n try {\n const result = await SpanContext.runAsync(span, async () => await fn());\n tracer.endSpan(span);\n return result;\n } catch (error) {\n const normalizedError = error instanceof Error ? error : new Error(String(error));\n tracer.endSpan(span, { error: normalizedError });\n throw error;\n }\n}\n\n/**\n * Shutdown the SDK and flush any pending spans.\n *\n * Call this before your application exits to ensure all spans are sent to the transport.\n * This is especially important for HTTP transport which has a queue of pending requests.\n *\n * @returns Promise that resolves when shutdown is complete\n *\n * @example\n * ```typescript\n * import { shutdown } from '@prefactor/langchain';\n *\n * process.on('SIGTERM', async () => {\n * await shutdown();\n * process.exit(0);\n * });\n * ```\n */\nexport async function shutdown(): Promise<void> {\n if (globalCore) {\n logger.info('Shutting down Prefactor SDK');\n await globalCore.shutdown();\n }\n globalCore = null;\n globalTracer = null;\n globalMiddleware = null;\n}\n\n// Automatic shutdown on process exit\nprocess.on('beforeExit', () => {\n shutdown().catch((error) => {\n console.error('Error during Prefactor SDK shutdown:', error);\n });\n});\n",
|
|
7
|
+
"import {\n type AgentInstanceManager,\n SpanContext,\n SpanType,\n serializeValue,\n type Tracer,\n} from '@prefactor/core';\nimport { extractTokenUsage } from './metadata-extractor.js';\n\n/**\n * Prefactor middleware for LangChain.js agents.\n *\n * This middleware automatically traces LLM calls, tool executions, and agent workflows.\n * It integrates with LangChain.js middleware API to provide transparent instrumentation.\n *\n * Features:\n * - Automatic parent-child span relationships via context propagation\n * - Token usage extraction for LLM calls\n * - Error tracking and debugging\n * - Zero-overhead instrumentation (graceful failure)\n *\n * @example\n * ```typescript\n * import { init } from '@prefactor/langchain';\n * import { createReactAgent } from '@langchain/langgraph/prebuilt';\n *\n * const middleware = init();\n * const agent = createReactAgent({\n * llm: model,\n * tools: [myTool],\n * middleware: [middleware],\n * });\n * ```\n */\nexport class PrefactorMiddleware {\n private rootSpan: ReturnType<Tracer['startSpan']> | null = null;\n\n constructor(\n private tracer: Tracer,\n private agentManager: AgentInstanceManager,\n private agentInfo?: Parameters<AgentInstanceManager['startInstance']>[0]\n ) {}\n\n /**\n * Called before agent execution starts\n *\n * @param state - Agent state containing messages\n */\n // biome-ignore lint/suspicious/noExplicitAny: LangChain state can be any structure\n async beforeAgent(state: any): Promise<void> {\n const messages = state?.messages ?? [];\n\n this.agentManager.startInstance(this.agentInfo);\n\n const span = this.tracer.startSpan({\n name: 'langchain:agent',\n spanType: SpanType.AGENT,\n inputs: { messages: serializeValue(messages.slice(-3)) },\n });\n\n this.rootSpan = span;\n SpanContext.enter(span);\n }\n\n /**\n * Called after agent execution completes\n *\n * @param state - Agent state containing messages\n */\n // biome-ignore lint/suspicious/noExplicitAny: LangChain state can be any structure\n async afterAgent(state: any): Promise<void> {\n if (!this.rootSpan) {\n return;\n }\n\n const messages = state?.messages ?? [];\n this.tracer.endSpan(this.rootSpan, {\n outputs: { messages: serializeValue(messages.slice(-3)) },\n });\n\n this.agentManager.finishInstance();\n SpanContext.exit();\n this.rootSpan = null;\n }\n\n /**\n * Wrap a model call to trace LLM invocations\n *\n * @param request - Model invocation request\n * @param handler - The actual model call function\n * @returns Promise resolving to the model response\n */\n // biome-ignore lint/suspicious/noExplicitAny: LangChain request/handler types are dynamic\n async wrapModelCall<T>(request: any, handler: (req: any) => Promise<T>): Promise<T> {\n const span = this.tracer.startSpan({\n name: this.extractModelName(request),\n spanType: SpanType.LLM,\n inputs: this.extractModelInputs(request),\n });\n\n try {\n // CRITICAL: Wrap handler in context so child operations see this span\n const response = await SpanContext.runAsync(span, async () => {\n return handler(request);\n });\n\n const outputs = this.extractModelOutputs(response);\n const tokenUsage = extractTokenUsage(response);\n\n this.tracer.endSpan(span, { outputs, tokenUsage: tokenUsage ?? undefined });\n return response;\n } catch (error) {\n this.tracer.endSpan(span, { error: error as Error });\n throw error;\n }\n }\n\n /**\n * Wrap a tool call to trace tool executions\n *\n * @param request - Tool invocation request\n * @param handler - The actual tool call function\n * @returns Promise resolving to the tool response\n */\n // biome-ignore lint/suspicious/noExplicitAny: LangChain request/handler types are dynamic\n async wrapToolCall<T>(request: any, handler: (req: any) => Promise<T>): Promise<T> {\n const span = this.tracer.startSpan({\n name: this.extractToolName(request),\n spanType: SpanType.TOOL,\n inputs: this.extractToolInputs(request),\n });\n\n try {\n // CRITICAL: Wrap handler in context so child operations see this span\n const response = await SpanContext.runAsync(span, async () => {\n return handler(request);\n });\n\n this.tracer.endSpan(span, {\n outputs: this.extractToolOutputs(response),\n });\n return response;\n } catch (error) {\n this.tracer.endSpan(span, { error: error as Error });\n throw error;\n }\n }\n\n /**\n * Extract model name from request\n */\n // biome-ignore lint/suspicious/noExplicitAny: LangChain request structure is dynamic\n private extractModelName(request: any): string {\n const candidate = request?.model ?? request?.modelName;\n\n if (typeof candidate === 'string') {\n return candidate;\n }\n\n if (candidate && typeof candidate === 'object') {\n const modelObject = candidate as Record<string, unknown>;\n if (\n Array.isArray(modelObject.id) &&\n modelObject.id.every((item) => typeof item === 'string')\n ) {\n return (modelObject.id as string[]).join('.');\n }\n\n if (typeof modelObject.modelName === 'string') {\n return modelObject.modelName;\n }\n\n if (typeof modelObject.name === 'string') {\n return modelObject.name;\n }\n }\n\n return 'unknown';\n }\n\n /**\n * Extract model inputs from request\n */\n // biome-ignore lint/suspicious/noExplicitAny: LangChain request structure is dynamic\n private extractModelInputs(request: any): Record<string, unknown> {\n const messages = request?.messages ?? [];\n return { messages: serializeValue(messages.slice(-3)) };\n }\n\n /**\n * Extract model outputs from response\n */\n // biome-ignore lint/suspicious/noExplicitAny: LangChain response structure is dynamic\n private extractModelOutputs(response: any): Record<string, unknown> {\n const content = response?.content ?? response?.text ?? '';\n return { content: serializeValue(content) };\n }\n\n /**\n * Extract tool name from request\n */\n // biome-ignore lint/suspicious/noExplicitAny: LangChain request structure is dynamic\n private extractToolName(request: any): string {\n return request?.name ?? request?.tool ?? 'unknown';\n }\n\n /**\n * Extract tool inputs from request\n */\n // biome-ignore lint/suspicious/noExplicitAny: LangChain request structure is dynamic\n private extractToolInputs(request: any): Record<string, unknown> {\n return { input: request?.input ?? request?.args ?? {} };\n }\n\n /**\n * Extract tool outputs from response\n */\n // biome-ignore lint/suspicious/noExplicitAny: LangChain response structure is dynamic\n private extractToolOutputs(response: any): Record<string, unknown> {\n return { output: response?.output ?? response };\n }\n}\n",
|
|
8
8
|
"import type { TokenUsage } from '@prefactor/core';\n\n/**\n * Extract token usage information from LLM responses.\n *\n * Handles multiple response formats from different LLM providers and LangChain versions.\n *\n * @param response - The LLM response object\n * @returns TokenUsage object or null if no usage data found\n *\n * @example\n * ```typescript\n * const response = await model.invoke(messages);\n * const tokenUsage = extractTokenUsage(response);\n * if (tokenUsage) {\n * console.log(`Tokens used: ${tokenUsage.totalTokens}`);\n * }\n * ```\n */\n// biome-ignore lint/suspicious/noExplicitAny: LLM response structure varies by provider\nexport function extractTokenUsage(response: any): TokenUsage | null {\n try {\n // Try token_usage field (common format)\n const tokenUsage = response?.token_usage ?? response?.usage;\n if (tokenUsage) {\n return {\n promptTokens: tokenUsage.prompt_tokens ?? 0,\n completionTokens: tokenUsage.completion_tokens ?? 0,\n totalTokens: tokenUsage.total_tokens ?? 0,\n };\n }\n\n // Try usage_metadata field (LangChain format)\n const usageMetadata = response?.usage_metadata;\n if (usageMetadata) {\n return {\n promptTokens: usageMetadata.input_tokens ?? 0,\n completionTokens: usageMetadata.output_tokens ?? 0,\n totalTokens: usageMetadata.total_tokens ?? 0,\n };\n }\n\n // Try response_metadata.token_usage (nested format)\n const responseMetadata = response?.response_metadata;\n if (responseMetadata?.token_usage) {\n return {\n promptTokens: responseMetadata.token_usage.prompt_tokens ?? 0,\n completionTokens: responseMetadata.token_usage.completion_tokens ?? 0,\n totalTokens: responseMetadata.token_usage.total_tokens ?? 0,\n };\n }\n\n return null;\n } catch {\n return null;\n }\n}\n"
|
|
9
9
|
],
|
|
10
|
-
"mappings": ";AAGA;AAAA;AAAA,
|
|
11
|
-
"debugId": "
|
|
10
|
+
"mappings": "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",
|
|
11
|
+
"debugId": "EBAE04F79C70EA8764756E2164756E21",
|
|
12
12
|
"names": []
|
|
13
13
|
}
|
package/dist/init.d.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
import { type Config, Tracer } from '@prefactor/core';
|
|
1
|
+
import { type Config, type Tracer } from '@prefactor/core';
|
|
2
2
|
import { type AgentMiddleware } from 'langchain';
|
|
3
|
+
export type ManualSpanOptions = {
|
|
4
|
+
name: string;
|
|
5
|
+
spanType: string;
|
|
6
|
+
inputs: Record<string, unknown>;
|
|
7
|
+
metadata?: Record<string, unknown>;
|
|
8
|
+
};
|
|
3
9
|
/**
|
|
4
10
|
* Initialize the Prefactor SDK and return middleware for LangChain.js
|
|
5
11
|
*
|
|
@@ -14,8 +20,15 @@ import { type AgentMiddleware } from 'langchain';
|
|
|
14
20
|
* import { init } from '@prefactor/langchain';
|
|
15
21
|
* import { createAgent } from 'langchain';
|
|
16
22
|
*
|
|
17
|
-
* // Initialize with
|
|
18
|
-
* const middleware = init(
|
|
23
|
+
* // Initialize with HTTP transport
|
|
24
|
+
* const middleware = init({
|
|
25
|
+
* transportType: 'http',
|
|
26
|
+
* httpConfig: {
|
|
27
|
+
* apiUrl: 'https://api.prefactor.ai',
|
|
28
|
+
* apiToken: process.env.PREFACTOR_API_TOKEN!,
|
|
29
|
+
* agentIdentifier: 'my-langchain-agent',
|
|
30
|
+
* },
|
|
31
|
+
* });
|
|
19
32
|
*
|
|
20
33
|
* // Or configure HTTP transport
|
|
21
34
|
* const middleware = init({
|
|
@@ -23,6 +36,8 @@ import { type AgentMiddleware } from 'langchain';
|
|
|
23
36
|
* httpConfig: {
|
|
24
37
|
* apiUrl: 'https://api.prefactor.ai',
|
|
25
38
|
* apiToken: process.env.PREFACTOR_API_TOKEN!,
|
|
39
|
+
* agentIdentifier: 'my-langchain-agent', // Required
|
|
40
|
+
* agentId: 'legacy-agent-id', // Optional legacy identifier
|
|
26
41
|
* }
|
|
27
42
|
* });
|
|
28
43
|
*
|
|
@@ -54,6 +69,7 @@ export declare function init(config?: Partial<Config>): AgentMiddleware;
|
|
|
54
69
|
* ```
|
|
55
70
|
*/
|
|
56
71
|
export declare function getTracer(): Tracer;
|
|
72
|
+
export declare function withSpan<T>(options: ManualSpanOptions, fn: () => Promise<T> | T): Promise<T>;
|
|
57
73
|
/**
|
|
58
74
|
* Shutdown the SDK and flush any pending spans.
|
|
59
75
|
*
|
package/dist/init.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,MAAM,EAOX,MAAM,
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,MAAM,EAOX,KAAK,MAAM,EACZ,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,KAAK,eAAe,EAAoB,MAAM,WAAW,CAAC;AAmBnE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAgB,IAAI,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,eAAe,CAuF9D;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAMlC;AAED,wBAAsB,QAAQ,CAAC,CAAC,EAC9B,OAAO,EAAE,iBAAiB,EAC1B,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,GACvB,OAAO,CAAC,CAAC,CAAC,CAaZ;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAQ9C"}
|
package/dist/init.js
CHANGED
|
@@ -1,8 +1,17 @@
|
|
|
1
|
-
import { configureLogging, createConfig,
|
|
2
|
-
import { extractPartition } from '@prefactor/pfid';
|
|
1
|
+
import { configureLogging, createConfig, createCore, getLogger, SpanContext, } from '@prefactor/core';
|
|
3
2
|
import { createMiddleware } from 'langchain';
|
|
4
3
|
import { PrefactorMiddleware } from './middleware.js';
|
|
5
4
|
const logger = getLogger('init');
|
|
5
|
+
const DEFAULT_LANGCHAIN_AGENT_SCHEMA = {
|
|
6
|
+
external_identifier: 'prefactor',
|
|
7
|
+
span_schemas: {
|
|
8
|
+
agent: { type: 'object', additionalProperties: true },
|
|
9
|
+
llm: { type: 'object', additionalProperties: true },
|
|
10
|
+
tool: { type: 'object', additionalProperties: true },
|
|
11
|
+
chain: { type: 'object', additionalProperties: true },
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
let globalCore = null;
|
|
6
15
|
let globalTracer = null;
|
|
7
16
|
let globalMiddleware = null;
|
|
8
17
|
/**
|
|
@@ -19,8 +28,15 @@ let globalMiddleware = null;
|
|
|
19
28
|
* import { init } from '@prefactor/langchain';
|
|
20
29
|
* import { createAgent } from 'langchain';
|
|
21
30
|
*
|
|
22
|
-
* // Initialize with
|
|
23
|
-
* const middleware = init(
|
|
31
|
+
* // Initialize with HTTP transport
|
|
32
|
+
* const middleware = init({
|
|
33
|
+
* transportType: 'http',
|
|
34
|
+
* httpConfig: {
|
|
35
|
+
* apiUrl: 'https://api.prefactor.ai',
|
|
36
|
+
* apiToken: process.env.PREFACTOR_API_TOKEN!,
|
|
37
|
+
* agentIdentifier: 'my-langchain-agent',
|
|
38
|
+
* },
|
|
39
|
+
* });
|
|
24
40
|
*
|
|
25
41
|
* // Or configure HTTP transport
|
|
26
42
|
* const middleware = init({
|
|
@@ -28,6 +44,8 @@ let globalMiddleware = null;
|
|
|
28
44
|
* httpConfig: {
|
|
29
45
|
* apiUrl: 'https://api.prefactor.ai',
|
|
30
46
|
* apiToken: process.env.PREFACTOR_API_TOKEN!,
|
|
47
|
+
* agentIdentifier: 'my-langchain-agent', // Required
|
|
48
|
+
* agentId: 'legacy-agent-id', // Optional legacy identifier
|
|
31
49
|
* }
|
|
32
50
|
* });
|
|
33
51
|
*
|
|
@@ -40,36 +58,57 @@ let globalMiddleware = null;
|
|
|
40
58
|
*/
|
|
41
59
|
export function init(config) {
|
|
42
60
|
configureLogging();
|
|
43
|
-
|
|
44
|
-
|
|
61
|
+
let configWithHttp = config;
|
|
62
|
+
const transportType = config?.transportType ?? process.env.PREFACTOR_TRANSPORT ?? 'http';
|
|
63
|
+
if (transportType === 'http' && !config?.httpConfig) {
|
|
64
|
+
const apiUrl = process.env.PREFACTOR_API_URL;
|
|
65
|
+
const apiToken = process.env.PREFACTOR_API_TOKEN;
|
|
66
|
+
if (!apiUrl || !apiToken) {
|
|
67
|
+
throw new Error('HTTP transport requires PREFACTOR_API_URL and PREFACTOR_API_TOKEN environment variables, ' +
|
|
68
|
+
'or httpConfig to be provided in configuration');
|
|
69
|
+
}
|
|
70
|
+
configWithHttp = {
|
|
71
|
+
...config,
|
|
72
|
+
transportType: 'http',
|
|
73
|
+
httpConfig: {
|
|
74
|
+
apiUrl,
|
|
75
|
+
apiToken,
|
|
76
|
+
agentId: process.env.PREFACTOR_AGENT_ID,
|
|
77
|
+
agentName: process.env.PREFACTOR_AGENT_NAME,
|
|
78
|
+
agentIdentifier: process.env.PREFACTOR_AGENT_IDENTIFIER || '1.0.0',
|
|
79
|
+
agentSchema: DEFAULT_LANGCHAIN_AGENT_SCHEMA,
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
else if (transportType === 'http' && config?.httpConfig && !config.httpConfig.agentSchema) {
|
|
84
|
+
configWithHttp = {
|
|
85
|
+
...config,
|
|
86
|
+
httpConfig: {
|
|
87
|
+
...config.httpConfig,
|
|
88
|
+
agentSchema: DEFAULT_LANGCHAIN_AGENT_SCHEMA,
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
const finalConfig = createConfig(configWithHttp);
|
|
45
93
|
if (globalMiddleware !== null) {
|
|
46
94
|
return globalMiddleware;
|
|
47
95
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
throw new Error('HTTP transport requires httpConfig to be provided in configuration');
|
|
55
|
-
}
|
|
56
|
-
// Parse httpConfig to apply defaults from schema
|
|
57
|
-
const httpConfig = HttpTransportConfigSchema.parse(finalConfig.httpConfig);
|
|
58
|
-
transport = new HttpTransport(httpConfig);
|
|
96
|
+
const core = createCore(finalConfig);
|
|
97
|
+
globalCore = core;
|
|
98
|
+
globalTracer = core.tracer;
|
|
99
|
+
const httpConfig = finalConfig.httpConfig;
|
|
100
|
+
if (httpConfig?.agentSchema) {
|
|
101
|
+
core.agentManager.registerSchema(httpConfig.agentSchema);
|
|
59
102
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
catch (error) {
|
|
68
|
-
logger.warn('Failed to extract partition from agent_id, using random partition', { error });
|
|
103
|
+
const agentInfo = finalConfig.httpConfig
|
|
104
|
+
? {
|
|
105
|
+
agentId: finalConfig.httpConfig.agentId,
|
|
106
|
+
agentIdentifier: finalConfig.httpConfig.agentIdentifier,
|
|
107
|
+
agentName: finalConfig.httpConfig.agentName,
|
|
108
|
+
agentDescription: finalConfig.httpConfig.agentDescription,
|
|
69
109
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const prefactorMiddleware = new PrefactorMiddleware(globalTracer);
|
|
110
|
+
: undefined;
|
|
111
|
+
const prefactorMiddleware = new PrefactorMiddleware(core.tracer, core.agentManager, agentInfo);
|
|
73
112
|
const middleware = createMiddleware({
|
|
74
113
|
name: 'prefactor',
|
|
75
114
|
// biome-ignore lint/suspicious/noExplicitAny: LangChain middleware hooks use dynamic types
|
|
@@ -118,6 +157,20 @@ export function getTracer() {
|
|
|
118
157
|
// Safe because init() always sets globalTracer
|
|
119
158
|
return globalTracer;
|
|
120
159
|
}
|
|
160
|
+
export async function withSpan(options, fn) {
|
|
161
|
+
const tracer = getTracer();
|
|
162
|
+
const span = tracer.startSpan(options);
|
|
163
|
+
try {
|
|
164
|
+
const result = await SpanContext.runAsync(span, async () => await fn());
|
|
165
|
+
tracer.endSpan(span);
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
const normalizedError = error instanceof Error ? error : new Error(String(error));
|
|
170
|
+
tracer.endSpan(span, { error: normalizedError });
|
|
171
|
+
throw error;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
121
174
|
/**
|
|
122
175
|
* Shutdown the SDK and flush any pending spans.
|
|
123
176
|
*
|
|
@@ -137,10 +190,11 @@ export function getTracer() {
|
|
|
137
190
|
* ```
|
|
138
191
|
*/
|
|
139
192
|
export async function shutdown() {
|
|
140
|
-
if (
|
|
193
|
+
if (globalCore) {
|
|
141
194
|
logger.info('Shutting down Prefactor SDK');
|
|
142
|
-
await
|
|
195
|
+
await globalCore.shutdown();
|
|
143
196
|
}
|
|
197
|
+
globalCore = null;
|
|
144
198
|
globalTracer = null;
|
|
145
199
|
globalMiddleware = null;
|
|
146
200
|
}
|
package/dist/init.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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"}
|
package/dist/middleware.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Tracer } from '@prefactor/core';
|
|
1
|
+
import { type AgentInstanceManager, type Tracer } from '@prefactor/core';
|
|
2
2
|
/**
|
|
3
3
|
* Prefactor middleware for LangChain.js agents.
|
|
4
4
|
*
|
|
@@ -26,8 +26,10 @@ import { type Tracer } from '@prefactor/core';
|
|
|
26
26
|
*/
|
|
27
27
|
export declare class PrefactorMiddleware {
|
|
28
28
|
private tracer;
|
|
29
|
+
private agentManager;
|
|
30
|
+
private agentInfo?;
|
|
29
31
|
private rootSpan;
|
|
30
|
-
constructor(tracer: Tracer);
|
|
32
|
+
constructor(tracer: Tracer, agentManager: AgentInstanceManager, agentInfo?: Parameters<AgentInstanceManager['startInstance']>[0]);
|
|
31
33
|
/**
|
|
32
34
|
* Called before agent execution starts
|
|
33
35
|
*
|
package/dist/middleware.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,oBAAoB,EAIzB,KAAK,MAAM,EACZ,MAAM,iBAAiB,CAAC;AAGzB;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,qBAAa,mBAAmB;IAI5B,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,SAAS,CAAC;IALpB,OAAO,CAAC,QAAQ,CAAgD;gBAGtD,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,oBAAoB,EAClC,SAAS,CAAC,EAAE,UAAU,CAAC,oBAAoB,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IAG1E;;;;OAIG;IAEG,WAAW,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAe5C;;;;OAIG;IAEG,UAAU,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAe3C;;;;;;OAMG;IAEG,aAAa,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAwBnF;;;;;;OAMG;IAEG,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAuBlF;;OAEG;IAEH,OAAO,CAAC,gBAAgB;IA4BxB;;OAEG;IAEH,OAAO,CAAC,kBAAkB;IAK1B;;OAEG;IAEH,OAAO,CAAC,mBAAmB;IAK3B;;OAEG;IAEH,OAAO,CAAC,eAAe;IAIvB;;OAEG;IAEH,OAAO,CAAC,iBAAiB;IAIzB;;OAEG;IAEH,OAAO,CAAC,kBAAkB;CAG3B"}
|
package/dist/middleware.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SpanContext, SpanType } from '@prefactor/core';
|
|
1
|
+
import { SpanContext, SpanType, serializeValue, } from '@prefactor/core';
|
|
2
2
|
import { extractTokenUsage } from './metadata-extractor.js';
|
|
3
3
|
/**
|
|
4
4
|
* Prefactor middleware for LangChain.js agents.
|
|
@@ -27,9 +27,13 @@ import { extractTokenUsage } from './metadata-extractor.js';
|
|
|
27
27
|
*/
|
|
28
28
|
export class PrefactorMiddleware {
|
|
29
29
|
tracer;
|
|
30
|
+
agentManager;
|
|
31
|
+
agentInfo;
|
|
30
32
|
rootSpan = null;
|
|
31
|
-
constructor(tracer) {
|
|
33
|
+
constructor(tracer, agentManager, agentInfo) {
|
|
32
34
|
this.tracer = tracer;
|
|
35
|
+
this.agentManager = agentManager;
|
|
36
|
+
this.agentInfo = agentInfo;
|
|
33
37
|
}
|
|
34
38
|
/**
|
|
35
39
|
* Called before agent execution starts
|
|
@@ -38,17 +42,15 @@ export class PrefactorMiddleware {
|
|
|
38
42
|
*/
|
|
39
43
|
// biome-ignore lint/suspicious/noExplicitAny: LangChain state can be any structure
|
|
40
44
|
async beforeAgent(state) {
|
|
41
|
-
const parentSpan = SpanContext.getCurrent();
|
|
42
45
|
const messages = state?.messages ?? [];
|
|
43
|
-
this.
|
|
46
|
+
this.agentManager.startInstance(this.agentInfo);
|
|
44
47
|
const span = this.tracer.startSpan({
|
|
45
|
-
name: 'agent',
|
|
48
|
+
name: 'langchain:agent',
|
|
46
49
|
spanType: SpanType.AGENT,
|
|
47
|
-
inputs: { messages: messages.slice(-3)
|
|
48
|
-
parentSpanId: parentSpan?.spanId,
|
|
49
|
-
traceId: parentSpan?.traceId,
|
|
50
|
+
inputs: { messages: serializeValue(messages.slice(-3)) },
|
|
50
51
|
});
|
|
51
52
|
this.rootSpan = span;
|
|
53
|
+
SpanContext.enter(span);
|
|
52
54
|
}
|
|
53
55
|
/**
|
|
54
56
|
* Called after agent execution completes
|
|
@@ -62,10 +64,10 @@ export class PrefactorMiddleware {
|
|
|
62
64
|
}
|
|
63
65
|
const messages = state?.messages ?? [];
|
|
64
66
|
this.tracer.endSpan(this.rootSpan, {
|
|
65
|
-
outputs: { messages: messages.slice(-3)
|
|
67
|
+
outputs: { messages: serializeValue(messages.slice(-3)) },
|
|
66
68
|
});
|
|
67
|
-
this.
|
|
68
|
-
SpanContext.
|
|
69
|
+
this.agentManager.finishInstance();
|
|
70
|
+
SpanContext.exit();
|
|
69
71
|
this.rootSpan = null;
|
|
70
72
|
}
|
|
71
73
|
/**
|
|
@@ -77,13 +79,10 @@ export class PrefactorMiddleware {
|
|
|
77
79
|
*/
|
|
78
80
|
// biome-ignore lint/suspicious/noExplicitAny: LangChain request/handler types are dynamic
|
|
79
81
|
async wrapModelCall(request, handler) {
|
|
80
|
-
const parentSpan = SpanContext.getCurrent();
|
|
81
82
|
const span = this.tracer.startSpan({
|
|
82
83
|
name: this.extractModelName(request),
|
|
83
84
|
spanType: SpanType.LLM,
|
|
84
85
|
inputs: this.extractModelInputs(request),
|
|
85
|
-
parentSpanId: parentSpan?.spanId,
|
|
86
|
-
traceId: parentSpan?.traceId,
|
|
87
86
|
});
|
|
88
87
|
try {
|
|
89
88
|
// CRITICAL: Wrap handler in context so child operations see this span
|
|
@@ -109,13 +108,10 @@ export class PrefactorMiddleware {
|
|
|
109
108
|
*/
|
|
110
109
|
// biome-ignore lint/suspicious/noExplicitAny: LangChain request/handler types are dynamic
|
|
111
110
|
async wrapToolCall(request, handler) {
|
|
112
|
-
const parentSpan = SpanContext.getCurrent();
|
|
113
111
|
const span = this.tracer.startSpan({
|
|
114
112
|
name: this.extractToolName(request),
|
|
115
113
|
spanType: SpanType.TOOL,
|
|
116
114
|
inputs: this.extractToolInputs(request),
|
|
117
|
-
parentSpanId: parentSpan?.spanId,
|
|
118
|
-
traceId: parentSpan?.traceId,
|
|
119
115
|
});
|
|
120
116
|
try {
|
|
121
117
|
// CRITICAL: Wrap handler in context so child operations see this span
|
|
@@ -137,7 +133,24 @@ export class PrefactorMiddleware {
|
|
|
137
133
|
*/
|
|
138
134
|
// biome-ignore lint/suspicious/noExplicitAny: LangChain request structure is dynamic
|
|
139
135
|
extractModelName(request) {
|
|
140
|
-
|
|
136
|
+
const candidate = request?.model ?? request?.modelName;
|
|
137
|
+
if (typeof candidate === 'string') {
|
|
138
|
+
return candidate;
|
|
139
|
+
}
|
|
140
|
+
if (candidate && typeof candidate === 'object') {
|
|
141
|
+
const modelObject = candidate;
|
|
142
|
+
if (Array.isArray(modelObject.id) &&
|
|
143
|
+
modelObject.id.every((item) => typeof item === 'string')) {
|
|
144
|
+
return modelObject.id.join('.');
|
|
145
|
+
}
|
|
146
|
+
if (typeof modelObject.modelName === 'string') {
|
|
147
|
+
return modelObject.modelName;
|
|
148
|
+
}
|
|
149
|
+
if (typeof modelObject.name === 'string') {
|
|
150
|
+
return modelObject.name;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return 'unknown';
|
|
141
154
|
}
|
|
142
155
|
/**
|
|
143
156
|
* Extract model inputs from request
|
|
@@ -145,7 +158,7 @@ export class PrefactorMiddleware {
|
|
|
145
158
|
// biome-ignore lint/suspicious/noExplicitAny: LangChain request structure is dynamic
|
|
146
159
|
extractModelInputs(request) {
|
|
147
160
|
const messages = request?.messages ?? [];
|
|
148
|
-
return { messages: messages.slice(-3)
|
|
161
|
+
return { messages: serializeValue(messages.slice(-3)) };
|
|
149
162
|
}
|
|
150
163
|
/**
|
|
151
164
|
* Extract model outputs from response
|
|
@@ -153,7 +166,7 @@ export class PrefactorMiddleware {
|
|
|
153
166
|
// biome-ignore lint/suspicious/noExplicitAny: LangChain response structure is dynamic
|
|
154
167
|
extractModelOutputs(response) {
|
|
155
168
|
const content = response?.content ?? response?.text ?? '';
|
|
156
|
-
return { content:
|
|
169
|
+
return { content: serializeValue(content) };
|
|
157
170
|
}
|
|
158
171
|
/**
|
|
159
172
|
* Extract tool name from request
|
package/dist/middleware.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prefactor/langchain",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "LangChain.js integration for Prefactor observability",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"author": "Prefactor",
|
|
29
29
|
"license": "MIT",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@prefactor/core": "0.1.
|
|
31
|
+
"@prefactor/core": "0.1.1",
|
|
32
32
|
"@prefactor/pfid": "^0.1.0"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|