1 | set flag Matches_fsi. |
2 | |
3 | static boolean hotwire_over_bot = false; |
4 | |
5 | static int maxAnswerLength = 1000, shortenTo = 200; |
6 | static int askSelfMax = 10; |
7 | |
8 | static L<S> botIDs = litlist("#1002317"); |
9 | static L<S> generalReleaseBots = litlist(); |
10 | static new L<Class> bots; |
11 | static new L<S> activeBots; |
12 | static Map<S, Class> botsByID = synchroTreeMap(); |
13 | |
14 | static new L<S> disabledBots; |
15 | |
16 | // information for "answer" functions |
17 | static new ThreadLocal<S> userName; |
18 | static new ThreadLocal<S> slackTS; |
19 | static new ThreadLocal<S> channelName; |
20 | static new ThreadLocal<S> dialogID; |
21 | static new ThreadLocal<S> actualURI; |
22 | static ThreadLocal<Map<S, S>> uploadFiles = new ThreadLocal; |
23 | static new ThreadLocal<Boolean> attn; |
24 | static new ThreadLocal<Boolean> dedicated; |
25 | static new ThreadLocal<S> originalLine; |
26 | static new ThreadLocal<S> answeringBot; |
27 | static ThreadLocal<Set<S>> involvedBots = new ThreadLocal; // bots involved with making the current answer |
28 | static new ThreadLocal<S> postAs; |
29 | static new ThreadLocal<S> botIcon; |
30 | |
31 | static volatile S loadingBotID; |
32 | static volatile Class loadingBot; |
33 | static volatile boolean loaded; |
34 | |
35 | static new L<Map> history; // stores all processed user questions (not whole chat log) |
36 | |
37 | static volatile S lastAnswerBy; |
38 | static volatile L<S> lastInvolvedBots; |
39 | |
40 | static void coreInit() { |
41 | load("disabledBots"); |
42 | reload(); |
43 | readLog(); |
44 | |
45 | loaded = true; |
46 | } |
47 | |
48 | static S answerImpl(S s, boolean generalRelease) { |
49 | new Matches m; |
50 | |
51 | S whoSaidThat = lastAnswerBy; |
52 | L<S> involvedBots = main.lastInvolvedBots; |
53 | |
54 | L<S> tok = javaTok(s); |
55 | if (isInteger(get(tok, 1)) && eq(get(tok, 3), ":")) { |
56 | Class bot = getBot(get(tok, 1)); |
57 | if (bot == null) |
58 | ret "Bot not found: " + get(tok, 1); |
59 | s = join(subList(tok, 5)); |
60 | S answer = callDehBots(litlist(bot), s); |
61 | ret empty(answer) ? "(no answer)" : answer; |
62 | } |
63 | |
64 | if "get home page bot" exceptionToUser { |
65 | if (!hasField(mc(), "homePageBotID")) |
66 | ret "Eleu was compiled without web integration"; |
67 | |
68 | ret str(get(mc(), "homePageBotID")); |
69 | } |
70 | |
71 | if (master()) { |
72 | if "set home page bot *" exceptionToUser { |
73 | S id = m.fsi(0); |
74 | if (!hasField(mc(), "homePageBotID")) |
75 | ret "Eleu was compiled without web integration"; |
76 | |
77 | set(mc(), "homePageBotID", id); |
78 | call(mc(), "save", "homePageBotID"); |
79 | ret format("OK, home page bot ID set to *", id); |
80 | } |
81 | |
82 | if "set no home page bot *" exceptionToUser { |
83 | S id = m.fsi(0); |
84 | if (!hasField(mc(), "homePageBotID")) |
85 | ret "Eleu was compiled without web integration"; |
86 | |
87 | set(mc(), "homePageBotID", null); |
88 | call(mc(), "save", "homePageBotID"); |
89 | ret format("OK, home page bot ID set to null"); |
90 | } |
91 | |
92 | if "disable bot *" { |
93 | setAdd(disabledBots, formatSnippetID(m.unq(0))); |
94 | save("disabledBots"); |
95 | ret "OK"; |
96 | } |
97 | |
98 | if "enable bot *" { |
99 | disabledBots.remove(formatSnippetID(m.unq(0))); |
100 | save("disabledBots"); |
101 | ret "OK"; |
102 | } |
103 | } |
104 | |
105 | if (match("reboot", s) && master()) { |
106 | int n = l(bots); |
107 | cleanUp(bots); |
108 | bots.clear(); |
109 | |
110 | thread { |
111 | sleepSeconds(1); |
112 | |
113 | // take latest args from source |
114 | S vmArgs = cast loadVariableDefinition("vmArgs"); |
115 | |
116 | directNohupJavax(getProgramID(), vmArgs); |
117 | System.exit(100); |
118 | } |
119 | ret n(n, "bot") + " cleaned up. Rebooting..."; |
120 | } |
121 | |
122 | if (match("who said that", s)) |
123 | ret (whoSaidThat == null ? "what?" : whoSaidThat) + " / " + structure(lastInvolvedBots); |
124 | |
125 | if (match("reload", s) && master()) { |
126 | time { reload(); } |
127 | ret l(bots) + "/" + l(botIDs) + " bots reloaded in "+ getLastTiming() + " ms."; |
128 | } |
129 | |
130 | if (match("reload *", s, m) && isSnippetID(m.unq(0)) && master()) { |
131 | reload(m.unq(0)); |
132 | ret "Bot " + formatSnippetID(m.unq(0)) + " reloaded."; |
133 | } |
134 | |
135 | if (match("list bots", s)) { |
136 | S answer = "Active bots: " + structure(activeBots); |
137 | L<S> inactiveBots = diff(botIDs, activeBots); |
138 | if (!inactiveBots.isEmpty()) |
139 | answer += ". Inactive/disabled bots: " + structure(inactiveBots); |
140 | if (!disabledBots.isEmpty()) |
141 | answer += ". Disabled bots: " + structure(disabledBots); |
142 | ret answer; |
143 | } |
144 | |
145 | if (match("test", s)) |
146 | ret "test me yes test me please!"; |
147 | |
148 | ret callDehBots(generalRelease ? getGeneralReleaseBots() : bots, s); |
149 | } |
150 | |
151 | static S callDehBots(L<Class> bots, S s) { |
152 | answeringBot.set(null); |
153 | involvedBots.set(new TreeSet); |
154 | postAs.set(null); |
155 | botIcon.set(null); |
156 | for (Class c : bots) try { |
157 | S botID = getBotID(c); |
158 | if (disabledBots.contains(formatSnippetID(botID))) continue; |
159 | //print("Calling bot " + botID); |
160 | S answer = callStaticAnswerMethod(c, s); |
161 | if (!empty(answer)) { |
162 | S whoSaidIt = or((S) getOpt(c, "whoSaidThat"), botID); |
163 | answeringBot.set(whoSaidIt); |
164 | involvedBots.get().add(formatSnippetID(whoSaidIt)); |
165 | lastAnswerBy = whoSaidIt; |
166 | lastInvolvedBots = new ArrayList(involvedBots.get()); |
167 | print("Answering bot: " + whoSaidIt); |
168 | ret answer; |
169 | } |
170 | } catch (Throwable e) { |
171 | print("Error calling " + getProgramID(c) + ":\n" + getStackTrace(e)); |
172 | } |
173 | ret null; |
174 | } |
175 | |
176 | static S getBotID(Class bot) { |
177 | ret reverseLookup(botsByID, bot); |
178 | } |
179 | |
180 | static int askSelfCounter; |
181 | |
182 | static synchronized S askSelf(S s) { |
183 | if (askSelfCounter >= askSelfMax) |
184 | fail("Too much recursion asking myself (depth " + askSelfMax + ")"); |
185 | ++askSelfCounter; |
186 | try { |
187 | ret answer(s); |
188 | } finally { |
189 | --askSelfCounter; |
190 | } |
191 | } |
192 | |
193 | static synchronized S answer(S s) { |
194 | ret answer(s, false); |
195 | } |
196 | |
197 | static synchronized S answer(S s, boolean generalRelease) { |
198 | long time = now(); |
199 | S a = "ERREUR"; |
200 | try { |
201 | a = answerImpl(s, generalRelease); |
202 | } finally { |
203 | pcall { |
204 | long x = now(); |
205 | // We should record which bot answered! |
206 | Map map = litmap("startTime", time, "duration", x-time, |
207 | "question", s, "answer", a, "botID", "?"); |
208 | printList(answerPriv(format("log timing *", structure(map)))); |
209 | } |
210 | } |
211 | ret a; |
212 | } |
213 | |
214 | // can give multiple answers |
215 | static synchronized L<S> answerPriv(S s) { |
216 | new L<S> l; |
217 | for (Class bot : bots) pcall { |
218 | S a = cast callOpt(bot, "answerPriv", s); |
219 | if (!empty(a)) |
220 | l.add(a); |
221 | } |
222 | ret l; |
223 | } |
224 | |
225 | static L<Class> getGeneralReleaseBots() { |
226 | new L<Class> l; |
227 | for (S botID : generalReleaseBots) { |
228 | Class c = botsByID.get("" + parseSnippetID(botID)); |
229 | if (c != null) |
230 | l.add(c); |
231 | } |
232 | ret l; |
233 | } |
234 | |
235 | static void recordFeedback(S probableQuestion, S answer, S answerTime, S feedback, int score) { |
236 | if (answer == null || probableQuestion == null) ret; |
237 | |
238 | Map data = litmap("realtime", now(), "question", probableQuestion, "answer", answer, "answertime", answerTime, "feedback", feedback, "score", score); |
239 | print("Recording feedback: " + data); |
240 | logQuoted(new File(programDir(), "feedback-log"), structure(data)); |
241 | logQuoted(new File(programDir(), "memory-log"), structure(data)); |
242 | } |
243 | |
244 | static void reloadLists() { |
245 | botIDs = or((L<S>) loadVariableDefinition("botIDs"), botIDs); |
246 | generalReleaseBots = or((L<S>) loadVariableDefinition("generalReleaseBots"), generalReleaseBots); |
247 | botIDs.addAll(generalReleaseBots); |
248 | } |
249 | |
250 | static void reload() { |
251 | reloadLists(); |
252 | |
253 | cleanUp(bots); |
254 | activeBots = new ArrayList(); |
255 | botsByID.clear(); |
256 | for (S botID : botIDs) |
257 | pcall { |
258 | loadBot(botID); |
259 | } |
260 | } |
261 | |
262 | static void reload(S botID) { |
263 | reloadLists(); |
264 | S parsedID = "" + parseSnippetID(botID); |
265 | Class bot = botsByID.get(parsedID); |
266 | if (bot != null) { |
267 | cleanUp(bot); |
268 | botsByID.remove(parsedID); |
269 | activeBots.remove(formatSnippetID(botID)); |
270 | bots.remove(bot); |
271 | } |
272 | loadBot(botID); |
273 | } |
274 | |
275 | static void loadBot(S botID) { |
276 | botID = formatSnippetID(botID); |
277 | if (!botIDs.contains(botID)) |
278 | fail("Bot not listed: " + botID); |
279 | |
280 | print("Loading bot: " + botID); |
281 | Class c = hotwire_over_bot ? hotwire_overBot(botID) : hotwire(botID); |
282 | setOpt(c, "mainBot", getMainClass()); |
283 | loadingBotID = botID; |
284 | loadingBot = c; |
285 | try { |
286 | callMain(c); |
287 | bots.add(c); |
288 | activeBots.add(formatSnippetID(botID)); // only if loading doesn't fail |
289 | botsByID.put("" + parseSnippetID(botID), c); |
290 | print("Loaded bot: " + botID + ", bots now: " + l(activeBots)); |
291 | } finally { |
292 | loadingBotID = null; |
293 | loadingBot = null; |
294 | } |
295 | } |
296 | |
297 | static void readLog() { |
298 | for (S prog : litlist("#1001915", getProgramID())) |
299 | for (S s : scanLog(prog, "memory-log")) pcall { |
300 | history.add((Map) safeUnstructure(s)); |
301 | } |
302 | print(l(history) + " history entries."); |
303 | } |
304 | |
305 | // query threadlocals (called by sub-bots) |
306 | |
307 | static S getUserName() { ret userName.get(); } |
308 | static S getSlackTS() { ret slackTS.get(); } |
309 | static S getChannelName() { ret channelName.get(); } |
310 | static S getDialogID() { ret dialogID.get(); } |
311 | static S getActualURI() { ret actualURI.get(); } |
312 | static Map<S, S> getUploadFiles() { ret uploadFiles.get(); } |
313 | static S getOriginalLine() { ret originalLine.get(); } |
314 | static boolean isAddressed() { ret attn.get(); } |
315 | static boolean dedicated() { ret dedicated.get(); } |
316 | static Set getInvolvedBots() { ret involvedBots.get(); } |
317 | |
318 | // get the sub-bot dispatcher (#1002317) |
319 | static O getDispatcher() { |
320 | ret botsByID.get("" + parseSnippetID("#1002317")); |
321 | } |
322 | |
323 | static Class getBot(S botID) { |
324 | Class bot = botsByID.get("" + parseSnippetID(botID)); |
325 | if (bot == null) { |
326 | O disp = getDispatcher(); |
327 | if (disp != null) |
328 | ret (Class) call(disp, "getSubBot", botID); |
329 | } |
330 | ret bot; |
331 | } |
332 | |
333 | static synchronized void historyAdd(Map logEntry) { |
334 | logEntry.put("realtime", now()); |
335 | logEntry.put("dialogID", getDialogID()); |
336 | logEntry.put("involvedBots", toList(getInvolvedBots())); |
337 | history.add(logEntry); |
338 | logQuoted(new File(programDir(), "memory-log"), structure(logEntry)); |
339 | } |
340 | |
341 | static void postAs(S name) { |
342 | postAs.set(name); |
343 | } |
344 | |
345 | static void botIcon(S url) { |
346 | botIcon.set(url); |
347 | } |
download show line numbers debug dex old transpilations
Travelled to 15 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt, xrpafgyirdlv
No comments. add comment
Snippet ID: | #1002578 |
Snippet name: | Eleu Core (Include) |
Eternal ID of this version: | #1002578/5 |
Text MD5: | e37561bfb18cfed771b75f0feea0df4b |
Author: | stefan |
Category: | eleu |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2020-07-02 11:52:28 |
Source code size: | 10041 bytes / 347 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 815 / 2073 |
Version history: | 4 change(s) |
Referenced in: | [show references] |