utilitas 1999.1.59 → 1999.1.61

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
@@ -5,7 +5,11 @@ import { end, loop } from './event.mjs';
5
5
  import { fileTypeFromBuffer } from 'file-type';
6
6
 
7
7
  import {
8
- BASE64, BUFFER, DATAURL, MIME_BINARY, MIME_JSON, MIME_TEXT, STREAM, convert,
8
+ BASE64, BUFFER, DATAURL, MIME_BINARY, MIME_JSON, MIME_TEXT, MIME_PNG,
9
+ MIME_JPEG, MIME_MOV, MIME_MPEG, MIME_MP4, MIME_MPG, MIME_AVI, MIME_WMV,
10
+ MIME_MPEGPS, MIME_FLV, MIME_GIF, MIME_WEBP, MIME_PDF, MIME_AAC, MIME_FLAC,
11
+ MIME_MP3, MIME_MPEGA, MIME_M4A, MIME_MPGA, MIME_OPUS, MIME_PCM, MIME_WAV,
12
+ MIME_WEBM, MIME_TGPP, MIME_PCM16, STREAM, convert,
9
13
  } from './storage.mjs';
10
14
 
11
15
  import {
@@ -43,18 +47,6 @@ const _NEED = [
43
47
  'js-tiktoken', 'OpenAI',
44
48
  ];
45
49
 
46
- const [
47
- png, jpeg, mov, mpeg, mp4, mpg, avi, wmv, mpegps, flv, gif, webp, pdf, aac,
48
- flac, mp3, mpega, m4a, mpga, opus, pcm, wav, webm, tgpp, pcm16, ogg,
49
- ] = [
50
- 'image/png', 'image/jpeg', 'video/mov', 'video/mpeg', 'video/mp4',
51
- 'video/mpg', 'video/avi', 'video/wmv', 'video/mpegps', 'video/x-flv',
52
- 'image/gif', 'image/webp', 'application/pdf', 'audio/aac', 'audio/flac',
53
- 'audio/mp3', 'audio/mpeg', 'audio/m4a', 'audio/mpga', 'audio/opus',
54
- 'audio/pcm', 'audio/wav', 'audio/webm', 'video/3gpp', 'audio/x-wav',
55
- 'audio/ogg',
56
- ];
57
-
58
50
  const [
59
51
  OPENAI, GEMINI, OPENAI_TRAINING, OLLAMA, GPT_4O, GPT_O3, GEMINI_25_FLASH,
60
52
  NOVA, DEEPSEEK_R1, MD_CODE, TEXT_EMBEDDING_3_SMALL, TEXT_EMBEDDING_3_LARGE,
@@ -112,8 +104,8 @@ const OPENAI_EBD = { ...EBD, maxInputTokens: k(8) - 1 };
112
104
  const OPENAI_RULES = {
113
105
  imageCostTokens: ~~(OPENAI_HI_RES_SIZE / (512 * 512) * 170 + 85),
114
106
  maxFileSize: m(20), maxImageSize: OPENAI_HI_RES_SIZE,
115
- supportedMimeTypes: [png, jpeg, gif, webp],
116
- supportedAudioTypes: [wav], audio: 'gpt-4o-audio-preview',
107
+ supportedMimeTypes: [MIME_PNG, MIME_JPEG, MIME_GIF, MIME_WEBP],
108
+ supportedAudioTypes: [MIME_WAV], audio: 'gpt-4o-audio-preview',
117
109
  json: true, tools: true, vision: true, defaultProvider: OPENAI,
118
110
  };
119
111
 
@@ -124,8 +116,10 @@ const GEMINI_RULES = {
124
116
  maxAudioPerPrompt: 1, maxFileSize: m(20), maxImagePerPrompt: 3000,
125
117
  maxImageSize: Infinity, maxUrlSize: gb(2), maxVideoLength: minute(45),
126
118
  maxVideoPerPrompt: 10, vision: true, supportedMimeTypes: [
127
- png, jpeg, mov, mpeg, mp4, mpg, avi, wmv, mpegps, flv, pdf, aac,
128
- flac, mp3, mpega, m4a, mpga, opus, pcm, wav, webm, tgpp,
119
+ MIME_PNG, MIME_JPEG, MIME_MOV, MIME_MPEG, MIME_MP4, MIME_MPG, MIME_AVI,
120
+ MIME_WMV, MIME_MPEGPS, MIME_FLV, MIME_PDF, MIME_AAC, MIME_FLAC,
121
+ MIME_MP3, MIME_MPEGA, MIME_M4A, MIME_MPGA, MIME_OPUS, MIME_PCM,
122
+ MIME_WAV, MIME_WEBM, MIME_TGPP,
129
123
  ], defaultProvider: GEMINI,
130
124
  };
131
125
 
@@ -150,15 +144,16 @@ const MODELS = {
150
144
  [GEMMA_3_27B]: {
151
145
  contextWindow: kT(128), maxOutputTokens: k(8),
152
146
  imageCostTokens: 256, maxImageSize: 896 * 896,
153
- supportedMimeTypes: [png, jpeg, gif],
147
+ supportedMimeTypes: [MIME_PNG, MIME_JPEG, MIME_GIF],
154
148
  fast: true, json: true, vision: true,
155
149
  defaultProvider: OLLAMA,
156
150
  },
157
151
  [JINA_DEEPSEARCH]: {
158
152
  contextWindow: Infinity, maxInputTokens: Infinity,
159
153
  maxOutputTokens: Infinity, imageCostTokens: 0, maxImageSize: Infinity,
160
- supportedMimeTypes: [png, jpeg, MIME_TEXT, webp, pdf], reasoning: true,
161
- json: true, vision: true, deepsearch: true, defaultProvider: JINA,
154
+ supportedMimeTypes: [MIME_PNG, MIME_JPEG, MIME_TEXT, MIME_WEBP, MIME_PDF],
155
+ reasoning: true, json: true, vision: true,
156
+ deepsearch: true, defaultProvider: JINA,
162
157
  },
163
158
  [DEEPSEEK_R1]: {
164
159
  contextWindow: kT(128), maxOutputTokens: k(8),
@@ -180,7 +175,7 @@ const MODELS = {
180
175
  maxDocumentPages: 100, imageCostTokens: ~~(v8k / 750),
181
176
  maxImagePerPrompt: Math.min(/*Anthropic:*/100, /*Vertex:*/20),
182
177
  maxFileSize: /*Vertex*/m(5), maxImageSize: 2000 * 2000,
183
- supportedMimeTypes: [png, jpeg, gif, webp, pdf],
178
+ supportedMimeTypes: [MIME_PNG, MIME_JPEG, MIME_GIF, MIME_WEBP, MIME_PDF],
184
179
  json: true, reasoning: true, tools: true, vision: true,
185
180
  defaultProvider: [ANTHROPIC, VERTEX_ANTHROPIC],
186
181
  }, // https://docs.anthropic.com/en/docs/build-with-claude/vision
@@ -623,9 +618,9 @@ const buildClaudeMessage = (text, options) => {
623
618
  assert(text, 'Text is required.');
624
619
  const attachments = (options?.attachments?.length ? options?.attachments : []).map(x => {
625
620
  let type = '';
626
- if ([pdf].includes(x.mime_type)) {
621
+ if ([MIME_PDF].includes(x.mime_type)) {
627
622
  type = 'document';
628
- } else if ([png, jpeg, gif, webp].includes(x.mime_type)) {
623
+ } else if ([MIME_PNG, MIME_JPEG, MIME_GIF, MIME_WEBP].includes(x.mime_type)) {
629
624
  type = 'image';
630
625
  } else { throwError(`Unsupported mime type: ${x.mime_type}`); }
631
626
  return {
@@ -982,7 +977,7 @@ const promptOpenAI = async (aiId, content, options = {}) => {
982
977
  && (options.reasoning_effort = GPT_REASONING_EFFORT);
983
978
  const modalities = options.modalities
984
979
  || (options.audioMode ? [TEXT, AUDIO] : undefined);
985
- [options.audioMimeType, options.suffix] = [pcm16, 'pcm.wav'];
980
+ [options.audioMimeType, options.suffix] = [MIME_PCM16, 'pcm.wav'];
986
981
  const resp = await client.chat.completions.create({
987
982
  model: azure ? undefined : options.model, ...history,
988
983
  ...options.jsonMode ? { response_format: { type: JSON_OBJECT } } : {},
@@ -1198,7 +1193,7 @@ const promptGemini = async (aiId, content, options = {}) => {
1198
1193
  event?.content?.parts?.map(x => {
1199
1194
  if (x.text) { deltaText = x.text; }
1200
1195
  else if (x.functionCall) { functionCalls.push(x); }
1201
- else if (x.inlineData?.mimeType === png) {
1196
+ else if (x.inlineData?.mimeType === MIME_PNG) {
1202
1197
  deltaImages.push(x.inlineData);
1203
1198
  images.push(x.inlineData);
1204
1199
  }
@@ -1536,6 +1531,7 @@ export {
1536
1531
  MODELS,
1537
1532
  OPENAI_VOICE,
1538
1533
  RETRIEVAL,
1534
+ TEXT_EMBEDDING_3_SMALL,
1539
1535
  analyzeSessions,
1540
1536
  buildGptTrainingCase,
1541
1537
  buildGptTrainingCases,
@@ -1553,18 +1549,10 @@ export {
1553
1549
  getSession,
1554
1550
  init,
1555
1551
  initChat,
1556
- jpeg,
1557
1552
  listFiles,
1558
1553
  listGptFineTuningEvents,
1559
1554
  listGptFineTuningJobs,
1560
1555
  listOpenAIModels,
1561
- m4a,
1562
- mp3,
1563
- mp4,
1564
- mpeg,
1565
- mpega,
1566
- mpga,
1567
- ogg,
1568
1556
  prompt,
1569
1557
  promptAnthropic,
1570
1558
  promptGemini,
@@ -1572,10 +1560,7 @@ export {
1572
1560
  resetSession,
1573
1561
  tailGptFineTuningEvents,
1574
1562
  talk,
1575
- TEXT_EMBEDDING_3_SMALL,
1576
1563
  trimPrompt,
1577
1564
  uploadFile,
1578
1565
  uploadFileForFineTuning,
1579
- wav,
1580
- webm,
1581
1566
  };
package/lib/gen.mjs CHANGED
@@ -1,9 +1,10 @@
1
1
  import {
2
- ensureString, log as _log, need, throwError, tryUntil,
2
+ ensureArray, ensureString, log as _log, need, throwError, tryUntil,
3
3
  } from './utilitas.mjs';
4
4
 
5
- import { convert, MIME_PNG } from './storage.mjs';
6
5
  import { assertCommand, exec } from './shell.mjs';
6
+ import { convert, MIME_PNG } from './storage.mjs';
7
+ import { createReadStream } from 'fs';
7
8
 
8
9
  const _NEED = ['OpenAI'];
9
10
  const log = (cnt, opt) => _log(cnt, import.meta.url, { time: 1, ...opt || {} });
@@ -25,7 +26,10 @@ const init = async (options) => {
25
26
  case OPENAI:
26
27
  const OpenAI = await need('openai');
27
28
  const openai = new OpenAI(options);
28
- clients[provider] = openai.images;
29
+ clients[provider] = {
30
+ image: openai.images,
31
+ toFile: OpenAI.toFile,
32
+ };
29
33
  break;
30
34
  case GEMINI:
31
35
  clients[provider] = {
@@ -48,6 +52,19 @@ const extractVideo = async (data, options) => await convert(
48
52
  data, { input: BASE64, suffix: 'mp4', ...options || {} }
49
53
  );
50
54
 
55
+ const prepareImage = async (files, repack, options) => {
56
+ if (!files) { return }
57
+ const multiple = Array.isArray(files);
58
+ files = ensureArray(files);
59
+ const resp = await Promise.all(files.map(async x => await repack(
60
+ createReadStream(await convert(
61
+ x, { expected: 'FILE', ...options || {} }
62
+ )), null, { type: MIME_PNG } // don't need to be right MIME type
63
+ )));
64
+ return multiple ? resp : resp[0];
65
+ };
66
+
67
+
51
68
  const image = async (prompt, options) => {
52
69
  let provider = ensureString(options?.provider, { case: 'UP' });
53
70
  if (!provider && clients?.[GEMINI]?.apiKey) { provider = GEMINI; }
@@ -64,19 +81,29 @@ const image = async (prompt, options) => {
64
81
  };
65
82
  switch (provider) {
66
83
  case OPENAI:
84
+ let [func, extraOptions] = ['generate', {}];
85
+ if (options?.reference || options?.mask) {
86
+ func = 'edit';
87
+ extraOptions = {
88
+ image: await prepareImage(options?.reference, client.toFile, options),
89
+ mask: await prepareImage(options?.mask, client.toFile, options),
90
+ };
91
+ }
67
92
  try { // https://platform.openai.com/docs/guides/image-generation?image-generation-model=gpt-image-1
68
- var resp = await client.generate({
93
+ var resp = await client.image[func]({
69
94
  prompt, model: OPENAI_MODEL, n, quality: 'high',
70
95
  size: '1536x1024', moderation: 'low',
71
96
  // 1024x1024 (square), 1536x1024 (landscape), 1024x1536 (portrait), auto (default)
72
97
  // background: 'transparent',
73
- ...options?.params || {},
98
+ ...extraOptions, ...options?.params || {},
74
99
  });
75
100
  } catch (err) { throwError(err?.message || ERROR_GENERATING); }
76
101
  if (!options?.raw) {
77
102
  resp.data = await Promise.all(resp.data.map(async x => ({
78
103
  caption: `🎨 by ${OPENAI_MODEL}`,
79
- data: await extractImage(x.b64_json, options),
104
+ data: await extractImage(x.b64_json, {
105
+ ...options || {}, input: BASE64,
106
+ }),
80
107
  mimeType: MIME_PNG,
81
108
  })));
82
109
  }
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.59",
4
+ "version": "1999.1.61",
5
5
  "private": false,
6
6
  "homepage": "https://github.com/Leask/utilitas",
7
7
  "main": "index.mjs",
package/lib/storage.mjs CHANGED
@@ -27,10 +27,19 @@ const sanitizeFilename = (s, r) => s.replace(/[\/?<>\\:*|"]/g, r || '_').trim();
27
27
  const [
28
28
  NULL, BASE64, BUFFER, FILE, STREAM, TEXT, _JSON, encoding, BINARY, BLOB,
29
29
  DATAURL, mode, dirMode, MIME_TEXT, MIME_BINARY, MIME_JSON, MIME_PNG,
30
+ MIME_JPEG, MIME_MOV, MIME_MPEG, MIME_MP4, MIME_MPG, MIME_AVI, MIME_WMV,
31
+ MIME_MPEGPS, MIME_FLV, MIME_GIF, MIME_WEBP, MIME_PDF, MIME_AAC, MIME_FLAC,
32
+ MIME_MP3, MIME_MPEGA, MIME_M4A, MIME_MPGA, MIME_OPUS, MIME_PCM, MIME_WAV,
33
+ MIME_WEBM, MIME_TGPP, MIME_PCM16, MIME_OGG,
30
34
  ] = [
31
35
  'NULL', 'BASE64', 'BUFFER', 'FILE', 'STREAM', 'TEXT', 'JSON', 'utf8',
32
36
  'binary', 'BLOB', 'DATAURL', '0644', '0755', 'text/plain',
33
37
  'application/octet-stream', 'application/json', 'image/png',
38
+ 'image/jpeg', 'video/mov', 'video/mpeg', 'video/mp4', 'video/mpg',
39
+ 'video/avi', 'video/wmv', 'video/mpegps', 'video/x-flv', 'image/gif',
40
+ 'image/webp', 'application/pdf', 'audio/aac', 'audio/flac', 'audio/mp3',
41
+ 'audio/mpeg', 'audio/m4a', 'audio/mpga', 'audio/opus', 'audio/pcm',
42
+ 'audio/wav', 'audio/webm', 'video/3gpp', 'audio/x-wav', 'audio/ogg',
34
43
  ];
35
44
 
36
45
  const [encodeBase64, encodeBinary, encodeNull]
@@ -473,10 +482,35 @@ export {
473
482
  BUFFER,
474
483
  DATAURL,
475
484
  FILE,
485
+ MIME_AAC,
486
+ MIME_AVI,
476
487
  MIME_BINARY,
488
+ MIME_FLAC,
489
+ MIME_FLV,
490
+ MIME_GIF,
491
+ MIME_JPEG,
477
492
  MIME_JSON,
493
+ MIME_M4A,
494
+ MIME_MOV,
495
+ MIME_MP3,
496
+ MIME_MP4,
497
+ MIME_MPEG,
498
+ MIME_MPEGA,
499
+ MIME_MPEGPS,
500
+ MIME_MPG,
501
+ MIME_MPGA,
502
+ MIME_OGG,
503
+ MIME_OPUS,
504
+ MIME_PCM,
505
+ MIME_PCM16,
506
+ MIME_PDF,
478
507
  MIME_PNG,
479
508
  MIME_TEXT,
509
+ MIME_TGPP,
510
+ MIME_WAV,
511
+ MIME_WEBM,
512
+ MIME_WEBP,
513
+ MIME_WMV,
480
514
  STREAM,
481
515
  analyzeFile,
482
516
  assertPath,
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.59",
4
+ "version": "1999.1.61",
5
5
  "private": false,
6
6
  "homepage": "https://github.com/Leask/utilitas",
7
7
  "main": "index.mjs",