utilitas 1999.1.72 → 1999.1.74

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/lib/alan.mjs CHANGED
@@ -51,7 +51,7 @@ const _NEED = [
51
51
  const [
52
52
  OPENAI, GEMINI, OPENAI_TRAINING, OLLAMA, GPT_4O, GPT_O3, GEMINI_25_FLASH,
53
53
  NOVA, DEEPSEEK_R1, MD_CODE, TEXT_EMBEDDING_3_SMALL, TEXT_EMBEDDING_3_LARGE,
54
- CLOUD_37_SONNET, AUDIO, WAV, ATTACHMENTS, CHAT, OPENAI_VOICE, MEDIUM, LOW,
54
+ CLOUD_40_OPUS, AUDIO, WAV, ATTACHMENTS, CHAT, OPENAI_VOICE, MEDIUM, LOW,
55
55
  HIGH, GPT_REASONING_EFFORT, THINK, THINK_STR, THINK_END, AZURE, TOOLS_STR,
56
56
  TOOLS_END, TOOLS, TEXT, THINKING, OK, FUNC, GPT_41, REDACTED_THINKING,
57
57
  GEMMA_3_27B, AZURE_OPENAI, ANTHROPIC, VERTEX_ANTHROPIC, v8k, ais,
@@ -64,7 +64,7 @@ const [
64
64
  'OpenAI', 'Gemini', 'OPENAI_TRAINING', 'Ollama', 'gpt-4o', 'o3',
65
65
  'gemini-2.5-flash-preview-05-20', 'nova', 'deepseek-r1', '```',
66
66
  'text-embedding-3-small', 'text-embedding-3-large',
67
- 'claude-3-7-sonnet@20250219', 'audio', 'wav', '[ATTACHMENTS]', 'CHAT',
67
+ 'claude-opus-4@20250514', 'audio', 'wav', '[ATTACHMENTS]', 'CHAT',
68
68
  'OPENAI_VOICE', 'medium', 'low', 'high', 'medium', 'think', '<think>',
69
69
  '</think>', 'AZURE', '<tools>', '</tools>', 'tools', 'text', 'thinking',
70
70
  'OK', 'function', 'gpt-4.1', 'redacted_thinking', 'gemma3:27b',
@@ -172,13 +172,12 @@ const MODELS = {
172
172
  [JINA_CLIP]: {
173
173
  maxInputTokens: k(8), maxImageSize: 512 * 512, dimension: k(1),
174
174
  },
175
- [CLOUD_37_SONNET]: {
176
- contextWindow: kT(200), maxOutputTokens: kT(64),
177
- documentCostTokens: 3000 * 100, maxDocumentFile: m(32),
175
+ [CLOUD_40_OPUS]: {
176
+ contextWindow: kT(200), maxOutputTokens: kT(32),
177
+ documentCostTokens: 3000 * 10, maxDocumentFile: m(32),
178
178
  maxDocumentPages: 100, imageCostTokens: ~~(v8k / 750),
179
- maxImagePerPrompt: Math.min(/*Anthropic:*/100, /*Vertex:*/20),
180
- maxFileSize: /*Vertex*/m(5), maxImageSize: 2000 * 2000,
181
- supportedMimeTypes: [MIME_PNG, MIME_JPEG, MIME_GIF, MIME_WEBP, MIME_PDF],
179
+ maxImagePerPrompt: 100, maxFileSize: m(5), maxImageSize: 2000 * 2000,
180
+ supportedMimeTypes: [MIME_TEXT, MIME_PNG, MIME_JPEG, MIME_GIF, MIME_WEBP, MIME_PDF],
182
181
  json: true, reasoning: true, tools: true, vision: true,
183
182
  defaultProvider: [ANTHROPIC, VERTEX_ANTHROPIC],
184
183
  }, // https://docs.anthropic.com/en/docs/build-with-claude/vision
@@ -208,8 +207,8 @@ const DEFAULT_MODELS = {
208
207
  [AZURE_OPENAI]: GPT_4O,
209
208
  [SILICONFLOW]: SF_DEEPSEEK_V3,
210
209
  [GEMINI]: GEMINI_25_FLASH,
211
- [ANTHROPIC]: CLOUD_37_SONNET,
212
- [VERTEX_ANTHROPIC]: CLOUD_37_SONNET,
210
+ [ANTHROPIC]: CLOUD_40_OPUS,
211
+ [VERTEX_ANTHROPIC]: CLOUD_40_OPUS,
213
212
  [JINA]: JINA_DEEPSEARCH,
214
213
  [OLLAMA]: GEMMA_3_27B,
215
214
  [OPENAI_VOICE]: NOVA,
@@ -911,13 +910,10 @@ const handleToolsCall = async (msg, options) => {
911
910
  toolsResponse = (toolsResponse + m).trim();
912
911
  await streamResp({ text: options?.delta ? m : toolsResponse }, options);
913
912
  };
914
- const calls = msg.tool_calls || msg.content || msg.parts || [];
913
+ const calls = msg.tool_calls || msg.content
914
+ || (msg.parts ? msg.parts.filter(x => x.functionCall) : null) || [];
915
915
  if (calls.length) {
916
- switch (options?.flavor) {
917
- case ANTHROPIC: preRes.push(msg); break;
918
- case GEMINI: preRes.push(msg); break;
919
- case OPENAI: default: preRes.push(msg); break;
920
- }
916
+ preRes.push(msg);
921
917
  for (const fn of calls) {
922
918
  switch (options?.flavor) {
923
919
  case ANTHROPIC:
@@ -977,7 +973,7 @@ const handleToolsCall = async (msg, options) => {
977
973
  if (content.length) {
978
974
  switch (options?.flavor) {
979
975
  case ANTHROPIC: content = [{ role: user, content }]; break;
980
- case GEMINI: content = [{ role: FUNC, parts: content }]; break;
976
+ case GEMINI: content = [{ role: user, parts: content }]; break;
981
977
  }
982
978
  }
983
979
  responded && await resp(TOOLS_END);
@@ -1091,6 +1087,7 @@ const promptAnthropic = async (aiId, content, options = {}) => {
1091
1087
  tool_choice: { type: 'auto' }, betas: [
1092
1088
  // https://docs.anthropic.com/en/docs/build-with-claude/tool-use/token-efficient-tool-use
1093
1089
  'token-efficient-tools-2025-02-19',
1090
+ 'interleaved-thinking-2025-05-14',
1094
1091
  // https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking
1095
1092
  ...options?.extendedThinking ? ['output-128k-2025-02-19'] : [],
1096
1093
  ],
@@ -1183,8 +1180,10 @@ const packGeminiReferences = (chunks, supports) => {
1183
1180
 
1184
1181
  const promptGemini = async (aiId, content, options = {}) => {
1185
1182
  let { provider, client, model } = await getAi(aiId);
1186
- let [event, result, references, functionCalls, responded, images] =
1187
- [null, options.result ?? '', null, [], false, []];
1183
+ let [
1184
+ event, result, text, thinking, references, functionCalls, responded,
1185
+ images, thinkEnd,
1186
+ ] = [null, options.result ?? '', '', '', null, [], false, [], false];
1188
1187
  options.model = options.model || model.name;
1189
1188
  model?.image === true && (options.imageMode = true);
1190
1189
  assert(!(options.imageMode && !model.image), 'Image mode is not supported.');
@@ -1198,12 +1197,11 @@ const promptGemini = async (aiId, content, options = {}) => {
1198
1197
  const chat = client.chats.create({
1199
1198
  model: options.model, history, config: {
1200
1199
  responseMimeType: options.jsonMode ? MIME_JSON : MIME_TEXT,
1200
+ thinkingConfig: model.reasoning ? { includeThoughts: true } : {},
1201
1201
  systemInstruction, responseModalities: options.modalities || (
1202
1202
  options.imageMode ? [TEXT, IMAGE] : undefined
1203
1203
  ), ...options?.config || {}, ...model?.tools && !options.jsonMode
1204
- // @todo: Gemini 2.5 flash 05-20 refusing to use certain tool calls
1205
- // https://discuss.ai.google.dev/t/gemini-2-5-flash-05-20-refusing-to-use-certain-tool-calls/84086
1206
- && ![GEMINI_20_FLASH, GEMINI_25_FLASH].includes(options.model)
1204
+ && ![GEMINI_20_FLASH].includes(options.model)
1207
1205
  ? (options.tools ?? {
1208
1206
  tools: [
1209
1207
  // @todo: Gemini will failed when using these tools together.
@@ -1228,15 +1226,23 @@ const promptGemini = async (aiId, content, options = {}) => {
1228
1226
  chunk?.promptFeedback?.blockReason
1229
1227
  );
1230
1228
  event = chunk?.candidates?.[0];
1231
- let [deltaText, deltaImages] = ['', []];
1229
+ let [deltaText, deltaThink, deltaImages] = ['', '', []];
1232
1230
  event?.content?.parts?.map(x => {
1233
- if (x.text) { deltaText = x.text; }
1231
+ if (x.text && x.thought) { deltaThink = x.text; }
1232
+ else if (x.text) { deltaText = x.text; }
1234
1233
  else if (x.functionCall) { functionCalls.push(x); }
1235
1234
  else if (x.inlineData?.mimeType === MIME_PNG) {
1236
1235
  deltaImages.push(x.inlineData);
1237
1236
  images.push(x.inlineData);
1238
1237
  }
1239
1238
  });
1239
+ text += deltaText;
1240
+ thinking += deltaThink;
1241
+ deltaThink && deltaThink === thinking
1242
+ && (deltaThink = `${THINK_STR}\n${deltaThink}`);
1243
+ thinking && deltaText && !thinkEnd
1244
+ && (thinkEnd = deltaThink = `${deltaThink}${THINK_END}\n\n`);
1245
+ deltaText = deltaThink + deltaText;
1240
1246
  const rfc = packGeminiReferences(
1241
1247
  event?.groundingMetadata?.groundingChunks,
1242
1248
  event?.groundingMetadata?.groundingSupports
@@ -1250,9 +1256,15 @@ const promptGemini = async (aiId, content, options = {}) => {
1250
1256
  images: options.delta ? deltaImages : images,
1251
1257
  }, options);
1252
1258
  }
1259
+ event = {
1260
+ role: MODEL, parts: [
1261
+ ...thinking ? [{ thought: true, text: thinking }] : [],
1262
+ ...text ? [{ text }] : [],
1263
+ ...functionCalls,
1264
+ ],
1265
+ };
1253
1266
  const { toolsResult, toolsResponse } = await handleToolsCall(
1254
- { role: MODEL, parts: functionCalls },
1255
- { ...options, result, flavor: GEMINI }
1267
+ event, { ...options, result, flavor: GEMINI }
1256
1268
  );
1257
1269
  if (toolsResult.length
1258
1270
  && countToolCalls(toolsResponse) < MAX_TOOL_RECURSION) {
@@ -1555,7 +1567,7 @@ export {
1555
1567
  _NEED,
1556
1568
  _NO_RENDER,
1557
1569
  ATTACHMENTS,
1558
- CLOUD_37_SONNET,
1570
+ CLOUD_40_OPUS,
1559
1571
  CODE_INTERPRETER,
1560
1572
  DEEPSEEK_R1,
1561
1573
  DEFAULT_MODELS,
package/lib/manifest.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  const manifest = {
2
2
  "name": "utilitas",
3
3
  "description": "Just another common utility for JavaScript.",
4
- "version": "1999.1.72",
4
+ "version": "1999.1.74",
5
5
  "private": false,
6
6
  "homepage": "https://github.com/Leask/utilitas",
7
7
  "main": "index.mjs",
package/lib/web.mjs CHANGED
@@ -198,7 +198,7 @@ const search = async (query, options = {}) => {
198
198
  return options?.raw ? resp.content : {
199
199
  totalResults: resp?.content?.searchInformation?.totalResults || 0,
200
200
  startIndex: resp?.content?.queries?.request?.[0]?.startIndex || 1,
201
- items: resp?.content?.items.map(x => ({
201
+ items: (resp?.content?.items || []).map(x => ({
202
202
  title: x.title, link: options?.image ? null : x.link,
203
203
  snippet: x.snippet, image: (
204
204
  options?.image ? x.link : x.pagemap?.cse_image?.[0]?.src
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "utilitas",
3
3
  "description": "Just another common utility for JavaScript.",
4
- "version": "1999.1.72",
4
+ "version": "1999.1.74",
5
5
  "private": false,
6
6
  "homepage": "https://github.com/Leask/utilitas",
7
7
  "main": "index.mjs",