botql 1.1.2 → 1.2.2
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/LICENSE +30 -10
- package/Parser.js +5 -1
- package/RAG.js +1 -572
- package/README.md +44 -18
- package/Terminal.js +96 -0
- package/botql.browser.js +248 -526
- package/botql.js +4 -4
- package/createBot.js +88 -0
- package/package.json +3 -2
- package/Bootstrap.js +0 -74
package/Terminal.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Terminal.js — feedback visual de "a pensar" para quando o BotQL corre
|
|
5
|
+
* num terminal Node.js puro (ex: bot ligado via Bootstrap.js, sem editor
|
|
6
|
+
* nenhum por perto).
|
|
7
|
+
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const FRAMES = ['|', '/', '-', '\\'];
|
|
11
|
+
const INTERVALO_MS = 100;
|
|
12
|
+
|
|
13
|
+
function isNodeRuntime() {
|
|
14
|
+
return typeof process !== 'undefined' && !!process.versions && !!process.versions.node;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function isInteractiveTerminal() {
|
|
18
|
+
return isNodeRuntime() && !!process.stdout && !!process.stdout.isTTY;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Liga um spinner de terminal ao onThinking do interpretador, e um
|
|
23
|
+
* fallback de console.log a onReply/onForward/onSend — só para os que
|
|
24
|
+
* ainda não tiverem sido definidos.
|
|
25
|
+
*
|
|
26
|
+
* @param {import('./botql.js').BotQLInterpreter} interpreter
|
|
27
|
+
* @returns {() => void} função para desligar o spinner manualmente, se
|
|
28
|
+
* for preciso parar antes do bot terminar (raramente necessário).
|
|
29
|
+
*/
|
|
30
|
+
function attachTerminalUI(interpreter) {
|
|
31
|
+
if (!isNodeRuntime()) {
|
|
32
|
+
// Browser/WebView: quem trata da UI é o próprio editor.
|
|
33
|
+
return () => {};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
let timer = null;
|
|
37
|
+
let ativo = false;
|
|
38
|
+
|
|
39
|
+
function pararSpinner() {
|
|
40
|
+
if (!ativo) return;
|
|
41
|
+
ativo = false;
|
|
42
|
+
if (timer) clearInterval(timer);
|
|
43
|
+
if (isInteractiveTerminal()) {
|
|
44
|
+
process.stdout.write('\r\x1b[K'); // limpa a linha do spinner
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (!interpreter.onThinking) {
|
|
49
|
+
interpreter.onThinking = ({ text }) => {
|
|
50
|
+
const rotulo = text ? text + ' ' : '';
|
|
51
|
+
|
|
52
|
+
if (!isInteractiveTerminal()) {
|
|
53
|
+
// Não interativo (ex: saída redirecionada para ficheiro,
|
|
54
|
+
// ou executado em CI): uma linha só, sem animação.
|
|
55
|
+
console.log(rotulo.trim() || '...');
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
ativo = true;
|
|
60
|
+
let frame = 0;
|
|
61
|
+
timer = setInterval(() => {
|
|
62
|
+
process.stdout.write('\r' + rotulo + FRAMES[frame]);
|
|
63
|
+
frame = (frame + 1) % FRAMES.length;
|
|
64
|
+
}, INTERVALO_MS);
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Sem isto o spinner nunca pararia sozinho — onReply/onForward/onSend
|
|
69
|
+
// são os eventos que sinalizam "o THINK/bloco terminou, já há resposta".
|
|
70
|
+
const envolverEPararSpinner = (onEvent) => async (payload) => {
|
|
71
|
+
pararSpinner();
|
|
72
|
+
if (onEvent) await onEvent(payload);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
if (!interpreter.onReply) {
|
|
76
|
+
interpreter.onReply = envolverEPararSpinner(({ text }) => console.log(text));
|
|
77
|
+
} else {
|
|
78
|
+
interpreter.onReply = envolverEPararSpinner(interpreter.onReply);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!interpreter.onForward) {
|
|
82
|
+
interpreter.onForward = envolverEPararSpinner(({ target }) => console.log(`(encaminhado para ${target})`));
|
|
83
|
+
} else {
|
|
84
|
+
interpreter.onForward = envolverEPararSpinner(interpreter.onForward);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (!interpreter.onSend) {
|
|
88
|
+
interpreter.onSend = envolverEPararSpinner(({ target, signal }) => console.log(`(enviado para ${target})`, signal));
|
|
89
|
+
} else {
|
|
90
|
+
interpreter.onSend = envolverEPararSpinner(interpreter.onSend);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return pararSpinner;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
module.exports = { attachTerminalUI, isInteractiveTerminal, isNodeRuntime };
|