@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.
- package/CHANGELOG.md +4 -3
- package/dist/browser/neurolink.min.js +439 -439
- package/dist/constants/enums.d.ts +4 -0
- package/dist/constants/enums.js +5 -0
- package/dist/core/toolExecutionGuards.js +9 -1
- package/dist/providers/catalog/index.generated.d.ts +1 -1
- package/dist/providers/catalog/index.generated.js +3 -0
- package/dist/providers/catalog/longcat.json +64 -0
- package/dist/providers/googleVertex/client.js +52 -12
- package/dist/services/server/ai/observability/instrumentation.d.ts +2 -0
- package/dist/services/server/ai/observability/instrumentation.js +4 -0
- package/dist/telemetry/attributes.d.ts +32 -0
- package/dist/telemetry/attributes.js +289 -0
- package/dist/telemetry/index.d.ts +1 -1
- package/dist/telemetry/index.js +1 -1
- package/dist/types/loopEngine.d.ts +12 -1
- package/dist/types/observability.d.ts +8 -0
- package/dist/types/providerCatalog.generated.d.ts +2 -2
- package/dist/types/providers.d.ts +4 -0
- package/docs-site/static/search-index.json +7 -0
- package/package.json +4 -2
|
@@ -125,6 +125,8 @@ export const LANGFUSE_ATTR = {
|
|
|
125
125
|
TRACE_NAME: "langfuse.trace.name",
|
|
126
126
|
TRACE_INPUT: "langfuse.trace.input",
|
|
127
127
|
TRACE_OUTPUT: "langfuse.trace.output",
|
|
128
|
+
TRACE_TAGS: "langfuse.trace.tags",
|
|
129
|
+
TRACE_METADATA: "langfuse.trace.metadata",
|
|
128
130
|
OBSERVATION_TYPE: "langfuse.observation.type",
|
|
129
131
|
OBSERVATION_INPUT: "langfuse.observation.input",
|
|
130
132
|
OBSERVATION_OUTPUT: "langfuse.observation.output",
|
|
@@ -138,6 +140,174 @@ export const LANGFUSE_ATTR = {
|
|
|
138
140
|
};
|
|
139
141
|
/** Default ceiling for serialized span attribute values. */
|
|
140
142
|
export const SPAN_ATTRIBUTE_MAX_CHARS = 40_000;
|
|
143
|
+
/** Opening of the system prompt a model-request attribute always keeps. */
|
|
144
|
+
const SYSTEM_PROMPT_FLOOR_CHARS = 2_000;
|
|
145
|
+
/** Room for the "...[truncated N chars]" note, kept outside that opening. */
|
|
146
|
+
const TRUNCATION_NOTE_ALLOWANCE_CHARS = 48;
|
|
147
|
+
const MIN_SHRINKABLE_STRING_CHARS = 64;
|
|
148
|
+
const REDACTED_VALUE = "[REDACTED]";
|
|
149
|
+
const REDACTION_FAILED_VALUE = "[content omitted: redaction failed]";
|
|
150
|
+
const SENSITIVE_KEY_PATTERN = /(authorization|password|passwd|secret|apikey|privatekey|token|credential|signature)/;
|
|
151
|
+
const COOKIE_KEY_PATTERN = /^(set)?cookies?$/;
|
|
152
|
+
// Cheap pre-check: text without any of these is returned untouched, so the
|
|
153
|
+
// common case costs one regex scan and stays byte-identical.
|
|
154
|
+
const SENSITIVE_HINT_PATTERN = /authorization|password|passwd|secret|api[_-]?key|private[_-]?key|token|credential|signature|cookie|bearer/i;
|
|
155
|
+
function isSensitiveKey(key) {
|
|
156
|
+
const normalized = key.replace(/[_-]/g, "").toLowerCase();
|
|
157
|
+
return (SENSITIVE_KEY_PATTERN.test(normalized) ||
|
|
158
|
+
COOKIE_KEY_PATTERN.test(normalized));
|
|
159
|
+
}
|
|
160
|
+
// JSON that a tool returned as text, carried inside JSON the model sees as a
|
|
161
|
+
// string, has its quotes escaped once per level of nesting, and each level
|
|
162
|
+
// doubles the backslashes before the quote: one, three, seven.
|
|
163
|
+
const ESCAPED_QUOTE_BACKSLASHES = [1, 3, 7];
|
|
164
|
+
const ESCAPED_PAIR_PATTERNS = ESCAPED_QUOTE_BACKSLASHES.map((backslashes) => {
|
|
165
|
+
const quote = `${"\\\\".repeat(backslashes)}"`;
|
|
166
|
+
return new RegExp(`${quote}([^"\\\\]{1,80})${quote}(\\s*:\\s*)${quote}((?:(?!${quote})[\\s\\S]){0,8192})${quote}`, "g");
|
|
167
|
+
});
|
|
168
|
+
/**
|
|
169
|
+
* Masks credentials in text that is about to be written to a span: bearer
|
|
170
|
+
* tokens, `name=value` credentials in URLs and form bodies, and the values of
|
|
171
|
+
* sensitive keys in JSON text (tool results arrive as JSON strings).
|
|
172
|
+
*/
|
|
173
|
+
function redactText(text) {
|
|
174
|
+
if (!SENSITIVE_HINT_PATTERN.test(text)) {
|
|
175
|
+
return text;
|
|
176
|
+
}
|
|
177
|
+
let redacted = text
|
|
178
|
+
.replace(/\bBearer\s+[\w.\-+/=]{16,}/gi, `Bearer ${REDACTED_VALUE}`)
|
|
179
|
+
.replace(/\b(access_token|refresh_token|id_token|api_key|apikey|client_secret|password|signature|credential)=([^&\s"]+)/gi, `$1=${REDACTED_VALUE}`)
|
|
180
|
+
.replace(/"([^"\\]{1,80})"(\s*:\s*)"(?:[^"\\]|\\.)*"/g, (match, key, separator) => isSensitiveKey(key) ? `"${key}"${separator}"${REDACTED_VALUE}"` : match);
|
|
181
|
+
ESCAPED_QUOTE_BACKSLASHES.forEach((backslashes, index) => {
|
|
182
|
+
const quote = `${"\\".repeat(backslashes)}"`;
|
|
183
|
+
redacted = redacted.replace(ESCAPED_PAIR_PATTERNS[index], (match, key, separator) => isSensitiveKey(key)
|
|
184
|
+
? `${quote}${key}${quote}${separator}${quote}${REDACTED_VALUE}${quote}`
|
|
185
|
+
: match);
|
|
186
|
+
});
|
|
187
|
+
return redacted;
|
|
188
|
+
}
|
|
189
|
+
function redactNode(value, ancestors) {
|
|
190
|
+
if (typeof value === "string") {
|
|
191
|
+
return redactText(value);
|
|
192
|
+
}
|
|
193
|
+
if (value === null || typeof value !== "object") {
|
|
194
|
+
return value;
|
|
195
|
+
}
|
|
196
|
+
if (ancestors.has(value)) {
|
|
197
|
+
return "[circular]";
|
|
198
|
+
}
|
|
199
|
+
ancestors.add(value);
|
|
200
|
+
try {
|
|
201
|
+
if ("toJSON" in value && typeof value.toJSON === "function") {
|
|
202
|
+
return redactNode(value.toJSON(), ancestors);
|
|
203
|
+
}
|
|
204
|
+
if (Array.isArray(value)) {
|
|
205
|
+
return value.map((entry) => redactNode(entry, ancestors));
|
|
206
|
+
}
|
|
207
|
+
// No prototype, so a key named __proto__ is data rather than an assignment.
|
|
208
|
+
const redacted = Object.create(null);
|
|
209
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
210
|
+
// Counts and flags under a sensitive-looking name (input_tokens: 5) are
|
|
211
|
+
// not credentials; only text and structures are masked.
|
|
212
|
+
redacted[key] =
|
|
213
|
+
isSensitiveKey(key) &&
|
|
214
|
+
(typeof entry === "string" ||
|
|
215
|
+
(typeof entry === "object" && entry !== null))
|
|
216
|
+
? REDACTED_VALUE
|
|
217
|
+
: redactNode(entry, ancestors);
|
|
218
|
+
}
|
|
219
|
+
return redacted;
|
|
220
|
+
}
|
|
221
|
+
finally {
|
|
222
|
+
ancestors.delete(value);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Returns a copy of `value` with credentials masked: values under keys such as
|
|
227
|
+
* `access_token`, `password`, `authorization` or `set-cookie`, bearer tokens
|
|
228
|
+
* and `name=value` credentials inside text. Content with nothing sensitive in
|
|
229
|
+
* it serializes exactly as it did before. Throws only if the value cannot be
|
|
230
|
+
* walked; callers on the tracing path use `spanContentAttribute`, which turns
|
|
231
|
+
* that into an omitted value instead of a leak or a failed turn.
|
|
232
|
+
*/
|
|
233
|
+
export function redactSpanContent(value) {
|
|
234
|
+
return redactNode(value, new WeakSet());
|
|
235
|
+
}
|
|
236
|
+
function redactSafely(value) {
|
|
237
|
+
try {
|
|
238
|
+
return redactSpanContent(value);
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
return REDACTION_FAILED_VALUE;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
const MAX_SHRINK_ATTEMPTS = 200;
|
|
245
|
+
/**
|
|
246
|
+
* Cuts the longest string inside `root` down by at least `excess` characters,
|
|
247
|
+
* in place, and says whether it found one worth cutting. Only ever called on
|
|
248
|
+
* the copy `redactSpanContent` made, never on the caller's own data.
|
|
249
|
+
*/
|
|
250
|
+
function shrinkLongestString(root, excess) {
|
|
251
|
+
let owner;
|
|
252
|
+
let ownerKey = "";
|
|
253
|
+
let longestText = "";
|
|
254
|
+
const visited = new Set();
|
|
255
|
+
const pending = [root];
|
|
256
|
+
while (pending.length > 0) {
|
|
257
|
+
const node = pending.pop();
|
|
258
|
+
if (node === undefined || visited.has(node)) {
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
visited.add(node);
|
|
262
|
+
for (const [key, entry] of Object.entries(node)) {
|
|
263
|
+
if (typeof entry === "string") {
|
|
264
|
+
if (entry.length > longestText.length &&
|
|
265
|
+
entry.length > MIN_SHRINKABLE_STRING_CHARS) {
|
|
266
|
+
longestText = entry;
|
|
267
|
+
owner = node;
|
|
268
|
+
ownerKey = key;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
else if (entry !== null && typeof entry === "object") {
|
|
272
|
+
pending.push(entry);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
if (owner === undefined) {
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
const keep = Math.max(MIN_SHRINKABLE_STRING_CHARS / 2, longestText.length - excess - TRUNCATION_NOTE_ALLOWANCE_CHARS);
|
|
280
|
+
Reflect.set(owner, ownerKey, `${longestText.slice(0, keep)}...[truncated ${longestText.length - keep} chars]`);
|
|
281
|
+
return true;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* `spanJsonAttribute` for content a person or model wrote or a tool returned
|
|
285
|
+
* (arguments, results, answers), with credentials masked first. Use the plain
|
|
286
|
+
* form for metadata such as usage counts and server ids.
|
|
287
|
+
*
|
|
288
|
+
* A structured value over the cap is shortened by trimming its longest
|
|
289
|
+
* strings, so the attribute stays valid JSON instead of ending mid-token.
|
|
290
|
+
*/
|
|
291
|
+
export function spanContentAttribute(value, maxChars = SPAN_ATTRIBUTE_MAX_CHARS) {
|
|
292
|
+
const redacted = redactSafely(value);
|
|
293
|
+
if (redacted === null || typeof redacted !== "object") {
|
|
294
|
+
return spanJsonAttribute(redacted, maxChars);
|
|
295
|
+
}
|
|
296
|
+
let serialized;
|
|
297
|
+
try {
|
|
298
|
+
serialized = JSON.stringify(redacted) ?? String(redacted);
|
|
299
|
+
}
|
|
300
|
+
catch {
|
|
301
|
+
return spanJsonAttribute(redacted, maxChars);
|
|
302
|
+
}
|
|
303
|
+
for (let attempt = 0; serialized.length > maxChars && attempt < MAX_SHRINK_ATTEMPTS; attempt++) {
|
|
304
|
+
if (!shrinkLongestString(redacted, serialized.length - maxChars)) {
|
|
305
|
+
break;
|
|
306
|
+
}
|
|
307
|
+
serialized = JSON.stringify(redacted);
|
|
308
|
+
}
|
|
309
|
+
return spanJsonAttribute(serialized, maxChars);
|
|
310
|
+
}
|
|
141
311
|
/**
|
|
142
312
|
* Serialize an arbitrary value for a span attribute, hard-capped at
|
|
143
313
|
* `maxChars` so a pathological prompt or tool result can't put megabytes
|
|
@@ -162,3 +332,122 @@ export function spanJsonAttribute(value, maxChars = SPAN_ATTRIBUTE_MAX_CHARS) {
|
|
|
162
332
|
}
|
|
163
333
|
return serialized;
|
|
164
334
|
}
|
|
335
|
+
/**
|
|
336
|
+
* Serialize a model request for a span attribute without losing the
|
|
337
|
+
* conversation to the cap.
|
|
338
|
+
*
|
|
339
|
+
* A head cut keeps the system prompt and drops everything after it, so a long
|
|
340
|
+
* system prompt hides every message, the user's question included. Here the
|
|
341
|
+
* prompt and the newest messages are budgeted first, older messages are
|
|
342
|
+
* dropped whole and counted, and the system prompt gets whatever room is left.
|
|
343
|
+
* The result is always valid JSON.
|
|
344
|
+
*/
|
|
345
|
+
export function spanModelRequestAttribute(rawRequest, maxChars = SPAN_ATTRIBUTE_MAX_CHARS) {
|
|
346
|
+
// Credentials are masked before anything is measured, so budgets apply to
|
|
347
|
+
// what is actually written. Each message is masked on its own: one that
|
|
348
|
+
// cannot be walked is omitted without losing the rest of the conversation.
|
|
349
|
+
const request = {
|
|
350
|
+
...(rawRequest.system !== undefined
|
|
351
|
+
? { system: redactSafely(rawRequest.system) }
|
|
352
|
+
: {}),
|
|
353
|
+
...(rawRequest.messages !== undefined
|
|
354
|
+
? {
|
|
355
|
+
messages: rawRequest.messages.map((message) => redactSafely(message)),
|
|
356
|
+
}
|
|
357
|
+
: {}),
|
|
358
|
+
...(rawRequest.prompt !== undefined
|
|
359
|
+
? { prompt: redactText(rawRequest.prompt) }
|
|
360
|
+
: {}),
|
|
361
|
+
};
|
|
362
|
+
const serialize = (value) => {
|
|
363
|
+
try {
|
|
364
|
+
return typeof value === "string"
|
|
365
|
+
? value
|
|
366
|
+
: (JSON.stringify(value) ?? String(value));
|
|
367
|
+
}
|
|
368
|
+
catch {
|
|
369
|
+
return String(value);
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
// Sizes are measured as JSON, which is what the attribute carries: escaping
|
|
373
|
+
// makes a JSON string longer than its text.
|
|
374
|
+
const jsonLength = (value) => {
|
|
375
|
+
try {
|
|
376
|
+
return (JSON.stringify(value) ?? "null").length;
|
|
377
|
+
}
|
|
378
|
+
catch {
|
|
379
|
+
return Number.POSITIVE_INFINITY;
|
|
380
|
+
}
|
|
381
|
+
};
|
|
382
|
+
// Never returns an empty string for non-empty text: when nothing fits, the
|
|
383
|
+
// truncation note alone says the value existed and how long it was.
|
|
384
|
+
const fitText = (text, budget) => {
|
|
385
|
+
if (jsonLength(text) <= budget) {
|
|
386
|
+
return text;
|
|
387
|
+
}
|
|
388
|
+
let keep = budget;
|
|
389
|
+
for (let attempt = 0; attempt < 12 && keep > 0; attempt++) {
|
|
390
|
+
const candidate = `${text.slice(0, keep)}...[truncated ${text.length - keep} chars]`;
|
|
391
|
+
const size = jsonLength(candidate);
|
|
392
|
+
if (size <= budget) {
|
|
393
|
+
return candidate;
|
|
394
|
+
}
|
|
395
|
+
keep = Math.floor((keep * budget) / size) - 1;
|
|
396
|
+
}
|
|
397
|
+
return `[truncated ${text.length} chars]`;
|
|
398
|
+
};
|
|
399
|
+
// Room for keys, brackets and the omitted-message count.
|
|
400
|
+
let remaining = maxChars - 128;
|
|
401
|
+
// The system prompt always keeps its opening, so a trace still shows which
|
|
402
|
+
// prompt was in use. Reserved before the messages are budgeted and returned
|
|
403
|
+
// to the system prompt afterwards; a request that fits is unaffected.
|
|
404
|
+
const systemFloor = request.system !== undefined
|
|
405
|
+
? Math.min(jsonLength(request.system), SYSTEM_PROMPT_FLOOR_CHARS + TRUNCATION_NOTE_ALLOWANCE_CHARS)
|
|
406
|
+
: 0;
|
|
407
|
+
remaining -= systemFloor;
|
|
408
|
+
let prompt;
|
|
409
|
+
if (request.prompt !== undefined) {
|
|
410
|
+
prompt = fitText(request.prompt, remaining);
|
|
411
|
+
remaining -= jsonLength(prompt);
|
|
412
|
+
}
|
|
413
|
+
const messages = request.messages ?? [];
|
|
414
|
+
const kept = [];
|
|
415
|
+
for (let index = messages.length - 1; index >= 0; index--) {
|
|
416
|
+
const size = jsonLength(messages[index]) + 1;
|
|
417
|
+
if (size <= remaining) {
|
|
418
|
+
kept.unshift(messages[index]);
|
|
419
|
+
remaining -= size;
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
if (kept.length === 0 && remaining > 64) {
|
|
423
|
+
const excerpt = fitText(serialize(messages[index]), remaining - 32);
|
|
424
|
+
kept.unshift({ truncatedMessage: excerpt });
|
|
425
|
+
remaining -= jsonLength(excerpt) + 32;
|
|
426
|
+
}
|
|
427
|
+
break;
|
|
428
|
+
}
|
|
429
|
+
const omittedMessages = messages.length - kept.length;
|
|
430
|
+
remaining += systemFloor;
|
|
431
|
+
const body = {};
|
|
432
|
+
if (request.system !== undefined) {
|
|
433
|
+
body.system =
|
|
434
|
+
jsonLength(request.system) <= remaining
|
|
435
|
+
? request.system
|
|
436
|
+
: fitText(serialize(request.system), Math.max(0, remaining));
|
|
437
|
+
}
|
|
438
|
+
if (request.messages !== undefined) {
|
|
439
|
+
body.messages = kept;
|
|
440
|
+
}
|
|
441
|
+
if (omittedMessages > 0) {
|
|
442
|
+
body.omittedMessages = omittedMessages;
|
|
443
|
+
}
|
|
444
|
+
if (prompt !== undefined) {
|
|
445
|
+
body.prompt = prompt;
|
|
446
|
+
}
|
|
447
|
+
try {
|
|
448
|
+
return JSON.stringify(body);
|
|
449
|
+
}
|
|
450
|
+
catch {
|
|
451
|
+
return spanJsonAttribute(body, maxChars);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { TelemetryService } from "./telemetryService.js";
|
|
2
2
|
export { tracers } from "./tracers.js";
|
|
3
3
|
export { withSpan, withClientSpan, withStreamSpan, withClientStreamSpan, } from "./withSpan.js";
|
|
4
|
-
export { ATTR, LANGFUSE_ATTR, SPAN_ATTRIBUTE_MAX_CHARS, spanJsonAttribute, } from "./attributes.js";
|
|
4
|
+
export { ATTR, LANGFUSE_ATTR, SPAN_ATTRIBUTE_MAX_CHARS, redactSpanContent, spanContentAttribute, spanJsonAttribute, spanModelRequestAttribute, } from "./attributes.js";
|
|
5
5
|
/**
|
|
6
6
|
* Initialize telemetry for NeuroLink
|
|
7
7
|
* Reuses an existing global TracerProvider when one is already registered,
|
package/dist/telemetry/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export { TelemetryService } from "./telemetryService.js";
|
|
3
3
|
export { tracers } from "./tracers.js";
|
|
4
4
|
export { withSpan, withClientSpan, withStreamSpan, withClientStreamSpan, } from "./withSpan.js";
|
|
5
|
-
export { ATTR, LANGFUSE_ATTR, SPAN_ATTRIBUTE_MAX_CHARS, spanJsonAttribute, } from "./attributes.js";
|
|
5
|
+
export { ATTR, LANGFUSE_ATTR, SPAN_ATTRIBUTE_MAX_CHARS, redactSpanContent, spanContentAttribute, spanJsonAttribute, spanModelRequestAttribute, } from "./attributes.js";
|
|
6
6
|
import { logger } from "../utils/logger.js";
|
|
7
7
|
/**
|
|
8
8
|
* Initialize telemetry for NeuroLink
|
|
@@ -346,6 +346,13 @@ export type AnthropicLoopAdapterConfig<TMessage = Anthropic.Messages.MessagePara
|
|
|
346
346
|
* it, so this cannot quietly give a provider behaviour its hand-rolled loops
|
|
347
347
|
* never had.
|
|
348
348
|
*/
|
|
349
|
+
/** One model-requested tool call, as recorded on the tool's observability span. */
|
|
350
|
+
export type ToolSpanCall = {
|
|
351
|
+
/** Arguments the model passed to the tool. */
|
|
352
|
+
args?: Record<string, unknown>;
|
|
353
|
+
/** The model's id for this call, shared with the tool_use block that requested it. */
|
|
354
|
+
toolCallId?: string;
|
|
355
|
+
};
|
|
349
356
|
export type ToolExecutionGuards = {
|
|
350
357
|
/**
|
|
351
358
|
* Upper bound on a single execute(). Omit, or pass `null`, for no bound.
|
|
@@ -380,8 +387,12 @@ export type ToolExecutionGuards = {
|
|
|
380
387
|
* mark a FAILURE THAT WAS RETURNED rather than thrown: MCP tools report
|
|
381
388
|
* errors in their payload, and an observation that only watches for
|
|
382
389
|
* exceptions records those calls as successful.
|
|
390
|
+
*
|
|
391
|
+
* `call` carries the arguments the model passed and the model's id for the
|
|
392
|
+
* call, so the observation can show what was asked and be paired with the
|
|
393
|
+
* request that asked it.
|
|
383
394
|
*/
|
|
384
|
-
withToolSpan?: <T>(name: string, run: () => Promise<T
|
|
395
|
+
withToolSpan?: <T>(name: string, run: () => Promise<T>, call?: ToolSpanCall) => Promise<T>;
|
|
385
396
|
};
|
|
386
397
|
/**
|
|
387
398
|
* @deprecated Renamed to `ToolExecutionGuards` — the guards were never
|
|
@@ -229,6 +229,12 @@ export type TraceView = {
|
|
|
229
229
|
* Extended context for Langfuse spans.
|
|
230
230
|
* Supports all Langfuse trace attributes for rich observability.
|
|
231
231
|
*/
|
|
232
|
+
/** A model request serialized onto a span: the system prompt plus messages, or a bare prompt. */
|
|
233
|
+
export type SpanModelRequest = {
|
|
234
|
+
system?: unknown;
|
|
235
|
+
messages?: readonly unknown[];
|
|
236
|
+
prompt?: string;
|
|
237
|
+
};
|
|
232
238
|
export type LangfuseContext = {
|
|
233
239
|
userId?: string | null;
|
|
234
240
|
sessionId?: string | null;
|
|
@@ -240,6 +246,8 @@ export type LangfuseContext = {
|
|
|
240
246
|
traceName?: string | null;
|
|
241
247
|
/** Custom metadata to attach to spans */
|
|
242
248
|
metadata?: Record<string, unknown> | null;
|
|
249
|
+
/** Langfuse trace tags, set on the trace's root span (e.g. to label what a trace is for) */
|
|
250
|
+
tags?: string[] | null;
|
|
243
251
|
/**
|
|
244
252
|
* Explicit operation name (e.g., "ai.streamText", "chat", "embeddings").
|
|
245
253
|
* If set, overrides auto-detection from the span name.
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export type CatalogProviderName = "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" | "laya" | "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";
|
|
2
|
-
export type CatalogCredentialKey = "a2agent" | "abliteration" | "aboveDev" | "ai21" | "aiand" | "aihubmix" | "aionlabs" | "ambient" | "apiRoute" | "arcee" | "atlasCloud" | "avianIo" | "baiduQianfan" | "baseten" | "beeHeossi" | "byteplusModelark" | "bytez" | "cerebras" | "charmHyper" | "chutes" | "cloudflare" | "crusoe" | "dashscope" | "deepinfra" | "deepseek" | "empiriolabs" | "featherlessAi" | "fireworks" | "friendli" | "gmicloud" | "gradientai" | "groq" | "hetznerInference" | "huggingFace" | "inceptionLabs" | "inceptron" | "inco" | "inferenceNet" | "ioIntelligence" | "koscompute" | "laya" | "lemonfoxAi" | "lilac" | "llmtech" | "mancer" | "metaModelApi" | "minimax" | "mistral" | "moark" | "modelscope" | "moonshotAi" | "morph" | "naverClovaStudio" | "nebius" | "neuralwatt" | "novita" | "ovhcloud" | "parasail" | "paretoInference" | "perplexity" | "poolside" | "primeIntellect" | "reka" | "sakanaAi" | "sambanova" | "sarvam" | "scaleway" | "siliconflow" | "stackit" | "stepfun" | "subconscious" | "synthetic" | "telnyx" | "thinkingMachines" | "tinfoil" | "together" | "umansAi" | "upstage" | "veniceAi" | "vispark" | "vultrInference" | "wafer" | "wandbInference" | "xai" | "xiaomiMimo" | "zAi";
|
|
1
|
+
export type CatalogProviderName = "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" | "laya" | "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";
|
|
2
|
+
export type CatalogCredentialKey = "a2agent" | "abliteration" | "aboveDev" | "ai21" | "aiand" | "aihubmix" | "aionlabs" | "ambient" | "apiRoute" | "arcee" | "atlasCloud" | "avianIo" | "baiduQianfan" | "baseten" | "beeHeossi" | "byteplusModelark" | "bytez" | "cerebras" | "charmHyper" | "chutes" | "cloudflare" | "crusoe" | "dashscope" | "deepinfra" | "deepseek" | "empiriolabs" | "featherlessAi" | "fireworks" | "friendli" | "gmicloud" | "gradientai" | "groq" | "hetznerInference" | "huggingFace" | "inceptionLabs" | "inceptron" | "inco" | "inferenceNet" | "ioIntelligence" | "koscompute" | "laya" | "lemonfoxAi" | "lilac" | "llmtech" | "longcat" | "mancer" | "metaModelApi" | "minimax" | "mistral" | "moark" | "modelscope" | "moonshotAi" | "morph" | "naverClovaStudio" | "nebius" | "neuralwatt" | "novita" | "ovhcloud" | "parasail" | "paretoInference" | "perplexity" | "poolside" | "primeIntellect" | "reka" | "sakanaAi" | "sambanova" | "sarvam" | "scaleway" | "siliconflow" | "stackit" | "stepfun" | "subconscious" | "synthetic" | "telnyx" | "thinkingMachines" | "tinfoil" | "together" | "umansAi" | "upstage" | "veniceAi" | "vispark" | "vultrInference" | "wafer" | "wandbInference" | "xai" | "xiaomiMimo" | "zAi";
|
|
@@ -9773,6 +9773,13 @@
|
|
|
9773
9773
|
{"objectID":"fc7a72298d8f37fbfe243bef675900bf026be9904d70e2b4a8f86bb3dd65f034","title":"Billing and retired models","url":"/docs/provider-integration/pilots/aihubmix-source-pilot#billing-and-retired-models","content":"The default gpt-4o-mini is usage-priced and requires the caller to establish\nfunding, permissions and model eligibility. The existing schema's free-tier\nvalue describes the vendor-level free-model programme, following the existing\nMancer profile, whose default\nis also paid. AIHubMix's separate programme is model-limited. Its published\nno-card and allowance claims do not grant free access to this paid default or\ncertify current eligibility on any account.\n\nCurrent model-specific guides mark gpt-4o-free and gpt-5.5-free retired and\ndescribe HTTP 404 model_retired. Both are excluded from the catalog and its\ndefault/fallback list. Older free-model marketing and readable static parameter\nschemas cannot establish current availability of these IDs.\n\nAIHubMix documents remote mapping, routing and fallback. The SDK's\ndisableInternalFallback option controls the SDK path; acceptance of gateway\nidentity, routing and billing remains a separate live/provider question.","hierarchy":{"lvl0":"Provider Integration","lvl1":"AIHubMix text and streaming pilot","lvl2":"Billing and retired models","lvl3":""}},
|
|
9774
9774
|
{"objectID":"b907206314120b22bc39550ab270d1f21c1e90d1d9266ee2f0d65b4bfac5dc05","title":"Local public contract","url":"/docs/provider-integration/pilots/aihubmix-source-pilot#local-public-contract","content":"test/continuous-test-suite-aihubmix-pilot.ts prepares 16 mandatory cases through\nthe built public SDK and built CLI, with optional --package-root support for a\nlater installed consumer:\n\n| Cases | Count | Required observation |\n| ------------------------------------------------ | ----: | ----------------------------------------------------------------------------------------------------------------------------------------------- |\n| SDK/CLI generate/stream default | 4 | Actual catalog default, route, Bearer header, unique user prompt, max_tokens: 32, stream mode, no tools/tool choice, and fresh backend answer |\n| SDK/CLI generate/stream invalid explicit model | 4 | All wire preconditions pass before HTTP 400 rejection; no fallback or successful reply |\n| SDK/CLI generate/stream each retired explicit ID | 8 | Same wire preconditions, HTTP 404 retirement cause, preserved caller rejection, no fallback or reply |\n\nThe fixture strips real credentials before imports, uses temporary homes and\nsets provider routes to its owned random-port listener. Public\nMODEL_CONFIG_URL uses that same listener's HEAD /health and\nGET /api/v1/models. A schema-valid empty registry keeps the provider's actual\ncatalog default in control. Positive metadata initialization requires the exact\nordered request pair; explicit CLI model paths require no metadata request.\nSuccessful SDK metadata checks run after shutdown, and preserve original SDK\nerrors when generation fails. CLI commands keep a 60-second deadline.\n\nThe standalone component now passes all 16 cases with zero failures, skips or\nunowned network attempts and known process cleanup. The fixture remains\nbyte-identical to the original source freeze.","hierarchy":{"lvl0":"Provider Integration","lvl1":"AIHubMix text and streaming pilot","lvl2":"Local public contract","lvl3":""}},
|
|
9775
9775
|
{"objectID":"1ad1b971263952542f0624327b54b7599081e5d8de4d5afbcc62c4ca39ec6e41","title":"Provenance and remaining gates","url":"/docs/provider-integration/pilots/aihubmix-source-pilot#provenance-and-remaining-gates","content":"The legacy evidence.rosterVerified slot contains the explicit\nPUBLIC_DOCS_ONLY_NOT_ROSTER_VERIFIED marker and documentation methods. It has\nno HTTP status, auth probe or billing probe. liveMatrix is null and the PR\nfield is the canonical introduction PR URL\n(https://github.com/juspay/neurolink/pull/1966), set after the PR existed; it was\nPENDING_PR while the work was local. Q04 source admission accepts either the\nmarker or a canonical introduction PR URL. Its source-stage report keeps roster, live, installed-package and delivery\nclaims separate and gives no provider-count credit. Structural parsing or\nsource-stage admission does not certify current account/API availability.\n\nThe Q04 successor starts from 08c3c4e4e2881874fdf0e453923a3507b759532d,\nwhich descends from the checked live release\n8c78cd172a8b2036b75132488f9d24548f2a1e88. Its public fixture is byte-identical\nto the original source freeze. The profile's only semantic change is the PR\nmarker required by Q04. Shared schema, runtime, helpers and original source\nreceipts are preserved. Actual Q04 source admission passed and reports zero\nprovider-count, roster, live, installed-package and publication credit.\n\nCanonical catalog generation affects the index, provider union, provider/model\nenum regions and generated credential region. The standalone frozen install,\ncanonical generation and fixed point, fresh SDK/CLI/browser build, normal lint,\nstrict source/tools/CI types and all 16 guarded public cases passed. Source\noutside the generated regions is preserved. A command-delimiter failure before\nQ04 admission was retained and corrected by invoking the same production\nvalidator directly; no source or fixture repair was required.\n\nIntegrated source/build/required suites, normal hooks and commit, any separately\nassigned production sensitivity controls and clean installed-consumer acceptance\nremain pending. Accounts, funding, provider inference, external delivery and\ntarget credit are separate.","hierarchy":{"lvl0":"Provider Integration","lvl1":"AIHubMix text and streaming pilot","lvl2":"Provenance and remaining gates","lvl3":""}},
|
|
9776
|
+
{"objectID":"4637f96f5a3c7591c96846fa477817cfa74f62231c97283d43a81767bda43a30","title":"LongCat text and streaming source pilot","url":"/docs/provider-integration/pilots/longcat-source-pilot","content":"LongCat text and streaming source pilot\n\nThis source-level catalog entry selects Meituan's LongCat-2.5-Preview model\nthrough https://api.longcat.chat/openai/v1/chat/completions with\nAuthorization: Bearer $LONGCAT_API_KEY. Its declared scope is text generation\nand streaming only. Source preparation, public contract acceptance,\ninstalled-package acceptance, current account/API availability and delivery are\nseparate gates. This entry gives no provider-count, roster, live, package or\ndelivery credit.\n\nWhat the entry declares\n\n| Field | Value |\n| -------------- | ------------------------------------------------------------------- |\n| Provider id | longcat (display name LongCat, operator Meituan) |\n| Base URL | https://api.longcat.chat/openai/v1 |\n| Route | POST /chat/completions |\n| Credential | LONGCAT_API_KEY as a Bearer token |\n| Default model | LongCat-2.5-Preview (the only model listed, so no other fallback) |\n| Context window | 1,048,576 tokens |\n| Maximum output | 131,072 tokens |\n| Capabilities | text and streaming; tools, structured output, thinking, vision off |\n| Billing policy | no-free-tier, usage-priced pay-as-you-go |\n\nLongCat-2.0 is served on the same route but is outside this pilot's catalog\nscope, so it is deliberately not a default and not a fallback. The capability booleans bound this pilot's declared scope; they\nare not evidence that the vendor lacks those features.\n\nBilling\n\nThe default model is usage-priced. Promotional credits, when an account has\nany, are consumed first, but no free allowance is stated, so the entry claims\nno free tier. The vendor's Pay-As-You-Go page says account verification is required before a\ntop-up, and its FAQ scopes that requirement to users in Mainland China; it was\nnot tried on an account.\n\nEvidence caveats\nThe context integer 1048576 rests on the vendor's own Retrieve Model response\n sample for the exact model id plus the 1M prose; no normative sentence states\n it. It has not been confirmed with GET /openai/v1/models/LongCat-2.5-Preview\n because that needs a key.\nThe vendor SDK snippet omits /v1 although the exact HTTP route includes it;\n the catalog base URL https://api.longcat.chat/openai/v1 is taken from the\n curl example and is proven only against the owned fixture.\nThe vendor's Pay-As-You-Go page says account verification is required before\n top-up; its FAQ scopes that to users in Mainland China. Both were read\n directly; it was not tried on an account. No live call was made.\n\nLocal public contract\n\ntest/continuous-test-suite-longcat-pilot.ts runs eight cases through the built\npublic SDK and built CLI, with optional --package-root support for a later\ninstalled consumer:\n\n| Cases | Count | Required observation |\n| ---------------------------------------------- | ----: | ----------------------------------------------------------------------------------------------------------------------------------------------------- |\n| SDK/CLI generate/stream default | 4 | Actual catalog default, /openai/v1/chat/completions, Bearer header, unique user prompt, max_tokens: 32, stream mode, no tools/tool choice, answer |\n| SDK/CLI generate/stream invalid explicit model | 4 | All wire preconditions pass before HTTP 400 rejection; no fallback or successful reply |\n\nThe fixture strips real credentials before imports, uses temporary homes and\npoints the provider at an owned random-port listener. Public MODEL_CONFIG_URL\nuses that same listener's HEAD /health and GET /api/v1/models; a\nschema-valid empty registry keeps the provider's actual catalog default in\ncontrol. The listener is the only server involved: no vendor host is contacted.\n\nProvenance and remaining gates\n\nThe legacy evidence.rosterVerified slot carries the explicit\nVENDOR_DOCS_ONLY_NOT_ROSTER_VERIFIED marker. It has no HTTP status, auth probe\nor billing probe; liveMatrix is null. evidence.addedInPR is the\nintroduction pull request URL (https://github.com/juspay/neurolink/pull/1980),\nset after the PR existed; it was PENDING_PR while the work was local. Source-stage admission does not certify current account or API\navailability.\n\nStill pending and separate: an authenticated GET /openai/v1/models roster, a\nfunded-account live matrix, installed-consumer acceptance and any delivery\nclaim.","hierarchy":{"lvl0":"Provider Integration","lvl1":"LongCat text and streaming source pilot","lvl2":"","lvl3":""}},
|
|
9777
|
+
{"objectID":"a6da0252ba5f518ac597d1fe37c29ec8e60a7a34d485b6dd89bc9a4759d56cd0","title":"LongCat text and streaming source pilot","url":"/docs/provider-integration/pilots/longcat-source-pilot#longcat-text-and-streaming-source-pilot","content":"This source-level catalog entry selects Meituan's LongCat-2.5-Preview model\nthrough https://api.longcat.chat/openai/v1/chat/completions with\nAuthorization: Bearer $LONGCAT_API_KEY. Its declared scope is text generation\nand streaming only. Source preparation, public contract acceptance,\ninstalled-package acceptance, current account/API availability and delivery are\nseparate gates. This entry gives no provider-count, roster, live, package or\ndelivery credit.","hierarchy":{"lvl0":"Provider Integration","lvl1":"LongCat text and streaming source pilot","lvl2":"LongCat text and streaming source pilot","lvl3":""}},
|
|
9778
|
+
{"objectID":"0a1fddbbb1bb8ccc1126efca91277458f9a63509324bfd0ef9d4313b45f6f328","title":"What the entry declares","url":"/docs/provider-integration/pilots/longcat-source-pilot#what-the-entry-declares","content":"| Field | Value |\n| -------------- | ------------------------------------------------------------------- |\n| Provider id | longcat (display name LongCat, operator Meituan) |\n| Base URL | https://api.longcat.chat/openai/v1 |\n| Route | POST /chat/completions |\n| Credential | LONGCAT_API_KEY as a Bearer token |\n| Default model | LongCat-2.5-Preview (the only model listed, so no other fallback) |\n| Context window | 1,048,576 tokens |\n| Maximum output | 131,072 tokens |\n| Capabilities | text and streaming; tools, structured output, thinking, vision off |\n| Billing policy | no-free-tier, usage-priced pay-as-you-go |\n\nLongCat-2.0 is served on the same route but is outside this pilot's catalog\nscope, so it is deliberately not a default and not a fallback. The capability booleans bound this pilot's declared scope; they\nare not evidence that the vendor lacks those features.","hierarchy":{"lvl0":"Provider Integration","lvl1":"LongCat text and streaming source pilot","lvl2":"What the entry declares","lvl3":""}},
|
|
9779
|
+
{"objectID":"7245e939d3a1b15b9e15b692373492c576c5b2dd0f67d368c0af06a6fa4d5e34","title":"Billing","url":"/docs/provider-integration/pilots/longcat-source-pilot#billing","content":"The default model is usage-priced. Promotional credits, when an account has\nany, are consumed first, but no free allowance is stated, so the entry claims\nno free tier. The vendor's Pay-As-You-Go page says account verification is required before a\ntop-up, and its FAQ scopes that requirement to users in Mainland China; it was\nnot tried on an account.","hierarchy":{"lvl0":"Provider Integration","lvl1":"LongCat text and streaming source pilot","lvl2":"Billing","lvl3":""}},
|
|
9780
|
+
{"objectID":"a322fab17ddf4673f0e395f7437585b973ad44a999dcee272403b57d889f2cae","title":"Evidence caveats","url":"/docs/provider-integration/pilots/longcat-source-pilot#evidence-caveats","content":"The context integer 1048576 rests on the vendor's own Retrieve Model response\n sample for the exact model id plus the 1M prose; no normative sentence states\n it. It has not been confirmed with GET /openai/v1/models/LongCat-2.5-Preview\n because that needs a key.\nThe vendor SDK snippet omits /v1 although the exact HTTP route includes it;\n the catalog base URL https://api.longcat.chat/openai/v1 is taken from the\n curl example and is proven only against the owned fixture.\nThe vendor's Pay-As-You-Go page says account verification is required before\n top-up; its FAQ scopes that to users in Mainland China. Both were read\n directly; it was not tried on an account. No live call was made.","hierarchy":{"lvl0":"Provider Integration","lvl1":"LongCat text and streaming source pilot","lvl2":"Evidence caveats","lvl3":""}},
|
|
9781
|
+
{"objectID":"5e1ec33de36acb2476ba272dd76207ff55e978dd2b109bc67f3fe64a0723ff03","title":"Local public contract","url":"/docs/provider-integration/pilots/longcat-source-pilot#local-public-contract","content":"test/continuous-test-suite-longcat-pilot.ts runs eight cases through the built\npublic SDK and built CLI, with optional --package-root support for a later\ninstalled consumer:\n\n| Cases | Count | Required observation |\n| ---------------------------------------------- | ----: | ----------------------------------------------------------------------------------------------------------------------------------------------------- |\n| SDK/CLI generate/stream default | 4 | Actual catalog default, /openai/v1/chat/completions, Bearer header, unique user prompt, max_tokens: 32, stream mode, no tools/tool choice, answer |\n| SDK/CLI generate/stream invalid explicit model | 4 | All wire preconditions pass before HTTP 400 rejection; no fallback or successful reply |\n\nThe fixture strips real credentials before imports, uses temporary homes and\npoints the provider at an owned random-port listener. Public MODEL_CONFIG_URL\nuses that same listener's HEAD /health and GET /api/v1/models; a\nschema-valid empty registry keeps the provider's actual catalog default in\ncontrol. The listener is the only server involved: no vendor host is contacted.","hierarchy":{"lvl0":"Provider Integration","lvl1":"LongCat text and streaming source pilot","lvl2":"Local public contract","lvl3":""}},
|
|
9782
|
+
{"objectID":"2ad17a5a824efd7422b7a421784f775f43eb6f34a7d9608725564c0f070b1e19","title":"Provenance and remaining gates","url":"/docs/provider-integration/pilots/longcat-source-pilot#provenance-and-remaining-gates","content":"The legacy evidence.rosterVerified slot carries the explicit\nVENDOR_DOCS_ONLY_NOT_ROSTER_VERIFIED marker. It has no HTTP status, auth probe\nor billing probe; liveMatrix is null. evidence.addedInPR is the\nintroduction pull request URL (https://github.com/juspay/neurolink/pull/1980),\nset after the PR existed; it was PENDING_PR while the work was local. Source-stage admission does not certify current account or API\navailability.\n\nStill pending and separate: an authenticated GET /openai/v1/models roster, a\nfunded-account live matrix, installed-consumer acceptance and any delivery\nclaim.","hierarchy":{"lvl0":"Provider Integration","lvl1":"LongCat text and streaming source pilot","lvl2":"Provenance and remaining gates","lvl3":""}},
|
|
9776
9783
|
{"objectID":"d7aebf13c33ee0a84a4651090aa0b463a2225173acb7dd93f2456adb58d06729","title":"NAVER CLOVA Studio source pilot","url":"/docs/provider-integration/pilots/naver-clova-source-pilot","content":"NAVER CLOVA Studio source pilot\n\nThis source entry uses the OpenAI-compatible chat route at\nhttps://clovastudio.stream.ntruss.com/v1/openai/chat/completions, a CLOVA\nStudio-issued Bearer API key, and the documented HCX-005 model. No actual\naccount, key, model roster, inference or payment operation was performed.\n\nThe vendor Chat Completions v3 reference\nstates that HCX-005 input and output together cannot exceed 128,000 tokens and\nthat requested output cannot exceed 4,096 tokens. The\nOpenAI-compatible guide\nuses that same exact model ID. These are explicit per-model constraints, not\nconversion of an approximate context label.\n\nThe CLOVA Studio prerequisites\nstate that model, purpose and token usage incur fees. The official\nnew-signup credit policy, retrieved on\nOctober 9, 2026, offers 100,000 KRW of conditional discount credit after\npayment-method registration and an application. Issued credit lasts three\nmonths. Eligibility follows the policy at application time; recipients of\nother discounts cannot apply. Free/trial products, Marketplace purchases and\nNAVER WORKS are excluded.\n\nThe bounded promotional-credit billing value records that offer without\nreclassifying it as a free tier or a card-only requirement. It preserves all\nthree existing billing values. It does not prove that a current account is\neligible, subscribed, funded, or able to call the API. Numeric model pricing is\nomitted rather than inventing a KRW-to-USD conversion.\n\nThe shim supports tool choice auto, none and a named tool object, but not\nrequired. The public SDK can express required, so the provider-scoped\nrejectRequiredToolChoice guard rejects that intent on a nonempty-tools\nrequest before sending. It preserves the accepted choices and leaves other\nproviders unchanged. It never changes required into auto.\n\nparallel_tool_calls: false is a documented endpoint limitation, but no\nordinary SDK generate/stream input channel for it was established; this change\nadds no unreachable parameter DSL. The shim ignores JSON-schema name and\nstrict, so this initial entry does not advertise native strict-schema or\nunproved tools-plus-schema support. Other models, native v3 payloads/events,\nembeddings, images, and SDK effort controls remain outside this pilot.\n\nThe dedicated public contract covers SDK and built CLI defaults and routes,\nunique user prompts and backend answers, effective stream modes, exact output\nbudgets, invalid-model rejection, tool nonce round trips for accepted choices,\nand intentional rejection of required. A paired existing-provider control\nmust still honor required. These are owned-endpoint proofs, not vendor live\navailability.\n\nDOCS_ONLY_ROSTER_NOT_OBSERVED labels the legacy required evidence field as\nsource documentation only. addedInPR names the introduction PR\n(https://github.com/juspay/neurolink/pull/1966); it is not proof of merge. Source, contract, installed package, actual account/live and\nreview/delivery states stay separate. Generated regions and heavy validation\nremain coordinator-owned after this source handoff.","hierarchy":{"lvl0":"Provider Integration","lvl1":"NAVER CLOVA Studio source pilot","lvl2":"","lvl3":""}},
|
|
9777
9784
|
{"objectID":"9d81c7d704b297c3886df857adf195cfb90daed24c49f8e64a69db25064c84c2","title":"NAVER CLOVA Studio source pilot","url":"/docs/provider-integration/pilots/naver-clova-source-pilot#naver-clova-studio-source-pilot","content":"This source entry uses the OpenAI-compatible chat route at\nhttps://clovastudio.stream.ntruss.com/v1/openai/chat/completions, a CLOVA\nStudio-issued Bearer API key, and the documented HCX-005 model. No actual\naccount, key, model roster, inference or payment operation was performed.\n\nThe vendor Chat Completions v3 reference\nstates that HCX-005 input and output together cannot exceed 128,000 tokens and\nthat requested output cannot exceed 4,096 tokens. The\nOpenAI-compatible guide\nuses that same exact model ID. These are explicit per-model constraints, not\nconversion of an approximate context label.\n\nThe CLOVA Studio prerequisites\nstate that model, purpose and token usage incur fees. The official\nnew-signup credit policy, retrieved on\nOctober 9, 2026, offers 100,000 KRW of conditional discount credit after\npayment-method registration and an application. Issued credit lasts three\nmonths. Eligibility follows the policy at application time; recipients of\nother discounts cannot apply. Free/trial products, Marketplace purchases and\nNAVER WORKS are excluded.\n\nThe bounded promotional-credit billing value records that offer without\nreclassifying it as a free tier or a card-only requirement. It preserves all\nthree existing billing values. It does not prove that a current account is\neligible, subscribed, funded, or able to call the API. Numeric model pricing is\nomitted rather than inventing a KRW-to-USD conversion.\n\nThe shim supports tool choice auto, none and a named tool object, but not\nrequired. The public SDK can express required, so the provider-scoped\nrejectRequiredToolChoice guard rejects that intent on a nonempty-tools\nrequest before sending. It preserves the accepted choices and leaves other\nproviders unchanged. It never changes required into auto.\n\nparallel_tool_calls: false is a documented endpoint limitation, but no\nordinary SDK generate/stream input channel for it was established; this change\nadds no unreachable parameter DSL.","hierarchy":{"lvl0":"Provider Integration","lvl1":"NAVER CLOVA Studio source pilot","lvl2":"NAVER CLOVA Studio source pilot","lvl3":""}},
|
|
9778
9785
|
{"objectID":"a2a1b3f3eace26df9887f72342446b632c131c811f5b8d9a34eea9f58c1c1ae8","title":"Xiaomi MiMo text and streaming pilot","url":"/docs/provider-integration/pilots/xiaomi-mimo-source-pilot","content":"Xiaomi MiMo text and streaming pilot\n\nThis local source pilot selects Xiaomi MiMo's usage-priced mimo-v2.6-flash\nmodel through https://api.xiaomimimo.com/v1/chat/completions. Its declared\nscope is text generation and streaming. Source preparation, public contract\nacceptance, installed-package acceptance, current account/API availability and\ndelivery are separate gates. This draft gives no live, delivered-provider or\nprovider-target credit.\n\nExact source facts\n\nAll pages below are on the vendor's own documentation host, mimo.mi.com, and\nwere retrieved on 2026-10-10 (hashes at the end).\nContext and output integers. The model table (model.md) shows only the\n rounded labels 1M and 128K, so nothing was expanded from it. The integers\n come from two vendor-authored client configurations that bind them to the\n exact id mimo-v2.6-flash: the OpenClaw guide (\"contextWindow\": 1048576,\n \"maxTokens\": 131072) and the OpenCode guide (\"limit\": { \"context\": 1048576,\n\"output\": 131072 }). Both name https://api.xiaomimimo.com/v1 as the\n pay-as-you-go base URL. The two pages use different client schemas and agree.\n The API reference independently gives [1, 131072] as the required range of\n max_completion_tokens and a default of 131072 for mimo-v2.6-flash; that\n parameter covers visible plus reasoning tokens. No first-party prose or spec\n table states the context integer; the OpenClaw and OpenCode snippets are the\n only bindings, and 1048576 equals 1024 * 1024.\nRoute and auth. The API reference documents\n https://api.xiaomimimo.com/v1/chat/completions and two alternative headers,\n api-key: $MIMO_API_KEY and Authorization: Bearer $MIMO_API_KEY. This entry\n uses the Bearer form.\nLifecycle. mimo-v2.6-flash is current and is the named replacement for\n the retiring mimo-v2.5; it is not itself on a retirement schedule. The\n deprecation page gives mimo-v2.5 and mimo-v2.5-pro a 10:00 (UTC+8)\n switch on 2026-10-14 in its table and 18:00 (UTC+8) in a note on the same page.\n The discrepancy is preserved here; no exact switch instant is certified.\n\nBilling\n\nThe API is usage-priced: the pay-as-you-go page says it \"consumes the account\nbalance based on the actual Token usage\". The promotions page describes bonus\ncredit, obtained through Refer & Earn or new-user registration, that \"can be\nused to offset pay-as-you-go API usage\" and is \"currently valid for 40 days\".\nIt also says eligibility, credit amounts and payout rules vary by campaign. The\ncatalog therefore uses promotional-credit, following the\nNAVER CLOVA Studio profile (src/lib/providers/catalog/naver-clova-studio.json).\nThis is not a free tier. Whether a payment method or identity verification is\nrequired to obtain a working key was not established for the real-time API, the\ncredit amount and eligibility were not checked on an account, and prices are\nnot recorded (the pay-as-you-go page lists CNY and USD and they were not\nconverted).\n\nScope that is deliberately not declared\n\nThe capability booleans limit the pilot's declared scope; false is not\nevidence that the vendor lacks a feature. Tools, vision, structured output and\nSDK thinking controls are not declared because none has been probed. The\ndeprecation page notes that in thinking mode mimo-v2.6-flash ignores custom\ntemperature and top_p, so a thinking mode exists; this entry exposes no\ncontrol for it. Token Plan keys and base URLs are a separate subscription\nproduct and are out of scope.\n\nKnown gaps the local contract cannot close\nOutput-budget field name. The vendor's request reference lists only\n max_completion_tokens. The SDK's shared chat-completions base sends\n max_tokens, and the suite pins that observed field. Whether the vendor\n honors max_tokens, ignores it (leaving the model's 131072 default) or\n rejects it is unverified. A catalog entry cannot rename the field; that would\n need a provider hook or a new catalog quirk, which is an operator decision.\nStreaming usage option. A streaming request carries\n stream_options: { \"include_usage\": true }. The vendor's reference documents\n stream but not stream_options. The suite does not observe how the vendor\n responds to the extra field.\nEnvironment variable. The vendor's own examples name MIMO_API_KEY. The\n catalog's derived primary variable is XIAOMI_MIMO_API_KEY, and MIMO_API_KEY\n is read as a fallback through wire.apiKeyFallbackEnvVars, the mechanism the\n Sakana AI entry also uses. Removing the fallback is a one-line change if the\n maintainers prefer the pure convention.\nCeilings are source-bound only. The shared wire builder fits max_tokens\n only to runtime-discovered ceilings, so the catalog's contextWindow and\n maxOutputTokens never appear on the wire, and no public CLI command or SDK\n export was found that reads them back. The owned endpoint cannot observe\n them; they rest on the cited source bindings alone.\n\nLocal public contract\n\ntest/continuous-test-suite-xiaomi-mimo-pilot.ts runs 12 cases through the\nbuilt public SDK and built CLI, with opt","hierarchy":{"lvl0":"Provider Integration","lvl1":"Xiaomi MiMo text and streaming pilot","lvl2":"","lvl3":""}},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.54.0",
|
|
4
4
|
"packageManager": "pnpm@10.15.1",
|
|
5
5
|
"description": "The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002/call) for routing, tool selection and context budgeting. MCP-native (4 transports), voice TTS/STT/realtime, RAG, agents, memory, compaction, 9 observability exporters. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · TypeSafe Jev and more.",
|
|
6
6
|
"author": {
|
|
@@ -113,6 +113,7 @@
|
|
|
113
113
|
"test:adjust-body-after-400": "pnpm exec tsx test/continuous-test-suite-adjust-body-after-400.ts",
|
|
114
114
|
"test:zod3-schema-native-path": "pnpm exec tsx test/continuous-test-suite-zod3-schema-native-path.ts",
|
|
115
115
|
"test:forced-tool-declared": "pnpm exec tsx test/continuous-test-suite-forced-tool-declared.ts",
|
|
116
|
+
"test:span-content-redaction": "pnpm exec tsx test/continuous-test-suite-span-content-redaction.ts",
|
|
116
117
|
"test:voice-turn-memory": "pnpm exec tsx test/continuous-test-suite-voice-turn-memory.ts",
|
|
117
118
|
"test:error-classification-e2e": "pnpm exec tsx test/continuous-test-suite-error-classification-e2e.ts",
|
|
118
119
|
"test:error-classifier-contract": "pnpm exec tsx test/continuous-test-suite-error-classifier-contract.ts",
|
|
@@ -163,6 +164,7 @@
|
|
|
163
164
|
"test:provider-wiring": "pnpm exec tsx test/continuous-test-suite-provider-wiring.ts",
|
|
164
165
|
"test:embedding-response-validation": "pnpm exec tsx test/continuous-test-suite-embedding-response-validation.ts",
|
|
165
166
|
"test:xiaomi-mimo-pilot": "pnpm exec tsx test/continuous-test-suite-xiaomi-mimo-pilot.ts",
|
|
167
|
+
"test:longcat-pilot": "pnpm exec tsx test/continuous-test-suite-longcat-pilot.ts",
|
|
166
168
|
"test:pdf-image-streaming": "pnpm exec tsx test/continuous-test-suite-pdf-image-streaming.ts",
|
|
167
169
|
"test:rag": "pnpm exec tsx test/continuous-test-suite-rag.ts",
|
|
168
170
|
"test:rag-html-markup": "pnpm exec tsx test/continuous-test-suite-rag-html-markup.ts",
|
|
@@ -221,7 +223,7 @@
|
|
|
221
223
|
"// CI tier — fast, no live AI calls, safe for every commit (test:unit; also see the separate provider-safety-net CI job, which runs build + test:providers-mocked + test:provider-structure + test:error-classifier-contract on every PR)": "",
|
|
222
224
|
"test:tool-routing": "pnpm exec tsx test/continuous-test-suite-tool-routing.ts",
|
|
223
225
|
"test:tool-routing-semantic": "pnpm exec tsx test/continuous-test-suite-tool-routing-semantic.ts",
|
|
224
|
-
"test:unit": "pnpm run test:bugfixes && pnpm run test:mcp:infra && pnpm run test:mcp:spans && pnpm run test:tool-routing && pnpm run test:tool-routing-cli && pnpm run test:tool-dedup && pnpm run test:model-pool && pnpm run test:classifier-router && pnpm run test:tool-routing-semantic && pnpm run test:mcp-result-cache && pnpm run test:mcp-direct-name-repair && pnpm run test:mcp-breaker-resolved-errors && pnpm run test:archive:security && pnpm run test:office:security && pnpm run test:image-exif && pnpm run test:vector-chroma && pnpm run test:vector-pgvector && pnpm run test:vector-pinecone && pnpm run test:provider-wiring && pnpm run test:docs-mcp && pnpm run test:retired-model-defaults && pnpm run test:cli-fallback && pnpm run test:embedding-response-validation && pnpm run test:xiaomi-mimo-pilot && pnpm run test:rag-bounds",
|
|
226
|
+
"test:unit": "pnpm run test:bugfixes && pnpm run test:mcp:infra && pnpm run test:mcp:spans && pnpm run test:tool-routing && pnpm run test:tool-routing-cli && pnpm run test:tool-dedup && pnpm run test:model-pool && pnpm run test:classifier-router && pnpm run test:tool-routing-semantic && pnpm run test:mcp-result-cache && pnpm run test:mcp-direct-name-repair && pnpm run test:mcp-breaker-resolved-errors && pnpm run test:archive:security && pnpm run test:office:security && pnpm run test:image-exif && pnpm run test:vector-chroma && pnpm run test:vector-pgvector && pnpm run test:vector-pinecone && pnpm run test:provider-wiring && pnpm run test:docs-mcp && pnpm run test:retired-model-defaults && pnpm run test:cli-fallback && pnpm run test:embedding-response-validation && pnpm run test:xiaomi-mimo-pilot && pnpm run test:rag-bounds && pnpm run test:longcat-pilot",
|
|
225
227
|
"// CI tier — live providers, runs only when API keys are present (test:credentials and test:dynamic make real provider calls when keys are set, so they live here, not in test:unit; test:matrix, a different suite covering the full provider capability matrix, runs nightly via .github/workflows/live-matrix.yml — test:providers itself is still only wired into test:live, not any GitHub Actions workflow)": "",
|
|
226
228
|
"test:live": "pnpm run test:providers && pnpm run test:mcp:http && pnpm run test:mcp:sdk && pnpm run test:mcp:cli && pnpm run test:observability && pnpm run test:context && pnpm run test:memory && pnpm run test:tool-reliability && pnpm run test:evaluation && pnpm run test:autoresearch && pnpm run test:credentials && pnpm run test:dynamic && pnpm run test:model-not-found-retryable",
|
|
227
229
|
"// CI tier — product output (image/video/TTS/PPT) — costs $$ per run (not wired into any GitHub Actions workflow as of this comment; run manually or add to live-matrix.yml if nightly coverage is needed)": "",
|