halbot 1993.2.90 → 1993.2.92
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/index.mjs +9 -5
- package/lib/hal.mjs +11 -6
- package/package.json +3 -3
- package/skills/-8845_thread.mjs +1 -1
- package/skills/40_dream.mjs +12 -5
- package/skills/70_chat.mjs +27 -20
package/index.mjs
CHANGED
|
@@ -6,8 +6,10 @@ const skillPath = utilitas.__(import.meta.url, 'skills');
|
|
|
6
6
|
|
|
7
7
|
const init = async (options = {}) => {
|
|
8
8
|
assert(options.telegramToken, 'Telegram Bot API Token is required.');
|
|
9
|
-
const [pkg, _speech, speechOptions, vision]
|
|
10
|
-
|
|
9
|
+
const [pkg, _speech, speechOptions, vision] = [
|
|
10
|
+
await utilitas.which(), options?.speech || {}, { tts: true, stt: true },
|
|
11
|
+
{},
|
|
12
|
+
];
|
|
11
13
|
const info = bot.lines([
|
|
12
14
|
`[${hal.EMOJI_BOT} ${pkg.title}](${pkg.homepage})`, pkg.description
|
|
13
15
|
]);
|
|
@@ -16,7 +18,7 @@ const init = async (options = {}) => {
|
|
|
16
18
|
if (options.openaiApiKey || options.googleApiKey) {
|
|
17
19
|
vision.read = alan.distillFile;
|
|
18
20
|
vision.see = alan.distillFile;
|
|
19
|
-
_speech.stt = alan.distillFile;
|
|
21
|
+
_speech?.stt || (_speech.stt = alan.distillFile);
|
|
20
22
|
}
|
|
21
23
|
// use openai embedding, dall-e, tts if openai is enabled
|
|
22
24
|
if (options.openaiApiKey) {
|
|
@@ -26,8 +28,10 @@ const init = async (options = {}) => {
|
|
|
26
28
|
priority: options.openaiPriority, ...options
|
|
27
29
|
});
|
|
28
30
|
await gen.init(apiKey);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
if (!_speech.tts) {
|
|
32
|
+
await speech.init({ ...apiKey, ...speechOptions });
|
|
33
|
+
_speech.tts = speech.tts;
|
|
34
|
+
}
|
|
31
35
|
}
|
|
32
36
|
// use gemini embedding if gemini is enabled and chatgpt is not enabled
|
|
33
37
|
// use google tts if google api key is ready
|
package/lib/hal.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
bot, callosum, dbio, media, speech, storage, uoid, utilitas, web,
|
|
3
3
|
} from 'utilitas';
|
|
4
4
|
|
|
5
5
|
import { basename, join } from 'path';
|
|
@@ -612,7 +612,11 @@ const subconscious = [{
|
|
|
612
612
|
const analyze = async () => {
|
|
613
613
|
const resp = await utilitas.ignoreErrFunc(async () => {
|
|
614
614
|
[
|
|
615
|
-
|
|
615
|
+
storage.MIME_MP3, storage.MIME_MPEGA,
|
|
616
|
+
storage.MIME_MP4, storage.MIME_MPEG,
|
|
617
|
+
storage.MIME_MPGA, storage.MIME_M4A,
|
|
618
|
+
storage.MIME_WAV, storage.MIME_WEBM,
|
|
619
|
+
storage.MIME_OGG,
|
|
616
620
|
].includes(audio.mime_type) || (
|
|
617
621
|
file = await media.convertAudioTo16kNanoPcmWave(
|
|
618
622
|
file, { input: storage.BUFFER, expected: storage.BUFFER }
|
|
@@ -623,9 +627,9 @@ const subconscious = [{
|
|
|
623
627
|
log(`STT: '${resp}'`);
|
|
624
628
|
ctx.collect(resp);
|
|
625
629
|
};
|
|
626
|
-
if (hal._.supportedMimeTypes.has(
|
|
630
|
+
if (hal._.supportedMimeTypes.has(storage.MIME_WAV)) {
|
|
627
631
|
ctx.collect({
|
|
628
|
-
mime_type:
|
|
632
|
+
mime_type: storage.MIME_WAV, url, analyze,
|
|
629
633
|
data: await media.convertAudioTo16kNanoPcmWave(file, {
|
|
630
634
|
input: storage.BUFFER, expected: storage.BASE64,
|
|
631
635
|
}),
|
|
@@ -736,9 +740,10 @@ const subconscious = [{
|
|
|
736
740
|
if (m.photo?.[m.photo?.length - 1]) {
|
|
737
741
|
const p = m.photo[m.photo.length - 1];
|
|
738
742
|
files.push({
|
|
739
|
-
asPrompt: hal._.supportedMimeTypes.has(
|
|
743
|
+
asPrompt: hal._.supportedMimeTypes.has(storage.MIME_JPEG),
|
|
740
744
|
file_name: `${p.file_id}.jpg`, fileId: p.file_id,
|
|
741
|
-
mime_type:
|
|
745
|
+
mime_type: storage.MIME_JPEG, type: 'PHOTO',
|
|
746
|
+
ocrFunc: ctx._.vision?.see,
|
|
742
747
|
});
|
|
743
748
|
}
|
|
744
749
|
if (m.video_note) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "halbot",
|
|
3
3
|
"description": "Just another `ChatGPT` / `Gemini` / `Claude` / `Azure` / `Jina` / `Ollama` Telegram bob, which is simple design, easy to use, extendable and fun.",
|
|
4
|
-
"version": "1993.2.
|
|
4
|
+
"version": "1993.2.92",
|
|
5
5
|
"private": false,
|
|
6
6
|
"homepage": "https://github.com/Leask/halbot",
|
|
7
7
|
"type": "module",
|
|
@@ -46,12 +46,12 @@
|
|
|
46
46
|
"mime": "^4.0.7",
|
|
47
47
|
"mysql2": "^3.14.1",
|
|
48
48
|
"office-text-extractor": "^3.0.3",
|
|
49
|
-
"openai": "^4.
|
|
49
|
+
"openai": "^4.97.0",
|
|
50
50
|
"pg": "^8.15.6",
|
|
51
51
|
"pgvector": "^0.2.0",
|
|
52
52
|
"telegraf": "^4.16.3",
|
|
53
53
|
"tesseract.js": "^6.0.1",
|
|
54
|
-
"utilitas": "^1999.1.
|
|
54
|
+
"utilitas": "^1999.1.63",
|
|
55
55
|
"youtube-transcript": "^1.2.1"
|
|
56
56
|
}
|
|
57
57
|
}
|
package/skills/-8845_thread.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { alan, hal, uoid, utilitas } from '../index.mjs';
|
|
2
2
|
|
|
3
|
-
const [EMIJI_FINISH, END, NEW, THREAD] = ['☑️', '❎', '✨', '🧵'];
|
|
3
|
+
const [EMIJI_FINISH, END, NEW, THREAD, CLR] = ['☑️', '❎', '✨', '🧵', '🆑'];
|
|
4
4
|
|
|
5
5
|
const [CREATED, SWITCHED] = [
|
|
6
6
|
`${NEW} Thread created: `, `${EMIJI_FINISH} Thread switched: `
|
package/skills/40_dream.mjs
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
|
-
import { bot } from '../index.mjs';
|
|
1
|
+
import { bot, storage } from '../index.mjs';
|
|
2
2
|
|
|
3
3
|
const GEMINI = 'GEMINI';
|
|
4
4
|
const types = { image: 'photo', video: 'video' };
|
|
5
5
|
|
|
6
6
|
const action = async (ctx, next) => {
|
|
7
|
-
let [provider, func] = [GEMINI, 'image'];
|
|
7
|
+
let [provider, func, reference] = [GEMINI, 'image', null];
|
|
8
8
|
switch (ctx.cmd.cmd) {
|
|
9
|
-
case '
|
|
10
|
-
case '
|
|
9
|
+
case 'fantasy': func = 'video'; break;
|
|
10
|
+
case 'gptimage':
|
|
11
|
+
provider = 'OPENAI';
|
|
12
|
+
reference = ctx.collected.filter(x => [
|
|
13
|
+
storage.MIME_JPEG, storage.MIME_PNG, storage.MIME_WEBP
|
|
14
|
+
].includes(x?.content?.mime_type)).slice(0, 16).map(
|
|
15
|
+
x => x?.content?.data
|
|
16
|
+
);
|
|
11
17
|
}
|
|
12
18
|
if (!ctx.cmd.args) {
|
|
13
19
|
return await ctx.ok('Please input your prompt.');
|
|
@@ -15,7 +21,8 @@ const action = async (ctx, next) => {
|
|
|
15
21
|
let [objMsg, output] = [(await ctx.ok('💭'))[0], null]; //tts = null
|
|
16
22
|
try {
|
|
17
23
|
output = (await ctx._.gen[func](ctx.cmd.args, {
|
|
18
|
-
provider, expected: 'FILE'
|
|
24
|
+
provider, expected: 'FILE',
|
|
25
|
+
...reference?.length ? { reference, input: 'BASE64' } : {},
|
|
19
26
|
})) || [];
|
|
20
27
|
} catch (err) {
|
|
21
28
|
return await ctx.er(err.message || `Error generating ${func}.`,
|
package/skills/70_chat.mjs
CHANGED
|
@@ -8,25 +8,31 @@ const log = content => utilitas.log(content, import.meta.url);
|
|
|
8
8
|
const action = async (ctx, next) => {
|
|
9
9
|
if (!ctx.prompt && !ctx.carry.attachments.length) { return await next(); }
|
|
10
10
|
let [
|
|
11
|
-
ais, YOU, msgs,
|
|
12
|
-
|
|
11
|
+
ais, YOU, msgs, pms, extra, lock, sResp, lastMsg, lastSent, references,
|
|
12
|
+
audio,
|
|
13
13
|
] = [
|
|
14
|
-
await alan.getAi(null, { all: true }), `${ctx.avatar} You:`, {},
|
|
15
|
-
{
|
|
14
|
+
await alan.getAi(null, { all: true }), `${ctx.avatar} You:`, {}, [],
|
|
15
|
+
{ buttons: [] }, 1000 * 5, null, null, 0, null, null,
|
|
16
16
|
];
|
|
17
17
|
const packMsg = options => {
|
|
18
18
|
const said = !options?.tts && ctx.result ? ctx.result : '';
|
|
19
19
|
const packed = [
|
|
20
20
|
...ctx.carry?.threadInfo, ...said ? [joinL2([YOU, said])] : [],
|
|
21
21
|
];
|
|
22
|
-
const source = options?.tts ? tts : msgs;
|
|
23
22
|
const pure = [];
|
|
24
23
|
ctx.selectedAi.map(n => {
|
|
25
|
-
const content =
|
|
24
|
+
const content = msgs[n]?.[options?.tts ? 'spoken' : 'text'] || '';
|
|
26
25
|
pure.push(content);
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
const ai = ais.find(x => x.id === n);
|
|
27
|
+
let aiName = ai.name;
|
|
28
|
+
const defModel = aiName.replace(/^.*\(.*\)$/, '$1');
|
|
29
|
+
const curModel = msgs[n]?.model;
|
|
30
|
+
if (defModel && curModel && defModel !== curModel) {
|
|
31
|
+
aiName = aiName.replace(/^(.*\().*(\))$/, `$1${curModel}$2`);
|
|
32
|
+
}
|
|
33
|
+
packed.push(joinL2([
|
|
34
|
+
...options?.tts ? [] : [`${aiName}:`], content
|
|
35
|
+
]));
|
|
30
36
|
});
|
|
31
37
|
return pure.join('').trim().length ? joinL1(packed) : '';
|
|
32
38
|
};
|
|
@@ -56,34 +62,35 @@ const action = async (ctx, next) => {
|
|
|
56
62
|
for (const n of ctx.selectedAi) {
|
|
57
63
|
pms.push((async ai => {
|
|
58
64
|
try {
|
|
59
|
-
const resp = await alan.talk(ctx.prompt ||
|
|
65
|
+
const resp = await alan.talk(ctx.prompt || alan.ATTACHMENTS, {
|
|
60
66
|
aiId: ai, ...ctx.carry, stream: async r => {
|
|
61
|
-
msgs[ai] = r
|
|
67
|
+
msgs[ai] = r;
|
|
62
68
|
ctx.carry.threadInfo.length || ok(onProgress);
|
|
63
69
|
},
|
|
64
70
|
});
|
|
65
71
|
references = resp.references;
|
|
66
72
|
audio = resp.audio;
|
|
67
|
-
msgs[ai] = resp
|
|
68
|
-
|
|
69
|
-
&& !
|
|
70
|
-
? resp.spoken :
|
|
73
|
+
msgs[ai] = resp;
|
|
74
|
+
msgs[ai].spoken = ctx.selectedAi.length === 1
|
|
75
|
+
&& !resp.text.split('\n').some(x => /^\s*```/.test(x))
|
|
76
|
+
? resp.spoken : null;
|
|
71
77
|
for (let img of resp?.images || []) {
|
|
72
78
|
await ctx.image(img.data, { caption: `🎨 by ${resp.model}` });
|
|
73
79
|
await ctx.timeout();
|
|
74
80
|
}
|
|
75
81
|
return resp;
|
|
76
82
|
} catch (err) {
|
|
77
|
-
msgs[ai] =
|
|
78
|
-
|
|
79
|
-
|
|
83
|
+
msgs[ai] = {
|
|
84
|
+
...msgs[ai], text: `⚠️ ${err?.message || err}`,
|
|
85
|
+
spoken: null,
|
|
86
|
+
};
|
|
80
87
|
log(err);
|
|
81
88
|
}
|
|
82
89
|
})(n));
|
|
83
90
|
}
|
|
84
91
|
await Promise.all(pms);
|
|
85
|
-
|
|
86
|
-
|
|
92
|
+
await (Object.values(msgs).map(x => x.text).join('').trim()
|
|
93
|
+
? ok({ final: true }) : ctx.deleteMessage(sResp[0].message_id));
|
|
87
94
|
ctx.tts = audio || packMsg({ tts: true });
|
|
88
95
|
await next();
|
|
89
96
|
};
|