@juspay/neurolink 12.52.1 → 12.54.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.
@@ -60,6 +60,7 @@ export declare enum AIProviderName {
60
60
  LEMONFOX_AI = "lemonfox-ai",
61
61
  LILAC = "lilac",
62
62
  LLMTECH = "llmtech",
63
+ LONGCAT = "longcat",
63
64
  MANCER = "mancer",
64
65
  META_MODEL_API = "meta-model-api",
65
66
  MINIMAX = "minimax",
@@ -1346,6 +1347,9 @@ export declare enum LilacModels {
1346
1347
  export declare enum LlmtechModels {
1347
1348
  NVIDIA_QWEN3_8_27B_NVFP4 = "nvidia/Qwen3.8-27B-NVFP4"
1348
1349
  }
1350
+ export declare enum LongCatModels {
1351
+ LONGCAT_2_5_PREVIEW = "LongCat-2.5-Preview"
1352
+ }
1349
1353
  export declare enum MancerModels {
1350
1354
  MYTHOMAX = "mythomax",
1351
1355
  DEEPSEEK_V4_FLASH = "deepseek-v4-flash",
@@ -65,6 +65,7 @@ export var AIProviderName;
65
65
  AIProviderName["LEMONFOX_AI"] = "lemonfox-ai";
66
66
  AIProviderName["LILAC"] = "lilac";
67
67
  AIProviderName["LLMTECH"] = "llmtech";
68
+ AIProviderName["LONGCAT"] = "longcat";
68
69
  AIProviderName["MANCER"] = "mancer";
69
70
  AIProviderName["META_MODEL_API"] = "meta-model-api";
70
71
  AIProviderName["MINIMAX"] = "minimax";
@@ -1626,6 +1627,10 @@ export var LlmtechModels;
1626
1627
  (function (LlmtechModels) {
1627
1628
  LlmtechModels["NVIDIA_QWEN3_8_27B_NVFP4"] = "nvidia/Qwen3.8-27B-NVFP4";
1628
1629
  })(LlmtechModels || (LlmtechModels = {}));
1630
+ export var LongCatModels;
1631
+ (function (LongCatModels) {
1632
+ LongCatModels["LONGCAT_2_5_PREVIEW"] = "LongCat-2.5-Preview";
1633
+ })(LongCatModels || (LongCatModels = {}));
1629
1634
  export var MancerModels;
1630
1635
  (function (MancerModels) {
1631
1636
  MancerModels["MYTHOMAX"] = "mythomax";
@@ -33,7 +33,15 @@ export function guardToolExecutor(name, execute, guards) {
33
33
  // The span wraps the CALL, not the guard: a timeout or an abort is a fact
34
34
  // about this tool invocation and belongs inside its observation.
35
35
  const wrapInSpan = guards.withToolSpan;
36
- const call = wrapInSpan ? () => wrapInSpan(name, invoke) : invoke;
36
+ const toolCallId = typeof opts === "object" &&
37
+ opts !== null &&
38
+ "toolCallId" in opts &&
39
+ typeof opts.toolCallId === "string"
40
+ ? opts.toolCallId
41
+ : undefined;
42
+ const call = wrapInSpan
43
+ ? () => wrapInSpan(name, invoke, { args, toolCallId })
44
+ : invoke;
37
45
  guards.onProgress?.();
38
46
  try {
39
47
  const raced = guards.abortSignal
@@ -1,5 +1,5 @@
1
1
  import type { DecideCatalogJson, ProviderCatalogJson } from "../../types/index.js";
2
2
  export declare const CATALOG_JSON_ENTRIES: ProviderCatalogJson[];
3
- export declare const CATALOG_PROVIDER_IDS: readonly ["a2agent", "abliteration", "above-dev", "ai21", "aiand", "aihubmix", "aionlabs", "ambient", "api-route", "arcee", "atlas-cloud", "avian-io", "baidu-qianfan", "baseten", "bee-heossi", "byteplus-modelark", "bytez", "cerebras", "charm-hyper", "chutes", "cloudflare", "crusoe", "dashscope", "deepinfra", "deepseek", "empiriolabs", "featherless-ai", "fireworks", "friendli", "gmicloud", "gradientai", "groq", "hetzner-inference", "huggingface", "inception-labs", "inceptron", "inco", "inference-net", "io-intelligence", "koscompute", "lemonfox-ai", "lilac", "llmtech", "mancer", "meta-model-api", "minimax", "mistral", "moark", "modelscope", "moonshot-ai", "morph", "naver-clova-studio", "nebius", "neuralwatt", "novita", "ovhcloud", "parasail", "pareto-inference", "perplexity", "poolside", "prime-intellect", "reka", "sakana-ai", "sambanova", "sarvam", "scaleway", "siliconflow", "stackit", "stepfun", "subconscious", "synthetic", "telnyx", "thinking-machines", "tinfoil", "together-ai", "umans-ai", "upstage", "venice-ai", "vispark", "vultr-inference", "wafer", "wandb-inference", "xai", "xiaomi-mimo", "z-ai"];
3
+ export declare const CATALOG_PROVIDER_IDS: readonly ["a2agent", "abliteration", "above-dev", "ai21", "aiand", "aihubmix", "aionlabs", "ambient", "api-route", "arcee", "atlas-cloud", "avian-io", "baidu-qianfan", "baseten", "bee-heossi", "byteplus-modelark", "bytez", "cerebras", "charm-hyper", "chutes", "cloudflare", "crusoe", "dashscope", "deepinfra", "deepseek", "empiriolabs", "featherless-ai", "fireworks", "friendli", "gmicloud", "gradientai", "groq", "hetzner-inference", "huggingface", "inception-labs", "inceptron", "inco", "inference-net", "io-intelligence", "koscompute", "lemonfox-ai", "lilac", "llmtech", "longcat", "mancer", "meta-model-api", "minimax", "mistral", "moark", "modelscope", "moonshot-ai", "morph", "naver-clova-studio", "nebius", "neuralwatt", "novita", "ovhcloud", "parasail", "pareto-inference", "perplexity", "poolside", "prime-intellect", "reka", "sakana-ai", "sambanova", "sarvam", "scaleway", "siliconflow", "stackit", "stepfun", "subconscious", "synthetic", "telnyx", "thinking-machines", "tinfoil", "together-ai", "umans-ai", "upstage", "venice-ai", "vispark", "vultr-inference", "wafer", "wandb-inference", "xai", "xiaomi-mimo", "z-ai"];
4
4
  export declare const DECIDE_CATALOG_JSON_ENTRIES: DecideCatalogJson[];
5
5
  export declare const DECIDE_CATALOG_PROVIDER_IDS: readonly ["laya"];
@@ -44,6 +44,7 @@ import layaJson from "./laya.json" with { type: "json" };
44
44
  import lemonfoxAiJson from "./lemonfox-ai.json" with { type: "json" };
45
45
  import lilacJson from "./lilac.json" with { type: "json" };
46
46
  import llmtechJson from "./llmtech.json" with { type: "json" };
47
+ import longcatJson from "./longcat.json" with { type: "json" };
47
48
  import mancerJson from "./mancer.json" with { type: "json" };
48
49
  import metaModelApiJson from "./meta-model-api.json" with { type: "json" };
49
50
  import minimaxJson from "./minimax.json" with { type: "json" };
@@ -138,6 +139,7 @@ export const CATALOG_JSON_ENTRIES = [
138
139
  lemonfoxAiJson,
139
140
  lilacJson,
140
141
  llmtechJson,
142
+ longcatJson,
141
143
  mancerJson,
142
144
  metaModelApiJson,
143
145
  minimaxJson,
@@ -225,6 +227,7 @@ export const CATALOG_PROVIDER_IDS = [
225
227
  "lemonfox-ai",
226
228
  "lilac",
227
229
  "llmtech",
230
+ "longcat",
228
231
  "mancer",
229
232
  "meta-model-api",
230
233
  "minimax",
@@ -0,0 +1,64 @@
1
+ {
2
+ "$schema": "./provider-catalog.schema.json",
3
+ "id": "longcat",
4
+ "displayName": "LongCat",
5
+ "enumTypeName": "LongCatModels",
6
+ "aliases": [],
7
+ "tier": 2,
8
+ "wire": {
9
+ "baseURL": "https://api.longcat.chat/openai/v1"
10
+ },
11
+ "models": {
12
+ "default": "LongCat-2.5-Preview",
13
+ "fallbacks": ["LongCat-2.5-Preview"],
14
+ "defaultContextWindow": 1048576,
15
+ "defaultMaxOutputTokens": 131072,
16
+ "catalog": {
17
+ "LongCat-2.5-Preview": {
18
+ "contextWindow": 1048576,
19
+ "maxOutputTokens": 131072,
20
+ "vision": false,
21
+ "status": "preview",
22
+ "description": "Meituan LongCat 2.5 Preview, the only model this pilot lists. The 1M-token context rests on the vendor's Retrieve Model sample for this model id, not on a normative sentence. This pilot declares text generate/stream only; tools, vision, structured output and thinking await separate evidence. Account access is unverified."
23
+ }
24
+ }
25
+ },
26
+ "capabilities": {
27
+ "text": true,
28
+ "streaming": true,
29
+ "tools": false,
30
+ "toolsWithStreaming": false,
31
+ "structuredOutput": false,
32
+ "structuredOutputWithTools": false,
33
+ "embeddings": false,
34
+ "thinking": false
35
+ },
36
+ "errorRules": [
37
+ {
38
+ "status": 401,
39
+ "class": "authentication",
40
+ "message": "Invalid or expired LongCat API key. Check {apiKeyEnvVar} and the key in the LongCat platform console at {setupUrl}."
41
+ }
42
+ ],
43
+ "setup": {
44
+ "url": "https://longcat.chat/platform",
45
+ "apiKeyFormat": null,
46
+ "billingPolicy": "no-free-tier",
47
+ "instructions": [
48
+ "1. Sign in to the LongCat API platform and create an API key.",
49
+ "2. LongCat-2.5-Preview is usage-priced pay-as-you-go. Promotional credits, if your account has any, are consumed first, but no free allowance is stated: do not assume free usage. The vendor's Pay-As-You-Go page says account verification is required before topping up, and its FAQ scopes that requirement to users in Mainland China (not tried on an account).",
50
+ "3. LongCat-2.0 is served on the same route but is outside this pilot's catalog scope, so it is not a default or a fallback here.",
51
+ "4. Set {apiKeyEnvVar} for this provider. The base URL is https://api.longcat.chat/openai/v1 and the chat route is POST /chat/completions with Authorization: Bearer authentication."
52
+ ],
53
+ "description": "LongCat (Meituan) text/stream pilot with a usage-priced LongCat-2.5-Preview default. No free allowance is stated; no account entitlement, roster, live inference or delivery is verified."
54
+ },
55
+ "evidence": {
56
+ "rosterVerified": {
57
+ "date": "2026-10-12",
58
+ "code": "VENDOR_DOCS_ONLY_NOT_ROSTER_VERIFIED",
59
+ "method": "Vendor API documentation facts supplied to this change: default model id, 1048576 context from the vendor's Retrieve Model sample plus the 1M prose, 131072 maximum output, base URL https://api.longcat.chat/openai/v1 and route POST /chat/completions with Bearer auth. No GET /models, credentials, account or inference ran; this legacy field does not assert roster verification."
60
+ },
61
+ "liveMatrix": null,
62
+ "addedInPR": "https://github.com/juspay/neurolink/pull/1980"
63
+ }
64
+ }
@@ -43,7 +43,7 @@ import { createStreamChannel } from "../../core/streamChannel.js";
43
43
  import { toNativeToolDeclarations } from "../../core/nativeToolFormat.js";
44
44
  import { getAvailableInputTokens, getContextWindowSize, } from "../../constants/contextWindows.js";
45
45
  import { resolveLiveTool } from "../../tools/toolDiscovery.js";
46
- import { ATTR, LANGFUSE_ATTR, spanJsonAttribute, tracers, withClientSpan, withClientStreamSpan, withSpan, } from "../../telemetry/index.js";
46
+ import { ATTR, LANGFUSE_ATTR, spanContentAttribute, spanJsonAttribute, spanModelRequestAttribute, tracers, withClientSpan, withClientStreamSpan, withSpan, } from "../../telemetry/index.js";
47
47
  import { SpanKind, SpanStatusCode, context as otelContext, trace as otelTrace, } from "@opentelemetry/api";
48
48
  import { calculateCost } from "../../utils/pricing.js";
49
49
  import { transformToolExecutions } from "../../utils/transformationUtils.js";
@@ -3459,7 +3459,7 @@ export class GoogleVertexProvider extends BaseProvider {
3459
3459
  // Usage lives ONLY on the generation spans (Langfuse sums usage across
3460
3460
  // observations for trace totals, so repeating it on the turn double-counts).
3461
3461
  const offeredToolNames = (tools ?? []).map((anthropicTool) => anthropicTool.name);
3462
- const turnInputAttribute = spanJsonAttribute({
3462
+ const turnInputAttribute = spanModelRequestAttribute({
3463
3463
  system: systemPromptWithSchema,
3464
3464
  messages: sanitizeAnthropicMessagesForTrace(messages),
3465
3465
  });
@@ -3543,6 +3543,7 @@ export class GoogleVertexProvider extends BaseProvider {
3543
3543
  const loopPromise = (async () => {
3544
3544
  let step = 0;
3545
3545
  const currentMessages = [...messages];
3546
+ let stepConversation = currentMessages;
3546
3547
  // Step-cap / abort bookkeeping (mirrors the generate twin): read by the
3547
3548
  // terminal recovery block after the loop and by the finishReason
3548
3549
  // mapping written into finishReasonRef.
@@ -3569,18 +3570,34 @@ export class GoogleVertexProvider extends BaseProvider {
3569
3570
  // migration. Shared with resolveToolOnMiss below: the old dispatch
3570
3571
  // opened the span before the executor lookup, so a tool hydrated
3571
3572
  // mid-turn was observed exactly like one declared up front.
3572
- const withToolSpan = (toolCallName, run) => {
3573
+ const withToolSpan = (toolCallName, run, call) => {
3574
+ // Arguments are inputs: honour the same opt-out the AI SDK path uses.
3575
+ const argsAttribute = call?.args !== undefined &&
3576
+ process.env.NEUROLINK_RECORD_INPUTS?.trim().toLowerCase() !==
3577
+ "false"
3578
+ ? spanContentAttribute(call.args)
3579
+ : undefined;
3573
3580
  const toolSpan = tracers.mcp.startSpan("ai.toolCall", {
3574
3581
  kind: SpanKind.INTERNAL,
3575
3582
  attributes: {
3576
3583
  [LANGFUSE_ATTR.OBSERVATION_TYPE]: "tool",
3577
3584
  [ATTR.GEN_AI_TOOL_NAME]: toolCallName,
3578
3585
  "ai.toolCall.name": toolCallName,
3586
+ ...(call?.toolCallId
3587
+ ? { "ai.toolCall.id": call.toolCallId }
3588
+ : {}),
3589
+ ...(argsAttribute !== undefined
3590
+ ? {
3591
+ "ai.toolCall.args": argsAttribute,
3592
+ [LANGFUSE_ATTR.OBSERVATION_INPUT]: argsAttribute,
3593
+ }
3594
+ : {}),
3579
3595
  },
3580
3596
  }, turnContext);
3581
3597
  const finish = (output, errorMessage) => {
3582
- toolSpan.setAttribute("ai.toolCall.result", spanJsonAttribute(output));
3583
- toolSpan.setAttribute(LANGFUSE_ATTR.OBSERVATION_OUTPUT, spanJsonAttribute(output));
3598
+ const outputAttribute = spanContentAttribute(output);
3599
+ toolSpan.setAttribute("ai.toolCall.result", outputAttribute);
3600
+ toolSpan.setAttribute(LANGFUSE_ATTR.OBSERVATION_OUTPUT, outputAttribute);
3584
3601
  if (errorMessage) {
3585
3602
  toolSpan.setAttribute(LANGFUSE_ATTR.OBSERVATION_LEVEL, "ERROR");
3586
3603
  toolSpan.setAttribute(LANGFUSE_ATTR.OBSERVATION_STATUS_MESSAGE, errorMessage);
@@ -3742,6 +3759,7 @@ export class GoogleVertexProvider extends BaseProvider {
3742
3759
  ...baseAdapter,
3743
3760
  buildStepRequest: (conversation, engineStep) => {
3744
3761
  step = engineStep + 1;
3762
+ stepConversation = conversation;
3745
3763
  turnClock.noteProgress();
3746
3764
  return baseAdapter.buildStepRequest(conversation, engineStep);
3747
3765
  },
@@ -3782,9 +3800,9 @@ export class GoogleVertexProvider extends BaseProvider {
3782
3800
  temperature: requestParams.temperature,
3783
3801
  top_p: requestParams.top_p,
3784
3802
  }),
3785
- [LANGFUSE_ATTR.OBSERVATION_INPUT]: spanJsonAttribute({
3803
+ [LANGFUSE_ATTR.OBSERVATION_INPUT]: spanModelRequestAttribute({
3786
3804
  system: systemPromptWithSchema,
3787
- messages: sanitizeAnthropicMessagesForTrace(currentMessages),
3805
+ messages: sanitizeAnthropicMessagesForTrace(stepConversation),
3788
3806
  }),
3789
3807
  [LANGFUSE_ATTR.OBSERVATION_METADATA]: spanJsonAttribute({
3790
3808
  step,
@@ -3812,7 +3830,13 @@ export class GoogleVertexProvider extends BaseProvider {
3812
3830
  turnCacheUsage.creation += result.usage.cacheWriteTokens ?? 0;
3813
3831
  turnCacheUsage.creation5m += result.usage.cacheWrite5mTokens ?? 0;
3814
3832
  turnCacheUsage.creation1h += result.usage.cacheWrite1hTokens ?? 0;
3815
- generationSpan.setAttribute(LANGFUSE_ATTR.OBSERVATION_OUTPUT, spanJsonAttribute({ text: result.text }));
3833
+ generationSpan.setAttribute(LANGFUSE_ATTR.OBSERVATION_OUTPUT, spanContentAttribute({
3834
+ text: result.text,
3835
+ ...(result.toolCalls.length > 0
3836
+ ? { toolCalls: result.toolCalls }
3837
+ : {}),
3838
+ }));
3839
+ generationSpan.setAttribute(`${LANGFUSE_ATTR.OBSERVATION_METADATA}.finishReason`, result.rawStopReason ?? "unknown");
3816
3840
  return result;
3817
3841
  }
3818
3842
  catch (error) {
@@ -4339,7 +4363,7 @@ export class GoogleVertexProvider extends BaseProvider {
4339
4363
  if (turnCacheUsage.creation > 0) {
4340
4364
  usage.cacheCreationTokens = turnCacheUsage.creation;
4341
4365
  }
4342
- const turnOutputAttribute = spanJsonAttribute({
4366
+ const turnOutputAttribute = spanContentAttribute({
4343
4367
  text: aggregatedTurnText,
4344
4368
  ...(structuredOutputRef.value
4345
4369
  ? { structuredOutput: structuredOutputRef.value }
@@ -4357,6 +4381,7 @@ export class GoogleVertexProvider extends BaseProvider {
4357
4381
  toolCallCount: metadata.totalToolExecutions,
4358
4382
  toolsCalled: toolsUsedRef.filter((name) => name !== "final_result"),
4359
4383
  structuredOutput: useFinalResultTool,
4384
+ ...(stopReasonRef.value ? { stopReason: stopReasonRef.value } : {}),
4360
4385
  usage: {
4361
4386
  input: usage.input,
4362
4387
  output: usage.output,
@@ -4366,10 +4391,25 @@ export class GoogleVertexProvider extends BaseProvider {
4366
4391
  input_cache_creation_1h: turnCacheUsage.creation1h,
4367
4392
  },
4368
4393
  }));
4394
+ // How the turn ended, on the trace itself, so an evaluator can select
4395
+ // only turns that finished ("completed") and skip capped, timed-out,
4396
+ // aborted and failed ones. A trace holding several turns keeps the last
4397
+ // one's; each turn's own is in its observation metadata above.
4398
+ if (stopReasonRef.value) {
4399
+ turnSpan.setAttribute(`${LANGFUSE_ATTR.TRACE_METADATA}.stopReason`, stopReasonRef.value);
4400
+ }
4369
4401
  turnSpan.setStatus({ code: SpanStatusCode.OK });
4370
4402
  channel.close();
4371
4403
  }
4372
4404
  catch (err) {
4405
+ turnSpan.setAttribute(LANGFUSE_ATTR.OBSERVATION_METADATA, spanJsonAttribute({
4406
+ toolsOffered: offeredToolNames,
4407
+ toolCount: offeredToolNames.length,
4408
+ maxSteps,
4409
+ structuredOutput: useFinalResultTool,
4410
+ stopReason: "provider-error",
4411
+ }));
4412
+ turnSpan.setAttribute(`${LANGFUSE_ATTR.TRACE_METADATA}.stopReason`, "provider-error");
4373
4413
  turnSpan.setStatus({
4374
4414
  code: SpanStatusCode.ERROR,
4375
4415
  message: err instanceof Error ? err.message : String(err),
@@ -5635,7 +5675,7 @@ export class GoogleVertexProvider extends BaseProvider {
5635
5675
  "";
5636
5676
  // Set generation input before the call so error paths still carry the
5637
5677
  // request; output is set after the native call resolves.
5638
- const generationInputAttribute = spanJsonAttribute({
5678
+ const generationInputAttribute = spanModelRequestAttribute({
5639
5679
  ...(mergedOptions.systemPrompt
5640
5680
  ? { system: mergedOptions.systemPrompt }
5641
5681
  : {}),
@@ -5676,7 +5716,7 @@ export class GoogleVertexProvider extends BaseProvider {
5676
5716
  });
5677
5717
  nativeResult = await this.runNativeGenerateWithMiddleware(mergedOptions, modelName, (effectiveOptions) => this.executeNativeGemini3GenerateWithSchemaFallback(effectiveOptions, modelName));
5678
5718
  }
5679
- executionSpan.setAttribute(LANGFUSE_ATTR.OBSERVATION_OUTPUT, spanJsonAttribute(nativeResult?.content ?? ""));
5719
+ executionSpan.setAttribute(LANGFUSE_ATTR.OBSERVATION_OUTPUT, spanContentAttribute(nativeResult?.content ?? ""));
5680
5720
  return nativeResult;
5681
5721
  });
5682
5722
  this.attachUsageAndCostAttributes(generateSpan, modelName, result?.usage);
@@ -5685,7 +5725,7 @@ export class GoogleVertexProvider extends BaseProvider {
5685
5725
  // enabled / useAiResponse is false, so the cost is zero on
5686
5726
  // non-TTS paths.
5687
5727
  result = await this.synthesizeAIResponseIfNeeded(result, options);
5688
- generateSpan.setAttribute(LANGFUSE_ATTR.OBSERVATION_OUTPUT, spanJsonAttribute(result?.content ?? ""));
5728
+ generateSpan.setAttribute(LANGFUSE_ATTR.OBSERVATION_OUTPUT, spanContentAttribute(result?.content ?? ""));
5689
5729
  // Fire onFinish lifecycle callback for the native generate path.
5690
5730
  // Pipeline A providers get this for free via the AI SDK middleware
5691
5731
  // wrapper (LifecycleMiddleware); native @google/genai bypasses
@@ -124,6 +124,8 @@ export declare function setLangfuseContext<T = void>(context: {
124
124
  requestId?: string | null;
125
125
  traceName?: string | null;
126
126
  metadata?: Record<string, unknown> | null;
127
+ /** Langfuse trace tags, set on the trace's root span */
128
+ tags?: string[] | null;
127
129
  /** Explicit operation name (overrides auto-detection) */
128
130
  operationName?: string | null;
129
131
  /** Override global autoDetectOperationName for this context */
@@ -298,6 +298,9 @@ class ContextEnricher {
298
298
  span.setAttribute("langfuse.trace.name", traceName);
299
299
  span.setAttribute("trace.name", traceName);
300
300
  }
301
+ if (isRootSpan && context?.tags && context.tags.length > 0) {
302
+ span.setAttribute("langfuse.trace.tags", [...context.tags]);
303
+ }
301
304
  // Set operation name as separate attribute for filtering/analytics
302
305
  if (operationName) {
303
306
  span.setAttribute("gen_ai.operation.name", operationName);
@@ -1163,6 +1166,7 @@ export async function setLangfuseContext(context, callback) {
1163
1166
  metadata: context.metadata !== undefined
1164
1167
  ? context.metadata
1165
1168
  : currentContext.metadata,
1169
+ tags: context.tags !== undefined ? context.tags : currentContext.tags,
1166
1170
  // Operation name support
1167
1171
  operationName: context.operationName !== undefined
1168
1172
  ? context.operationName
@@ -1,3 +1,4 @@
1
+ import type { SpanModelRequest } from "../types/index.js";
1
2
  export declare const ATTR: {
2
3
  readonly GEN_AI_SYSTEM: "gen_ai.system";
3
4
  readonly GEN_AI_MODEL: "gen_ai.request.model";
@@ -114,6 +115,8 @@ export declare const LANGFUSE_ATTR: {
114
115
  readonly TRACE_NAME: "langfuse.trace.name";
115
116
  readonly TRACE_INPUT: "langfuse.trace.input";
116
117
  readonly TRACE_OUTPUT: "langfuse.trace.output";
118
+ readonly TRACE_TAGS: "langfuse.trace.tags";
119
+ readonly TRACE_METADATA: "langfuse.trace.metadata";
117
120
  readonly OBSERVATION_TYPE: "langfuse.observation.type";
118
121
  readonly OBSERVATION_INPUT: "langfuse.observation.input";
119
122
  readonly OBSERVATION_OUTPUT: "langfuse.observation.output";
@@ -127,6 +130,24 @@ export declare const LANGFUSE_ATTR: {
127
130
  };
128
131
  /** Default ceiling for serialized span attribute values. */
129
132
  export declare const SPAN_ATTRIBUTE_MAX_CHARS = 40000;
133
+ /**
134
+ * Returns a copy of `value` with credentials masked: values under keys such as
135
+ * `access_token`, `password`, `authorization` or `set-cookie`, bearer tokens
136
+ * and `name=value` credentials inside text. Content with nothing sensitive in
137
+ * it serializes exactly as it did before. Throws only if the value cannot be
138
+ * walked; callers on the tracing path use `spanContentAttribute`, which turns
139
+ * that into an omitted value instead of a leak or a failed turn.
140
+ */
141
+ export declare function redactSpanContent(value: unknown): unknown;
142
+ /**
143
+ * `spanJsonAttribute` for content a person or model wrote or a tool returned
144
+ * (arguments, results, answers), with credentials masked first. Use the plain
145
+ * form for metadata such as usage counts and server ids.
146
+ *
147
+ * A structured value over the cap is shortened by trimming its longest
148
+ * strings, so the attribute stays valid JSON instead of ending mid-token.
149
+ */
150
+ export declare function spanContentAttribute(value: unknown, maxChars?: number): string;
130
151
  /**
131
152
  * Serialize an arbitrary value for a span attribute, hard-capped at
132
153
  * `maxChars` so a pathological prompt or tool result can't put megabytes
@@ -134,3 +155,14 @@ export declare const SPAN_ATTRIBUTE_MAX_CHARS = 40000;
134
155
  * JSON-stringified with a String() fallback for circular structures.
135
156
  */
136
157
  export declare function spanJsonAttribute(value: unknown, maxChars?: number): string;
158
+ /**
159
+ * Serialize a model request for a span attribute without losing the
160
+ * conversation to the cap.
161
+ *
162
+ * A head cut keeps the system prompt and drops everything after it, so a long
163
+ * system prompt hides every message, the user's question included. Here the
164
+ * prompt and the newest messages are budgeted first, older messages are
165
+ * dropped whole and counted, and the system prompt gets whatever room is left.
166
+ * The result is always valid JSON.
167
+ */
168
+ export declare function spanModelRequestAttribute(rawRequest: SpanModelRequest, maxChars?: number): string;