halbot 1991.2.21 → 1991.2.23

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "halbot",
3
3
  "description": "Just another `ChatGPT` / `Gemini` / `Mistral (by ollama)` Telegram bob, which is simple design, easy to use, extendable and fun.",
4
- "version": "1991.2.21",
4
+ "version": "1991.2.23",
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": "^5.1.0",
54
- "utilitas": "^1997.1.2",
54
+ "utilitas": "^1997.1.4",
55
55
  "youtube-transcript": "^1.2.1"
56
56
  }
57
57
  }
@@ -1,19 +1,25 @@
1
1
  import { alan, bot, uoid, utilitas } from 'utilitas';
2
2
 
3
- const EMIJI_FINISH = '☑️';
3
+ const [EMIJI_FINISH, END, NEW, THREAD, CLR] = ['☑️', '❎', '✨', '🧵', '🆑'];
4
+
5
+ const [CREATED, SWITCHED] = [
6
+ `${NEW} Thread created: `, `${EMIJI_FINISH} Thread switched: `
7
+ ];
4
8
 
5
9
  // moved to help and configs
6
10
  const keyboards = [[
7
- { text: '/clear this thread 🆑' },
8
- { text: '/clearall threads 🔄' }
11
+ { text: `/clear ${CLR}` },
12
+ { text: `/end ${END}` },
13
+ { text: `/list ${THREAD}` },
14
+ { text: `/new ${NEW}` },
9
15
  ], [
10
- { text: '/end this thread ❎' },
11
- { text: '/list threads 🧵' },
12
- { text: '/new thread ✨' },
16
+ { text: '/polish ❇️' },
17
+ { text: '/translate 🇨🇳' },
18
+ { text: '/translate 🇺🇸' },
13
19
  ], [
14
20
  { text: '/help 🛟' },
15
- { text: '/ttsoff 🔇' },
16
- { text: '/ttson 🔊' },
21
+ { text: '/set --tts=🔇' },
22
+ { text: '/set --tts=🔊' },
17
23
  ]];
18
24
 
19
25
  const action = async (ctx, next) => {
@@ -24,10 +30,25 @@ const action = async (ctx, next) => {
24
30
  const resetSessions = () => ctx.session.sessions = [];
25
31
  const resetContext = context => ctx.session.context = context || {};
26
32
  const now = Date.now();
27
- ctx.session.sessionId || resetSession();
33
+ const preSessionId = ctx.session.sessionId || resetSession();
28
34
  ctx.session.sessions || resetSessions();
29
35
  ctx.session.context || resetContext();
36
+ ctx.carry || (ctx.carry = {});
37
+ ctx.carry.threadInfo || (ctx.carry.threadInfo = []);
30
38
  // load functions
39
+ ctx.clear = async context => {
40
+ await alan.resetSession(
41
+ ctx.session.sessionId,
42
+ // { systemPrompt: context?.prompt } // @todo: switch to real system prompt
43
+ );
44
+ resetContext(context);
45
+ const id = findSession(ctx.session.sessionId);
46
+ ctx.cmd.ignored = true;
47
+ ctx.session.sessions?.[id] && (
48
+ ctx.session.sessions[id].context = ctx.session.context
49
+ );
50
+ ctx.hello(context?.prompt);
51
+ };
31
52
  const switchSession = async () => {
32
53
  let resp;
33
54
  for (const session of ctx.session.sessions) {
@@ -36,6 +57,9 @@ const action = async (ctx, next) => {
36
57
  ctx.session.context = session.context;
37
58
  session.touchedAt = now;
38
59
  resp = session;
60
+ preSessionId !== ctx.session.sessionId
61
+ && ctx.carry.threadInfo.push(SWITCHED
62
+ + getLabel(findSession(ctx.session.sessionId)));
39
63
  break;
40
64
  }
41
65
  }
@@ -44,9 +68,12 @@ const action = async (ctx, next) => {
44
68
  id: resetSession(),
45
69
  createdAt: now, touchedAt: now, context: {},
46
70
  });
71
+ ctx.carry.threadInfo.push(CREATED
72
+ + getLabel(findSession(ctx.session.sessionId)));
47
73
  await ctx.clear();
48
74
  }
49
- ctx.carry = { sessionId: ctx.session.sessionId };
75
+ ctx.carry.sessionId = ctx.session.sessionId;
76
+ ctx.carry.threadInfo.length && (ctx.carry.keyboards = keyboards);
50
77
  return resp;
51
78
  };
52
79
  const defauleTitle = i => (ctx.session.sessions[i]?.context?.cmd
@@ -60,26 +87,13 @@ const action = async (ctx, next) => {
60
87
  }
61
88
  }
62
89
  };
63
- ctx.clear = async context => {
64
- await alan.resetSession(
65
- ctx.session.sessionId,
66
- // { systemPrompt: context?.prompt } // @todo: switch to real system prompt
67
- );
68
- resetContext(context);
69
- const id = findSession(ctx.session.sessionId);
70
- ctx.cmd.ignored = true;
71
- ctx.session.sessions?.[id] && (
72
- ctx.session.sessions[id].context = ctx.session.context
73
- );
74
- ctx.hello(context?.prompt);
75
- };
76
90
  const ok = async (message, options) => await ctx.ok(message, {
77
- ...options || {}, ...options?.buttons ? {} : { keyboards }
91
+ ...options || {},
92
+ ...options?.buttons ? {} : (options?.keyboards || { keyboards }),
78
93
  });
79
- // handle commands
80
94
  const sendList = async (names, lastMsgId) => {
81
95
  lastMsgId = lastMsgId || ctx.update?.callback_query?.message?.message_id;
82
- const message = `🧵 Thread${ctx.session.sessions.length > 0 ? 's' : ''}:`;
96
+ const message = `{THREAD} Thread${ctx.session.sessions.length > 0 ? 's' : ''}:`;
83
97
  const buttons = ctx.session.sessions.map((x, i) => {
84
98
  names?.[x.id]
85
99
  && (ctx.session.sessions[i].label = names[x.id])
@@ -92,14 +106,26 @@ const action = async (ctx, next) => {
92
106
  });
93
107
  return await ok(message, { lastMessageId: lastMsgId, buttons });
94
108
  };
95
- const switched = async preTitle => await ok(
96
- `${preTitle ? `❎ Thread ended: \`${preTitle}\`.\n\n` : ''}` +
97
- `${EMIJI_FINISH} Thread switched: \`${getLabel(findSession(ctx.session.sessionId))}\`.`
98
- );
109
+ const switched = async (preTitle, newThread) => await ok(`${preTitle
110
+ ? `${END} Thread ended: \`${preTitle}\`\n\n` : ''}`
111
+ + (newThread ? CREATED : SWITCHED)
112
+ + getLabel(findSession(ctx.session.sessionId)), { pageBreak: true });
113
+ // handle commands
99
114
  switch (ctx.cmd?.cmd) {
100
- case 'clear': await ctx.clear(); break;
101
- case 'clearall': resetSessions(); break;
102
- case 'new': resetSession(); break;
115
+ case 'clearkb':
116
+ return await ok(EMIJI_FINISH, { keyboards: [] });
117
+ case 'clear':
118
+ ctx.carry.threadInfo.push(`${CLR} Thread cleared: `
119
+ + getLabel(findSession(ctx.session.sessionId)));
120
+ await ctx.clear();
121
+ break;
122
+ case 'clearall':
123
+ ctx.carry.threadInfo.push(`🔄 All threads have been cleared.`);
124
+ resetSessions();
125
+ break;
126
+ case 'new':
127
+ resetSession();
128
+ break;
103
129
  case 'list':
104
130
  const resp = await sendList();
105
131
  utilitas.ignoreErrFunc(async () => {
@@ -119,16 +145,18 @@ const action = async (ctx, next) => {
119
145
  let preTitle = '';
120
146
  ctx.session.sessions?.[id] && (preTitle = getLabel(id))
121
147
  && (ctx.session.sessions.splice(id, 1));
148
+ const newThread = ctx.session.sessions.length === 0
122
149
  const sorted = ctx.session.sessions.slice().sort(
123
150
  (x, y) => y.touchedAt - x.touchedAt
124
151
  );
125
152
  ctx.session.sessionId = sorted?.[0]?.id;
126
153
  await switchSession();
127
- return await switched(preTitle);
154
+ return await switched(preTitle, newThread);
128
155
  case 'switch':
129
156
  ctx.session.sessionId = utilitas.trim(ctx.cmd.args);
130
157
  await switchSession();
131
- return await sendList();
158
+ await sendList();
159
+ return await switched();
132
160
  case 'factory':
133
161
  case 'reset':
134
162
  await alan.resetSession(ctx.session.sessionId);
@@ -139,17 +167,17 @@ const action = async (ctx, next) => {
139
167
  };
140
168
 
141
169
  export const { name, run, priority, func, help, cmds, cmdx } = {
142
- name: 'session',
170
+ name: 'Thread',
143
171
  run: true,
144
172
  priority: -8845,
145
173
  func: action,
146
- help: '',
174
+ help: 'Thread management.',
147
175
  cmdx: {
148
- new: 'Add a session.',
149
- end: 'Delete a session.',
150
- switch: 'Switch to a session.',
151
- clear: 'Clear current AI conversation session and start a new one.',
152
- clearall: 'Clear all AI conversation sessions.',
153
- list: 'List all AI conversation sessions.',
176
+ new: 'Create a new thread.',
177
+ end: 'End current thread.',
178
+ switch: 'Switch to a thread. Usage: /switch `THREAD_ID`.',
179
+ clear: 'Clear current thread.',
180
+ clearall: 'Clear all threads.',
181
+ list: 'List all threads.',
154
182
  },
155
183
  };
@@ -13,7 +13,9 @@ const action = async (ctx, next) => {
13
13
  let [lastMsg, lastSent] = [null, 0];
14
14
  const packMsg = options => {
15
15
  const said = !options?.tts && ctx.result ? ctx.result : '';
16
- const packed = [...said ? [joinL2([YOU, said])] : []];
16
+ const packed = [
17
+ ...ctx.carry?.threadInfo, ...said ? [joinL2([YOU, said])] : [],
18
+ ];
17
19
  const source = options?.tts ? tts : msgs;
18
20
  const pure = [];
19
21
  ctx.selectedAi.map(n => {
@@ -36,9 +38,12 @@ const action = async (ctx, next) => {
36
38
  options?.final && cmd && (extra.buttons = [{
37
39
  label: `❎ End context: \`${cmd}\``, text: '/clear',
38
40
  }]);
39
- return await ctx.ok(curMsg, { md: true, ...extra, ...options || {} });
41
+ return await ctx.ok(curMsg, {
42
+ ...ctx.carry.keyboards ? { keyboards: ctx.carry.keyboards } : {},
43
+ md: true, ...extra, ...options || {},
44
+ });
40
45
  };
41
- await ok(onProgress);
46
+ ctx.carry.threadInfo.length || await ok(onProgress);
42
47
  for (let n of ctx.selectedAi) {
43
48
  pms.push((async () => {
44
49
  try {
@@ -46,7 +51,7 @@ const action = async (ctx, next) => {
46
51
  engine: ctx._.ai[n].engine, ...ctx.carry,
47
52
  stream: async r => {
48
53
  msgs[n] = r[0].text;
49
- await ok(onProgress);
54
+ ctx.carry.threadInfo.length || await ok(onProgress);
50
55
  },
51
56
  });
52
57
  msgs[n] = ctx.session.config?.render === true