@aui-x/prism 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{client-B9WXHjpz.cjs → client--PC-VXip.cjs} +52 -21
- package/dist/client--PC-VXip.cjs.map +1 -0
- package/dist/{client-BrZstMQX.d.ts → client-9E6ncwtH.d.ts} +11 -6
- package/dist/client-9E6ncwtH.d.ts.map +1 -0
- package/dist/{client-C7RiAn7a.js → client-B49Ds9fR.js} +52 -21
- package/dist/client-B49Ds9fR.js.map +1 -0
- package/dist/{client-BSsSpkZY.d.cts → client-BhQrlPEQ.d.cts} +11 -6
- package/dist/client-BhQrlPEQ.d.cts.map +1 -0
- package/dist/core.cjs +1 -1
- package/dist/core.d.cts +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.js +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/integrations/ai-sdk.cjs +1 -1
- package/dist/integrations/ai-sdk.d.cts +1 -1
- package/dist/integrations/ai-sdk.d.ts +1 -1
- package/dist/integrations/ai-sdk.js +1 -1
- package/dist/integrations/anthropic.cjs +11 -84
- package/dist/integrations/anthropic.cjs.map +1 -1
- package/dist/integrations/anthropic.d.cts +1 -1
- package/dist/integrations/anthropic.d.cts.map +1 -1
- package/dist/integrations/anthropic.d.ts +1 -1
- package/dist/integrations/anthropic.d.ts.map +1 -1
- package/dist/integrations/anthropic.js +5 -77
- package/dist/integrations/anthropic.js.map +1 -1
- package/dist/integrations/openai.cjs +13 -82
- package/dist/integrations/openai.cjs.map +1 -1
- package/dist/integrations/openai.d.cts +1 -1
- package/dist/integrations/openai.d.cts.map +1 -1
- package/dist/integrations/openai.d.ts +1 -1
- package/dist/integrations/openai.d.ts.map +1 -1
- package/dist/integrations/openai.js +6 -74
- package/dist/integrations/openai.js.map +1 -1
- package/dist/shared-BsY3-hy4.js +79 -0
- package/dist/shared-BsY3-hy4.js.map +1 -0
- package/dist/shared-Ch80RlSv.cjs +109 -0
- package/dist/shared-Ch80RlSv.cjs.map +1 -0
- package/dist/{wrapper-ByspXfxS.cjs → wrapper-C9LHP_r5.cjs} +14 -84
- package/dist/wrapper-C9LHP_r5.cjs.map +1 -0
- package/dist/{wrapper-7jRyp54U.js → wrapper-R8mpaNge.js} +6 -76
- package/dist/wrapper-R8mpaNge.js.map +1 -0
- package/package.json +1 -1
- package/dist/client-B9WXHjpz.cjs.map +0 -1
- package/dist/client-BSsSpkZY.d.cts.map +0 -1
- package/dist/client-BrZstMQX.d.ts.map +0 -1
- package/dist/client-C7RiAn7a.js.map +0 -1
- package/dist/wrapper-7jRyp54U.js.map +0 -1
- package/dist/wrapper-ByspXfxS.cjs.map +0 -1
|
@@ -1,76 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
const require_shared = require('../shared-Ch80RlSv.cjs');
|
|
2
3
|
|
|
3
4
|
//#region src/integrations/anthropic.ts
|
|
4
|
-
function truncateInput(messages, maxBytes = 32768) {
|
|
5
|
-
let json = JSON.stringify(messages);
|
|
6
|
-
if (new TextEncoder().encode(json).length <= maxBytes) return messages;
|
|
7
|
-
if (!Array.isArray(messages)) return messages;
|
|
8
|
-
const arr = [...messages];
|
|
9
|
-
while (arr.length > 1) {
|
|
10
|
-
arr.shift();
|
|
11
|
-
json = JSON.stringify(arr);
|
|
12
|
-
if (new TextEncoder().encode(json).length <= maxBytes) return arr;
|
|
13
|
-
}
|
|
14
|
-
return arr;
|
|
15
|
-
}
|
|
16
|
-
function createRootHandle(tracer, opts, model, input, metadata) {
|
|
17
|
-
const parentTraceId = opts?.parentTraceId;
|
|
18
|
-
if (parentTraceId) return {
|
|
19
|
-
isSpanMode: true,
|
|
20
|
-
traceId: parentTraceId,
|
|
21
|
-
handle: tracer.startSpanOnTrace(parentTraceId, {
|
|
22
|
-
name: opts?.name ?? model,
|
|
23
|
-
type: "llm",
|
|
24
|
-
input,
|
|
25
|
-
model,
|
|
26
|
-
provider: "anthropic",
|
|
27
|
-
metadata
|
|
28
|
-
})
|
|
29
|
-
};
|
|
30
|
-
const handle = tracer.startTrace({
|
|
31
|
-
name: opts?.name ?? model,
|
|
32
|
-
model,
|
|
33
|
-
provider: "anthropic",
|
|
34
|
-
input,
|
|
35
|
-
metadata,
|
|
36
|
-
tags: opts?.tags,
|
|
37
|
-
endUserId: opts?.endUserId
|
|
38
|
-
});
|
|
39
|
-
return {
|
|
40
|
-
isSpanMode: false,
|
|
41
|
-
traceId: handle.traceId,
|
|
42
|
-
handle
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
function createToolSpan(tracer, root, toolCall) {
|
|
46
|
-
if (root.isSpanMode) return tracer.startSpanOnTrace(root.traceId, {
|
|
47
|
-
name: toolCall.name,
|
|
48
|
-
type: "tool",
|
|
49
|
-
input: toolCall.arguments,
|
|
50
|
-
parentSpanId: root.handle.spanId
|
|
51
|
-
});
|
|
52
|
-
return root.handle.startSpan({
|
|
53
|
-
name: toolCall.name,
|
|
54
|
-
type: "tool",
|
|
55
|
-
input: toolCall.arguments
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
function endRootHandle(root, result) {
|
|
59
|
-
root.handle.end({
|
|
60
|
-
output: result.output,
|
|
61
|
-
status: "completed",
|
|
62
|
-
totalTokens: result.inputTokens + result.outputTokens,
|
|
63
|
-
promptTokens: result.inputTokens,
|
|
64
|
-
completionTokens: result.outputTokens,
|
|
65
|
-
ttftMs: result.ttftMs
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
function cleanupOnError(root, error) {
|
|
69
|
-
root.handle.end({
|
|
70
|
-
status: "error",
|
|
71
|
-
error: error instanceof Error ? error.message : String(error)
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
5
|
/**
|
|
75
6
|
* Wraps an Anthropic client to automatically trace `messages.create` calls.
|
|
76
7
|
*
|
|
@@ -92,10 +23,10 @@ function prismAnthropic(tracer, client, opts) {
|
|
|
92
23
|
function createInterceptor(tracer, originalCreate, opts) {
|
|
93
24
|
return async (params, ...rest) => {
|
|
94
25
|
const model = params.model ?? "unknown";
|
|
95
|
-
const input = truncateInput(params.messages);
|
|
26
|
+
const input = require_shared.truncateInput(params.messages);
|
|
96
27
|
const metadata = opts?.metadata;
|
|
97
28
|
const isStream = !!params.stream;
|
|
98
|
-
const root = createRootHandle(tracer, opts, model, input, metadata);
|
|
29
|
+
const root = require_shared.createRootHandle(tracer, opts, model, "anthropic", input, metadata);
|
|
99
30
|
if (!isStream) return handleNonStreaming(tracer, root, originalCreate, params, rest);
|
|
100
31
|
return handleStreaming(tracer, root, originalCreate, params, rest);
|
|
101
32
|
};
|
|
@@ -108,19 +39,19 @@ async function handleNonStreaming(tracer, root, originalCreate, params, rest) {
|
|
|
108
39
|
const inputTokens = result.usage?.input_tokens ?? 0;
|
|
109
40
|
const outputTokens = result.usage?.output_tokens ?? 0;
|
|
110
41
|
const toolUseBlocks = content.filter((b) => b.type === "tool_use");
|
|
111
|
-
for (const tc of toolUseBlocks) createToolSpan(tracer, root, {
|
|
42
|
+
for (const tc of toolUseBlocks) require_shared.createToolSpan(tracer, root, {
|
|
112
43
|
id: tc.id,
|
|
113
44
|
name: tc.name,
|
|
114
|
-
|
|
45
|
+
input: JSON.stringify(tc.input)
|
|
115
46
|
}).end({ status: "completed" });
|
|
116
|
-
endRootHandle(root, {
|
|
47
|
+
require_shared.endRootHandle(root, {
|
|
117
48
|
output,
|
|
118
49
|
inputTokens,
|
|
119
50
|
outputTokens
|
|
120
51
|
});
|
|
121
52
|
return result;
|
|
122
53
|
} catch (error) {
|
|
123
|
-
cleanupOnError(root, error);
|
|
54
|
+
require_shared.cleanupOnError(root, error);
|
|
124
55
|
throw error;
|
|
125
56
|
}
|
|
126
57
|
}
|
|
@@ -173,12 +104,8 @@ async function handleStreaming(tracer, root, originalCreate, params, rest) {
|
|
|
173
104
|
const finalizeStream = () => {
|
|
174
105
|
if (finalized) return;
|
|
175
106
|
finalized = true;
|
|
176
|
-
for (const tc of Array.from(toolCallAccum.values())) createToolSpan(tracer, root, {
|
|
177
|
-
|
|
178
|
-
name: tc.name,
|
|
179
|
-
arguments: tc.input
|
|
180
|
-
}).end({ status: "completed" });
|
|
181
|
-
endRootHandle(root, {
|
|
107
|
+
for (const tc of Array.from(toolCallAccum.values())) require_shared.createToolSpan(tracer, root, tc).end({ status: "completed" });
|
|
108
|
+
require_shared.endRootHandle(root, {
|
|
182
109
|
output,
|
|
183
110
|
inputTokens,
|
|
184
111
|
outputTokens,
|
|
@@ -204,7 +131,7 @@ async function handleStreaming(tracer, root, originalCreate, params, rest) {
|
|
|
204
131
|
};
|
|
205
132
|
},
|
|
206
133
|
async throw(err) {
|
|
207
|
-
cleanupOnError(root, err);
|
|
134
|
+
require_shared.cleanupOnError(root, err);
|
|
208
135
|
return iter.throw?.(err) ?? {
|
|
209
136
|
done: true,
|
|
210
137
|
value: void 0
|
|
@@ -216,7 +143,7 @@ async function handleStreaming(tracer, root, originalCreate, params, rest) {
|
|
|
216
143
|
return Reflect.get(target, prop, receiver);
|
|
217
144
|
} });
|
|
218
145
|
} catch (error) {
|
|
219
|
-
cleanupOnError(root, error);
|
|
146
|
+
require_shared.cleanupOnError(root, error);
|
|
220
147
|
throw error;
|
|
221
148
|
}
|
|
222
149
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic.cjs","names":[],"sources":["../../src/integrations/anthropic.ts"],"sourcesContent":["import type { AuixPrism, SpanHandle, TraceHandle } from \"../client\";\n\nexport interface AnthropicPrismOptions {\n name?: string;\n tags?: string[];\n metadata?: Record<string, unknown>;\n parentTraceId?: string;\n endUserId?: string;\n}\n\ntype RootHandle =\n | { isSpanMode: true; traceId: string; handle: SpanHandle }\n | { isSpanMode: false; traceId: string; handle: TraceHandle };\n\nfunction truncateInput(messages: unknown, maxBytes = 32768): unknown {\n let json = JSON.stringify(messages);\n if (new TextEncoder().encode(json).length <= maxBytes) {\n return messages;\n }\n\n if (!Array.isArray(messages)) return messages;\n const arr = [...messages];\n while (arr.length > 1) {\n arr.shift();\n json = JSON.stringify(arr);\n if (new TextEncoder().encode(json).length <= maxBytes) {\n return arr;\n }\n }\n return arr;\n}\n\nfunction createRootHandle(\n tracer: AuixPrism,\n opts: AnthropicPrismOptions | undefined,\n model: string,\n input: unknown,\n metadata: Record<string, unknown> | undefined,\n): RootHandle {\n const parentTraceId = opts?.parentTraceId;\n\n if (parentTraceId) {\n const handle = tracer.startSpanOnTrace(parentTraceId, {\n name: opts?.name ?? model,\n type: \"llm\",\n input,\n model,\n provider: \"anthropic\",\n metadata,\n });\n return { isSpanMode: true, traceId: parentTraceId, handle };\n }\n\n const handle = tracer.startTrace({\n name: opts?.name ?? model,\n model,\n provider: \"anthropic\",\n input,\n metadata,\n tags: opts?.tags,\n endUserId: opts?.endUserId,\n });\n return { isSpanMode: false, traceId: handle.traceId, handle };\n}\n\nfunction createToolSpan(\n tracer: AuixPrism,\n root: RootHandle,\n toolCall: { id: string; name: string; arguments: string },\n): SpanHandle {\n if (root.isSpanMode) {\n return tracer.startSpanOnTrace(root.traceId, {\n name: toolCall.name,\n type: \"tool\",\n input: toolCall.arguments,\n parentSpanId: root.handle.spanId,\n });\n }\n return root.handle.startSpan({\n name: toolCall.name,\n type: \"tool\",\n input: toolCall.arguments,\n });\n}\n\nfunction endRootHandle(\n root: RootHandle,\n result: {\n output: string;\n inputTokens: number;\n outputTokens: number;\n ttftMs?: number;\n },\n): void {\n root.handle.end({\n output: result.output,\n status: \"completed\",\n totalTokens: result.inputTokens + result.outputTokens,\n promptTokens: result.inputTokens,\n completionTokens: result.outputTokens,\n ttftMs: result.ttftMs,\n });\n}\n\nfunction cleanupOnError(root: RootHandle, error: unknown): void {\n root.handle.end({\n status: \"error\",\n error: error instanceof Error ? error.message : String(error),\n });\n}\n\ninterface StreamEvent {\n type: string;\n message?: { usage?: { input_tokens?: number } };\n index?: number;\n content_block?: {\n type: string;\n id?: string;\n name?: string;\n text?: string;\n };\n delta?: {\n type: string;\n text?: string;\n partial_json?: string;\n stop_reason?: string;\n };\n usage?: { output_tokens?: number };\n}\n\ninterface AccumulatedToolCall {\n id: string;\n name: string;\n input: string;\n}\n\n/**\n * Wraps an Anthropic client to automatically trace `messages.create` calls.\n *\n * Returns a proxy that behaves identically to the original client, but emits\n * trace events for both streaming and non-streaming message calls.\n */\nexport function prismAnthropic<T extends object>(\n tracer: AuixPrism,\n client: T,\n opts?: AnthropicPrismOptions,\n): T {\n return new Proxy(client, {\n get(target, prop, receiver) {\n if (prop === \"messages\") {\n const messages = Reflect.get(target, prop, receiver) as object;\n return new Proxy(messages, {\n get(msgTarget, msgProp, msgReceiver) {\n if (msgProp === \"create\") {\n return createInterceptor(\n tracer,\n Reflect.get(msgTarget, msgProp, msgReceiver).bind(msgTarget),\n opts,\n );\n }\n return Reflect.get(msgTarget, msgProp, msgReceiver);\n },\n });\n }\n return Reflect.get(target, prop, receiver);\n },\n });\n}\n\nfunction createInterceptor(\n tracer: AuixPrism,\n originalCreate: (...args: unknown[]) => Promise<unknown>,\n opts?: AnthropicPrismOptions,\n) {\n return async (params: Record<string, unknown>, ...rest: unknown[]) => {\n const model = (params.model as string) ?? \"unknown\";\n const input = truncateInput(params.messages);\n const metadata = opts?.metadata;\n const isStream = !!params.stream;\n\n const root = createRootHandle(tracer, opts, model, input, metadata);\n\n if (!isStream) {\n return handleNonStreaming(tracer, root, originalCreate, params, rest);\n }\n\n return handleStreaming(tracer, root, originalCreate, params, rest);\n };\n}\n\nasync function handleNonStreaming(\n tracer: AuixPrism,\n root: RootHandle,\n originalCreate: (...args: unknown[]) => Promise<unknown>,\n params: Record<string, unknown>,\n rest: unknown[],\n): Promise<unknown> {\n try {\n const result = (await originalCreate(params, ...rest)) as {\n content?: Array<\n | { type: \"text\"; text: string }\n | { type: \"tool_use\"; id: string; name: string; input: unknown }\n >;\n usage?: { input_tokens?: number; output_tokens?: number };\n };\n\n const content = result.content ?? [];\n const output = content\n .filter((b): b is { type: \"text\"; text: string } => b.type === \"text\")\n .map((b) => b.text)\n .join(\"\");\n\n const inputTokens = result.usage?.input_tokens ?? 0;\n const outputTokens = result.usage?.output_tokens ?? 0;\n\n const toolUseBlocks = content.filter(\n (\n b,\n ): b is { type: \"tool_use\"; id: string; name: string; input: unknown } =>\n b.type === \"tool_use\",\n );\n\n for (const tc of toolUseBlocks) {\n const span = createToolSpan(tracer, root, {\n id: tc.id,\n name: tc.name,\n arguments: JSON.stringify(tc.input),\n });\n span.end({ status: \"completed\" });\n }\n\n endRootHandle(root, { output, inputTokens, outputTokens });\n return result;\n } catch (error) {\n cleanupOnError(root, error);\n throw error;\n }\n}\n\nasync function handleStreaming(\n tracer: AuixPrism,\n root: RootHandle,\n originalCreate: (...args: unknown[]) => Promise<unknown>,\n params: Record<string, unknown>,\n rest: unknown[],\n): Promise<unknown> {\n try {\n const streamStart = Date.now();\n const stream = await originalCreate(params, ...rest);\n\n let output = \"\";\n let inputTokens = 0;\n let outputTokens = 0;\n let ttftMs: number | undefined;\n let firstTextDelta = true;\n let finalized = false;\n const toolCallAccum = new Map<number, AccumulatedToolCall>();\n let currentToolIndex = -1;\n\n const processEvent = (event: StreamEvent) => {\n switch (event.type) {\n case \"message_start\": {\n inputTokens = event.message?.usage?.input_tokens ?? 0;\n break;\n }\n case \"content_block_start\": {\n if (event.content_block?.type === \"tool_use\") {\n currentToolIndex = event.index ?? currentToolIndex + 1;\n toolCallAccum.set(currentToolIndex, {\n id: event.content_block.id ?? \"\",\n name: event.content_block.name ?? \"\",\n input: \"\",\n });\n }\n break;\n }\n case \"content_block_delta\": {\n if (event.delta?.type === \"text_delta\" && event.delta.text) {\n if (firstTextDelta) {\n ttftMs = Date.now() - streamStart;\n firstTextDelta = false;\n }\n output += event.delta.text;\n }\n if (\n event.delta?.type === \"input_json_delta\" &&\n event.delta.partial_json\n ) {\n const idx = event.index ?? currentToolIndex;\n const accum = toolCallAccum.get(idx);\n if (accum) {\n accum.input += event.delta.partial_json;\n }\n }\n break;\n }\n case \"message_delta\": {\n outputTokens = event.usage?.output_tokens ?? outputTokens;\n break;\n }\n }\n };\n\n const finalizeStream = () => {\n if (finalized) return;\n finalized = true;\n\n for (const tc of Array.from(toolCallAccum.values())) {\n const span = createToolSpan(tracer, root, {\n id: tc.id,\n name: tc.name,\n arguments: tc.input,\n });\n span.end({ status: \"completed\" });\n }\n\n endRootHandle(root, { output, inputTokens, outputTokens, ttftMs });\n };\n\n const originalIterator = (\n stream as { [Symbol.asyncIterator](): AsyncIterator<unknown> }\n )[Symbol.asyncIterator].bind(stream);\n\n return new Proxy(stream as object, {\n get(target, prop, receiver) {\n if (prop === Symbol.asyncIterator) {\n return () => {\n const iter = originalIterator();\n return {\n async next() {\n const result = await iter.next();\n if (!result.done) {\n processEvent(result.value as StreamEvent);\n }\n if (result.done) {\n finalizeStream();\n }\n return result;\n },\n async return(value?: unknown) {\n finalizeStream();\n return iter.return?.(value) ?? { done: true, value: undefined };\n },\n async throw(err?: unknown) {\n cleanupOnError(root, err);\n return iter.throw?.(err) ?? { done: true, value: undefined };\n },\n };\n };\n }\n if (prop === \"tee\") {\n return undefined;\n }\n return Reflect.get(target, prop, receiver);\n },\n });\n } catch (error) {\n cleanupOnError(root, error);\n throw error;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"anthropic.cjs","names":["truncateInput","createRootHandle","createToolSpan"],"sources":["../../src/integrations/anthropic.ts"],"sourcesContent":["import type { AuixPrism } from \"../client\";\nimport type { ToolCallInput } from \"../shared\";\nimport {\n cleanupOnError,\n createRootHandle,\n createToolSpan,\n endRootHandle,\n truncateInput,\n} from \"../shared\";\n\nexport interface AnthropicPrismOptions {\n name?: string;\n tags?: string[];\n metadata?: Record<string, unknown>;\n parentTraceId?: string;\n endUserId?: string;\n}\n\ninterface StreamEvent {\n type: string;\n message?: { usage?: { input_tokens?: number } };\n index?: number;\n content_block?: {\n type: string;\n id?: string;\n name?: string;\n text?: string;\n };\n delta?: {\n type: string;\n text?: string;\n partial_json?: string;\n stop_reason?: string;\n };\n usage?: { output_tokens?: number };\n}\n\n/**\n * Wraps an Anthropic client to automatically trace `messages.create` calls.\n *\n * Returns a proxy that behaves identically to the original client, but emits\n * trace events for both streaming and non-streaming message calls.\n */\nexport function prismAnthropic<T extends object>(\n tracer: AuixPrism,\n client: T,\n opts?: AnthropicPrismOptions,\n): T {\n return new Proxy(client, {\n get(target, prop, receiver) {\n if (prop === \"messages\") {\n const messages = Reflect.get(target, prop, receiver) as object;\n return new Proxy(messages, {\n get(msgTarget, msgProp, msgReceiver) {\n if (msgProp === \"create\") {\n return createInterceptor(\n tracer,\n Reflect.get(msgTarget, msgProp, msgReceiver).bind(msgTarget),\n opts,\n );\n }\n return Reflect.get(msgTarget, msgProp, msgReceiver);\n },\n });\n }\n return Reflect.get(target, prop, receiver);\n },\n });\n}\n\nfunction createInterceptor(\n tracer: AuixPrism,\n originalCreate: (...args: unknown[]) => Promise<unknown>,\n opts?: AnthropicPrismOptions,\n) {\n return async (params: Record<string, unknown>, ...rest: unknown[]) => {\n const model = (params.model as string) ?? \"unknown\";\n const input = truncateInput(params.messages);\n const metadata = opts?.metadata;\n const isStream = !!params.stream;\n\n const root = createRootHandle(\n tracer,\n opts,\n model,\n \"anthropic\",\n input,\n metadata,\n );\n\n if (!isStream) {\n return handleNonStreaming(tracer, root, originalCreate, params, rest);\n }\n\n return handleStreaming(tracer, root, originalCreate, params, rest);\n };\n}\n\nasync function handleNonStreaming(\n tracer: AuixPrism,\n root: ReturnType<typeof createRootHandle>,\n originalCreate: (...args: unknown[]) => Promise<unknown>,\n params: Record<string, unknown>,\n rest: unknown[],\n): Promise<unknown> {\n try {\n const result = (await originalCreate(params, ...rest)) as {\n content?: Array<\n | { type: \"text\"; text: string }\n | {\n type: \"tool_use\";\n id: string;\n name: string;\n input: unknown;\n }\n >;\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n };\n };\n\n const content = result.content ?? [];\n const output = content\n .filter((b): b is { type: \"text\"; text: string } => b.type === \"text\")\n .map((b) => b.text)\n .join(\"\");\n\n const inputTokens = result.usage?.input_tokens ?? 0;\n const outputTokens = result.usage?.output_tokens ?? 0;\n\n const toolUseBlocks = content.filter(\n (\n b,\n ): b is {\n type: \"tool_use\";\n id: string;\n name: string;\n input: unknown;\n } => b.type === \"tool_use\",\n );\n\n for (const tc of toolUseBlocks) {\n const span = createToolSpan(tracer, root, {\n id: tc.id,\n name: tc.name,\n input: JSON.stringify(tc.input),\n });\n span.end({ status: \"completed\" });\n }\n\n endRootHandle(root, { output, inputTokens, outputTokens });\n return result;\n } catch (error) {\n cleanupOnError(root, error);\n throw error;\n }\n}\n\nasync function handleStreaming(\n tracer: AuixPrism,\n root: ReturnType<typeof createRootHandle>,\n originalCreate: (...args: unknown[]) => Promise<unknown>,\n params: Record<string, unknown>,\n rest: unknown[],\n): Promise<unknown> {\n try {\n const streamStart = Date.now();\n const stream = await originalCreate(params, ...rest);\n\n let output = \"\";\n let inputTokens = 0;\n let outputTokens = 0;\n let ttftMs: number | undefined;\n let firstTextDelta = true;\n let finalized = false;\n const toolCallAccum = new Map<number, ToolCallInput>();\n let currentToolIndex = -1;\n\n const processEvent = (event: StreamEvent) => {\n switch (event.type) {\n case \"message_start\": {\n inputTokens = event.message?.usage?.input_tokens ?? 0;\n break;\n }\n case \"content_block_start\": {\n if (event.content_block?.type === \"tool_use\") {\n currentToolIndex = event.index ?? currentToolIndex + 1;\n toolCallAccum.set(currentToolIndex, {\n id: event.content_block.id ?? \"\",\n name: event.content_block.name ?? \"\",\n input: \"\",\n });\n }\n break;\n }\n case \"content_block_delta\": {\n if (event.delta?.type === \"text_delta\" && event.delta.text) {\n if (firstTextDelta) {\n ttftMs = Date.now() - streamStart;\n firstTextDelta = false;\n }\n output += event.delta.text;\n }\n if (\n event.delta?.type === \"input_json_delta\" &&\n event.delta.partial_json\n ) {\n const idx = event.index ?? currentToolIndex;\n const accum = toolCallAccum.get(idx);\n if (accum) {\n accum.input += event.delta.partial_json;\n }\n }\n break;\n }\n case \"message_delta\": {\n outputTokens = event.usage?.output_tokens ?? outputTokens;\n break;\n }\n }\n };\n\n const finalizeStream = () => {\n if (finalized) return;\n finalized = true;\n\n for (const tc of Array.from(toolCallAccum.values())) {\n const span = createToolSpan(tracer, root, tc);\n span.end({ status: \"completed\" });\n }\n\n endRootHandle(root, {\n output,\n inputTokens,\n outputTokens,\n ttftMs,\n });\n };\n\n const originalIterator = (\n stream as {\n [Symbol.asyncIterator](): AsyncIterator<unknown>;\n }\n )[Symbol.asyncIterator].bind(stream);\n\n return new Proxy(stream as object, {\n get(target, prop, receiver) {\n if (prop === Symbol.asyncIterator) {\n return () => {\n const iter = originalIterator();\n return {\n async next() {\n const result = await iter.next();\n if (!result.done) {\n processEvent(result.value as StreamEvent);\n }\n if (result.done) {\n finalizeStream();\n }\n return result;\n },\n async return(value?: unknown) {\n finalizeStream();\n return (\n iter.return?.(value) ?? {\n done: true,\n value: undefined,\n }\n );\n },\n async throw(err?: unknown) {\n cleanupOnError(root, err);\n return (\n iter.throw?.(err) ?? {\n done: true,\n value: undefined,\n }\n );\n },\n };\n };\n }\n if (prop === \"tee\") {\n return undefined;\n }\n return Reflect.get(target, prop, receiver);\n },\n });\n } catch (error) {\n cleanupOnError(root, error);\n throw error;\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic.d.cts","names":[],"sources":["../../src/integrations/anthropic.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"anthropic.d.cts","names":[],"sources":["../../src/integrations/anthropic.ts"],"mappings":";;;UAUiB,qBAAA;EACf,IAAA;EACA,IAAA;EACA,QAAA,GAAW,MAAA;EACX,aAAA;EACA,SAAA;AAAA;;;;;;;iBA4Bc,cAAA,kBAAA,CACd,MAAA,EAAQ,SAAA,EACR,MAAA,EAAQ,CAAA,EACR,IAAA,GAAO,qBAAA,GACN,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic.d.ts","names":[],"sources":["../../src/integrations/anthropic.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"anthropic.d.ts","names":[],"sources":["../../src/integrations/anthropic.ts"],"mappings":";;;UAUiB,qBAAA;EACf,IAAA;EACA,IAAA;EACA,QAAA,GAAW,MAAA;EACX,aAAA;EACA,SAAA;AAAA;;;;;;;iBA4Bc,cAAA,kBAAA,CACd,MAAA,EAAQ,SAAA,EACR,MAAA,EAAQ,CAAA,EACR,IAAA,GAAO,qBAAA,GACN,CAAA"}
|
|
@@ -1,74 +1,6 @@
|
|
|
1
|
+
import { a as truncateInput, i as endRootHandle, n as createRootHandle, r as createToolSpan, t as cleanupOnError } from "../shared-BsY3-hy4.js";
|
|
2
|
+
|
|
1
3
|
//#region src/integrations/anthropic.ts
|
|
2
|
-
function truncateInput(messages, maxBytes = 32768) {
|
|
3
|
-
let json = JSON.stringify(messages);
|
|
4
|
-
if (new TextEncoder().encode(json).length <= maxBytes) return messages;
|
|
5
|
-
if (!Array.isArray(messages)) return messages;
|
|
6
|
-
const arr = [...messages];
|
|
7
|
-
while (arr.length > 1) {
|
|
8
|
-
arr.shift();
|
|
9
|
-
json = JSON.stringify(arr);
|
|
10
|
-
if (new TextEncoder().encode(json).length <= maxBytes) return arr;
|
|
11
|
-
}
|
|
12
|
-
return arr;
|
|
13
|
-
}
|
|
14
|
-
function createRootHandle(tracer, opts, model, input, metadata) {
|
|
15
|
-
const parentTraceId = opts?.parentTraceId;
|
|
16
|
-
if (parentTraceId) return {
|
|
17
|
-
isSpanMode: true,
|
|
18
|
-
traceId: parentTraceId,
|
|
19
|
-
handle: tracer.startSpanOnTrace(parentTraceId, {
|
|
20
|
-
name: opts?.name ?? model,
|
|
21
|
-
type: "llm",
|
|
22
|
-
input,
|
|
23
|
-
model,
|
|
24
|
-
provider: "anthropic",
|
|
25
|
-
metadata
|
|
26
|
-
})
|
|
27
|
-
};
|
|
28
|
-
const handle = tracer.startTrace({
|
|
29
|
-
name: opts?.name ?? model,
|
|
30
|
-
model,
|
|
31
|
-
provider: "anthropic",
|
|
32
|
-
input,
|
|
33
|
-
metadata,
|
|
34
|
-
tags: opts?.tags,
|
|
35
|
-
endUserId: opts?.endUserId
|
|
36
|
-
});
|
|
37
|
-
return {
|
|
38
|
-
isSpanMode: false,
|
|
39
|
-
traceId: handle.traceId,
|
|
40
|
-
handle
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
function createToolSpan(tracer, root, toolCall) {
|
|
44
|
-
if (root.isSpanMode) return tracer.startSpanOnTrace(root.traceId, {
|
|
45
|
-
name: toolCall.name,
|
|
46
|
-
type: "tool",
|
|
47
|
-
input: toolCall.arguments,
|
|
48
|
-
parentSpanId: root.handle.spanId
|
|
49
|
-
});
|
|
50
|
-
return root.handle.startSpan({
|
|
51
|
-
name: toolCall.name,
|
|
52
|
-
type: "tool",
|
|
53
|
-
input: toolCall.arguments
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
function endRootHandle(root, result) {
|
|
57
|
-
root.handle.end({
|
|
58
|
-
output: result.output,
|
|
59
|
-
status: "completed",
|
|
60
|
-
totalTokens: result.inputTokens + result.outputTokens,
|
|
61
|
-
promptTokens: result.inputTokens,
|
|
62
|
-
completionTokens: result.outputTokens,
|
|
63
|
-
ttftMs: result.ttftMs
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
function cleanupOnError(root, error) {
|
|
67
|
-
root.handle.end({
|
|
68
|
-
status: "error",
|
|
69
|
-
error: error instanceof Error ? error.message : String(error)
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
4
|
/**
|
|
73
5
|
* Wraps an Anthropic client to automatically trace `messages.create` calls.
|
|
74
6
|
*
|
|
@@ -93,7 +25,7 @@ function createInterceptor(tracer, originalCreate, opts) {
|
|
|
93
25
|
const input = truncateInput(params.messages);
|
|
94
26
|
const metadata = opts?.metadata;
|
|
95
27
|
const isStream = !!params.stream;
|
|
96
|
-
const root = createRootHandle(tracer, opts, model, input, metadata);
|
|
28
|
+
const root = createRootHandle(tracer, opts, model, "anthropic", input, metadata);
|
|
97
29
|
if (!isStream) return handleNonStreaming(tracer, root, originalCreate, params, rest);
|
|
98
30
|
return handleStreaming(tracer, root, originalCreate, params, rest);
|
|
99
31
|
};
|
|
@@ -109,7 +41,7 @@ async function handleNonStreaming(tracer, root, originalCreate, params, rest) {
|
|
|
109
41
|
for (const tc of toolUseBlocks) createToolSpan(tracer, root, {
|
|
110
42
|
id: tc.id,
|
|
111
43
|
name: tc.name,
|
|
112
|
-
|
|
44
|
+
input: JSON.stringify(tc.input)
|
|
113
45
|
}).end({ status: "completed" });
|
|
114
46
|
endRootHandle(root, {
|
|
115
47
|
output,
|
|
@@ -171,11 +103,7 @@ async function handleStreaming(tracer, root, originalCreate, params, rest) {
|
|
|
171
103
|
const finalizeStream = () => {
|
|
172
104
|
if (finalized) return;
|
|
173
105
|
finalized = true;
|
|
174
|
-
for (const tc of Array.from(toolCallAccum.values())) createToolSpan(tracer, root, {
|
|
175
|
-
id: tc.id,
|
|
176
|
-
name: tc.name,
|
|
177
|
-
arguments: tc.input
|
|
178
|
-
}).end({ status: "completed" });
|
|
106
|
+
for (const tc of Array.from(toolCallAccum.values())) createToolSpan(tracer, root, tc).end({ status: "completed" });
|
|
179
107
|
endRootHandle(root, {
|
|
180
108
|
output,
|
|
181
109
|
inputTokens,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anthropic.js","names":[],"sources":["../../src/integrations/anthropic.ts"],"sourcesContent":["import type { AuixPrism, SpanHandle, TraceHandle } from \"../client\";\n\nexport interface AnthropicPrismOptions {\n name?: string;\n tags?: string[];\n metadata?: Record<string, unknown>;\n parentTraceId?: string;\n endUserId?: string;\n}\n\ntype RootHandle =\n | { isSpanMode: true; traceId: string; handle: SpanHandle }\n | { isSpanMode: false; traceId: string; handle: TraceHandle };\n\nfunction truncateInput(messages: unknown, maxBytes = 32768): unknown {\n let json = JSON.stringify(messages);\n if (new TextEncoder().encode(json).length <= maxBytes) {\n return messages;\n }\n\n if (!Array.isArray(messages)) return messages;\n const arr = [...messages];\n while (arr.length > 1) {\n arr.shift();\n json = JSON.stringify(arr);\n if (new TextEncoder().encode(json).length <= maxBytes) {\n return arr;\n }\n }\n return arr;\n}\n\nfunction createRootHandle(\n tracer: AuixPrism,\n opts: AnthropicPrismOptions | undefined,\n model: string,\n input: unknown,\n metadata: Record<string, unknown> | undefined,\n): RootHandle {\n const parentTraceId = opts?.parentTraceId;\n\n if (parentTraceId) {\n const handle = tracer.startSpanOnTrace(parentTraceId, {\n name: opts?.name ?? model,\n type: \"llm\",\n input,\n model,\n provider: \"anthropic\",\n metadata,\n });\n return { isSpanMode: true, traceId: parentTraceId, handle };\n }\n\n const handle = tracer.startTrace({\n name: opts?.name ?? model,\n model,\n provider: \"anthropic\",\n input,\n metadata,\n tags: opts?.tags,\n endUserId: opts?.endUserId,\n });\n return { isSpanMode: false, traceId: handle.traceId, handle };\n}\n\nfunction createToolSpan(\n tracer: AuixPrism,\n root: RootHandle,\n toolCall: { id: string; name: string; arguments: string },\n): SpanHandle {\n if (root.isSpanMode) {\n return tracer.startSpanOnTrace(root.traceId, {\n name: toolCall.name,\n type: \"tool\",\n input: toolCall.arguments,\n parentSpanId: root.handle.spanId,\n });\n }\n return root.handle.startSpan({\n name: toolCall.name,\n type: \"tool\",\n input: toolCall.arguments,\n });\n}\n\nfunction endRootHandle(\n root: RootHandle,\n result: {\n output: string;\n inputTokens: number;\n outputTokens: number;\n ttftMs?: number;\n },\n): void {\n root.handle.end({\n output: result.output,\n status: \"completed\",\n totalTokens: result.inputTokens + result.outputTokens,\n promptTokens: result.inputTokens,\n completionTokens: result.outputTokens,\n ttftMs: result.ttftMs,\n });\n}\n\nfunction cleanupOnError(root: RootHandle, error: unknown): void {\n root.handle.end({\n status: \"error\",\n error: error instanceof Error ? error.message : String(error),\n });\n}\n\ninterface StreamEvent {\n type: string;\n message?: { usage?: { input_tokens?: number } };\n index?: number;\n content_block?: {\n type: string;\n id?: string;\n name?: string;\n text?: string;\n };\n delta?: {\n type: string;\n text?: string;\n partial_json?: string;\n stop_reason?: string;\n };\n usage?: { output_tokens?: number };\n}\n\ninterface AccumulatedToolCall {\n id: string;\n name: string;\n input: string;\n}\n\n/**\n * Wraps an Anthropic client to automatically trace `messages.create` calls.\n *\n * Returns a proxy that behaves identically to the original client, but emits\n * trace events for both streaming and non-streaming message calls.\n */\nexport function prismAnthropic<T extends object>(\n tracer: AuixPrism,\n client: T,\n opts?: AnthropicPrismOptions,\n): T {\n return new Proxy(client, {\n get(target, prop, receiver) {\n if (prop === \"messages\") {\n const messages = Reflect.get(target, prop, receiver) as object;\n return new Proxy(messages, {\n get(msgTarget, msgProp, msgReceiver) {\n if (msgProp === \"create\") {\n return createInterceptor(\n tracer,\n Reflect.get(msgTarget, msgProp, msgReceiver).bind(msgTarget),\n opts,\n );\n }\n return Reflect.get(msgTarget, msgProp, msgReceiver);\n },\n });\n }\n return Reflect.get(target, prop, receiver);\n },\n });\n}\n\nfunction createInterceptor(\n tracer: AuixPrism,\n originalCreate: (...args: unknown[]) => Promise<unknown>,\n opts?: AnthropicPrismOptions,\n) {\n return async (params: Record<string, unknown>, ...rest: unknown[]) => {\n const model = (params.model as string) ?? \"unknown\";\n const input = truncateInput(params.messages);\n const metadata = opts?.metadata;\n const isStream = !!params.stream;\n\n const root = createRootHandle(tracer, opts, model, input, metadata);\n\n if (!isStream) {\n return handleNonStreaming(tracer, root, originalCreate, params, rest);\n }\n\n return handleStreaming(tracer, root, originalCreate, params, rest);\n };\n}\n\nasync function handleNonStreaming(\n tracer: AuixPrism,\n root: RootHandle,\n originalCreate: (...args: unknown[]) => Promise<unknown>,\n params: Record<string, unknown>,\n rest: unknown[],\n): Promise<unknown> {\n try {\n const result = (await originalCreate(params, ...rest)) as {\n content?: Array<\n | { type: \"text\"; text: string }\n | { type: \"tool_use\"; id: string; name: string; input: unknown }\n >;\n usage?: { input_tokens?: number; output_tokens?: number };\n };\n\n const content = result.content ?? [];\n const output = content\n .filter((b): b is { type: \"text\"; text: string } => b.type === \"text\")\n .map((b) => b.text)\n .join(\"\");\n\n const inputTokens = result.usage?.input_tokens ?? 0;\n const outputTokens = result.usage?.output_tokens ?? 0;\n\n const toolUseBlocks = content.filter(\n (\n b,\n ): b is { type: \"tool_use\"; id: string; name: string; input: unknown } =>\n b.type === \"tool_use\",\n );\n\n for (const tc of toolUseBlocks) {\n const span = createToolSpan(tracer, root, {\n id: tc.id,\n name: tc.name,\n arguments: JSON.stringify(tc.input),\n });\n span.end({ status: \"completed\" });\n }\n\n endRootHandle(root, { output, inputTokens, outputTokens });\n return result;\n } catch (error) {\n cleanupOnError(root, error);\n throw error;\n }\n}\n\nasync function handleStreaming(\n tracer: AuixPrism,\n root: RootHandle,\n originalCreate: (...args: unknown[]) => Promise<unknown>,\n params: Record<string, unknown>,\n rest: unknown[],\n): Promise<unknown> {\n try {\n const streamStart = Date.now();\n const stream = await originalCreate(params, ...rest);\n\n let output = \"\";\n let inputTokens = 0;\n let outputTokens = 0;\n let ttftMs: number | undefined;\n let firstTextDelta = true;\n let finalized = false;\n const toolCallAccum = new Map<number, AccumulatedToolCall>();\n let currentToolIndex = -1;\n\n const processEvent = (event: StreamEvent) => {\n switch (event.type) {\n case \"message_start\": {\n inputTokens = event.message?.usage?.input_tokens ?? 0;\n break;\n }\n case \"content_block_start\": {\n if (event.content_block?.type === \"tool_use\") {\n currentToolIndex = event.index ?? currentToolIndex + 1;\n toolCallAccum.set(currentToolIndex, {\n id: event.content_block.id ?? \"\",\n name: event.content_block.name ?? \"\",\n input: \"\",\n });\n }\n break;\n }\n case \"content_block_delta\": {\n if (event.delta?.type === \"text_delta\" && event.delta.text) {\n if (firstTextDelta) {\n ttftMs = Date.now() - streamStart;\n firstTextDelta = false;\n }\n output += event.delta.text;\n }\n if (\n event.delta?.type === \"input_json_delta\" &&\n event.delta.partial_json\n ) {\n const idx = event.index ?? currentToolIndex;\n const accum = toolCallAccum.get(idx);\n if (accum) {\n accum.input += event.delta.partial_json;\n }\n }\n break;\n }\n case \"message_delta\": {\n outputTokens = event.usage?.output_tokens ?? outputTokens;\n break;\n }\n }\n };\n\n const finalizeStream = () => {\n if (finalized) return;\n finalized = true;\n\n for (const tc of Array.from(toolCallAccum.values())) {\n const span = createToolSpan(tracer, root, {\n id: tc.id,\n name: tc.name,\n arguments: tc.input,\n });\n span.end({ status: \"completed\" });\n }\n\n endRootHandle(root, { output, inputTokens, outputTokens, ttftMs });\n };\n\n const originalIterator = (\n stream as { [Symbol.asyncIterator](): AsyncIterator<unknown> }\n )[Symbol.asyncIterator].bind(stream);\n\n return new Proxy(stream as object, {\n get(target, prop, receiver) {\n if (prop === Symbol.asyncIterator) {\n return () => {\n const iter = originalIterator();\n return {\n async next() {\n const result = await iter.next();\n if (!result.done) {\n processEvent(result.value as StreamEvent);\n }\n if (result.done) {\n finalizeStream();\n }\n return result;\n },\n async return(value?: unknown) {\n finalizeStream();\n return iter.return?.(value) ?? { done: true, value: undefined };\n },\n async throw(err?: unknown) {\n cleanupOnError(root, err);\n return iter.throw?.(err) ?? { done: true, value: undefined };\n },\n };\n };\n }\n if (prop === \"tee\") {\n return undefined;\n }\n return Reflect.get(target, prop, receiver);\n },\n });\n } catch (error) {\n cleanupOnError(root, error);\n throw error;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"anthropic.js","names":[],"sources":["../../src/integrations/anthropic.ts"],"sourcesContent":["import type { AuixPrism } from \"../client\";\nimport type { ToolCallInput } from \"../shared\";\nimport {\n cleanupOnError,\n createRootHandle,\n createToolSpan,\n endRootHandle,\n truncateInput,\n} from \"../shared\";\n\nexport interface AnthropicPrismOptions {\n name?: string;\n tags?: string[];\n metadata?: Record<string, unknown>;\n parentTraceId?: string;\n endUserId?: string;\n}\n\ninterface StreamEvent {\n type: string;\n message?: { usage?: { input_tokens?: number } };\n index?: number;\n content_block?: {\n type: string;\n id?: string;\n name?: string;\n text?: string;\n };\n delta?: {\n type: string;\n text?: string;\n partial_json?: string;\n stop_reason?: string;\n };\n usage?: { output_tokens?: number };\n}\n\n/**\n * Wraps an Anthropic client to automatically trace `messages.create` calls.\n *\n * Returns a proxy that behaves identically to the original client, but emits\n * trace events for both streaming and non-streaming message calls.\n */\nexport function prismAnthropic<T extends object>(\n tracer: AuixPrism,\n client: T,\n opts?: AnthropicPrismOptions,\n): T {\n return new Proxy(client, {\n get(target, prop, receiver) {\n if (prop === \"messages\") {\n const messages = Reflect.get(target, prop, receiver) as object;\n return new Proxy(messages, {\n get(msgTarget, msgProp, msgReceiver) {\n if (msgProp === \"create\") {\n return createInterceptor(\n tracer,\n Reflect.get(msgTarget, msgProp, msgReceiver).bind(msgTarget),\n opts,\n );\n }\n return Reflect.get(msgTarget, msgProp, msgReceiver);\n },\n });\n }\n return Reflect.get(target, prop, receiver);\n },\n });\n}\n\nfunction createInterceptor(\n tracer: AuixPrism,\n originalCreate: (...args: unknown[]) => Promise<unknown>,\n opts?: AnthropicPrismOptions,\n) {\n return async (params: Record<string, unknown>, ...rest: unknown[]) => {\n const model = (params.model as string) ?? \"unknown\";\n const input = truncateInput(params.messages);\n const metadata = opts?.metadata;\n const isStream = !!params.stream;\n\n const root = createRootHandle(\n tracer,\n opts,\n model,\n \"anthropic\",\n input,\n metadata,\n );\n\n if (!isStream) {\n return handleNonStreaming(tracer, root, originalCreate, params, rest);\n }\n\n return handleStreaming(tracer, root, originalCreate, params, rest);\n };\n}\n\nasync function handleNonStreaming(\n tracer: AuixPrism,\n root: ReturnType<typeof createRootHandle>,\n originalCreate: (...args: unknown[]) => Promise<unknown>,\n params: Record<string, unknown>,\n rest: unknown[],\n): Promise<unknown> {\n try {\n const result = (await originalCreate(params, ...rest)) as {\n content?: Array<\n | { type: \"text\"; text: string }\n | {\n type: \"tool_use\";\n id: string;\n name: string;\n input: unknown;\n }\n >;\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n };\n };\n\n const content = result.content ?? [];\n const output = content\n .filter((b): b is { type: \"text\"; text: string } => b.type === \"text\")\n .map((b) => b.text)\n .join(\"\");\n\n const inputTokens = result.usage?.input_tokens ?? 0;\n const outputTokens = result.usage?.output_tokens ?? 0;\n\n const toolUseBlocks = content.filter(\n (\n b,\n ): b is {\n type: \"tool_use\";\n id: string;\n name: string;\n input: unknown;\n } => b.type === \"tool_use\",\n );\n\n for (const tc of toolUseBlocks) {\n const span = createToolSpan(tracer, root, {\n id: tc.id,\n name: tc.name,\n input: JSON.stringify(tc.input),\n });\n span.end({ status: \"completed\" });\n }\n\n endRootHandle(root, { output, inputTokens, outputTokens });\n return result;\n } catch (error) {\n cleanupOnError(root, error);\n throw error;\n }\n}\n\nasync function handleStreaming(\n tracer: AuixPrism,\n root: ReturnType<typeof createRootHandle>,\n originalCreate: (...args: unknown[]) => Promise<unknown>,\n params: Record<string, unknown>,\n rest: unknown[],\n): Promise<unknown> {\n try {\n const streamStart = Date.now();\n const stream = await originalCreate(params, ...rest);\n\n let output = \"\";\n let inputTokens = 0;\n let outputTokens = 0;\n let ttftMs: number | undefined;\n let firstTextDelta = true;\n let finalized = false;\n const toolCallAccum = new Map<number, ToolCallInput>();\n let currentToolIndex = -1;\n\n const processEvent = (event: StreamEvent) => {\n switch (event.type) {\n case \"message_start\": {\n inputTokens = event.message?.usage?.input_tokens ?? 0;\n break;\n }\n case \"content_block_start\": {\n if (event.content_block?.type === \"tool_use\") {\n currentToolIndex = event.index ?? currentToolIndex + 1;\n toolCallAccum.set(currentToolIndex, {\n id: event.content_block.id ?? \"\",\n name: event.content_block.name ?? \"\",\n input: \"\",\n });\n }\n break;\n }\n case \"content_block_delta\": {\n if (event.delta?.type === \"text_delta\" && event.delta.text) {\n if (firstTextDelta) {\n ttftMs = Date.now() - streamStart;\n firstTextDelta = false;\n }\n output += event.delta.text;\n }\n if (\n event.delta?.type === \"input_json_delta\" &&\n event.delta.partial_json\n ) {\n const idx = event.index ?? currentToolIndex;\n const accum = toolCallAccum.get(idx);\n if (accum) {\n accum.input += event.delta.partial_json;\n }\n }\n break;\n }\n case \"message_delta\": {\n outputTokens = event.usage?.output_tokens ?? outputTokens;\n break;\n }\n }\n };\n\n const finalizeStream = () => {\n if (finalized) return;\n finalized = true;\n\n for (const tc of Array.from(toolCallAccum.values())) {\n const span = createToolSpan(tracer, root, tc);\n span.end({ status: \"completed\" });\n }\n\n endRootHandle(root, {\n output,\n inputTokens,\n outputTokens,\n ttftMs,\n });\n };\n\n const originalIterator = (\n stream as {\n [Symbol.asyncIterator](): AsyncIterator<unknown>;\n }\n )[Symbol.asyncIterator].bind(stream);\n\n return new Proxy(stream as object, {\n get(target, prop, receiver) {\n if (prop === Symbol.asyncIterator) {\n return () => {\n const iter = originalIterator();\n return {\n async next() {\n const result = await iter.next();\n if (!result.done) {\n processEvent(result.value as StreamEvent);\n }\n if (result.done) {\n finalizeStream();\n }\n return result;\n },\n async return(value?: unknown) {\n finalizeStream();\n return (\n iter.return?.(value) ?? {\n done: true,\n value: undefined,\n }\n );\n },\n async throw(err?: unknown) {\n cleanupOnError(root, err);\n return (\n iter.throw?.(err) ?? {\n done: true,\n value: undefined,\n }\n );\n },\n };\n };\n }\n if (prop === \"tee\") {\n return undefined;\n }\n return Reflect.get(target, prop, receiver);\n },\n });\n } catch (error) {\n cleanupOnError(root, error);\n throw error;\n }\n}\n"],"mappings":";;;;;;;;;AA2CA,SAAgB,eACd,QACA,QACA,MACG;AACH,QAAO,IAAI,MAAM,QAAQ,EACvB,IAAI,QAAQ,MAAM,UAAU;AAC1B,MAAI,SAAS,YAAY;GACvB,MAAM,WAAW,QAAQ,IAAI,QAAQ,MAAM,SAAS;AACpD,UAAO,IAAI,MAAM,UAAU,EACzB,IAAI,WAAW,SAAS,aAAa;AACnC,QAAI,YAAY,SACd,QAAO,kBACL,QACA,QAAQ,IAAI,WAAW,SAAS,YAAY,CAAC,KAAK,UAAU,EAC5D,KACD;AAEH,WAAO,QAAQ,IAAI,WAAW,SAAS,YAAY;MAEtD,CAAC;;AAEJ,SAAO,QAAQ,IAAI,QAAQ,MAAM,SAAS;IAE7C,CAAC;;AAGJ,SAAS,kBACP,QACA,gBACA,MACA;AACA,QAAO,OAAO,QAAiC,GAAG,SAAoB;EACpE,MAAM,QAAS,OAAO,SAAoB;EAC1C,MAAM,QAAQ,cAAc,OAAO,SAAS;EAC5C,MAAM,WAAW,MAAM;EACvB,MAAM,WAAW,CAAC,CAAC,OAAO;EAE1B,MAAM,OAAO,iBACX,QACA,MACA,OACA,aACA,OACA,SACD;AAED,MAAI,CAAC,SACH,QAAO,mBAAmB,QAAQ,MAAM,gBAAgB,QAAQ,KAAK;AAGvE,SAAO,gBAAgB,QAAQ,MAAM,gBAAgB,QAAQ,KAAK;;;AAItE,eAAe,mBACb,QACA,MACA,gBACA,QACA,MACkB;AAClB,KAAI;EACF,MAAM,SAAU,MAAM,eAAe,QAAQ,GAAG,KAAK;EAgBrD,MAAM,UAAU,OAAO,WAAW,EAAE;EACpC,MAAM,SAAS,QACZ,QAAQ,MAA2C,EAAE,SAAS,OAAO,CACrE,KAAK,MAAM,EAAE,KAAK,CAClB,KAAK,GAAG;EAEX,MAAM,cAAc,OAAO,OAAO,gBAAgB;EAClD,MAAM,eAAe,OAAO,OAAO,iBAAiB;EAEpD,MAAM,gBAAgB,QAAQ,QAE1B,MAMG,EAAE,SAAS,WACjB;AAED,OAAK,MAAM,MAAM,cAMf,CALa,eAAe,QAAQ,MAAM;GACxC,IAAI,GAAG;GACP,MAAM,GAAG;GACT,OAAO,KAAK,UAAU,GAAG,MAAM;GAChC,CAAC,CACG,IAAI,EAAE,QAAQ,aAAa,CAAC;AAGnC,gBAAc,MAAM;GAAE;GAAQ;GAAa;GAAc,CAAC;AAC1D,SAAO;UACA,OAAO;AACd,iBAAe,MAAM,MAAM;AAC3B,QAAM;;;AAIV,eAAe,gBACb,QACA,MACA,gBACA,QACA,MACkB;AAClB,KAAI;EACF,MAAM,cAAc,KAAK,KAAK;EAC9B,MAAM,SAAS,MAAM,eAAe,QAAQ,GAAG,KAAK;EAEpD,IAAI,SAAS;EACb,IAAI,cAAc;EAClB,IAAI,eAAe;EACnB,IAAI;EACJ,IAAI,iBAAiB;EACrB,IAAI,YAAY;EAChB,MAAM,gCAAgB,IAAI,KAA4B;EACtD,IAAI,mBAAmB;EAEvB,MAAM,gBAAgB,UAAuB;AAC3C,WAAQ,MAAM,MAAd;IACE,KAAK;AACH,mBAAc,MAAM,SAAS,OAAO,gBAAgB;AACpD;IAEF,KAAK;AACH,SAAI,MAAM,eAAe,SAAS,YAAY;AAC5C,yBAAmB,MAAM,SAAS,mBAAmB;AACrD,oBAAc,IAAI,kBAAkB;OAClC,IAAI,MAAM,cAAc,MAAM;OAC9B,MAAM,MAAM,cAAc,QAAQ;OAClC,OAAO;OACR,CAAC;;AAEJ;IAEF,KAAK;AACH,SAAI,MAAM,OAAO,SAAS,gBAAgB,MAAM,MAAM,MAAM;AAC1D,UAAI,gBAAgB;AAClB,gBAAS,KAAK,KAAK,GAAG;AACtB,wBAAiB;;AAEnB,gBAAU,MAAM,MAAM;;AAExB,SACE,MAAM,OAAO,SAAS,sBACtB,MAAM,MAAM,cACZ;MACA,MAAM,MAAM,MAAM,SAAS;MAC3B,MAAM,QAAQ,cAAc,IAAI,IAAI;AACpC,UAAI,MACF,OAAM,SAAS,MAAM,MAAM;;AAG/B;IAEF,KAAK;AACH,oBAAe,MAAM,OAAO,iBAAiB;AAC7C;;;EAKN,MAAM,uBAAuB;AAC3B,OAAI,UAAW;AACf,eAAY;AAEZ,QAAK,MAAM,MAAM,MAAM,KAAK,cAAc,QAAQ,CAAC,CAEjD,CADa,eAAe,QAAQ,MAAM,GAAG,CACxC,IAAI,EAAE,QAAQ,aAAa,CAAC;AAGnC,iBAAc,MAAM;IAClB;IACA;IACA;IACA;IACD,CAAC;;EAGJ,MAAM,mBACJ,OAGA,OAAO,eAAe,KAAK,OAAO;AAEpC,SAAO,IAAI,MAAM,QAAkB,EACjC,IAAI,QAAQ,MAAM,UAAU;AAC1B,OAAI,SAAS,OAAO,cAClB,cAAa;IACX,MAAM,OAAO,kBAAkB;AAC/B,WAAO;KACL,MAAM,OAAO;MACX,MAAM,SAAS,MAAM,KAAK,MAAM;AAChC,UAAI,CAAC,OAAO,KACV,cAAa,OAAO,MAAqB;AAE3C,UAAI,OAAO,KACT,iBAAgB;AAElB,aAAO;;KAET,MAAM,OAAO,OAAiB;AAC5B,sBAAgB;AAChB,aACE,KAAK,SAAS,MAAM,IAAI;OACtB,MAAM;OACN,OAAO;OACR;;KAGL,MAAM,MAAM,KAAe;AACzB,qBAAe,MAAM,IAAI;AACzB,aACE,KAAK,QAAQ,IAAI,IAAI;OACnB,MAAM;OACN,OAAO;OACR;;KAGN;;AAGL,OAAI,SAAS,MACX;AAEF,UAAO,QAAQ,IAAI,QAAQ,MAAM,SAAS;KAE7C,CAAC;UACK,OAAO;AACd,iBAAe,MAAM,MAAM;AAC3B,QAAM"}
|
|
@@ -1,76 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
const require_shared = require('../shared-Ch80RlSv.cjs');
|
|
2
3
|
|
|
3
4
|
//#region src/integrations/openai.ts
|
|
4
|
-
function truncateInput(messages, maxBytes = 32768) {
|
|
5
|
-
let json = JSON.stringify(messages);
|
|
6
|
-
if (new TextEncoder().encode(json).length <= maxBytes) return messages;
|
|
7
|
-
if (!Array.isArray(messages)) return messages;
|
|
8
|
-
const arr = [...messages];
|
|
9
|
-
while (arr.length > 1) {
|
|
10
|
-
arr.shift();
|
|
11
|
-
json = JSON.stringify(arr);
|
|
12
|
-
if (new TextEncoder().encode(json).length <= maxBytes) return arr;
|
|
13
|
-
}
|
|
14
|
-
return arr;
|
|
15
|
-
}
|
|
16
|
-
function createRootHandle(tracer, opts, model, input, metadata) {
|
|
17
|
-
const parentTraceId = opts?.parentTraceId;
|
|
18
|
-
if (parentTraceId) return {
|
|
19
|
-
isSpanMode: true,
|
|
20
|
-
traceId: parentTraceId,
|
|
21
|
-
handle: tracer.startSpanOnTrace(parentTraceId, {
|
|
22
|
-
name: opts?.name ?? model,
|
|
23
|
-
type: "llm",
|
|
24
|
-
input,
|
|
25
|
-
model,
|
|
26
|
-
provider: "openai",
|
|
27
|
-
metadata
|
|
28
|
-
})
|
|
29
|
-
};
|
|
30
|
-
const handle = tracer.startTrace({
|
|
31
|
-
name: opts?.name ?? model,
|
|
32
|
-
model,
|
|
33
|
-
provider: "openai",
|
|
34
|
-
input,
|
|
35
|
-
metadata,
|
|
36
|
-
tags: opts?.tags,
|
|
37
|
-
endUserId: opts?.endUserId
|
|
38
|
-
});
|
|
39
|
-
return {
|
|
40
|
-
isSpanMode: false,
|
|
41
|
-
traceId: handle.traceId,
|
|
42
|
-
handle
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
function createToolSpan(tracer, root, toolCall) {
|
|
46
|
-
if (root.isSpanMode) return tracer.startSpanOnTrace(root.traceId, {
|
|
47
|
-
name: toolCall.name,
|
|
48
|
-
type: "tool",
|
|
49
|
-
input: toolCall.arguments,
|
|
50
|
-
parentSpanId: root.handle.spanId
|
|
51
|
-
});
|
|
52
|
-
return root.handle.startSpan({
|
|
53
|
-
name: toolCall.name,
|
|
54
|
-
type: "tool",
|
|
55
|
-
input: toolCall.arguments
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
function endRootHandle(root, result) {
|
|
59
|
-
root.handle.end({
|
|
60
|
-
output: result.output,
|
|
61
|
-
status: "completed",
|
|
62
|
-
totalTokens: result.inputTokens + result.outputTokens,
|
|
63
|
-
promptTokens: result.inputTokens,
|
|
64
|
-
completionTokens: result.outputTokens,
|
|
65
|
-
ttftMs: result.ttftMs
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
function cleanupOnError(root, error) {
|
|
69
|
-
root.handle.end({
|
|
70
|
-
status: "error",
|
|
71
|
-
error: error instanceof Error ? error.message : String(error)
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
5
|
/**
|
|
75
6
|
* Wraps an OpenAI client to automatically trace `chat.completions.create` calls.
|
|
76
7
|
*
|
|
@@ -98,10 +29,10 @@ function prismOpenAI(tracer, client, opts) {
|
|
|
98
29
|
function createInterceptor(tracer, originalCreate, opts) {
|
|
99
30
|
return async (params, ...rest) => {
|
|
100
31
|
const model = params.model ?? "unknown";
|
|
101
|
-
const input = truncateInput(params.messages);
|
|
32
|
+
const input = require_shared.truncateInput(params.messages);
|
|
102
33
|
const metadata = opts?.metadata;
|
|
103
34
|
const isStream = !!params.stream;
|
|
104
|
-
const root = createRootHandle(tracer, opts, model, input, metadata);
|
|
35
|
+
const root = require_shared.createRootHandle(tracer, opts, model, "openai", input, metadata);
|
|
105
36
|
if (!isStream) return handleNonStreaming(tracer, root, originalCreate, params, rest);
|
|
106
37
|
return handleStreaming(tracer, root, originalCreate, params, rest);
|
|
107
38
|
};
|
|
@@ -113,19 +44,19 @@ async function handleNonStreaming(tracer, root, originalCreate, params, rest) {
|
|
|
113
44
|
const output = message?.content ?? "";
|
|
114
45
|
const inputTokens = result.usage?.prompt_tokens ?? 0;
|
|
115
46
|
const outputTokens = result.usage?.completion_tokens ?? 0;
|
|
116
|
-
if (message?.tool_calls) for (const tc of message.tool_calls) createToolSpan(tracer, root, {
|
|
47
|
+
if (message?.tool_calls) for (const tc of message.tool_calls) require_shared.createToolSpan(tracer, root, {
|
|
117
48
|
id: tc.id,
|
|
118
49
|
name: tc.function.name,
|
|
119
|
-
|
|
50
|
+
input: tc.function.arguments
|
|
120
51
|
}).end({ status: "completed" });
|
|
121
|
-
endRootHandle(root, {
|
|
52
|
+
require_shared.endRootHandle(root, {
|
|
122
53
|
output,
|
|
123
54
|
inputTokens,
|
|
124
55
|
outputTokens
|
|
125
56
|
});
|
|
126
57
|
return result;
|
|
127
58
|
} catch (error) {
|
|
128
|
-
cleanupOnError(root, error);
|
|
59
|
+
require_shared.cleanupOnError(root, error);
|
|
129
60
|
throw error;
|
|
130
61
|
}
|
|
131
62
|
}
|
|
@@ -162,13 +93,13 @@ async function handleStreaming(tracer, root, originalCreate, params, rest) {
|
|
|
162
93
|
accum = {
|
|
163
94
|
id: tc.id ?? "",
|
|
164
95
|
name: tc.function?.name ?? "",
|
|
165
|
-
|
|
96
|
+
input: ""
|
|
166
97
|
};
|
|
167
98
|
toolCallAccum.set(tc.index, accum);
|
|
168
99
|
}
|
|
169
100
|
if (tc.id) accum.id = tc.id;
|
|
170
101
|
if (tc.function?.name) accum.name = tc.function.name;
|
|
171
|
-
if (tc.function?.arguments) accum.
|
|
102
|
+
if (tc.function?.arguments) accum.input += tc.function.arguments;
|
|
172
103
|
}
|
|
173
104
|
if (chunk.usage) {
|
|
174
105
|
inputTokens = chunk.usage.prompt_tokens ?? 0;
|
|
@@ -178,8 +109,8 @@ async function handleStreaming(tracer, root, originalCreate, params, rest) {
|
|
|
178
109
|
const finalizeStream = () => {
|
|
179
110
|
if (finalized) return;
|
|
180
111
|
finalized = true;
|
|
181
|
-
for (const tc of Array.from(toolCallAccum.values())) createToolSpan(tracer, root, tc).end({ status: "completed" });
|
|
182
|
-
endRootHandle(root, {
|
|
112
|
+
for (const tc of Array.from(toolCallAccum.values())) require_shared.createToolSpan(tracer, root, tc).end({ status: "completed" });
|
|
113
|
+
require_shared.endRootHandle(root, {
|
|
183
114
|
output,
|
|
184
115
|
inputTokens,
|
|
185
116
|
outputTokens,
|
|
@@ -205,7 +136,7 @@ async function handleStreaming(tracer, root, originalCreate, params, rest) {
|
|
|
205
136
|
};
|
|
206
137
|
},
|
|
207
138
|
async throw(err) {
|
|
208
|
-
cleanupOnError(root, err);
|
|
139
|
+
require_shared.cleanupOnError(root, err);
|
|
209
140
|
return iter.throw?.(err) ?? {
|
|
210
141
|
done: true,
|
|
211
142
|
value: void 0
|
|
@@ -217,7 +148,7 @@ async function handleStreaming(tracer, root, originalCreate, params, rest) {
|
|
|
217
148
|
return Reflect.get(target, prop, receiver);
|
|
218
149
|
} });
|
|
219
150
|
} catch (error) {
|
|
220
|
-
cleanupOnError(root, error);
|
|
151
|
+
require_shared.cleanupOnError(root, error);
|
|
221
152
|
throw error;
|
|
222
153
|
}
|
|
223
154
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai.cjs","names":[],"sources":["../../src/integrations/openai.ts"],"sourcesContent":["import type { AuixPrism, SpanHandle, TraceHandle } from \"../client\";\n\nexport interface OpenAIPrismOptions {\n name?: string;\n tags?: string[];\n metadata?: Record<string, unknown>;\n parentTraceId?: string;\n endUserId?: string;\n}\n\ntype RootHandle =\n | { isSpanMode: true; traceId: string; handle: SpanHandle }\n | { isSpanMode: false; traceId: string; handle: TraceHandle };\n\nfunction truncateInput(messages: unknown, maxBytes = 32768): unknown {\n let json = JSON.stringify(messages);\n if (new TextEncoder().encode(json).length <= maxBytes) {\n return messages;\n }\n\n if (!Array.isArray(messages)) return messages;\n const arr = [...messages];\n while (arr.length > 1) {\n arr.shift();\n json = JSON.stringify(arr);\n if (new TextEncoder().encode(json).length <= maxBytes) {\n return arr;\n }\n }\n return arr;\n}\n\nfunction createRootHandle(\n tracer: AuixPrism,\n opts: OpenAIPrismOptions | undefined,\n model: string,\n input: unknown,\n metadata: Record<string, unknown> | undefined,\n): RootHandle {\n const parentTraceId = opts?.parentTraceId;\n\n if (parentTraceId) {\n const handle = tracer.startSpanOnTrace(parentTraceId, {\n name: opts?.name ?? model,\n type: \"llm\",\n input,\n model,\n provider: \"openai\",\n metadata,\n });\n return { isSpanMode: true, traceId: parentTraceId, handle };\n }\n\n const handle = tracer.startTrace({\n name: opts?.name ?? model,\n model,\n provider: \"openai\",\n input,\n metadata,\n tags: opts?.tags,\n endUserId: opts?.endUserId,\n });\n return { isSpanMode: false, traceId: handle.traceId, handle };\n}\n\nfunction createToolSpan(\n tracer: AuixPrism,\n root: RootHandle,\n toolCall: { id: string; name: string; arguments: string },\n): SpanHandle {\n if (root.isSpanMode) {\n return tracer.startSpanOnTrace(root.traceId, {\n name: toolCall.name,\n type: \"tool\",\n input: toolCall.arguments,\n parentSpanId: root.handle.spanId,\n });\n }\n return root.handle.startSpan({\n name: toolCall.name,\n type: \"tool\",\n input: toolCall.arguments,\n });\n}\n\nfunction endRootHandle(\n root: RootHandle,\n result: {\n output: string;\n inputTokens: number;\n outputTokens: number;\n ttftMs?: number;\n },\n): void {\n root.handle.end({\n output: result.output,\n status: \"completed\",\n totalTokens: result.inputTokens + result.outputTokens,\n promptTokens: result.inputTokens,\n completionTokens: result.outputTokens,\n ttftMs: result.ttftMs,\n });\n}\n\nfunction cleanupOnError(root: RootHandle, error: unknown): void {\n root.handle.end({\n status: \"error\",\n error: error instanceof Error ? error.message : String(error),\n });\n}\n\ninterface ToolCallDelta {\n index: number;\n id?: string;\n function?: { name?: string; arguments?: string };\n}\n\ninterface AccumulatedToolCall {\n id: string;\n name: string;\n arguments: string;\n}\n\n/**\n * Wraps an OpenAI client to automatically trace `chat.completions.create` calls.\n *\n * Returns a proxy that behaves identically to the original client, but emits\n * trace events for both streaming and non-streaming chat completions.\n */\nexport function prismOpenAI<T extends object>(\n tracer: AuixPrism,\n client: T,\n opts?: OpenAIPrismOptions,\n): T {\n return new Proxy(client, {\n get(target, prop, receiver) {\n if (prop === \"chat\") {\n const chat = Reflect.get(target, prop, receiver) as object;\n return new Proxy(chat, {\n get(chatTarget, chatProp, chatReceiver) {\n if (chatProp === \"completions\") {\n const completions = Reflect.get(\n chatTarget,\n chatProp,\n chatReceiver,\n );\n return new Proxy(completions, {\n get(compTarget, compProp, compReceiver) {\n if (compProp === \"create\") {\n return createInterceptor(\n tracer,\n Reflect.get(compTarget, compProp, compReceiver).bind(\n compTarget,\n ),\n opts,\n );\n }\n return Reflect.get(compTarget, compProp, compReceiver);\n },\n });\n }\n return Reflect.get(chatTarget, chatProp, chatReceiver);\n },\n });\n }\n return Reflect.get(target, prop, receiver);\n },\n });\n}\n\nfunction createInterceptor(\n tracer: AuixPrism,\n originalCreate: (...args: unknown[]) => Promise<unknown>,\n opts?: OpenAIPrismOptions,\n) {\n return async (params: Record<string, unknown>, ...rest: unknown[]) => {\n const model = (params.model as string) ?? \"unknown\";\n const input = truncateInput(params.messages);\n const metadata = opts?.metadata;\n const isStream = !!params.stream;\n\n const root = createRootHandle(tracer, opts, model, input, metadata);\n\n if (!isStream) {\n return handleNonStreaming(tracer, root, originalCreate, params, rest);\n }\n\n return handleStreaming(tracer, root, originalCreate, params, rest);\n };\n}\n\nasync function handleNonStreaming(\n tracer: AuixPrism,\n root: RootHandle,\n originalCreate: (...args: unknown[]) => Promise<unknown>,\n params: Record<string, unknown>,\n rest: unknown[],\n): Promise<unknown> {\n try {\n const result = (await originalCreate(params, ...rest)) as {\n choices?: Array<{\n message?: {\n content?: string | null;\n tool_calls?: Array<{\n id: string;\n function: { name: string; arguments: string };\n }>;\n };\n }>;\n usage?: {\n prompt_tokens?: number;\n completion_tokens?: number;\n total_tokens?: number;\n };\n };\n\n const message = result.choices?.[0]?.message;\n const output = message?.content ?? \"\";\n const inputTokens = result.usage?.prompt_tokens ?? 0;\n const outputTokens = result.usage?.completion_tokens ?? 0;\n\n if (message?.tool_calls) {\n for (const tc of message.tool_calls) {\n const span = createToolSpan(tracer, root, {\n id: tc.id,\n name: tc.function.name,\n arguments: tc.function.arguments,\n });\n span.end({ status: \"completed\" });\n }\n }\n\n endRootHandle(root, { output, inputTokens, outputTokens });\n return result;\n } catch (error) {\n cleanupOnError(root, error);\n throw error;\n }\n}\n\nasync function handleStreaming(\n tracer: AuixPrism,\n root: RootHandle,\n originalCreate: (...args: unknown[]) => Promise<unknown>,\n params: Record<string, unknown>,\n rest: unknown[],\n): Promise<unknown> {\n // Auto-inject stream_options to get usage data in the final chunk\n const patchedParams = {\n ...params,\n stream_options: {\n ...(params.stream_options as Record<string, unknown> | undefined),\n include_usage: true,\n },\n };\n\n try {\n const streamStart = Date.now();\n const stream = await originalCreate(patchedParams, ...rest);\n\n let output = \"\";\n let inputTokens = 0;\n let outputTokens = 0;\n let ttftMs: number | undefined;\n let firstChunk = true;\n let finalized = false;\n const toolCallAccum = new Map<number, AccumulatedToolCall>();\n\n const processChunk = (chunk: StreamChunk) => {\n const delta = chunk.choices?.[0]?.delta;\n\n if (delta?.content) {\n if (firstChunk) {\n ttftMs = Date.now() - streamStart;\n firstChunk = false;\n }\n output += delta.content;\n }\n\n if (delta?.tool_calls) {\n for (const tc of delta.tool_calls as ToolCallDelta[]) {\n let accum = toolCallAccum.get(tc.index);\n if (!accum) {\n accum = {\n id: tc.id ?? \"\",\n name: tc.function?.name ?? \"\",\n arguments: \"\",\n };\n toolCallAccum.set(tc.index, accum);\n }\n if (tc.id) accum.id = tc.id;\n if (tc.function?.name) accum.name = tc.function.name;\n if (tc.function?.arguments) accum.arguments += tc.function.arguments;\n }\n }\n\n if (chunk.usage) {\n inputTokens = chunk.usage.prompt_tokens ?? 0;\n outputTokens = chunk.usage.completion_tokens ?? 0;\n }\n };\n\n const finalizeStream = () => {\n if (finalized) return;\n finalized = true;\n\n for (const tc of Array.from(toolCallAccum.values())) {\n const span = createToolSpan(tracer, root, tc);\n span.end({ status: \"completed\" });\n }\n\n endRootHandle(root, { output, inputTokens, outputTokens, ttftMs });\n };\n\n const originalIterator = (\n stream as { [Symbol.asyncIterator](): AsyncIterator<unknown> }\n )[Symbol.asyncIterator].bind(stream);\n\n return new Proxy(stream as object, {\n get(target, prop, receiver) {\n if (prop === Symbol.asyncIterator) {\n return () => {\n const iter = originalIterator();\n return {\n async next() {\n const result = await iter.next();\n if (!result.done) {\n processChunk(result.value as StreamChunk);\n }\n if (result.done) {\n finalizeStream();\n }\n return result;\n },\n async return(value?: unknown) {\n finalizeStream();\n return iter.return?.(value) ?? { done: true, value: undefined };\n },\n async throw(err?: unknown) {\n cleanupOnError(root, err);\n return iter.throw?.(err) ?? { done: true, value: undefined };\n },\n };\n };\n }\n if (prop === \"tee\") {\n return undefined;\n }\n return Reflect.get(target, prop, receiver);\n },\n });\n } catch (error) {\n cleanupOnError(root, error);\n throw error;\n }\n}\n\ninterface StreamChunk {\n choices?: Array<{\n delta?: {\n content?: string;\n tool_calls?: ToolCallDelta[];\n };\n }>;\n usage?: {\n prompt_tokens?: number;\n completion_tokens?: number;\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"openai.cjs","names":["truncateInput","createRootHandle","createToolSpan"],"sources":["../../src/integrations/openai.ts"],"sourcesContent":["import type { AuixPrism } from \"../client\";\nimport type { ToolCallInput } from \"../shared\";\nimport {\n cleanupOnError,\n createRootHandle,\n createToolSpan,\n endRootHandle,\n truncateInput,\n} from \"../shared\";\n\nexport interface OpenAIPrismOptions {\n name?: string;\n tags?: string[];\n metadata?: Record<string, unknown>;\n parentTraceId?: string;\n endUserId?: string;\n}\n\ninterface ToolCallDelta {\n index: number;\n id?: string;\n function?: { name?: string; arguments?: string };\n}\n\n/**\n * Wraps an OpenAI client to automatically trace `chat.completions.create` calls.\n *\n * Returns a proxy that behaves identically to the original client, but emits\n * trace events for both streaming and non-streaming chat completions.\n */\nexport function prismOpenAI<T extends object>(\n tracer: AuixPrism,\n client: T,\n opts?: OpenAIPrismOptions,\n): T {\n return new Proxy(client, {\n get(target, prop, receiver) {\n if (prop === \"chat\") {\n const chat = Reflect.get(target, prop, receiver) as object;\n return new Proxy(chat, {\n get(chatTarget, chatProp, chatReceiver) {\n if (chatProp === \"completions\") {\n const completions = Reflect.get(\n chatTarget,\n chatProp,\n chatReceiver,\n );\n return new Proxy(completions, {\n get(compTarget, compProp, compReceiver) {\n if (compProp === \"create\") {\n return createInterceptor(\n tracer,\n Reflect.get(compTarget, compProp, compReceiver).bind(\n compTarget,\n ),\n opts,\n );\n }\n return Reflect.get(compTarget, compProp, compReceiver);\n },\n });\n }\n return Reflect.get(chatTarget, chatProp, chatReceiver);\n },\n });\n }\n return Reflect.get(target, prop, receiver);\n },\n });\n}\n\nfunction createInterceptor(\n tracer: AuixPrism,\n originalCreate: (...args: unknown[]) => Promise<unknown>,\n opts?: OpenAIPrismOptions,\n) {\n return async (params: Record<string, unknown>, ...rest: unknown[]) => {\n const model = (params.model as string) ?? \"unknown\";\n const input = truncateInput(params.messages);\n const metadata = opts?.metadata;\n const isStream = !!params.stream;\n\n const root = createRootHandle(\n tracer,\n opts,\n model,\n \"openai\",\n input,\n metadata,\n );\n\n if (!isStream) {\n return handleNonStreaming(tracer, root, originalCreate, params, rest);\n }\n\n return handleStreaming(tracer, root, originalCreate, params, rest);\n };\n}\n\nasync function handleNonStreaming(\n tracer: AuixPrism,\n root: ReturnType<typeof createRootHandle>,\n originalCreate: (...args: unknown[]) => Promise<unknown>,\n params: Record<string, unknown>,\n rest: unknown[],\n): Promise<unknown> {\n try {\n const result = (await originalCreate(params, ...rest)) as {\n choices?: Array<{\n message?: {\n content?: string | null;\n tool_calls?: Array<{\n id: string;\n function: { name: string; arguments: string };\n }>;\n };\n }>;\n usage?: {\n prompt_tokens?: number;\n completion_tokens?: number;\n total_tokens?: number;\n };\n };\n\n const message = result.choices?.[0]?.message;\n const output = message?.content ?? \"\";\n const inputTokens = result.usage?.prompt_tokens ?? 0;\n const outputTokens = result.usage?.completion_tokens ?? 0;\n\n if (message?.tool_calls) {\n for (const tc of message.tool_calls) {\n const span = createToolSpan(tracer, root, {\n id: tc.id,\n name: tc.function.name,\n input: tc.function.arguments,\n });\n span.end({ status: \"completed\" });\n }\n }\n\n endRootHandle(root, { output, inputTokens, outputTokens });\n return result;\n } catch (error) {\n cleanupOnError(root, error);\n throw error;\n }\n}\n\nasync function handleStreaming(\n tracer: AuixPrism,\n root: ReturnType<typeof createRootHandle>,\n originalCreate: (...args: unknown[]) => Promise<unknown>,\n params: Record<string, unknown>,\n rest: unknown[],\n): Promise<unknown> {\n const patchedParams = {\n ...params,\n stream_options: {\n ...(params.stream_options as Record<string, unknown> | undefined),\n include_usage: true,\n },\n };\n\n try {\n const streamStart = Date.now();\n const stream = await originalCreate(patchedParams, ...rest);\n\n let output = \"\";\n let inputTokens = 0;\n let outputTokens = 0;\n let ttftMs: number | undefined;\n let firstChunk = true;\n let finalized = false;\n const toolCallAccum = new Map<number, ToolCallInput>();\n\n const processChunk = (chunk: StreamChunk) => {\n const delta = chunk.choices?.[0]?.delta;\n\n if (delta?.content) {\n if (firstChunk) {\n ttftMs = Date.now() - streamStart;\n firstChunk = false;\n }\n output += delta.content;\n }\n\n if (delta?.tool_calls) {\n for (const tc of delta.tool_calls as ToolCallDelta[]) {\n let accum = toolCallAccum.get(tc.index);\n if (!accum) {\n accum = {\n id: tc.id ?? \"\",\n name: tc.function?.name ?? \"\",\n input: \"\",\n };\n toolCallAccum.set(tc.index, accum);\n }\n if (tc.id) accum.id = tc.id;\n if (tc.function?.name) accum.name = tc.function.name;\n if (tc.function?.arguments) accum.input += tc.function.arguments;\n }\n }\n\n if (chunk.usage) {\n inputTokens = chunk.usage.prompt_tokens ?? 0;\n outputTokens = chunk.usage.completion_tokens ?? 0;\n }\n };\n\n const finalizeStream = () => {\n if (finalized) return;\n finalized = true;\n\n for (const tc of Array.from(toolCallAccum.values())) {\n const span = createToolSpan(tracer, root, tc);\n span.end({ status: \"completed\" });\n }\n\n endRootHandle(root, {\n output,\n inputTokens,\n outputTokens,\n ttftMs,\n });\n };\n\n const originalIterator = (\n stream as {\n [Symbol.asyncIterator](): AsyncIterator<unknown>;\n }\n )[Symbol.asyncIterator].bind(stream);\n\n return new Proxy(stream as object, {\n get(target, prop, receiver) {\n if (prop === Symbol.asyncIterator) {\n return () => {\n const iter = originalIterator();\n return {\n async next() {\n const result = await iter.next();\n if (!result.done) {\n processChunk(result.value as StreamChunk);\n }\n if (result.done) {\n finalizeStream();\n }\n return result;\n },\n async return(value?: unknown) {\n finalizeStream();\n return (\n iter.return?.(value) ?? {\n done: true,\n value: undefined,\n }\n );\n },\n async throw(err?: unknown) {\n cleanupOnError(root, err);\n return (\n iter.throw?.(err) ?? {\n done: true,\n value: undefined,\n }\n );\n },\n };\n };\n }\n if (prop === \"tee\") {\n return undefined;\n }\n return Reflect.get(target, prop, receiver);\n },\n });\n } catch (error) {\n cleanupOnError(root, error);\n throw error;\n }\n}\n\ninterface StreamChunk {\n choices?: Array<{\n delta?: {\n content?: string;\n tool_calls?: ToolCallDelta[];\n };\n }>;\n usage?: {\n prompt_tokens?: number;\n completion_tokens?: number;\n };\n}\n"],"mappings":"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"}
|