@juspay/neurolink 12.11.3 → 12.12.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 +3 -4
- package/dist/browser/neurolink.min.js +533 -581
- package/dist/constants/enums.d.ts +13 -0
- package/dist/constants/enums.js +14 -0
- package/dist/core/baseProvider.d.ts +71 -3
- package/dist/core/baseProvider.js +152 -44
- package/dist/core/modules/GenerationHandler.d.ts +22 -24
- package/dist/core/modules/GenerationHandler.js +28 -463
- package/dist/core/nativeGenerateLoop.d.ts +35 -0
- package/dist/core/nativeGenerateLoop.js +261 -0
- package/dist/files/fileTools.d.ts +5 -5
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4 -0
- package/dist/middleware/builtin/guardrails.d.ts +0 -5
- package/dist/middleware/builtin/guardrails.js +33 -5
- package/dist/middleware/factory.js +1 -1
- package/dist/middleware/wrapLanguageModel.d.ts +18 -0
- package/dist/middleware/wrapLanguageModel.js +53 -0
- package/dist/processors/media/AudioProcessor.js +46 -11
- package/dist/providers/amazonSagemaker.d.ts +17 -1
- package/dist/providers/amazonSagemaker.js +110 -0
- package/dist/providers/anthropic/client.d.ts +11 -0
- package/dist/providers/anthropic/client.js +148 -1
- package/dist/providers/catalog/index.generated.d.ts +1 -1
- package/dist/providers/catalog/index.generated.js +3 -0
- package/dist/providers/catalog/loader.js +1 -0
- package/dist/providers/catalog/mancer.json +192 -0
- package/dist/providers/configuredOpenAICompat.d.ts +11 -0
- package/dist/providers/configuredOpenAICompat.js +16 -0
- package/dist/providers/googleVertex/client.d.ts +0 -9
- package/dist/providers/googleVertex/client.js +0 -33
- package/dist/providers/openaiChatCompletionsBase.d.ts +21 -1
- package/dist/providers/openaiChatCompletionsBase.js +178 -0
- package/dist/providers/providerTypeUtils.d.ts +1 -2
- package/dist/providers/providerTypeUtils.js +5 -1
- package/dist/types/aiCompat.d.ts +485 -0
- package/dist/types/aiCompat.js +17 -0
- package/dist/types/conversation.d.ts +1 -1
- package/dist/types/generate.d.ts +52 -0
- package/dist/types/middleware.d.ts +3 -6
- package/dist/types/providerCatalog.generated.d.ts +2 -2
- package/dist/types/providers.d.ts +14 -1
- package/dist/types/tools.d.ts +2 -2
- package/dist/utils/generationErrors.d.ts +78 -6
- package/dist/utils/generationErrors.js +114 -6
- package/dist/utils/nativeSingleShot.d.ts +3 -0
- package/dist/utils/nativeSingleShot.js +83 -0
- package/dist/utils/tool.d.ts +30 -5
- package/dist/utils/tool.js +43 -5
- package/package.json +3 -6
- package/dist/utils/generation.d.ts +0 -8
- package/dist/utils/generation.js +0 -8
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { BaseProvider } from "../core/baseProvider.js";
|
|
2
2
|
import { createStreamChannel } from "../core/streamChannel.js";
|
|
3
3
|
import { logger } from "../utils/logger.js";
|
|
4
|
+
import { resolveRequestKind } from "../core/resolveRequestKind.js";
|
|
5
|
+
import { resolveToolExecutionRecords } from "../core/toolExecutionRecorder.js";
|
|
6
|
+
import { transformToolExecutions } from "../utils/transformationUtils.js";
|
|
7
|
+
import { convertZodToJsonSchema } from "../utils/schemaConversion.js";
|
|
8
|
+
import { withProviderRetry } from "../utils/providerRetry.js";
|
|
9
|
+
import { DEFAULT_MAX_STEPS } from "../core/constants.js";
|
|
10
|
+
import { hasNativeDoGenerate, runNativeGenerateLoop, } from "../core/nativeGenerateLoop.js";
|
|
4
11
|
import { withSpan } from "../telemetry/withSpan.js";
|
|
5
12
|
import { tracers } from "../telemetry/tracers.js";
|
|
6
13
|
// SageMaker-specific imports
|
|
@@ -93,6 +100,109 @@ export class AmazonSageMakerProvider extends BaseProvider {
|
|
|
93
100
|
const smModel = this.sagemakerModel;
|
|
94
101
|
return smModel;
|
|
95
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Native non-streaming generate.
|
|
105
|
+
*
|
|
106
|
+
* SageMaker's doGenerate makes one invokeEndpoint call and already returns
|
|
107
|
+
* toolCalls; no streaming is involved, so the wire hazard that reverted the
|
|
108
|
+
* first migration does not apply here. This supplies only the multi-step
|
|
109
|
+
* iteration the ai package used to.
|
|
110
|
+
*
|
|
111
|
+
* NOT EXERCISED LIVE. This machine has no SageMaker endpoint or credentials.
|
|
112
|
+
* The single-step shape is identical by construction — with no tool calls the
|
|
113
|
+
* loop breaks after exactly one doGenerate carrying the same options the ai
|
|
114
|
+
* loop passed. The multi-step branch is the new code and wants a real
|
|
115
|
+
* endpoint before it is trusted.
|
|
116
|
+
*/
|
|
117
|
+
async generate(optionsOrPrompt, analysisSchema) {
|
|
118
|
+
await this.ensureModelLimits();
|
|
119
|
+
const options = this.normalizeTextOptions(optionsOrPrompt);
|
|
120
|
+
if (resolveRequestKind(options, this.modelName) !== "text") {
|
|
121
|
+
return super.generate(options, analysisSchema);
|
|
122
|
+
}
|
|
123
|
+
this.validateOptions(options);
|
|
124
|
+
const mergedTools = await this.getToolsForStream(options);
|
|
125
|
+
const callerOwnsFallback = "disableInternalFallback" in options &&
|
|
126
|
+
options.disableInternalFallback === true;
|
|
127
|
+
// The native loop bypasses BaseProvider.executeGeneration, so the turn
|
|
128
|
+
// budget has to be composed here or it stops existing for this provider.
|
|
129
|
+
return this.runGenerateWithModelFallback(() => this.withTurnTimeout({ ...options, tools: mergedTools }, this.getDescriptorGenerateMs(), (timedOptions) => this.executeNativeGenerate(timedOptions)), callerOwnsFallback);
|
|
130
|
+
}
|
|
131
|
+
async executeNativeGenerate(options) {
|
|
132
|
+
const startTime = Date.now();
|
|
133
|
+
// Middleware must wrap the model here. The native loop bypasses
|
|
134
|
+
// BaseProvider.executeGeneration, and with it the only place middleware was
|
|
135
|
+
// ever applied — a probe showed a caller's wrapGenerate running zero times
|
|
136
|
+
// on every native provider while their onFinish still fired, because
|
|
137
|
+
// onFinish had been special-cased and nothing else had.
|
|
138
|
+
const model = await this.getAISDKModelWithMiddleware(options);
|
|
139
|
+
if (!hasNativeDoGenerate(model)) {
|
|
140
|
+
throw this.handleProviderError(new Error("sagemaker: model handle exposes no doGenerate()"));
|
|
141
|
+
}
|
|
142
|
+
const doGenerate = model.doGenerate.bind(model);
|
|
143
|
+
const shouldUseTools = !options.disableTools && this.supportsTools();
|
|
144
|
+
const toolsRecord = shouldUseTools
|
|
145
|
+
? options.tools || {}
|
|
146
|
+
: {};
|
|
147
|
+
const v3Tools = Object.entries(toolsRecord).map(([name, t]) => {
|
|
148
|
+
const tool = t;
|
|
149
|
+
return {
|
|
150
|
+
type: "function",
|
|
151
|
+
name,
|
|
152
|
+
description: tool.description ?? "",
|
|
153
|
+
inputSchema: (tool.inputSchema
|
|
154
|
+
? convertZodToJsonSchema(tool.inputSchema)
|
|
155
|
+
: { type: "object", properties: {} }),
|
|
156
|
+
};
|
|
157
|
+
});
|
|
158
|
+
// Structured output was dropped entirely on this path: the schema never
|
|
159
|
+
// reached the request, and nothing downstream re-imposed it, so a caller
|
|
160
|
+
// asking for an object got whatever JSON coerceJsonToSchema could scrape
|
|
161
|
+
// out of prose.
|
|
162
|
+
const responseFormat = options.schema
|
|
163
|
+
? {
|
|
164
|
+
type: "json",
|
|
165
|
+
schema: convertZodToJsonSchema(options.schema),
|
|
166
|
+
}
|
|
167
|
+
: undefined;
|
|
168
|
+
const conversation = (await this.buildMessagesForStream(options));
|
|
169
|
+
const toolExecutionSummaries = [];
|
|
170
|
+
const loop = await runNativeGenerateLoop({
|
|
171
|
+
doGenerate,
|
|
172
|
+
conversation,
|
|
173
|
+
...(responseFormat ? { responseFormat } : {}),
|
|
174
|
+
...(v3Tools.length > 0 ? { tools: v3Tools } : {}),
|
|
175
|
+
toolsRecord,
|
|
176
|
+
maxSteps: options.maxSteps || DEFAULT_MAX_STEPS,
|
|
177
|
+
...(options.maxTokens ? { maxOutputTokens: options.maxTokens } : {}),
|
|
178
|
+
...(options.temperature !== undefined
|
|
179
|
+
? { temperature: options.temperature }
|
|
180
|
+
: {}),
|
|
181
|
+
...(options.abortSignal ? { abortSignal: options.abortSignal } : {}),
|
|
182
|
+
...(options.toolTimeoutMs !== undefined
|
|
183
|
+
? { toolTimeoutMs: options.toolTimeoutMs }
|
|
184
|
+
: {}),
|
|
185
|
+
runStep: (call) => withProviderRetry(call, undefined, "sagemaker generate").catch((err) => {
|
|
186
|
+
throw this.handleProviderError(err);
|
|
187
|
+
}),
|
|
188
|
+
}, toolExecutionSummaries);
|
|
189
|
+
const enhanced = {
|
|
190
|
+
content: loop.text,
|
|
191
|
+
provider: this.providerName,
|
|
192
|
+
model: this.modelName,
|
|
193
|
+
finishReason: loop.finishReason,
|
|
194
|
+
usage: {
|
|
195
|
+
input: loop.inputTokens,
|
|
196
|
+
output: loop.outputTokens,
|
|
197
|
+
total: loop.inputTokens + loop.outputTokens,
|
|
198
|
+
},
|
|
199
|
+
responseTime: Date.now() - startTime,
|
|
200
|
+
toolsUsed: loop.toolsUsed,
|
|
201
|
+
toolExecutions: resolveToolExecutionRecords(options, transformToolExecutions(toolExecutionSummaries)),
|
|
202
|
+
enhancedWithTools: loop.toolsUsed.length > 0,
|
|
203
|
+
};
|
|
204
|
+
return this.finalizeNativeGenerate(enhanced, options, startTime);
|
|
205
|
+
}
|
|
96
206
|
/**
|
|
97
207
|
* Streaming was previously an `executeStream` override that unconditionally
|
|
98
208
|
* threw "not yet fully implemented" — while `SageMakerLanguageModel.doStream`
|
|
@@ -133,6 +133,17 @@ export declare class AnthropicProvider extends BaseProvider {
|
|
|
133
133
|
* BaseProvider so that expired tokens are renewed automatically.
|
|
134
134
|
*/
|
|
135
135
|
generate(optionsOrPrompt: TextGenerationOptions | string, analysisSchema?: ValidationSchema): Promise<EnhancedGenerateResult | null>;
|
|
136
|
+
/**
|
|
137
|
+
* Text turns run natively; every other request kind still goes to
|
|
138
|
+
* BaseProvider.generate().
|
|
139
|
+
*
|
|
140
|
+
* The loop runs over this provider's own delegating-model `doGenerate`,
|
|
141
|
+
* which issues a NON-streaming `messages.create`. That matters: the streaming
|
|
142
|
+
* loop adapter hardcodes `stream: true`, and an earlier attempt that routed
|
|
143
|
+
* generate through it silently changed the wire.
|
|
144
|
+
*/
|
|
145
|
+
private dispatchGenerate;
|
|
146
|
+
private executeNativeGenerate;
|
|
136
147
|
/**
|
|
137
148
|
* Fold a captured snapshot into the provider's usage bookkeeping and log it.
|
|
138
149
|
*
|
|
@@ -25,6 +25,11 @@ import { calculateCost } from "../../utils/pricing.js";
|
|
|
25
25
|
import { stringifyAnthropicToolOutput } from "./toolOutput.js";
|
|
26
26
|
import { createAnthropicLoopAdapter } from "./loopAdapter.js";
|
|
27
27
|
import { runAgenticLoop } from "../../core/loopEngine.js";
|
|
28
|
+
import { hasNativeDoGenerate, runNativeGenerateLoop, } from "../../core/nativeGenerateLoop.js";
|
|
29
|
+
import { withProviderRetry } from "../../utils/providerRetry.js";
|
|
30
|
+
import { resolveRequestKind } from "../../core/resolveRequestKind.js";
|
|
31
|
+
import { resolveToolExecutionRecords } from "../../core/toolExecutionRecorder.js";
|
|
32
|
+
import { transformToolExecutions } from "../../utils/transformationUtils.js";
|
|
28
33
|
import { createAnthropicConfig, getProviderModel, validateApiKey, } from "../../utils/providerConfig.js";
|
|
29
34
|
import { composeAbortSignals, createTimeoutController, mergeAbortSignals, TimeoutError, } from "../../utils/timeout.js";
|
|
30
35
|
import { resolveToolChoice } from "../../utils/toolChoice.js";
|
|
@@ -1327,7 +1332,7 @@ export class AnthropicProvider extends BaseProvider {
|
|
|
1327
1332
|
// rather than on the instance is what makes it concurrency-safe: several
|
|
1328
1333
|
// generate() calls can be in flight on one provider instance, and an
|
|
1329
1334
|
// instance field would attribute one call's limits to another.
|
|
1330
|
-
const { result, snapshot } = await withLimitCapture(() =>
|
|
1335
|
+
const { result, snapshot } = await withLimitCapture(() => this.dispatchGenerate(optionsOrPrompt, analysisSchema));
|
|
1331
1336
|
if (result && snapshot) {
|
|
1332
1337
|
this.recordLimitSnapshot(snapshot);
|
|
1333
1338
|
result.limits = snapshot;
|
|
@@ -1337,6 +1342,148 @@ export class AnthropicProvider extends BaseProvider {
|
|
|
1337
1342
|
}
|
|
1338
1343
|
return result;
|
|
1339
1344
|
}
|
|
1345
|
+
/**
|
|
1346
|
+
* Text turns run natively; every other request kind still goes to
|
|
1347
|
+
* BaseProvider.generate().
|
|
1348
|
+
*
|
|
1349
|
+
* The loop runs over this provider's own delegating-model `doGenerate`,
|
|
1350
|
+
* which issues a NON-streaming `messages.create`. That matters: the streaming
|
|
1351
|
+
* loop adapter hardcodes `stream: true`, and an earlier attempt that routed
|
|
1352
|
+
* generate through it silently changed the wire.
|
|
1353
|
+
*/
|
|
1354
|
+
async dispatchGenerate(optionsOrPrompt, analysisSchema) {
|
|
1355
|
+
await this.ensureModelLimits();
|
|
1356
|
+
const options = this.normalizeTextOptions(optionsOrPrompt);
|
|
1357
|
+
if (resolveRequestKind(options, this.modelName) !== "text") {
|
|
1358
|
+
return super.generate(options, analysisSchema);
|
|
1359
|
+
}
|
|
1360
|
+
this.validateOptions(options);
|
|
1361
|
+
const mergedTools = await this.getToolsForStream(options);
|
|
1362
|
+
const callerOwnsFallback = "disableInternalFallback" in options &&
|
|
1363
|
+
options.disableInternalFallback === true;
|
|
1364
|
+
// The native loop bypasses BaseProvider.executeGeneration, so the turn
|
|
1365
|
+
// budget has to be composed here or it stops existing for this provider.
|
|
1366
|
+
return this.runGenerateWithModelFallback(() => this.withTurnTimeout({ ...options, tools: mergedTools }, this.getDescriptorGenerateMs(), (timedOptions) => this.executeNativeGenerate(timedOptions)), callerOwnsFallback);
|
|
1367
|
+
}
|
|
1368
|
+
async executeNativeGenerate(options) {
|
|
1369
|
+
const startTime = Date.now();
|
|
1370
|
+
const modelId = this.modelName || getDefaultAnthropicModel();
|
|
1371
|
+
// Middleware must wrap the model here. The native loop bypasses
|
|
1372
|
+
// BaseProvider.executeGeneration, and with it the only place middleware was
|
|
1373
|
+
// ever applied — a probe showed a caller's wrapGenerate running zero times
|
|
1374
|
+
// on every native provider while their onFinish still fired, because
|
|
1375
|
+
// onFinish had been special-cased and nothing else had.
|
|
1376
|
+
const model = await this.getAISDKModelWithMiddleware(options);
|
|
1377
|
+
if (!hasNativeDoGenerate(model)) {
|
|
1378
|
+
throw this.handleProviderError(new Error("anthropic: model handle exposes no doGenerate()"));
|
|
1379
|
+
}
|
|
1380
|
+
const doGenerate = model.doGenerate.bind(model);
|
|
1381
|
+
const shouldUseTools = !options.disableTools && this.supportsTools();
|
|
1382
|
+
const toolsRecord = shouldUseTools
|
|
1383
|
+
? options.tools || {}
|
|
1384
|
+
: {};
|
|
1385
|
+
const v3Tools = Object.entries(toolsRecord).map(([name, t]) => {
|
|
1386
|
+
const tool = t;
|
|
1387
|
+
return {
|
|
1388
|
+
type: "function",
|
|
1389
|
+
name,
|
|
1390
|
+
description: tool.description ?? "",
|
|
1391
|
+
inputSchema: (tool.inputSchema
|
|
1392
|
+
? convertZodToJsonSchema(tool.inputSchema)
|
|
1393
|
+
: { type: "object", properties: {} }),
|
|
1394
|
+
};
|
|
1395
|
+
});
|
|
1396
|
+
const hasTools = v3Tools.length > 0;
|
|
1397
|
+
// Two structured-output routes, and doGenerate implements both. With no
|
|
1398
|
+
// tools it replaces the tool list with one forced json tool; with tools it
|
|
1399
|
+
// APPENDS final_result so the real tools stay callable. Picking the wrong
|
|
1400
|
+
// one is what dropped structuredData to null on the first attempt.
|
|
1401
|
+
const schemaJson = options.schema
|
|
1402
|
+
? convertZodToJsonSchema(options.schema)
|
|
1403
|
+
: undefined;
|
|
1404
|
+
const responseFormat = schemaJson && !hasTools
|
|
1405
|
+
? { type: "json", schema: schemaJson }
|
|
1406
|
+
: undefined;
|
|
1407
|
+
const anthropicNamespace = {};
|
|
1408
|
+
if (schemaJson && hasTools) {
|
|
1409
|
+
anthropicNamespace.finalResultSchema = schemaJson;
|
|
1410
|
+
}
|
|
1411
|
+
if (options.thinkingConfig?.enabled &&
|
|
1412
|
+
options.thinkingConfig.budgetTokens) {
|
|
1413
|
+
anthropicNamespace.thinking = {
|
|
1414
|
+
type: "enabled",
|
|
1415
|
+
budget_tokens: options.thinkingConfig.budgetTokens,
|
|
1416
|
+
};
|
|
1417
|
+
}
|
|
1418
|
+
// The per-call `timeout` keeps its per-MODEL-CALL meaning once
|
|
1419
|
+
// `turnTimeoutMs` owns the whole-turn deadline, and it reaches the model
|
|
1420
|
+
// layer only through providerOptions.neurolink. Without it each step fell
|
|
1421
|
+
// back to the provider default.
|
|
1422
|
+
const mergedProviderOptions = {};
|
|
1423
|
+
if (Object.keys(anthropicNamespace).length > 0) {
|
|
1424
|
+
mergedProviderOptions.anthropic = anthropicNamespace;
|
|
1425
|
+
}
|
|
1426
|
+
if (typeof options.timeout === "number") {
|
|
1427
|
+
mergedProviderOptions.neurolink = { timeoutMs: options.timeout };
|
|
1428
|
+
}
|
|
1429
|
+
const providerOptions = Object.keys(mergedProviderOptions).length > 0
|
|
1430
|
+
? mergedProviderOptions
|
|
1431
|
+
: undefined;
|
|
1432
|
+
const conversation = (await this.buildMessagesForStream(options));
|
|
1433
|
+
const toolExecutionSummaries = [];
|
|
1434
|
+
const loop = await runNativeGenerateLoop({
|
|
1435
|
+
doGenerate,
|
|
1436
|
+
conversation,
|
|
1437
|
+
...(hasTools ? { tools: v3Tools } : {}),
|
|
1438
|
+
toolsRecord,
|
|
1439
|
+
// A caller's toolChoice was dropped here while the streaming path and
|
|
1440
|
+
// the OpenAI-compatible native path both forwarded it, so
|
|
1441
|
+
// `toolChoice: "required"` and named-tool choices silently degraded to
|
|
1442
|
+
// Anthropic's default `auto` on generate().
|
|
1443
|
+
...(hasTools && options.toolChoice
|
|
1444
|
+
? { toolChoice: resolveToolChoice(options, toolsRecord, true) }
|
|
1445
|
+
: {}),
|
|
1446
|
+
...(responseFormat ? { responseFormat } : {}),
|
|
1447
|
+
...(providerOptions ? { providerOptions } : {}),
|
|
1448
|
+
maxSteps: options.maxSteps || DEFAULT_MAX_STEPS,
|
|
1449
|
+
...(options.maxTokens ? { maxOutputTokens: options.maxTokens } : {}),
|
|
1450
|
+
...(options.temperature !== undefined
|
|
1451
|
+
? { temperature: options.temperature }
|
|
1452
|
+
: {}),
|
|
1453
|
+
...(options.abortSignal ? { abortSignal: options.abortSignal } : {}),
|
|
1454
|
+
...(options.toolTimeoutMs !== undefined
|
|
1455
|
+
? { toolTimeoutMs: options.toolTimeoutMs }
|
|
1456
|
+
: {}),
|
|
1457
|
+
runStep: (call) => withProviderRetry(call, trace.getActiveSpan() ?? undefined, "anthropic generate").catch((err) => {
|
|
1458
|
+
throw this.handleProviderError(err);
|
|
1459
|
+
}),
|
|
1460
|
+
}, toolExecutionSummaries);
|
|
1461
|
+
const enhanced = {
|
|
1462
|
+
content: loop.text,
|
|
1463
|
+
provider: this.providerName,
|
|
1464
|
+
model: modelId,
|
|
1465
|
+
finishReason: loop.finishReason,
|
|
1466
|
+
...(loop.rawFinishReason
|
|
1467
|
+
? { rawFinishReason: loop.rawFinishReason }
|
|
1468
|
+
: {}),
|
|
1469
|
+
usage: {
|
|
1470
|
+
input: loop.inputTokens,
|
|
1471
|
+
output: loop.outputTokens,
|
|
1472
|
+
total: loop.inputTokens + loop.outputTokens,
|
|
1473
|
+
...(loop.cacheReadTokens
|
|
1474
|
+
? { cacheReadTokens: loop.cacheReadTokens }
|
|
1475
|
+
: {}),
|
|
1476
|
+
...(loop.cacheWriteTokens
|
|
1477
|
+
? { cacheCreationTokens: loop.cacheWriteTokens }
|
|
1478
|
+
: {}),
|
|
1479
|
+
},
|
|
1480
|
+
responseTime: Date.now() - startTime,
|
|
1481
|
+
toolsUsed: loop.toolsUsed,
|
|
1482
|
+
toolExecutions: resolveToolExecutionRecords(options, transformToolExecutions(toolExecutionSummaries)),
|
|
1483
|
+
enhancedWithTools: loop.toolsUsed.length > 0,
|
|
1484
|
+
};
|
|
1485
|
+
return this.finalizeNativeGenerate(enhanced, options, startTime);
|
|
1486
|
+
}
|
|
1340
1487
|
/**
|
|
1341
1488
|
* Fold a captured snapshot into the provider's usage bookkeeping and log it.
|
|
1342
1489
|
*
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { ProviderCatalogJson } from "../../types/index.js";
|
|
2
2
|
export declare const CATALOG_JSON_ENTRIES: ProviderCatalogJson[];
|
|
3
|
-
export declare const CATALOG_PROVIDER_IDS: readonly ["baseten", "cerebras", "cloudflare", "fireworks", "gmicloud", "groq", "inception-labs", "io-intelligence", "mistral", "perplexity", "sambanova", "together-ai", "upstage", "xai"];
|
|
3
|
+
export declare const CATALOG_PROVIDER_IDS: readonly ["baseten", "cerebras", "cloudflare", "fireworks", "gmicloud", "groq", "inception-labs", "io-intelligence", "mancer", "mistral", "perplexity", "sambanova", "together-ai", "upstage", "xai"];
|
|
@@ -8,6 +8,7 @@ import gmicloudJson from "./gmicloud.json" with { type: "json" };
|
|
|
8
8
|
import groqJson from "./groq.json" with { type: "json" };
|
|
9
9
|
import inceptionLabsJson from "./inception-labs.json" with { type: "json" };
|
|
10
10
|
import ioIntelligenceJson from "./io-intelligence.json" with { type: "json" };
|
|
11
|
+
import mancerJson from "./mancer.json" with { type: "json" };
|
|
11
12
|
import mistralJson from "./mistral.json" with { type: "json" };
|
|
12
13
|
import perplexityJson from "./perplexity.json" with { type: "json" };
|
|
13
14
|
import sambanovaJson from "./sambanova.json" with { type: "json" };
|
|
@@ -23,6 +24,7 @@ export const CATALOG_JSON_ENTRIES = [
|
|
|
23
24
|
groqJson,
|
|
24
25
|
inceptionLabsJson,
|
|
25
26
|
ioIntelligenceJson,
|
|
27
|
+
mancerJson,
|
|
26
28
|
mistralJson,
|
|
27
29
|
perplexityJson,
|
|
28
30
|
sambanovaJson,
|
|
@@ -39,6 +41,7 @@ export const CATALOG_PROVIDER_IDS = [
|
|
|
39
41
|
"groq",
|
|
40
42
|
"inception-labs",
|
|
41
43
|
"io-intelligence",
|
|
44
|
+
"mancer",
|
|
42
45
|
"mistral",
|
|
43
46
|
"perplexity",
|
|
44
47
|
"sambanova",
|
|
@@ -89,6 +89,7 @@ export function buildCatalogEntries() {
|
|
|
89
89
|
entry.models.fallbacks[0],
|
|
90
90
|
fallbackModels: [...entry.models.fallbacks],
|
|
91
91
|
errorRules: buildErrorRules(entry),
|
|
92
|
+
supportsTools: entry.capabilities.tools,
|
|
92
93
|
};
|
|
93
94
|
const { baseURLTemplate } = entry.wire;
|
|
94
95
|
if (baseURLTemplate) {
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "./provider-catalog.schema.json",
|
|
3
|
+
"id": "mancer",
|
|
4
|
+
"displayName": "Mancer",
|
|
5
|
+
"aliases": ["mancer-tech"],
|
|
6
|
+
"tier": 2,
|
|
7
|
+
"wire": {
|
|
8
|
+
"baseURL": "https://neuro.mancer.tech/oai/v1"
|
|
9
|
+
},
|
|
10
|
+
"models": {
|
|
11
|
+
"default": "deepseek-v4-flash",
|
|
12
|
+
"fallbacks": ["deepseek-v4-flash", "gpt-oss-120b"],
|
|
13
|
+
"defaultContextWindow": 1048576,
|
|
14
|
+
"defaultMaxOutputTokens": 1048576,
|
|
15
|
+
"catalog": {
|
|
16
|
+
"mythomax": {
|
|
17
|
+
"contextWindow": 8192,
|
|
18
|
+
"maxOutputTokens": 8192,
|
|
19
|
+
"pricingPerMTok": {
|
|
20
|
+
"input": 0.14,
|
|
21
|
+
"output": 0.24
|
|
22
|
+
},
|
|
23
|
+
"vision": false,
|
|
24
|
+
"status": "production",
|
|
25
|
+
"description": "MythoMax (LLaMA 2, Simplified Alpaca format) — pricing and limits from the authenticated /oai/v1/models roster, 2026-09-03"
|
|
26
|
+
},
|
|
27
|
+
"deepseek-v4-flash": {
|
|
28
|
+
"contextWindow": 1048576,
|
|
29
|
+
"maxOutputTokens": 1048576,
|
|
30
|
+
"pricingPerMTok": {
|
|
31
|
+
"input": 0.07,
|
|
32
|
+
"output": 0.2
|
|
33
|
+
},
|
|
34
|
+
"vision": false,
|
|
35
|
+
"status": "production",
|
|
36
|
+
"description": "DeepSeek V4 Flash — Mancer's flagship general model; paid credits required — pricing and limits from the authenticated /oai/v1/models roster, 2026-09-03"
|
|
37
|
+
},
|
|
38
|
+
"deepseek-v4-flash-0731": {
|
|
39
|
+
"contextWindow": 1048576,
|
|
40
|
+
"maxOutputTokens": 1048576,
|
|
41
|
+
"pricingPerMTok": {
|
|
42
|
+
"input": 0.07,
|
|
43
|
+
"output": 0.2
|
|
44
|
+
},
|
|
45
|
+
"vision": false,
|
|
46
|
+
"status": "production",
|
|
47
|
+
"description": "DeepSeek V4 Flash, 2026-07-31 snapshot; paid credits required — pricing and limits from the authenticated /oai/v1/models roster, 2026-09-03"
|
|
48
|
+
},
|
|
49
|
+
"mytholite": {
|
|
50
|
+
"contextWindow": 2560,
|
|
51
|
+
"maxOutputTokens": 150,
|
|
52
|
+
"pricingPerMTok": {
|
|
53
|
+
"input": 0,
|
|
54
|
+
"output": 0
|
|
55
|
+
},
|
|
56
|
+
"vision": false,
|
|
57
|
+
"status": "production",
|
|
58
|
+
"description": "MythoLite — Mancer's free demo model (2,560-token context, 150-token completions, Simplified Alpaca format); the only model usable with a zero balance — pricing and limits from the authenticated /oai/v1/models roster, 2026-09-03"
|
|
59
|
+
},
|
|
60
|
+
"remm-slerp": {
|
|
61
|
+
"contextWindow": 6144,
|
|
62
|
+
"maxOutputTokens": 6144,
|
|
63
|
+
"pricingPerMTok": {
|
|
64
|
+
"input": 0.14,
|
|
65
|
+
"output": 0.26
|
|
66
|
+
},
|
|
67
|
+
"vision": false,
|
|
68
|
+
"status": "production",
|
|
69
|
+
"description": "ReMM-SLERP (Simplified Alpaca format) — pricing and limits from the authenticated /oai/v1/models roster, 2026-09-03"
|
|
70
|
+
},
|
|
71
|
+
"magnum-72b-v4": {
|
|
72
|
+
"contextWindow": 32768,
|
|
73
|
+
"maxOutputTokens": 4096,
|
|
74
|
+
"pricingPerMTok": {
|
|
75
|
+
"input": 1,
|
|
76
|
+
"output": 2
|
|
77
|
+
},
|
|
78
|
+
"vision": false,
|
|
79
|
+
"status": "production",
|
|
80
|
+
"description": "Magnum 72B v4 (ChatML format) — pricing and limits from the authenticated /oai/v1/models roster, 2026-09-03"
|
|
81
|
+
},
|
|
82
|
+
"glm-4.7": {
|
|
83
|
+
"contextWindow": 131072,
|
|
84
|
+
"maxOutputTokens": 131072,
|
|
85
|
+
"pricingPerMTok": {
|
|
86
|
+
"input": 0.28,
|
|
87
|
+
"output": 1
|
|
88
|
+
},
|
|
89
|
+
"vision": false,
|
|
90
|
+
"status": "production",
|
|
91
|
+
"description": "GLM-4.7 — pricing and limits from the authenticated /oai/v1/models roster, 2026-09-03"
|
|
92
|
+
},
|
|
93
|
+
"gpt-oss-120b": {
|
|
94
|
+
"contextWindow": 131072,
|
|
95
|
+
"maxOutputTokens": 131072,
|
|
96
|
+
"pricingPerMTok": {
|
|
97
|
+
"input": 0.022,
|
|
98
|
+
"output": 0.2
|
|
99
|
+
},
|
|
100
|
+
"vision": false,
|
|
101
|
+
"status": "production",
|
|
102
|
+
"description": "GPT-OSS 120B — pricing and limits from the authenticated /oai/v1/models roster, 2026-09-03"
|
|
103
|
+
},
|
|
104
|
+
"weaver-alpha": {
|
|
105
|
+
"contextWindow": 8000,
|
|
106
|
+
"maxOutputTokens": 6000,
|
|
107
|
+
"pricingPerMTok": {
|
|
108
|
+
"input": 0.16,
|
|
109
|
+
"output": 0.3
|
|
110
|
+
},
|
|
111
|
+
"vision": false,
|
|
112
|
+
"status": "production",
|
|
113
|
+
"description": "Weaver Alpha (Simplified Alpaca format) — pricing and limits from the authenticated /oai/v1/models roster, 2026-09-03"
|
|
114
|
+
},
|
|
115
|
+
"dans-pe-1.3-24b": {
|
|
116
|
+
"contextWindow": 32768,
|
|
117
|
+
"maxOutputTokens": 8192,
|
|
118
|
+
"pricingPerMTok": {
|
|
119
|
+
"input": 0.2,
|
|
120
|
+
"output": 0.8
|
|
121
|
+
},
|
|
122
|
+
"vision": false,
|
|
123
|
+
"status": "production",
|
|
124
|
+
"description": "Dan's PersonalityEngine 1.3 24B — pricing and limits from the authenticated /oai/v1/models roster, 2026-09-03"
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
"topModels": ["deepseek-v4-flash", "gpt-oss-120b", "glm-4.7", "mytholite"],
|
|
128
|
+
"testModel": "mytholite"
|
|
129
|
+
},
|
|
130
|
+
"capabilities": {
|
|
131
|
+
"text": true,
|
|
132
|
+
"streaming": true,
|
|
133
|
+
"tools": false,
|
|
134
|
+
"toolsWithStreaming": false,
|
|
135
|
+
"structuredOutput": true,
|
|
136
|
+
"structuredOutputWithTools": false,
|
|
137
|
+
"embeddings": false,
|
|
138
|
+
"thinking": false
|
|
139
|
+
},
|
|
140
|
+
"errorRules": [
|
|
141
|
+
{
|
|
142
|
+
"status": 401,
|
|
143
|
+
"pattern": "Bad API key",
|
|
144
|
+
"class": "authentication",
|
|
145
|
+
"message": "Invalid Mancer API key. Check {apiKeyEnvVar}. Get one at https://mancer.tech/dashboard"
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"pattern": "Unknown Model",
|
|
149
|
+
"class": "invalid-model",
|
|
150
|
+
"message": "Mancer model '{model}' is unknown. Pick a current model from the /oai/v1/models roster or https://mancer.tech/pricing."
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"status": 402,
|
|
154
|
+
"pattern": "requires paid credits",
|
|
155
|
+
"class": "provider",
|
|
156
|
+
"message": "Mancer model '{model}' requires paid credits; with a zero balance only the free model 'mytholite' works. Add credits at https://mancer.tech/dashboard or see https://mancer.tech/pricing."
|
|
157
|
+
}
|
|
158
|
+
],
|
|
159
|
+
"setup": {
|
|
160
|
+
"url": "https://mancer.tech/dashboard",
|
|
161
|
+
"apiKeyFormat": "^mcr_[A-Za-z0-9]+$",
|
|
162
|
+
"billingPolicy": "free-tier",
|
|
163
|
+
"instructions": [
|
|
164
|
+
"1. Visit: https://mancer.tech/dashboard and sign in",
|
|
165
|
+
"2. Create an API key (prefix mcr_)",
|
|
166
|
+
"3. Without credits only the free model 'mytholite' answers; every other model returns 402 until you add credits at https://mancer.tech/pricing",
|
|
167
|
+
"4. Set {apiKeyEnvVar} in your .env file"
|
|
168
|
+
],
|
|
169
|
+
"description": "OpenAI-compatible endpoint at https://neuro.mancer.tech/oai/v1. One free demo model; paid credits unlock the rest of the roster."
|
|
170
|
+
},
|
|
171
|
+
"evidence": {
|
|
172
|
+
"rosterVerified": {
|
|
173
|
+
"date": "2026-09-03",
|
|
174
|
+
"method": "authenticated GET /oai/v1/models; full response retained as evidence/mancer-roster-authenticated.json in the campaign scratchpad and every catalog price/limit machine-checked against it (Mancer re-prices — gpt-oss-120b input moved 0.024 → 0.022 within the day)",
|
|
175
|
+
"status": 200
|
|
176
|
+
},
|
|
177
|
+
"authProbe": {
|
|
178
|
+
"date": "2026-09-03",
|
|
179
|
+
"status": 401
|
|
180
|
+
},
|
|
181
|
+
"billingProbe": {
|
|
182
|
+
"date": "2026-09-03",
|
|
183
|
+
"status": 402,
|
|
184
|
+
"method": "POST /oai/v1/chat/completions on deepseek-v4-flash with a zero balance: {\"error\":{\"type\":\"CANT_AFFORD\",\"message\":\"This model requires paid credits to use!\"}}"
|
|
185
|
+
},
|
|
186
|
+
"liveMatrix": {
|
|
187
|
+
"date": "2026-09-03",
|
|
188
|
+
"result": "18-probe harness on the free model mytholite: roster, chat, max_completion_tokens, system role, content parts, sampling params, SSE stream (usage chunk + [DONE]), json_schema (valid JSON matching schema) and json_object all 200; tools and tools+schema 400 BAD_PARAMETERS ('\"auto\" tool choice requires --enable-auto-tool-choice and --tool-call-parser') so tools are declared false; vision 200 but text-only (image ignored); bad key 401 'Bad API key'; unknown model 400 'Unknown Model'. Paid models could not be capability-probed without credits — tools may work there and can be re-declared once probed. Nightly matrix pins testModel mytholite."
|
|
189
|
+
},
|
|
190
|
+
"addedInPR": "pending"
|
|
191
|
+
}
|
|
192
|
+
}
|
|
@@ -36,6 +36,17 @@ export declare class ConfiguredOpenAICompatProvider extends OpenAIChatCompletion
|
|
|
36
36
|
protected getDefaultModel(): string;
|
|
37
37
|
protected getFallbackModelName(): string;
|
|
38
38
|
protected getFallbackModels(): string[];
|
|
39
|
+
/**
|
|
40
|
+
* The catalog's `capabilities.tools` is the vendor's own answer, probed on
|
|
41
|
+
* the wire when the entry was written; the model registry (the base
|
|
42
|
+
* default) knows nothing about Tier-2 models and answers "supported" for
|
|
43
|
+
* every unknown id. A vendor that declares tools: false must never receive
|
|
44
|
+
* a `tools` array — Mancer's free model rejects one with 400 — so the
|
|
45
|
+
* declaration wins here and the registry is only consulted otherwise.
|
|
46
|
+
* Like the other entry-reading overrides above, this runs only after
|
|
47
|
+
* construction: BaseProvider merely closes over it for GenerationHandler.
|
|
48
|
+
*/
|
|
49
|
+
supportsTools(): boolean;
|
|
39
50
|
protected adjustRequestBody(body: OpenAICompatChatRequest, modelId: string): OpenAICompatChatRequest;
|
|
40
51
|
protected formatProviderError(error: unknown): Error;
|
|
41
52
|
}
|
|
@@ -86,6 +86,22 @@ export class ConfiguredOpenAICompatProvider extends OpenAIChatCompletionsProvide
|
|
|
86
86
|
getFallbackModels() {
|
|
87
87
|
return this.entry.fallbackModels;
|
|
88
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* The catalog's `capabilities.tools` is the vendor's own answer, probed on
|
|
91
|
+
* the wire when the entry was written; the model registry (the base
|
|
92
|
+
* default) knows nothing about Tier-2 models and answers "supported" for
|
|
93
|
+
* every unknown id. A vendor that declares tools: false must never receive
|
|
94
|
+
* a `tools` array — Mancer's free model rejects one with 400 — so the
|
|
95
|
+
* declaration wins here and the registry is only consulted otherwise.
|
|
96
|
+
* Like the other entry-reading overrides above, this runs only after
|
|
97
|
+
* construction: BaseProvider merely closes over it for GenerationHandler.
|
|
98
|
+
*/
|
|
99
|
+
supportsTools() {
|
|
100
|
+
if (this.entry.supportsTools === false) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
return super.supportsTools();
|
|
104
|
+
}
|
|
89
105
|
adjustRequestBody(body, modelId) {
|
|
90
106
|
const adjusted = super.adjustRequestBody(body, modelId);
|
|
91
107
|
if (this.entry.messageContentFormat !== "string") {
|
|
@@ -242,15 +242,6 @@ export declare class GoogleVertexProvider extends BaseProvider {
|
|
|
242
242
|
* No more @ai-sdk/google-vertex dependency
|
|
243
243
|
*/
|
|
244
244
|
generate(optionsOrPrompt: TextGenerationOptions | string): Promise<EnhancedGenerateResult | null>;
|
|
245
|
-
/**
|
|
246
|
-
* Invoke `options.onFinish` with the lifecycle payload shape consumers
|
|
247
|
-
* (and `test:middleware`) expect. Pulled out so generate / image-gen /
|
|
248
|
-
* Anthropic / Gemini code paths share one implementation. Errors thrown
|
|
249
|
-
* by the user's callback are swallowed so they cannot poison the
|
|
250
|
-
* primary generate path — same contract as the AI SDK middleware
|
|
251
|
-
* wrapGenerate uses.
|
|
252
|
-
*/
|
|
253
|
-
private fireGenerateOnFinish;
|
|
254
245
|
/**
|
|
255
246
|
* Invoke `options.onError` with the lifecycle payload shape consumers
|
|
256
247
|
* (and `test:middleware`) expect. Mirrors {@link fireGenerateOnFinish}.
|
|
@@ -5342,39 +5342,6 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
5342
5342
|
}
|
|
5343
5343
|
});
|
|
5344
5344
|
}
|
|
5345
|
-
/**
|
|
5346
|
-
* Invoke `options.onFinish` with the lifecycle payload shape consumers
|
|
5347
|
-
* (and `test:middleware`) expect. Pulled out so generate / image-gen /
|
|
5348
|
-
* Anthropic / Gemini code paths share one implementation. Errors thrown
|
|
5349
|
-
* by the user's callback are swallowed so they cannot poison the
|
|
5350
|
-
* primary generate path — same contract as the AI SDK middleware
|
|
5351
|
-
* wrapGenerate uses.
|
|
5352
|
-
*/
|
|
5353
|
-
fireGenerateOnFinish(options, result, startTime) {
|
|
5354
|
-
const onFinish = options
|
|
5355
|
-
.onFinish;
|
|
5356
|
-
if (typeof onFinish !== "function") {
|
|
5357
|
-
return;
|
|
5358
|
-
}
|
|
5359
|
-
try {
|
|
5360
|
-
const usage = result?.usage;
|
|
5361
|
-
const callbackResult = onFinish({
|
|
5362
|
-
text: result?.content || "",
|
|
5363
|
-
usage: usage
|
|
5364
|
-
? {
|
|
5365
|
-
promptTokens: usage.input ?? 0,
|
|
5366
|
-
completionTokens: usage.output ?? 0,
|
|
5367
|
-
}
|
|
5368
|
-
: undefined,
|
|
5369
|
-
duration: Date.now() - startTime,
|
|
5370
|
-
finishReason: result?.finishReason ?? "stop",
|
|
5371
|
-
});
|
|
5372
|
-
Promise.resolve(callbackResult).catch((err) => logger.warn(`[GoogleVertex] onFinish callback rejected: ${err instanceof Error ? err.message : String(err)}`));
|
|
5373
|
-
}
|
|
5374
|
-
catch (err) {
|
|
5375
|
-
logger.warn(`[GoogleVertex] onFinish callback threw: ${err instanceof Error ? err.message : String(err)}`);
|
|
5376
|
-
}
|
|
5377
|
-
}
|
|
5378
5345
|
/**
|
|
5379
5346
|
* Invoke `options.onError` with the lifecycle payload shape consumers
|
|
5380
5347
|
* (and `test:middleware`) expect. Mirrors {@link fireGenerateOnFinish}.
|