oh-langfuse 0.1.29 → 0.1.30

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-langfuse",
3
- "version": "0.1.29",
3
+ "version": "0.1.30",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Use npm scripts to configure Claude Code / OpenCode / Codex with Langfuse tracing.",
@@ -132,10 +132,10 @@ export function buildInteractionMetadata(options = {}) {
132
132
  const sessionId = String(options.sessionId || options.session_id || "unknown");
133
133
  const turnNumber = Number(options.turnNumber ?? options.turn_number ?? 0) || 0;
134
134
  const tokenMetrics = normalizeTokenMetrics(options.tokenMetrics);
135
- const toolCallCount = Number(options.toolCallCount ?? options.tool_call_count ?? 0) || 0;
136
- const toolResultCount = Number(options.toolResultCount ?? options.tool_result_count ?? 0) || 0;
137
135
  const skillNames = normalizeSkillNames(options.skillNames ?? options.skill_names);
138
136
  const skillUseCount = skillNames.length || Number(options.skillUseCount ?? options.skill_use_count ?? 0) || 0;
137
+ const toolCallCount = Math.max(Number(options.toolCallCount ?? options.tool_call_count ?? 0) || 0, skillUseCount);
138
+ const toolResultCount = Math.max(Number(options.toolResultCount ?? options.tool_result_count ?? 0) || 0, skillUseCount);
139
139
 
140
140
  const metadata = {
141
141
  source,
@@ -172,47 +172,14 @@ export function buildInteractionMetadata(options = {}) {
172
172
  export function buildOpencodeMetricAttributes(options = {}) {
173
173
  const attrs = options.attributes || {};
174
174
  const userId = String(options.userId || attrs["oh.langfuse.user_id"] || attrs["langfuse.user.id"] || "");
175
- const sessionId = String(attrs["ai.request.headers.x-opencode-session"] || options.sessionId || options.session_id || "unknown");
176
- const requestId = String(attrs["ai.request.headers.x-opencode-request"] || options.requestId || options.request_id || "unknown");
177
- const spanId = String(options.spanId || attrs["span.id"] || "unknown");
178
175
  const provider = attrs["ai.model.provider"] || attrs["gen_ai.system"] || "";
179
176
  const modelId = attrs["ai.model.id"] || attrs["gen_ai.request.model"] || attrs["ai.response.model"] || "";
180
177
  const model = provider && modelId ? `${provider}/${modelId}` : provider || modelId || null;
181
- const skillNames = normalizeSkillNames(options.skillNames ?? options.skill_names);
182
- const toolCallCount = Number(options.toolCallCount ?? options.tool_call_count ?? 0) || 0;
183
- const toolResultCount = Number(options.toolResultCount ?? options.tool_result_count ?? 0) || 0;
184
- const tokenMetrics = normalizeTokenMetrics({
185
- input: attrs["ai.usage.inputTokens"] ?? attrs["ai.usage.promptTokens"] ?? attrs["gen_ai.usage.input_tokens"],
186
- output: attrs["ai.usage.outputTokens"] ?? attrs["ai.usage.completionTokens"] ?? attrs["gen_ai.usage.output_tokens"],
187
- total: attrs["ai.usage.totalTokens"],
188
- cacheRead: attrs["ai.usage.cachedInputTokens"] ?? attrs["ai.usage.inputTokenDetails.cacheReadTokens"],
189
- reasoning: attrs["ai.usage.reasoningTokens"] ?? attrs["ai.usage.outputTokenDetails.reasoningTokens"],
190
- });
191
-
192
- const out = {
178
+
179
+ return {
193
180
  "langfuse.observation.metadata.source": "opencode",
194
181
  "langfuse.observation.metadata.user_id": userId,
195
- "langfuse.observation.metadata.session_id": sessionId,
196
- "langfuse.observation.metadata.interaction_id": `opencode:${userId || "unknown"}:${sessionId}:${requestId}:${spanId}`,
197
182
  "langfuse.observation.metadata.metrics_schema_version": METRICS_SCHEMA_VERSION,
198
- "langfuse.observation.metadata.interaction_count": 1,
199
- "langfuse.observation.metadata.user_message_count": 1,
200
- "langfuse.observation.metadata.assistant_message_count": 1,
201
- "langfuse.observation.metadata.tool_call_count": toolCallCount,
202
- "langfuse.observation.metadata.tool_result_count": toolResultCount,
203
- "langfuse.observation.metadata.skill_use_count": skillNames.length,
204
- "langfuse.observation.metadata.token_metrics_available": tokenMetrics.token_metrics_available,
205
183
  "langfuse.observation.metadata.model": model,
206
184
  };
207
-
208
- if (skillNames.length) {
209
- out["langfuse.observation.metadata.skill_names"] = skillNames;
210
- out["langfuse.observation.metadata.skill_names_json"] = JSON.stringify(skillNames);
211
- }
212
-
213
- for (const key of ["input_tokens", "output_tokens", "total_tokens", "cache_read_tokens", "reasoning_tokens"]) {
214
- if (tokenMetrics[key] != null) out[`langfuse.observation.metadata.${key}`] = tokenMetrics[key];
215
- }
216
-
217
- return out;
218
185
  }
@@ -218,34 +218,10 @@ function getPatchedLangfuseDistIndexJs() {
218
218
  ' const hasModel = attrs["ai.model.id"] || attrs["ai.model.provider"] || attrs["gen_ai.request.model"];',
219
219
  ' const isTool = attrs["ai.toolCall.name"] || attrs["ai.toolCall.id"];',
220
220
  " if (!hasModel || isTool) return false;",
221
- ' if (typeof span.updateName === "function") span.updateName("AI Interaction");',
222
- ' const sessionId = String(attrs["ai.request.headers.x-opencode-session"] || attrs["session.id"] || "unknown");',
223
- ' const requestId = String(attrs["ai.request.headers.x-opencode-request"] || attrs["ai.response.id"] || attrs["ai.operationId"] || "unknown");',
224
- ' const spanId = span.spanContext?.().spanId || attrs["span.id"] || "unknown";',
225
221
  ' const provider = attrs["ai.model.provider"] || attrs["gen_ai.system"] || "";',
226
222
  ' const modelId = attrs["ai.model.id"] || attrs["gen_ai.request.model"] || attrs["ai.response.model"] || "";',
227
223
  ' const model = provider && modelId ? `${provider}/${modelId}` : provider || modelId || undefined;',
228
- ' const inputTokens = metricNumber(attrs["ai.usage.inputTokens"] ?? attrs["ai.usage.promptTokens"] ?? attrs["gen_ai.usage.input_tokens"]);',
229
- ' const outputTokens = metricNumber(attrs["ai.usage.outputTokens"] ?? attrs["ai.usage.completionTokens"] ?? attrs["gen_ai.usage.output_tokens"]);',
230
- ' const totalTokens = metricNumber(attrs["ai.usage.totalTokens"]) ?? (inputTokens !== undefined && outputTokens !== undefined ? inputTokens + outputTokens : undefined);',
231
- ' const cacheReadTokens = metricNumber(attrs["ai.usage.cachedInputTokens"] ?? attrs["ai.usage.inputTokenDetails.cacheReadTokens"]);',
232
- ' const reasoningTokens = metricNumber(attrs["ai.usage.reasoningTokens"] ?? attrs["ai.usage.outputTokenDetails.reasoningTokens"]);',
233
- " const tokenAvailable = [inputTokens, outputTokens, totalTokens, cacheReadTokens, reasoningTokens].some((value) => value !== undefined);",
234
- ' writeMetric(span, "session_id", sessionId);',
235
- ' writeMetric(span, "interaction_id", `opencode:${userId || "unknown"}:${sessionId}:${requestId}:${spanId}`);',
236
- ' writeMetric(span, "interaction_count", 1);',
237
- ' writeMetric(span, "user_message_count", 1);',
238
- ' writeMetric(span, "assistant_message_count", 1);',
239
- ' writeMetric(span, "token_metrics_available", tokenAvailable);',
240
- ' writeMetric(span, "tool_call_count", 0);',
241
- ' writeMetric(span, "tool_result_count", 0);',
242
- ' writeMetric(span, "skill_use_count", 0);',
243
224
  ' writeMetric(span, "model", model);',
244
- ' writeMetric(span, "input_tokens", inputTokens);',
245
- ' writeMetric(span, "output_tokens", outputTokens);',
246
- ' writeMetric(span, "total_tokens", totalTokens);',
247
- ' writeMetric(span, "cache_read_tokens", cacheReadTokens);',
248
- ' writeMetric(span, "reasoning_tokens", reasoningTokens);',
249
225
  " return true;",
250
226
  "};",
251
227
  "",
@@ -499,8 +475,8 @@ function getPatchedLangfuseDistIndexJs() {
499
475
  " const span = metricsTracer.startSpan('AI Interaction');",
500
476
  " const text = messageTextById.get(messageId) || '';",
501
477
  " const skillNames = [...new Set([...(skillNamesByMessageId.get(messageId) ?? []), ...(skillNamesBySessionId.get(sessionId) ?? [])])];",
502
- " const toolCallCount = new Set([...(toolCallIdsByMessageId.get(messageId) ?? []), ...(toolCallIdsBySessionId.get(sessionId) ?? [])]).size;",
503
- " const toolResultCount = new Set([...(toolResultIdsByMessageId.get(messageId) ?? []), ...(toolResultIdsBySessionId.get(sessionId) ?? [])]).size;",
478
+ " const toolCallCount = Math.max(new Set([...(toolCallIdsByMessageId.get(messageId) ?? []), ...(toolCallIdsBySessionId.get(sessionId) ?? [])]).size, skillNames.length);",
479
+ " const toolResultCount = Math.max(new Set([...(toolResultIdsByMessageId.get(messageId) ?? []), ...(toolResultIdsBySessionId.get(sessionId) ?? [])]).size, skillNames.length);",
504
480
  ' span.setAttribute("oh.langfuse.source", "opencode");',
505
481
  ' span.setAttribute("oh.langfuse.user_id", userId || "");',
506
482
  ' span.setAttribute("oh.langfuse.metrics_schema_version", "1.0");',