@tessar/opentelemetry 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,50 @@
1
+ import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
2
+ import { ExportResultCode } from "@opentelemetry/core";
3
+ class MappedExporter {
4
+ exporter;
5
+ map;
6
+ constructor(exporter, map) {
7
+ this.exporter = exporter;
8
+ this.map = map;
9
+ }
10
+ export(spans, done) {
11
+ try {
12
+ this.exporter.export(spans.map(this.map), done);
13
+ }
14
+ catch (error) {
15
+ done({
16
+ code: ExportResultCode.FAILED,
17
+ error: error instanceof Error ? error : Error(String(error)),
18
+ });
19
+ }
20
+ }
21
+ shutdown() {
22
+ return this.exporter.shutdown();
23
+ }
24
+ forceFlush() {
25
+ return this.exporter.forceFlush?.() ?? Promise.resolve();
26
+ }
27
+ }
28
+ /** Standard OTLP/HTTP JSON export, for compatible receivers and collectors. */
29
+ export class OTLPAdapter {
30
+ #options;
31
+ constructor(options = {}) {
32
+ if (options.endpoint &&
33
+ !["http:", "https:"].includes(new URL(options.endpoint).protocol))
34
+ throw Error("OTLP endpoint must use HTTP or HTTPS");
35
+ this.#options = {
36
+ ...options,
37
+ headers: options.headers ? { ...options.headers } : undefined,
38
+ };
39
+ }
40
+ mapSpan(span) {
41
+ return span;
42
+ }
43
+ createExporter() {
44
+ return new MappedExporter(new OTLPTraceExporter({
45
+ url: this.#options.endpoint,
46
+ headers: this.#options.headers,
47
+ }), (span) => this.mapSpan(span));
48
+ }
49
+ }
50
+ //# sourceMappingURL=otlp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otlp.js","sourceRoot":"","sources":["../../src/adapters/otlp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAC5E,OAAO,EAAE,gBAAgB,EAAqB,MAAM,qBAAqB,CAAC;AAU1E,MAAM,cAAc;IAEC,QAAQ;IACR,GAAG;IAFtB,YACmB,QAAsB,EACtB,GAAyC;wBADzC,QAAQ;mBACR,GAAG;IACnB,CAAC;IACJ,MAAM,CAAC,KAAqB,EAAE,IAAoC;QAChE,IAAI,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC;QAClD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC;gBACH,IAAI,EAAE,gBAAgB,CAAC,MAAM;gBAC7B,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;aAC7D,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,QAAQ;QACN,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;IAClC,CAAC;IACD,UAAU;QACR,OAAO,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3D,CAAC;CACF;AAED,+EAA+E;AAC/E,MAAM,OAAO,WAAW;IACb,QAAQ,CAAc;IAC/B,YAAY,OAAO,GAAgB,EAAE;QACnC,IACE,OAAO,CAAC,QAAQ;YAChB,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC;YAEjE,MAAM,KAAK,CAAC,sCAAsC,CAAC,CAAC;QACtD,IAAI,CAAC,QAAQ,GAAG;YACd,GAAG,OAAO;YACV,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS;SAC9D,CAAC;IACJ,CAAC;IACS,OAAO,CAAC,IAAkB;QAClC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,cAAc;QACZ,OAAO,IAAI,cAAc,CACvB,IAAI,iBAAiB,CAAC;YACpB,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ;YAC3B,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,OAAO;SAC/B,CAAC,EACF,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAC7B,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,8 @@
1
+ import type { Attributes } from "@opentelemetry/api";
2
+ import type { ReadableSpan } from "@opentelemetry/sdk-trace-base";
3
+ import type { ObservationAttributes, ObservationType } from "./types.js";
4
+ /** Shared spans contain standard GenAI fields and lossless Tessar payloads. */
5
+ export declare function observationAttributes(type: ObservationType, value: ObservationAttributes): Attributes;
6
+ export declare function readJson<T>(span: ReadableSpan, key: string): T | undefined;
7
+ /** Exporter-specific snapshots keep mappings isolated from the original span. */
8
+ export declare function mappedSpan(span: ReadableSpan, attributes: Attributes, resource?: import("@opentelemetry/resources").Resource): ReadableSpan;
@@ -0,0 +1,106 @@
1
+ import { genAIMessages } from "./messages.js";
2
+ /** Shared spans contain standard GenAI fields and lossless Tessar payloads. */
3
+ export function observationAttributes(type, value) {
4
+ const result = { "tessar.observation.type": type };
5
+ for (const [key, data] of Object.entries({
6
+ input: value.input,
7
+ output: value.output,
8
+ usage: value.usage,
9
+ "model.parameters": value.modelParameters,
10
+ }))
11
+ if (data !== undefined)
12
+ result["tessar." + key] = JSON.stringify(data);
13
+ if (value.completionStartTime !== undefined)
14
+ result["tessar.completion_start_time"] =
15
+ value.completionStartTime.toISOString();
16
+ for (const [key, data] of Object.entries(value.metadata ?? {}))
17
+ if (data !== undefined)
18
+ result["tessar.metadata." + key] = JSON.stringify(data);
19
+ if (value.level !== undefined)
20
+ result["tessar.level"] = value.level;
21
+ if (value.statusMessage !== undefined)
22
+ result["tessar.status_message"] = value.statusMessage;
23
+ if (value.model !== undefined)
24
+ result["gen_ai.request.model"] = value.model;
25
+ if (typeof value.metadata?.providerId === "string")
26
+ result["gen_ai.provider.name"] = value.metadata.providerId;
27
+ const operation = {
28
+ agent: "invoke_agent",
29
+ generation: "chat",
30
+ tool: "execute_tool",
31
+ span: undefined,
32
+ }[type];
33
+ if (operation)
34
+ result["gen_ai.operation.name"] = operation;
35
+ if (type === "tool") {
36
+ if (typeof value.metadata?.toolDescription === "string")
37
+ result["gen_ai.tool.description"] = value.metadata.toolDescription;
38
+ if (typeof value.metadata?.toolCallId === "string")
39
+ result["gen_ai.tool.call.id"] = value.metadata.toolCallId;
40
+ if (value.input !== undefined)
41
+ result["gen_ai.tool.call.arguments"] = JSON.stringify(value.input);
42
+ const output = value.output;
43
+ if (output?.role === "tool") {
44
+ const part = genAIMessages([output])[0].parts[0];
45
+ if ("response" in part)
46
+ result["gen_ai.tool.call.result"] = JSON.stringify(part.response);
47
+ }
48
+ }
49
+ if (type === "generation") {
50
+ const request = value.input;
51
+ if (request?.tools)
52
+ result["gen_ai.tool.definitions"] = JSON.stringify(request.tools.map((tool) => ({
53
+ type: "function",
54
+ name: tool.name,
55
+ description: tool.description,
56
+ parameters: tool.inputSchema,
57
+ })));
58
+ const instructions = request?.instructions?.sections
59
+ .filter((section) => section.content.length > 0)
60
+ .map((section) => ({ type: "text", content: section.content }));
61
+ if (instructions?.length)
62
+ result["gen_ai.system_instructions"] = JSON.stringify(instructions);
63
+ if (request?.messages)
64
+ result["gen_ai.input.messages"] = JSON.stringify(genAIMessages(request.messages));
65
+ const output = value.output;
66
+ if (output?.content)
67
+ result["gen_ai.output.messages"] = JSON.stringify(genAIMessages([output]));
68
+ }
69
+ for (const [key, count] of Object.entries({
70
+ input_tokens: value.usage?.inputTokens,
71
+ output_tokens: value.usage?.outputTokens,
72
+ "cache_read.input_tokens": value.usage?.cacheReadInputTokens,
73
+ "cache_creation.input_tokens": value.usage?.cacheWriteInputTokens,
74
+ "reasoning.output_tokens": value.usage?.reasoningOutputTokens,
75
+ }))
76
+ if (count !== null && count !== undefined)
77
+ result["gen_ai.usage." + key] = count;
78
+ return result;
79
+ }
80
+ export function readJson(span, key) {
81
+ const value = span.attributes[key];
82
+ return typeof value === "string" ? JSON.parse(value) : undefined;
83
+ }
84
+ /** Exporter-specific snapshots keep mappings isolated from the original span. */
85
+ export function mappedSpan(span, attributes, resource = span.resource) {
86
+ return {
87
+ name: span.name,
88
+ kind: span.kind,
89
+ spanContext: () => span.spanContext(),
90
+ parentSpanContext: span.parentSpanContext,
91
+ startTime: span.startTime,
92
+ endTime: span.endTime,
93
+ status: span.status,
94
+ attributes,
95
+ links: span.links,
96
+ events: span.events,
97
+ duration: span.duration,
98
+ ended: span.ended,
99
+ resource,
100
+ instrumentationScope: span.instrumentationScope,
101
+ droppedAttributesCount: span.droppedAttributesCount,
102
+ droppedEventsCount: span.droppedEventsCount,
103
+ droppedLinksCount: span.droppedLinksCount,
104
+ };
105
+ }
106
+ //# sourceMappingURL=attributes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attributes.js","sourceRoot":"","sources":["../src/attributes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { OpenTelemetryPlugin } from "./plugin.js";
2
+ export type { OpenTelemetryOptions, TraceAdapter } from "./types.js";
3
+ export { OTLPAdapter, type OTLPOptions } from "./adapters/otlp.js";
4
+ export { LangfuseAdapter, type LangfuseOptions } from "./adapters/langfuse.js";
5
+ export { LaminarAdapter, type LaminarOptions } from "./adapters/laminar.js";
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { OpenTelemetryPlugin } from "./plugin.js";
2
+ export { OTLPAdapter } from "./adapters/otlp.js";
3
+ export { LangfuseAdapter } from "./adapters/langfuse.js";
4
+ export { LaminarAdapter } from "./adapters/laminar.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,WAAW,EAAoB,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,eAAe,EAAwB,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,cAAc,EAAuB,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { type PluginContext } from "@tessar/core";
2
+ import { type TraceRuntime } from "./trace.js";
3
+ /** Persists Thread Turn counters and observes each execution segment. */
4
+ export declare function registerLifecycleHooks(tessar: PluginContext, tracing: TraceRuntime): void;
@@ -0,0 +1,162 @@
1
+ import { input, stream, turn, message, checkpoint as checkpointHooks, } from "@tessar/core";
2
+ import { update } from "./trace.js";
3
+ /** Persists Thread Turn counters and observes each execution segment. */
4
+ export function registerLifecycleHooks(tessar, tracing) {
5
+ const { executions, links, begin, current, parentTurn, end, finish } = tracing;
6
+ const savedTrace = tessar.state.define({
7
+ namespace: "trace",
8
+ schemaVersion: 1,
9
+ initial: {
10
+ turnCount: 0,
11
+ turnId: "",
12
+ },
13
+ fork: "reset",
14
+ });
15
+ tessar.hook(input.prepare, (event, context) => {
16
+ if (!event.sessionId || !event.streamId)
17
+ return;
18
+ const saved = context.state.get(savedTrace);
19
+ links.set(event.streamId, {
20
+ turnCount: saved.turnCount,
21
+ turnId: saved.turnId,
22
+ });
23
+ });
24
+ tessar.hook(turn.start, async (event, context) => {
25
+ if (!event.sessionId || !event.payload.turnId)
26
+ return;
27
+ const link = links.get(event.streamId);
28
+ if (!link)
29
+ return;
30
+ const saved = context.state.get(savedTrace), fresh = saved.turnId !== event.payload.turnId;
31
+ const value = {
32
+ turnId: event.payload.turnId,
33
+ turnCount: saved.turnCount + (fresh ? 1 : 0),
34
+ };
35
+ context.state.update(savedTrace, value);
36
+ Object.assign(link, value);
37
+ await context.state.commit();
38
+ });
39
+ tessar.defer(async () => {
40
+ for (const streamId of [...executions.keys()])
41
+ finish({ streamId }, "interrupted");
42
+ links.clear();
43
+ await tracing.shutdown();
44
+ });
45
+ tessar.hook(stream.started, (event) => {
46
+ begin(event, undefined, event.payload.startedAt);
47
+ });
48
+ const restore = (event, checkpointId, checkpoint) => {
49
+ const existing = current(event);
50
+ if (existing)
51
+ return existing;
52
+ // Keep counters from old snapshots; root/Turn-created flags are obsolete.
53
+ const snapshot = checkpoint?.state.pluginStates.find((value) => value.pluginId === "opentelemetry" &&
54
+ value.namespace === "trace" &&
55
+ value.ownerType === "thread");
56
+ if (event.sessionId && event.streamId && snapshot) {
57
+ const saved = snapshot.data;
58
+ links.set(event.streamId, {
59
+ turnCount: saved.turnCount,
60
+ turnId: saved.turnId,
61
+ });
62
+ }
63
+ const state = begin(event, checkpointId);
64
+ if (!state)
65
+ return;
66
+ update(state.root, "agent", {
67
+ input: { checkpointId },
68
+ metadata: { inputSource: "resume" },
69
+ });
70
+ if (!checkpoint)
71
+ return state;
72
+ const execution = checkpoint.execution;
73
+ if (!execution?.turnId || execution.phase === "BeforeTurn")
74
+ return state;
75
+ state.currentTurn = execution.turnId;
76
+ const span = parentTurn(state, event, execution.turnId, execution.budgets.turns - 1);
77
+ update(span, "span", {
78
+ input: { messages: checkpoint.state.messages },
79
+ metadata: { inputSource: "checkpoint" },
80
+ });
81
+ for (const message of checkpoint.state.messages)
82
+ for (const part of message.content)
83
+ if (part.type === "tool-call")
84
+ state.calls.set(part.toolCallId, {
85
+ name: part.name,
86
+ arguments: part.arguments,
87
+ });
88
+ return state;
89
+ };
90
+ tessar.hook(checkpointHooks.committed, async (event, context) => {
91
+ // Recovery can publish saved tool results before stream.resumed. Open its
92
+ // segment first; normal input.prepare has already installed its counter.
93
+ if (!event.streamId || current(event) || links.has(event.streamId))
94
+ return;
95
+ const checkpoint = await context.thread?.getCheckpoint(event.payload.checkpointId);
96
+ if (checkpoint?.execution)
97
+ restore(event, checkpoint.id, checkpoint);
98
+ });
99
+ tessar.hook(stream.resumed, async (event, context) => {
100
+ const checkpoint = await context.thread?.getCheckpoint(event.payload.checkpointId);
101
+ const state = restore(event, event.payload.checkpointId, checkpoint);
102
+ if (state)
103
+ update(state.root, "agent", {
104
+ input: event.payload,
105
+ metadata: { inputSource: "resume" },
106
+ });
107
+ });
108
+ tessar.hook(input.received, (event) => {
109
+ const state = current(event);
110
+ if (!state)
111
+ return;
112
+ update(state.root, "agent", { input: event.payload.messages });
113
+ });
114
+ tessar.hook(turn.start, (event) => {
115
+ const state = current(event);
116
+ if (!state)
117
+ return;
118
+ state.currentTurn = event.payload.turnId;
119
+ state.turnStartedAt = event.payload.startedAt ?? event.timestamp;
120
+ // Thread numbering is updated at turn.start before a model is selected.
121
+ if (!state.link)
122
+ parentTurn(state, event, event.payload.turnId, event.payload.index);
123
+ });
124
+ tessar.hook(turn.end, (event) => {
125
+ const state = current(event), turn = state?.turns.get(event.payload.turnId);
126
+ if (!turn)
127
+ return;
128
+ update(turn.span, "span", {
129
+ metadata: { usage: event.payload.usage, status: "ended" },
130
+ });
131
+ end(turn.span, event, event.payload.endedAt);
132
+ state.turns.delete(event.payload.turnId);
133
+ if (state.currentTurn === event.payload.turnId)
134
+ state.currentTurn = undefined;
135
+ });
136
+ tessar.hook(message.committed, (event) => {
137
+ const state = current(event), value = event.payload.message;
138
+ if (!state || (value.role !== "assistant" && value.role !== "tool"))
139
+ return;
140
+ state.output.push(value);
141
+ const turn = state.currentTurn
142
+ ? state.turns.get(state.currentTurn)
143
+ : undefined;
144
+ if (turn) {
145
+ turn.output.push(value);
146
+ update(turn.span, "span", { output: turn.output });
147
+ }
148
+ });
149
+ tessar.hook(stream.suspended, (event) => {
150
+ finish(event, "suspended");
151
+ });
152
+ tessar.hook(stream.end, (event) => {
153
+ finish(event, event.payload.status, event.payload.error, event.payload.output, event.payload.endedAt);
154
+ });
155
+ tessar.hook(stream.error, (event) => {
156
+ if (event.payload.target === "consumer")
157
+ return;
158
+ begin(event);
159
+ finish(event, "failed", event.payload.error, undefined, event.payload.endedAt);
160
+ });
161
+ }
162
+ //# sourceMappingURL=lifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../src/lifecycle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ import type { MessageData, ModelRequest } from "@tessar/core";
2
+ type TraceMessage = Pick<MessageData, "role" | "content" | "toolCallId">;
3
+ /** Display projection only: the provider request and its history remain unchanged. */
4
+ export declare function inputMessages(request: Pick<ModelRequest, "instructions" | "messages">): readonly TraceMessage[];
5
+ /** GenAI message parts keep visible reasoning separate from the final answer. */
6
+ export declare function genAIMessages(values: readonly TraceMessage[]): {
7
+ role: import("@tessar/core").MessageRole;
8
+ parts: {
9
+ type: string;
10
+ id?: string | undefined;
11
+ response: (import("@tessar/core").JsonValue | ({
12
+ readonly type: "reasoning";
13
+ readonly text: string;
14
+ readonly providerState?: import("@tessar/core").JsonValue;
15
+ } & {
16
+ readonly metadata?: import("@tessar/core").JsonObject;
17
+ }) | ({
18
+ readonly type: "tool-call";
19
+ readonly toolCallId: string;
20
+ readonly name: string;
21
+ readonly arguments: import("@tessar/core").JsonObject;
22
+ } & {
23
+ readonly metadata?: import("@tessar/core").JsonObject;
24
+ }) | ({
25
+ readonly type: "image" | "audio" | "file";
26
+ readonly mediaType: string;
27
+ readonly data: string;
28
+ } & {
29
+ readonly metadata?: import("@tessar/core").JsonObject;
30
+ }))[] | import("@tessar/core").JsonValue | ({
31
+ readonly type: "reasoning";
32
+ readonly text: string;
33
+ readonly providerState?: import("@tessar/core").JsonValue;
34
+ } & {
35
+ readonly metadata?: import("@tessar/core").JsonObject;
36
+ }) | ({
37
+ readonly type: "tool-call";
38
+ readonly toolCallId: string;
39
+ readonly name: string;
40
+ readonly arguments: import("@tessar/core").JsonObject;
41
+ } & {
42
+ readonly metadata?: import("@tessar/core").JsonObject;
43
+ }) | ({
44
+ readonly type: "image" | "audio" | "file";
45
+ readonly mediaType: string;
46
+ readonly data: string;
47
+ } & {
48
+ readonly metadata?: import("@tessar/core").JsonObject;
49
+ });
50
+ }[] | ({
51
+ type: "reasoning" | "text";
52
+ content: string;
53
+ id?: undefined;
54
+ name?: undefined;
55
+ arguments?: undefined;
56
+ } | {
57
+ content?: undefined;
58
+ type: string;
59
+ id: string;
60
+ name: string;
61
+ arguments: import("@tessar/core").JsonObject;
62
+ } | ({
63
+ readonly type: "image" | "audio" | "file";
64
+ readonly mediaType: string;
65
+ readonly data: string;
66
+ } & {
67
+ readonly metadata?: import("@tessar/core").JsonObject;
68
+ }) | ({
69
+ readonly type: "data";
70
+ readonly data: import("@tessar/core").JsonValue;
71
+ } & {
72
+ readonly metadata?: import("@tessar/core").JsonObject;
73
+ }))[];
74
+ }[];
75
+ export {};
@@ -0,0 +1,55 @@
1
+ /** Display projection only: the provider request and its history remain unchanged. */
2
+ export function inputMessages(request) {
3
+ const sections = request.instructions.sections;
4
+ if (!sections.some((section) => section.content.length > 0))
5
+ return request.messages;
6
+ return [
7
+ {
8
+ role: "system",
9
+ content: [
10
+ {
11
+ type: "text",
12
+ text: sections.map((section) => section.content).join("\n\n"),
13
+ },
14
+ ],
15
+ },
16
+ ...request.messages,
17
+ ];
18
+ }
19
+ /** GenAI message parts keep visible reasoning separate from the final answer. */
20
+ export function genAIMessages(values) {
21
+ return values.map((message) => ({
22
+ role: message.role,
23
+ parts: message.role === "tool"
24
+ ? [
25
+ {
26
+ type: "tool_call_response",
27
+ ...(message.toolCallId ? { id: message.toolCallId } : {}),
28
+ response: message.content.length === 1
29
+ ? toolContent(message.content[0])
30
+ : message.content.map(toolContent),
31
+ },
32
+ ]
33
+ : message.content.map((part) => {
34
+ if (part.type === "text" || part.type === "reasoning")
35
+ return { type: part.type, content: part.text };
36
+ if (part.type === "tool-call")
37
+ return {
38
+ type: "tool_call",
39
+ id: part.toolCallId,
40
+ name: part.name,
41
+ arguments: part.arguments,
42
+ };
43
+ // Media/custom parts retain their declared type and data as generic parts.
44
+ return part;
45
+ }),
46
+ }));
47
+ }
48
+ function toolContent(part) {
49
+ return part.type === "text"
50
+ ? part.text
51
+ : part.type === "data"
52
+ ? part.data
53
+ : part;
54
+ }
55
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"AAIA,sFAAsF;AACtF,MAAM,UAAU,aAAa,CAC3B,OAAwD;IAExD,MAAM,QAAQ,GAAG,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC;IAC/C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;QACzD,OAAO,OAAO,CAAC,QAAQ,CAAC;IAC1B,OAAO;QACL;YACE,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;iBAC9D;aACF;SACF;QACD,GAAG,OAAO,CAAC,QAAQ;KACpB,CAAC;AACJ,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,aAAa,CAAC,MAA+B;IAC3D,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC9B,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,KAAK,EACH,OAAO,CAAC,IAAI,KAAK,MAAM;YACrB,CAAC,CAAC;gBACE;oBACE,IAAI,EAAE,oBAAoB;oBAC1B,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACzD,QAAQ,EACN,OAAO,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;wBAC1B,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC;wBAClC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;iBACvC;aACF;YACH,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;gBAC3B,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW;oBACnD,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;gBACjD,IAAI,IAAI,CAAC,IAAI,KAAK,WAAW;oBAC3B,OAAO;wBACL,IAAI,EAAE,WAAW;wBACjB,EAAE,EAAE,IAAI,CAAC,UAAU;wBACnB,IAAI,EAAE,IAAI,CAAC,IAAI;wBACf,SAAS,EAAE,IAAI,CAAC,SAAS;qBAC1B,CAAC;gBACJ,2EAA2E;gBAC3E,OAAO,IAAI,CAAC;YACd,CAAC,CAAC;KACT,CAAC,CAAC,CAAC;AACN,CAAC;AAED,SAAS,WAAW,CAAC,IAAoC;IACvD,OAAO,IAAI,CAAC,IAAI,KAAK,MAAM;QACzB,CAAC,CAAC,IAAI,CAAC,IAAI;QACX,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,MAAM;YACpB,CAAC,CAAC,IAAI,CAAC,IAAI;YACX,CAAC,CAAC,IAAI,CAAC;AACb,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { type PluginContext } from "@tessar/core";
2
+ import { type TraceRuntime } from "./trace.js";
3
+ /** Records model requests, retries, usage and time to first output. */
4
+ export declare function registerModelHooks(tessar: PluginContext, tracing: TraceRuntime): void;
package/dist/models.js ADDED
@@ -0,0 +1,103 @@
1
+ import { model, text, reasoning, } from "@tessar/core";
2
+ import { time, update } from "./trace.js";
3
+ /** Records model requests, retries, usage and time to first output. */
4
+ export function registerModelHooks(tessar, tracing) {
5
+ const { current, parentTurn, start, end, failure } = tracing;
6
+ const capturedInstructions = new WeakSet();
7
+ tessar.hook(model.start, (event) => {
8
+ const state = current(event);
9
+ if (!state || state.models.has(event.payload.attemptId))
10
+ return;
11
+ const { attemptId, request, purpose, parentToolExecutionId, turnId } = event.payload;
12
+ if (turnId && purpose !== "auxiliary")
13
+ state.currentTurn = turnId;
14
+ if (purpose !== "auxiliary" && request) {
15
+ // Keep the first effective primary instructions for root display without
16
+ // replacing the invocation input or letting later Turns overwrite it.
17
+ if (!capturedInstructions.has(state.root)) {
18
+ state.root.setAttribute("tessar.instructions", JSON.stringify(request.instructions));
19
+ capturedInstructions.add(state.root);
20
+ }
21
+ update(parentTurn(state, event, turnId), "span", {
22
+ input: request,
23
+ metadata: { inputSource: "normalized-context" },
24
+ });
25
+ }
26
+ const parent = parentToolExecutionId
27
+ ? state.tools.get(parentToolExecutionId)
28
+ : undefined;
29
+ const span = start(event.payload.model.modelId, "generation", event, {
30
+ ...state.identity,
31
+ attemptId,
32
+ purpose,
33
+ parentToolExecutionId,
34
+ turnId,
35
+ providerId: event.payload.model.providerId,
36
+ options: request?.options,
37
+ }, parent ??
38
+ (purpose === "auxiliary" && state.currentTurn !== turnId
39
+ ? state.root
40
+ : parentTurn(state, event, turnId)), {
41
+ model: event.payload.model.modelId,
42
+ input: request,
43
+ modelParameters: Object.fromEntries(Object.entries(request?.options ?? {}).filter(([, value]) => typeof value === "string" || typeof value === "number")),
44
+ }, event.payload.startedAt);
45
+ state.models.set(attemptId, span);
46
+ });
47
+ for (const name of [text.delta, reasoning.delta])
48
+ tessar.hook(name, (event) => {
49
+ if (!event.payload.delta)
50
+ return;
51
+ const state = current(event), span = state?.models.get(event.payload.attemptId);
52
+ if (!span || state.firstOutputs.has(event.payload.attemptId))
53
+ return;
54
+ state.firstOutputs.add(event.payload.attemptId);
55
+ update(span, "generation", {
56
+ completionStartTime: time(event) ?? new Date(),
57
+ });
58
+ });
59
+ const recordUsage = (span, usage) => update(span, "generation", {
60
+ usage,
61
+ metadata: { usage },
62
+ });
63
+ tessar.hook(model.usage, (event) => {
64
+ const span = current(event)?.models.get(event.payload.attemptId);
65
+ if (span)
66
+ recordUsage(span, event.payload.usage);
67
+ });
68
+ tessar.hook(model.end, (event) => {
69
+ const state = current(event), span = state?.models.get(event.payload.attemptId);
70
+ if (!span)
71
+ return;
72
+ const { response } = event.payload;
73
+ if (response.usage)
74
+ recordUsage(span, response.usage);
75
+ update(span, "generation", {
76
+ output: response.message,
77
+ metadata: {
78
+ finishReason: response.finishReason,
79
+ providerRequestId: response.providerRequestId,
80
+ },
81
+ });
82
+ if (event.payload.purpose !== "auxiliary")
83
+ for (const part of response.message.content)
84
+ if (part.type === "tool-call")
85
+ state.calls.set(part.toolCallId, {
86
+ name: part.name,
87
+ arguments: part.arguments,
88
+ });
89
+ end(span, event, event.payload.endedAt);
90
+ state.models.delete(event.payload.attemptId);
91
+ state.firstOutputs.delete(event.payload.attemptId);
92
+ });
93
+ tessar.hook(model.error, (event) => {
94
+ const state = current(event), span = state?.models.get(event.payload.attemptId);
95
+ if (!span)
96
+ return;
97
+ failure(span, "generation", event.payload.error);
98
+ end(span, event, event.payload.endedAt);
99
+ state.models.delete(event.payload.attemptId);
100
+ state.firstOutputs.delete(event.payload.attemptId);
101
+ });
102
+ }
103
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../src/models.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { Plugin, PluginContext } from "@tessar/core";
2
+ import type { OpenTelemetryOptions } from "./types.js";
3
+ /** One shared tracing lifecycle with independently mapped export destinations. */
4
+ export declare class OpenTelemetryPlugin implements Plugin {
5
+ #private;
6
+ readonly id = "opentelemetry";
7
+ constructor(options: OpenTelemetryOptions);
8
+ setup(tessar: PluginContext): Promise<void>;
9
+ }