utilitas 1999.1.63 → 1999.1.65
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/README.md +1 -1
- package/dist/utilitas.lite.mjs +1 -1
- package/dist/utilitas.lite.mjs.map +1 -1
- package/lib/alan.mjs +35 -7
- package/lib/gen.mjs +9 -7
- package/lib/manifest.mjs +1 -1
- package/lib/shell.mjs +1 -1
- package/lib/storage.mjs +4 -2
- package/package.json +1 -1
package/lib/alan.mjs
CHANGED
|
@@ -3,13 +3,14 @@ import { create as createUoid } from './uoid.mjs';
|
|
|
3
3
|
import { createWavHeader } from './media.mjs';
|
|
4
4
|
import { end, loop } from './event.mjs';
|
|
5
5
|
import { fileTypeFromBuffer } from 'file-type';
|
|
6
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
6
7
|
|
|
7
8
|
import {
|
|
8
9
|
BASE64, BUFFER, DATAURL, MIME_BINARY, MIME_JSON, MIME_TEXT, MIME_PNG,
|
|
9
10
|
MIME_JPEG, MIME_MOV, MIME_MPEG, MIME_MP4, MIME_MPG, MIME_AVI, MIME_WMV,
|
|
10
11
|
MIME_MPEGPS, MIME_FLV, MIME_GIF, MIME_WEBP, MIME_PDF, MIME_AAC, MIME_FLAC,
|
|
11
12
|
MIME_MP3, MIME_MPEGA, MIME_M4A, MIME_MPGA, MIME_OPUS, MIME_PCM, MIME_WAV,
|
|
12
|
-
MIME_WEBM, MIME_TGPP, MIME_PCM16, STREAM, convert,
|
|
13
|
+
MIME_WEBM, MIME_TGPP, MIME_PCM16, STREAM, convert, formatDataURL
|
|
13
14
|
} from './storage.mjs';
|
|
14
15
|
|
|
15
16
|
import {
|
|
@@ -105,6 +106,7 @@ const OPENAI_RULES = {
|
|
|
105
106
|
imageCostTokens: ~~(OPENAI_HI_RES_SIZE / (512 * 512) * 170 + 85),
|
|
106
107
|
maxFileSize: m(20), maxImageSize: OPENAI_HI_RES_SIZE,
|
|
107
108
|
supportedMimeTypes: [MIME_PNG, MIME_JPEG, MIME_GIF, MIME_WEBP],
|
|
109
|
+
supportedDocTypes: [MIME_PDF],
|
|
108
110
|
supportedAudioTypes: [MIME_WAV], audio: 'gpt-4o-audio-preview',
|
|
109
111
|
json: true, tools: true, vision: true, defaultProvider: OPENAI,
|
|
110
112
|
};
|
|
@@ -187,6 +189,8 @@ for (const n in MODELS) {
|
|
|
187
189
|
MODELS[n]['name'] = n;
|
|
188
190
|
if (!MODELS[n].embedding) {
|
|
189
191
|
MODELS[n].supportedMimeTypes = MODELS[n].supportedMimeTypes || [];
|
|
192
|
+
MODELS[n].supportedDocTypes = MODELS[n].supportedDocTypes || [];
|
|
193
|
+
MODELS[n].supportedAudioTypes = MODELS[n].supportedAudioTypes || [];
|
|
190
194
|
MODELS[n].maxOutputTokens = MODELS[n].maxOutputTokens
|
|
191
195
|
|| Math.ceil(MODELS[n].contextWindow * 0.4);
|
|
192
196
|
MODELS[n].maxInputTokens = MODELS[n].maxInputTokens
|
|
@@ -556,12 +560,22 @@ const countTokens = async (input, options) => {
|
|
|
556
560
|
);
|
|
557
561
|
};
|
|
558
562
|
|
|
563
|
+
const selectGptVisionModel = options => {
|
|
564
|
+
assert(
|
|
565
|
+
MODELS[options.model]?.vision,
|
|
566
|
+
`Vision modality is not supported by model: ${options.model}`
|
|
567
|
+
);
|
|
568
|
+
return String.isString(MODELS[options.model].vision)
|
|
569
|
+
? MODELS[options.model].vision : null;
|
|
570
|
+
};
|
|
571
|
+
|
|
559
572
|
const selectGptAudioModel = options => {
|
|
560
573
|
assert(
|
|
561
574
|
MODELS[options.model]?.audio,
|
|
562
575
|
`Audio modality is not supported by model: ${options.model}`
|
|
563
576
|
);
|
|
564
|
-
return MODELS[options.model]?.audio
|
|
577
|
+
return String.isString(MODELS[options.model]?.audio)
|
|
578
|
+
? MODELS[options.model]?.audio : null;
|
|
565
579
|
};
|
|
566
580
|
|
|
567
581
|
const buildGptMessage = (content, options) => {
|
|
@@ -570,10 +584,22 @@ const buildGptMessage = (content, options) => {
|
|
|
570
584
|
const attachments = (options?.attachments || []).map(x => {
|
|
571
585
|
assert(MODELS[options?.model], 'Model is required.');
|
|
572
586
|
if (MODELS[options.model]?.supportedMimeTypes?.includes?.(x.mime_type)) {
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
587
|
+
alterModel = selectGptVisionModel(options); // URL or Base64URL
|
|
588
|
+
return {
|
|
589
|
+
type: 'image_url',
|
|
590
|
+
image_url: { url: x.url, detail: 'high' },
|
|
591
|
+
};
|
|
592
|
+
} else if (MODELS[options.model]?.supportedDocTypes?.includes?.(x.mime_type)) {
|
|
593
|
+
alterModel = selectGptVisionModel(options);
|
|
594
|
+
print(formatDataURL(x.mime_type, x.data));
|
|
595
|
+
return {
|
|
596
|
+
type: 'file',
|
|
597
|
+
file: {
|
|
598
|
+
file_data: formatDataURL(x.mime_type, x.data),
|
|
599
|
+
filename: x.file_name
|
|
600
|
+
|| `${uuidv4()}.${x.mime_type.split('/')[1]}`,
|
|
601
|
+
},
|
|
602
|
+
};
|
|
577
603
|
} else if (MODELS[options.model]?.supportedAudioTypes?.includes?.(x.mime_type)) {
|
|
578
604
|
alterModel = selectGptAudioModel(options);
|
|
579
605
|
return {
|
|
@@ -791,7 +817,9 @@ const buildPrompts = async (model, input, options = {}) => {
|
|
|
791
817
|
options.attachments = (
|
|
792
818
|
options.attachments?.length ? options.attachments : []
|
|
793
819
|
).filter(x => [
|
|
794
|
-
...model?.supportedMimeTypes
|
|
820
|
+
...model?.supportedMimeTypes,
|
|
821
|
+
...model?.supportedDocTypes,
|
|
822
|
+
...model?.supportedAudioTypes,
|
|
795
823
|
].includes(x.mime_type));
|
|
796
824
|
switch (options.flavor) {
|
|
797
825
|
case OPENAI:
|
package/lib/gen.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
|
-
ensureArray, ensureString, log as _log, need, throwError,
|
|
2
|
+
ensureArray, ensureString, ignoreErrFunc, log as _log, need, throwError,
|
|
3
|
+
tryUntil,
|
|
3
4
|
} from './utilitas.mjs';
|
|
4
5
|
|
|
5
|
-
import {
|
|
6
|
+
import { assertExist, exec } from './shell.mjs';
|
|
6
7
|
import { convert, MIME_PNG } from './storage.mjs';
|
|
7
8
|
import { createReadStream } from 'fs';
|
|
8
9
|
|
|
@@ -180,12 +181,13 @@ const image = async (prompt, options) => {
|
|
|
180
181
|
};
|
|
181
182
|
|
|
182
183
|
const getGeminiAccessToken = async (credentials) => {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
184
|
+
const bin = 'gcloud';
|
|
185
|
+
await assertExist(bin);
|
|
186
|
+
const actResp = await ignoreErrFunc(async () => await exec(
|
|
187
|
+
`${bin} auth activate-service-account --key-file=${credentials}`,
|
|
186
188
|
{ acceptError: true }
|
|
187
|
-
);
|
|
188
|
-
assert(actResp
|
|
189
|
+
), { log: true });
|
|
190
|
+
assert(actResp?.includes?.('Activated service account credentials'),
|
|
189
191
|
'Failed to activate service account credentials.', 500);
|
|
190
192
|
const tokResp = (await exec(`gcloud auth print-access-token`)).trim();
|
|
191
193
|
assert(tokResp, 'Failed to get access token.', 500);
|
package/lib/manifest.mjs
CHANGED
package/lib/shell.mjs
CHANGED
package/lib/storage.mjs
CHANGED
|
@@ -23,6 +23,7 @@ const mapFilename = name => join(name.substr(0, 2), name.substr(2, 2));
|
|
|
23
23
|
const [_zip, _unzip] = [__zip, __unzip].map(promisify);
|
|
24
24
|
const log = content => _log(content, import.meta.url);
|
|
25
25
|
const sanitizeFilename = (s, r) => s.replace(/[\/?<>\\:*|"]/g, r || '_').trim();
|
|
26
|
+
const formatDataURL = (mt, b64) => `data:${mt};${BASE64.toLowerCase()},${b64}`;
|
|
26
27
|
|
|
27
28
|
const [
|
|
28
29
|
NULL, BASE64, BUFFER, FILE, STREAM, TEXT, _JSON, encoding, BINARY, BLOB,
|
|
@@ -175,7 +176,7 @@ const encodeBase64DataURL = async (mime, buffer) => {
|
|
|
175
176
|
) || MIME_BINARY;
|
|
176
177
|
assert(mime, 'MIME type is required.', 400);
|
|
177
178
|
assert(Buffer.isBuffer(buffer), 'Data buffer is required.', 400);
|
|
178
|
-
return
|
|
179
|
+
return formatDataURL(mime, base64Encode(buffer, true));
|
|
179
180
|
};
|
|
180
181
|
|
|
181
182
|
const decodeBase64DataURL = dataUrl => {
|
|
@@ -524,6 +525,7 @@ export {
|
|
|
524
525
|
encodeBase64DataURL,
|
|
525
526
|
exists,
|
|
526
527
|
existsOnCloud,
|
|
528
|
+
formatDataURL,
|
|
527
529
|
getConfig,
|
|
528
530
|
getConfigFilename,
|
|
529
531
|
getGcUrlByBucket,
|
|
@@ -548,5 +550,5 @@ export {
|
|
|
548
550
|
writeFile,
|
|
549
551
|
writeJson,
|
|
550
552
|
writeTempFile,
|
|
551
|
-
zip
|
|
553
|
+
zip,
|
|
552
554
|
};
|