@fgv/ts-extras 5.1.0-44 → 5.1.0-45

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.
Files changed (75) hide show
  1. package/dist/packlets/ai-assist/apiClient.js +38 -14
  2. package/dist/packlets/ai-assist/apiClient.js.map +1 -1
  3. package/dist/packlets/ai-assist/index.js +1 -1
  4. package/dist/packlets/ai-assist/index.js.map +1 -1
  5. package/dist/packlets/ai-assist/jsonResponse.js +16 -5
  6. package/dist/packlets/ai-assist/jsonResponse.js.map +1 -1
  7. package/dist/packlets/ai-assist/model.js +94 -0
  8. package/dist/packlets/ai-assist/model.js.map +1 -1
  9. package/dist/packlets/ai-assist/registry.js +18 -3
  10. package/dist/packlets/ai-assist/registry.js.map +1 -1
  11. package/dist/packlets/ai-assist/streamingAdapters/anthropic.js +17 -6
  12. package/dist/packlets/ai-assist/streamingAdapters/anthropic.js.map +1 -1
  13. package/dist/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js +5 -5
  14. package/dist/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js.map +1 -1
  15. package/dist/packlets/ai-assist/streamingAdapters/common.js.map +1 -1
  16. package/dist/packlets/ai-assist/streamingAdapters/gemini.js +4 -1
  17. package/dist/packlets/ai-assist/streamingAdapters/gemini.js.map +1 -1
  18. package/dist/packlets/ai-assist/streamingAdapters/openaiChat.js +6 -1
  19. package/dist/packlets/ai-assist/streamingAdapters/openaiChat.js.map +1 -1
  20. package/dist/packlets/ai-assist/streamingAdapters/openaiResponses.js +5 -1
  21. package/dist/packlets/ai-assist/streamingAdapters/openaiResponses.js.map +1 -1
  22. package/dist/packlets/ai-assist/streamingAdapters/proxy.js +6 -1
  23. package/dist/packlets/ai-assist/streamingAdapters/proxy.js.map +1 -1
  24. package/dist/packlets/ai-assist/streamingClient.js +6 -6
  25. package/dist/packlets/ai-assist/streamingClient.js.map +1 -1
  26. package/dist/ts-extras.d.ts +143 -1
  27. package/lib/packlets/ai-assist/apiClient.d.ts +9 -0
  28. package/lib/packlets/ai-assist/apiClient.d.ts.map +1 -1
  29. package/lib/packlets/ai-assist/apiClient.js +37 -13
  30. package/lib/packlets/ai-assist/apiClient.js.map +1 -1
  31. package/lib/packlets/ai-assist/index.d.ts +1 -1
  32. package/lib/packlets/ai-assist/index.d.ts.map +1 -1
  33. package/lib/packlets/ai-assist/index.js +6 -1
  34. package/lib/packlets/ai-assist/index.js.map +1 -1
  35. package/lib/packlets/ai-assist/jsonResponse.d.ts +7 -0
  36. package/lib/packlets/ai-assist/jsonResponse.d.ts.map +1 -1
  37. package/lib/packlets/ai-assist/jsonResponse.js +16 -5
  38. package/lib/packlets/ai-assist/jsonResponse.js.map +1 -1
  39. package/lib/packlets/ai-assist/model.d.ts +101 -1
  40. package/lib/packlets/ai-assist/model.d.ts.map +1 -1
  41. package/lib/packlets/ai-assist/model.js +98 -1
  42. package/lib/packlets/ai-assist/model.js.map +1 -1
  43. package/lib/packlets/ai-assist/registry.d.ts.map +1 -1
  44. package/lib/packlets/ai-assist/registry.js +18 -3
  45. package/lib/packlets/ai-assist/registry.js.map +1 -1
  46. package/lib/packlets/ai-assist/streamingAdapters/anthropic.d.ts +1 -1
  47. package/lib/packlets/ai-assist/streamingAdapters/anthropic.d.ts.map +1 -1
  48. package/lib/packlets/ai-assist/streamingAdapters/anthropic.js +17 -6
  49. package/lib/packlets/ai-assist/streamingAdapters/anthropic.js.map +1 -1
  50. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.d.ts +9 -0
  51. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.d.ts.map +1 -1
  52. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js +4 -4
  53. package/lib/packlets/ai-assist/streamingAdapters/clientToolContinuationBuilder.js.map +1 -1
  54. package/lib/packlets/ai-assist/streamingAdapters/common.d.ts +9 -0
  55. package/lib/packlets/ai-assist/streamingAdapters/common.d.ts.map +1 -1
  56. package/lib/packlets/ai-assist/streamingAdapters/common.js.map +1 -1
  57. package/lib/packlets/ai-assist/streamingAdapters/gemini.d.ts +1 -1
  58. package/lib/packlets/ai-assist/streamingAdapters/gemini.d.ts.map +1 -1
  59. package/lib/packlets/ai-assist/streamingAdapters/gemini.js +4 -1
  60. package/lib/packlets/ai-assist/streamingAdapters/gemini.js.map +1 -1
  61. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.d.ts +1 -1
  62. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.d.ts.map +1 -1
  63. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.js +6 -1
  64. package/lib/packlets/ai-assist/streamingAdapters/openaiChat.js.map +1 -1
  65. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.d.ts +1 -1
  66. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.d.ts.map +1 -1
  67. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.js +5 -1
  68. package/lib/packlets/ai-assist/streamingAdapters/openaiResponses.js.map +1 -1
  69. package/lib/packlets/ai-assist/streamingAdapters/proxy.d.ts.map +1 -1
  70. package/lib/packlets/ai-assist/streamingAdapters/proxy.js +6 -1
  71. package/lib/packlets/ai-assist/streamingAdapters/proxy.js.map +1 -1
  72. package/lib/packlets/ai-assist/streamingClient.d.ts.map +1 -1
  73. package/lib/packlets/ai-assist/streamingClient.js +5 -5
  74. package/lib/packlets/ai-assist/streamingClient.js.map +1 -1
  75. package/package.json +7 -7
@@ -229,14 +229,15 @@ const geminiResponse = ts_utils_1.Validators.object({
229
229
  * Works for xAI Grok, OpenAI, Groq, and Mistral.
230
230
  * @internal
231
231
  */
232
- async function callOpenAiCompletion(config, prompt, head, temperature, logger, signal, resolvedThinking) {
232
+ async function callOpenAiCompletion(config, prompt, head, temperature, logger, signal, resolvedThinking, maxTokens, useMaxCompletionTokensField = false) {
233
233
  var _a;
234
234
  const url = `${config.baseUrl}/chat/completions`;
235
235
  const messages = (0, chatRequestBuilders_1.buildMessages)(prompt.system, (0, chatRequestBuilders_1.buildOpenAiChatUserContent)(prompt), {
236
236
  head
237
237
  });
238
238
  const effort = (_a = resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.openAiEffort) !== null && _a !== void 0 ? _a : resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.xaiEffort;
239
- const body = Object.assign(Object.assign({ model: config.model, messages }, (temperature !== undefined ? { temperature } : {})), (effort !== undefined && config.model !== 'grok-4' ? { reasoning_effort: effort } : {}));
239
+ const maxTokensField = useMaxCompletionTokensField ? 'max_completion_tokens' : 'max_tokens';
240
+ const body = Object.assign(Object.assign(Object.assign({ model: config.model, messages }, (temperature !== undefined ? { temperature } : {})), (effort !== undefined && config.model !== 'grok-4' ? { reasoning_effort: effort } : {})), (maxTokens !== undefined ? { [maxTokensField]: maxTokens } : {}));
240
241
  if ((resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.otherParams) !== undefined) {
241
242
  Object.assign(body, resolvedThinking.otherParams);
242
243
  }
@@ -282,7 +283,7 @@ function extractResponsesApiText(output) {
282
283
  * Used when tools are configured for an openai-format provider.
283
284
  * @internal
284
285
  */
285
- async function callOpenAiResponsesCompletion(config, prompt, tools = [], head, temperature, logger, signal, resolvedThinking) {
286
+ async function callOpenAiResponsesCompletion(config, prompt, tools = [], head, temperature, logger, signal, resolvedThinking, maxTokens) {
286
287
  var _a;
287
288
  const url = `${config.baseUrl}/responses`;
288
289
  const input = (0, chatRequestBuilders_1.buildMessages)(prompt.system, (0, chatRequestBuilders_1.buildOpenAiResponsesUserContent)(prompt), {
@@ -290,6 +291,10 @@ async function callOpenAiResponsesCompletion(config, prompt, tools = [], head, t
290
291
  });
291
292
  const effort = (_a = resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.openAiEffort) !== null && _a !== void 0 ? _a : resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.xaiEffort;
292
293
  const body = Object.assign(Object.assign(Object.assign({ model: config.model, input }, (tools.length > 0 ? { tools: (0, toolFormats_1.toResponsesApiTools)(tools) } : {})), (temperature !== undefined ? { temperature } : {})), (effort !== undefined && config.model !== 'grok-4' ? { reasoning: { effort } } : {}));
294
+ // Shared by OpenAI and xAI — both route through the Responses API with the same field name.
295
+ if (maxTokens !== undefined) {
296
+ body.max_output_tokens = maxTokens;
297
+ }
293
298
  if ((resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.otherParams) !== undefined) {
294
299
  Object.assign(body, resolvedThinking.otherParams);
295
300
  }
@@ -336,13 +341,24 @@ function extractAnthropicText(content) {
336
341
  return (0, ts_utils_1.succeed)(textParts.join(''));
337
342
  }
338
343
  /** Calls the Anthropic Messages API with optional tool support. @internal */
339
- async function callAnthropicCompletion(config, prompt, head, temperature, logger, tools, signal, resolvedThinking) {
344
+ async function callAnthropicCompletion(config, prompt, head, temperature, logger, tools, signal, resolvedThinking, useAdaptiveThinking = false, maxTokens) {
340
345
  const url = `${config.baseUrl}/messages`;
341
346
  const messages = (0, chatRequestBuilders_1.buildAnthropicMessages)(prompt, { head });
342
- const body = Object.assign({ model: config.model, system: prompt.system, messages, max_tokens: 4096 }, (temperature !== undefined ? { temperature } : {}));
347
+ const body = Object.assign({ model: config.model, system: prompt.system, messages,
348
+ // Anthropic's Messages API requires max_tokens on every request — see
349
+ // AiAssist.DEFAULT_ANTHROPIC_MAX_TOKENS for why only this provider defaults it.
350
+ max_tokens: maxTokens !== null && maxTokens !== void 0 ? maxTokens : model_1.DEFAULT_ANTHROPIC_MAX_TOKENS }, (temperature !== undefined ? { temperature } : {}));
343
351
  const effort = resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.anthropicEffort;
344
352
  if (effort !== undefined) {
345
- body.thinking = { type: 'enabled', budget_tokens: (0, thinkingOptionsResolver_1.anthropicEffortToBudgetTokens)(effort) };
353
+ if (useAdaptiveThinking) {
354
+ // Claude 5 family: adaptive thinking — no budget_tokens; effort moves to the
355
+ // top-level output_config block. See AiAssist.isAdaptiveThinkingModel.
356
+ body.thinking = { type: 'adaptive' };
357
+ body.output_config = { effort };
358
+ }
359
+ else {
360
+ body.thinking = { type: 'enabled', budget_tokens: (0, thinkingOptionsResolver_1.anthropicEffortToBudgetTokens)(effort) };
361
+ }
346
362
  }
347
363
  if ((resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.otherParams) !== undefined) {
348
364
  Object.assign(body, resolvedThinking.otherParams);
@@ -386,7 +402,7 @@ async function callAnthropicCompletion(config, prompt, head, temperature, logger
386
402
  * When tools are configured, includes Google Search grounding.
387
403
  * @internal
388
404
  */
389
- async function callGeminiCompletion(config, prompt, head, temperature, logger, tools, signal, resolvedThinking) {
405
+ async function callGeminiCompletion(config, prompt, head, temperature, logger, tools, signal, resolvedThinking, maxTokens) {
390
406
  const url = `${config.baseUrl}/models/${config.model}:generateContent`;
391
407
  const contents = (0, chatRequestBuilders_1.buildGeminiContents)(prompt, { head });
392
408
  // Temperature is sent only when explicitly provided; otherwise Gemini's default applies.
@@ -394,6 +410,9 @@ async function callGeminiCompletion(config, prompt, head, temperature, logger, t
394
410
  if (temperature !== undefined) {
395
411
  generationConfig.temperature = temperature;
396
412
  }
413
+ if (maxTokens !== undefined) {
414
+ generationConfig.maxOutputTokens = maxTokens;
415
+ }
397
416
  if ((resolvedThinking === null || resolvedThinking === void 0 ? void 0 : resolvedThinking.geminiThinkingBudget) !== undefined) {
398
417
  generationConfig.thinkingConfig = { thinkingBudget: resolvedThinking.geminiThinkingBudget };
399
418
  }
@@ -442,7 +461,7 @@ async function callGeminiCompletion(config, prompt, head, temperature, logger, t
442
461
  * @public
443
462
  */
444
463
  async function callProviderCompletion(params) {
445
- const { descriptor, apiKey, system, messages, temperature, modelOverride, tier, logger, tools, signal, endpoint, thinking } = params;
464
+ const { descriptor, apiKey, system, messages, temperature, modelOverride, tier, logger, tools, signal, endpoint, thinking, maxTokens } = params;
446
465
  const splitResult = (0, chatRequestBuilders_1.splitChatRequest)(system, messages);
447
466
  if (splitResult.isFailure()) {
448
467
  return (0, ts_utils_1.fail)(splitResult.message);
@@ -497,13 +516,13 @@ async function callProviderCompletion(params) {
497
516
  // Responses-API-only models (e.g. gpt-5.5-pro) 400 on /chat/completions, so they route
498
517
  // to the Responses path even with no tools requested — same path the tools case uses.
499
518
  if (hasTools || (0, model_1.isResponsesOnlyModel)(descriptor, config.model)) {
500
- return callOpenAiResponsesCompletion(config, prompt, tools, head, temperature, logger, signal, resolvedThinking);
519
+ return callOpenAiResponsesCompletion(config, prompt, tools, head, temperature, logger, signal, resolvedThinking, maxTokens);
501
520
  }
502
- return callOpenAiCompletion(config, prompt, head, temperature, logger, signal, resolvedThinking);
521
+ return callOpenAiCompletion(config, prompt, head, temperature, logger, signal, resolvedThinking, maxTokens, (0, model_1.usesMaxCompletionTokensField)(descriptor));
503
522
  case 'anthropic':
504
- return callAnthropicCompletion(config, prompt, head, temperature, logger, tools, signal, resolvedThinking);
523
+ return callAnthropicCompletion(config, prompt, head, temperature, logger, tools, signal, resolvedThinking, (0, model_1.isAdaptiveThinkingModel)(descriptor, config.model), maxTokens);
505
524
  case 'gemini':
506
- return callGeminiCompletion(config, prompt, head, temperature, logger, tools, signal, resolvedThinking);
525
+ return callGeminiCompletion(config, prompt, head, temperature, logger, tools, signal, resolvedThinking, maxTokens);
507
526
  /* c8 ignore next 4 - defensive coding: exhaustive switch guaranteed by TypeScript */
508
527
  default: {
509
528
  const _exhaustive = descriptor.apiFormat;
@@ -1128,7 +1147,7 @@ async function callProxiedListModels(proxyUrl, params) {
1128
1147
  * @public
1129
1148
  */
1130
1149
  async function callProxiedCompletion(proxyUrl, params) {
1131
- const { descriptor, apiKey, system, messages, temperature, modelOverride, logger, tools, signal, thinking } = params;
1150
+ const { descriptor, apiKey, system, messages, temperature, modelOverride, logger, tools, signal, thinking, maxTokens } = params;
1132
1151
  const splitResult = (0, chatRequestBuilders_1.splitChatRequest)(system, messages);
1133
1152
  if (splitResult.isFailure()) {
1134
1153
  return (0, ts_utils_1.fail)(splitResult.message);
@@ -1158,6 +1177,11 @@ async function callProxiedCompletion(proxyUrl, params) {
1158
1177
  if (thinking !== undefined) {
1159
1178
  body.thinking = thinking;
1160
1179
  }
1180
+ // Forwarded only when explicitly provided; the proxy is responsible for mapping it to the
1181
+ // correct upstream provider field (see AiAssist.usesMaxCompletionTokensField).
1182
+ if (maxTokens !== undefined) {
1183
+ body.maxTokens = maxTokens;
1184
+ }
1161
1185
  /* c8 ignore next 1 - optional logger */
1162
1186
  logger === null || logger === void 0 ? void 0 : logger.info(`AI proxy request: provider=${descriptor.id}, proxy=${proxyUrl}`);
1163
1187
  const url = `${proxyUrl}/api/ai/completion`;