halbot 1993.2.91 → 1993.2.93

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 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
- = [await utilitas.which(), {}, { tts: true, stt: true }, {}];
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
- await speech.init({ ...apiKey, ...speechOptions });
30
- _speech.tts = speech.tts;
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,8 @@
1
+ import {
2
+ bot, callosum, dbio, media, speech, storage, uoid, utilitas, web,
3
+ } from 'utilitas';
4
+
1
5
  import { basename, join } from 'path';
2
- import { bot, callosum, dbio, storage, uoid, utilitas, web } from 'utilitas';
3
6
  import { parseArgs as _parseArgs } from 'node:util';
4
7
  import { readdirSync } from 'fs';
5
8
 
@@ -624,9 +627,9 @@ const subconscious = [{
624
627
  log(`STT: '${resp}'`);
625
628
  ctx.collect(resp);
626
629
  };
627
- if (hal._.supportedMimeTypes.has(MIME_WAV)) {
630
+ if (hal._.supportedMimeTypes.has(storage.MIME_WAV)) {
628
631
  ctx.collect({
629
- mime_type: MIME_WAV, url, analyze,
632
+ mime_type: storage.MIME_WAV, url, analyze,
630
633
  data: await media.convertAudioTo16kNanoPcmWave(file, {
631
634
  input: storage.BUFFER, expected: storage.BASE64,
632
635
  }),
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.91",
4
+ "version": "1993.2.93",
5
5
  "private": false,
6
6
  "homepage": "https://github.com/Leask/halbot",
7
7
  "type": "module",
@@ -51,7 +51,7 @@
51
51
  "pgvector": "^0.2.0",
52
52
  "telegraf": "^4.16.3",
53
53
  "tesseract.js": "^6.0.1",
54
- "utilitas": "^1999.1.61",
54
+ "utilitas": "^1999.1.64",
55
55
  "youtube-transcript": "^1.2.1"
56
56
  }
57
57
  }
@@ -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: `
@@ -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, tts, rsm, pms, extra, lock, sResp, lastMsg, lastSent,
12
- references, audio
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
- {}, [], { buttons: [] }, 1000 * 5, null, null, 0, null, null,
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 = source[n] || '';
24
+ const content = msgs[n]?.[options?.tts ? 'spoken' : 'text'] || '';
26
25
  pure.push(content);
27
- packed.push(joinL2([...options?.tts ? [] : [
28
- `${ais.find(x => x.id === n).name}:`
29
- ], content]));
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 || alen.ATTACHMENTS, {
65
+ const resp = await alan.talk(ctx.prompt || alan.ATTACHMENTS, {
60
66
  aiId: ai, ...ctx.carry, stream: async r => {
61
- msgs[ai] = r.text;
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.text;
68
- tts[ai] = ctx.selectedAi.length === 1
69
- && !msgs[ai].split('\n').some(x => /^\s*```/.test(x))
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] = `⚠️ ${err?.message || err}`;
78
- tts[ai] = null;
79
- rsm[ai] = null;
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
- if (Object.values(msgs).join('').trim()) { await ok({ final: true }); }
86
- else { await ctx.deleteMessage(sResp[0].message_id); }
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
  };