utilitas 2000.3.31 → 2000.3.33
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 -0
- package/dist/utilitas.lite.mjs +1 -1
- package/dist/utilitas.lite.mjs.map +1 -1
- package/lib/alan.mjs +62 -88
- package/lib/manifest.mjs +1 -1
- package/lib/storage.mjs +1 -0
- package/package.json +1 -1
package/lib/alan.mjs
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import { checkSearch, distill, search } from './web.mjs';
|
|
2
2
|
import { create as createUoid } from './uoid.mjs';
|
|
3
|
-
import { fileTypeFromBuffer } from 'file-type';
|
|
4
3
|
import { packPcmToWav } from './media.mjs';
|
|
5
4
|
import { v4 as uuidv4 } from 'uuid';
|
|
6
5
|
|
|
7
6
|
import {
|
|
8
|
-
STREAM, FILE, BASE64, BUFFER, DATAURL,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
STREAM, FILE, BASE64, BUFFER, DATAURL, MIME_TEXT, MIME_PNG, MIME_JPEG,
|
|
8
|
+
MIME_MOV, MIME_MPEG, MIME_MP4, MIME_MPG, MIME_AVI, MIME_WMV, MIME_MPEGPS,
|
|
9
|
+
MIME_FLV, MIME_GIF, MIME_WEBP, MIME_PDF, MIME_AAC, MIME_FLAC, MIME_MP3,
|
|
10
|
+
MIME_MPEGA, MIME_M4A, MIME_MPGA, MIME_OPUS, MIME_PCM, MIME_WAV, MIME_WEBM,
|
|
11
|
+
MIME_TGPP, MIME_PCM16, MIME_OGG, convert, getTempPath, decodeBase64DataURL,
|
|
12
|
+
getMime,
|
|
14
13
|
} from './storage.mjs';
|
|
15
14
|
|
|
16
15
|
import {
|
|
17
|
-
log as _log, renderText as _renderText, ensureArray, ensureString,
|
|
16
|
+
log as _log, renderText as _renderText, ensureArray, ensureString,
|
|
18
17
|
ignoreErrFunc, insensitiveCompare, isSet, need, parseJson, throwError,
|
|
19
18
|
tryUntil, timeout, mergeAtoB,
|
|
20
19
|
} from './utilitas.mjs';
|
|
@@ -225,8 +224,6 @@ let ATTACHMENT_TOKEN_COST = 0;
|
|
|
225
224
|
for (const n in MODELS) {
|
|
226
225
|
MODELS[n]['name'] = n;
|
|
227
226
|
MODELS[n].supportedMimeTypes = MODELS[n].supportedMimeTypes || [];
|
|
228
|
-
MODELS[n].supportedDocTypes = MODELS[n].supportedDocTypes || [];
|
|
229
|
-
MODELS[n].supportedAudioTypes = MODELS[n].supportedAudioTypes || [];
|
|
230
227
|
MODELS[n].maxOutputTokens = MODELS[n].maxOutputTokens
|
|
231
228
|
|| Math.ceil(MODELS[n].contextWindow * 0.4);
|
|
232
229
|
MODELS[n].maxInputTokens = MODELS[n].maxInputTokens
|
|
@@ -258,9 +255,7 @@ for (const n in MODELS) {
|
|
|
258
255
|
// );
|
|
259
256
|
// }
|
|
260
257
|
// // combine supported types
|
|
261
|
-
// for (const key of [
|
|
262
|
-
// 'supportedAudioTypes', 'supportedDocTypes', 'supportedMimeTypes',
|
|
263
|
-
// ]) {
|
|
258
|
+
// for (const key of ['supportedMimeTypes']) {
|
|
264
259
|
// MODELS[AUTO][key] = [...new Set(
|
|
265
260
|
// [...MODELS[AUTO][key] || [], ...MODELS[n][key] || []]
|
|
266
261
|
// )];
|
|
@@ -588,55 +583,51 @@ const isOpenrouter = (provider, model) => insensitiveCompare(
|
|
|
588
583
|
provider, OPENROUTER
|
|
589
584
|
) && (model ? model?.source : true);
|
|
590
585
|
|
|
591
|
-
const
|
|
592
|
-
assert(
|
|
593
|
-
MODELS[options.model]?.vision,
|
|
594
|
-
`Vision modality is not supported by model: ${options.model}`
|
|
595
|
-
);
|
|
596
|
-
return String.isString(MODELS[options.model].vision)
|
|
597
|
-
? MODELS[options.model].vision : null;
|
|
598
|
-
};
|
|
599
|
-
|
|
600
|
-
const selectAudioModel = options => {
|
|
601
|
-
assert(
|
|
602
|
-
MODELS[options.model]?.audio,
|
|
603
|
-
`Audio modality is not supported by model: ${options.model}`
|
|
604
|
-
);
|
|
605
|
-
return String.isString(MODELS[options.model]?.audio)
|
|
606
|
-
? MODELS[options.model]?.audio : null;
|
|
607
|
-
};
|
|
608
|
-
|
|
609
|
-
const buildMessage = (content, options) => {
|
|
586
|
+
const buildMessage = async (content, options) => {
|
|
610
587
|
content = content || '';
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
588
|
+
const attachments = await Promise.all((options?.attachments || []).map(async x => {
|
|
589
|
+
assert(
|
|
590
|
+
MODELS[options?.model]?.supportedMimeTypes?.includes?.(x.mime_type),
|
|
591
|
+
`Unsupported mime type: '${x.mime_type}'.`
|
|
592
|
+
);
|
|
593
|
+
if ([
|
|
594
|
+
MIME_PNG, MIME_JPEG, MIME_GIF, MIME_WEBP
|
|
595
|
+
].includes?.(x.mime_type)) {
|
|
616
596
|
return {
|
|
617
597
|
type: 'image_url',
|
|
618
|
-
image_url: {
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
return {
|
|
623
|
-
type: 'file',
|
|
624
|
-
file: {
|
|
625
|
-
file_data: formatDataURL(x.mime_type, x.data),
|
|
626
|
-
filename: x.file_name
|
|
627
|
-
|| `${uuidv4()}.${x.mime_type.split('/')[1]}`,
|
|
598
|
+
image_url: {
|
|
599
|
+
url: x.url || await convert(x.data, {
|
|
600
|
+
input: BUFFER, expected: DATAURL,
|
|
601
|
+
}), detail: 'high',
|
|
628
602
|
},
|
|
629
603
|
};
|
|
630
|
-
} else if (
|
|
631
|
-
|
|
604
|
+
} else if ([
|
|
605
|
+
MIME_AAC, MIME_FLAC, MIME_MP3, MIME_MPEGA, MIME_M4A, MIME_MPGA,
|
|
606
|
+
MIME_OPUS, MIME_PCM, MIME_WAV, MIME_TGPP, MIME_PCM16, MIME_OGG,
|
|
607
|
+
].includes?.(x.mime_type)) {
|
|
632
608
|
return {
|
|
633
609
|
type: 'input_audio',
|
|
634
|
-
input_audio: {
|
|
610
|
+
input_audio: {
|
|
611
|
+
data: x.url || await convert(x.data, {
|
|
612
|
+
input: BUFFER, expected: BASE64,
|
|
613
|
+
}), format: WAV,
|
|
614
|
+
},
|
|
635
615
|
};
|
|
636
616
|
}
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
617
|
+
[
|
|
618
|
+
MIME_TEXT, MIME_MOV, MIME_MPEG, MIME_WEBM, MIME_MP4, MIME_MPG,
|
|
619
|
+
MIME_AVI, MIME_WMV, MIME_MPEGPS, MIME_FLV, MIME_PDF,
|
|
620
|
+
].includes?.(x.mime_type)
|
|
621
|
+
|| log(`Unknown mime type: '${x.mime_type}', fallbacked.`);
|
|
622
|
+
return {
|
|
623
|
+
type: 'file', file: {
|
|
624
|
+
file_data: await convert(x.data, {
|
|
625
|
+
input: BUFFER, expected: DATAURL,
|
|
626
|
+
}), filename: x.file_name
|
|
627
|
+
|| `${uuidv4()}.${x.mime_type.split('/')[1]}`,
|
|
628
|
+
},
|
|
629
|
+
};
|
|
630
|
+
}));
|
|
640
631
|
const message = String.isString(content) ? {
|
|
641
632
|
role: options?.role || user,
|
|
642
633
|
content: content.length ? [{ type: TEXT, text: content }] : [],
|
|
@@ -786,10 +777,10 @@ const packModelLabel = (model_reference) => {
|
|
|
786
777
|
const buildPrompts = async (model, input, options = {}) => {
|
|
787
778
|
assert(!(
|
|
788
779
|
options.jsonMode && !model?.json
|
|
789
|
-
), `This model does not support JSON output: ${
|
|
780
|
+
), `This model does not support JSON output: ${model.name}`);
|
|
790
781
|
assert(!(
|
|
791
782
|
options.reasoning && !model?.reasoning
|
|
792
|
-
), `This model does not support reasoning: ${
|
|
783
|
+
), `This model does not support reasoning: ${model.name}`);
|
|
793
784
|
let [history, content, prompt, _model, _assistant, _history]
|
|
794
785
|
= [null, input, null, { role: MODEL }, { role: assistant }, null];
|
|
795
786
|
options.systemPrompt = options.systemPrompt || INSTRUCTIONS;
|
|
@@ -797,42 +788,31 @@ const buildPrompts = async (model, input, options = {}) => {
|
|
|
797
788
|
options.attachments?.length ? options.attachments : []
|
|
798
789
|
).map(async x => {
|
|
799
790
|
if (String.isString(x)) {
|
|
800
|
-
var convResp = await convert(x, { input: FILE, expected:
|
|
801
|
-
return {
|
|
802
|
-
url: convResp.content,
|
|
803
|
-
mime_type: convResp.mime,
|
|
804
|
-
}
|
|
791
|
+
var convResp = await convert(x, { input: FILE, expected: BUFFER, meta: true });
|
|
792
|
+
return { data: convResp.content, mime_type: convResp.mime };
|
|
805
793
|
} else if (Buffer.isBuffer(x)) {
|
|
806
|
-
|
|
807
|
-
return {
|
|
808
|
-
url: convResp.content,
|
|
809
|
-
mime_type: convResp.mime,
|
|
810
|
-
}
|
|
794
|
+
return { data: x, mime_type: (await getMime(x))?.mime }
|
|
811
795
|
} else if (Object.isObject(x)) { return x; } else { return null; }
|
|
812
|
-
}))).filter(x =>
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
...model?.supportedAudioTypes,
|
|
816
|
-
].includes(x.mime_type));
|
|
817
|
-
const systemPrompt = buildMessage(options.systemPrompt, system);
|
|
818
|
-
const msgBuilder = () => {
|
|
796
|
+
}))).filter(x => (model?.supportedMimeTypes || []).includes(x.mime_type));
|
|
797
|
+
const systemPrompt = await buildMessage(options.systemPrompt, system);
|
|
798
|
+
const msgBuilder = async () => {
|
|
819
799
|
[history, _history] = [[], []];
|
|
820
|
-
(options.messages?.length ? options.messages : []).map((x, i) => {
|
|
821
|
-
_history.push(buildMessage(x.request));
|
|
822
|
-
_history.push(buildMessage(x.response, _assistant));
|
|
823
|
-
});
|
|
800
|
+
await Promise.all((options.messages?.length ? options.messages : []).map(async (x, i) => {
|
|
801
|
+
_history.push(await buildMessage(x.request));
|
|
802
|
+
_history.push(await buildMessage(x.response, _assistant));
|
|
803
|
+
}));
|
|
824
804
|
history = messages([
|
|
825
|
-
systemPrompt, ..._history, buildMessage(content, options),
|
|
805
|
+
systemPrompt, ..._history, await buildMessage(content, options),
|
|
826
806
|
...options.toolsResult?.length ? options.toolsResult : []
|
|
827
807
|
]);
|
|
828
808
|
};
|
|
829
|
-
msgBuilder();
|
|
809
|
+
await msgBuilder();
|
|
830
810
|
await trimPrompt(() => [
|
|
831
811
|
systemPrompt, _history, content, options.toolsResult
|
|
832
|
-
], () => {
|
|
812
|
+
], async () => {
|
|
833
813
|
if (options.messages?.length) {
|
|
834
814
|
options.messages?.shift();
|
|
835
|
-
msgBuilder();
|
|
815
|
+
await msgBuilder();
|
|
836
816
|
} else if (options.trimBeginning) {
|
|
837
817
|
content = '...' + trimBeginning(trimBeginning(content).slice(1));
|
|
838
818
|
} else {
|
|
@@ -1251,7 +1231,7 @@ const initChat = async (options = {}) => {
|
|
|
1251
1231
|
}
|
|
1252
1232
|
options.instructions && (chatConfig.systemPrompt = options.instructions);
|
|
1253
1233
|
// Use Gemini instead of ChatGPT because of the longer package.
|
|
1254
|
-
const [spTokens, ais] = await Promise.all([countTokens([buildMessage(
|
|
1234
|
+
const [spTokens, ais] = await Promise.all([countTokens([await buildMessage(
|
|
1255
1235
|
chatConfig.systemPrompt, system
|
|
1256
1236
|
)]), getAi(null, { all: true })]);
|
|
1257
1237
|
for (const ai of ais.filter(x => ![
|
|
@@ -1348,15 +1328,9 @@ const distillFile = async (attachments, o) => {
|
|
|
1348
1328
|
o?.keepPaging ? '' : '- If the document has multiple pages, merge them into one page. Please do not return any paging information.',
|
|
1349
1329
|
o?.keepDecoration ? '' : '- If the document has side notes, headers, footers, or watermarks, please ignore them.',
|
|
1350
1330
|
].filter(x => x).join('\n');
|
|
1351
|
-
attachments = await Promise.all(ensureArray(attachments).map(async x => {
|
|
1352
|
-
const convResp = await convert(
|
|
1353
|
-
x, { expected: DATAURL, ...o || {}, meta: true }
|
|
1354
|
-
);
|
|
1355
|
-
return { url: convResp.content, mime_type: convResp.mime };
|
|
1356
|
-
}));
|
|
1357
1331
|
return await prompt(strPmt, {
|
|
1358
1332
|
select: { vision: true, hearing: true, fast: true },
|
|
1359
|
-
simple: true, ...o, attachments,
|
|
1333
|
+
simple: true, ...o, attachments: ensureArray(attachments),
|
|
1360
1334
|
});
|
|
1361
1335
|
};
|
|
1362
1336
|
|
package/lib/manifest.mjs
CHANGED
package/lib/storage.mjs
CHANGED