!7 set flag hotwire_here. // to honor classesToShare sbool greetCookies, theoryOn; sbool cloned; static long clonedSince, cloningSince; sS postStartUpMessageToChat; static new L thoughtBots; static long started, indexMakingTime, bootTime; static Class theoryModule; static Lock theoryLock = lock(); static S selectedWord; static int inputNr = 1; static int myPort = 4678; static int ultimateAnswerLimit = 500000; static double speculationTimeoutForHttp = 5.0; // 5 seconds static double speculationTimeoutForNewChatLine = 30.0; static int autoComplete_timeOut = 1000; // 1 second static Set speculationQueue = synchroHashSet(); static double spammerSleep = 10.0; static Set blockedIPs = synchroHashSet(); sS classesToShare = smartBot_sharedClasses(); static Lock aiLock = lock(); static new ThreadLocal httpAuthed; static Map> lastUserLines = syncCIMap(); static new ThreadLocal afterAnswering; static new ThreadLocal answering; static L latestWebs = synchroList(LatestList(1000)); static TimedCache cachedNumberOfThreads = TimedCache(f numberOfAllThreads, 10.0); static L tripleAnswerFunctions = ll( f ai_tripleAnswer_regexpMatches ); set flag allpublic. // save space sclass E {} set flag noCLParse. p { set profilePoint_print; print("yo"); started = sysNow(); try { setGCFrequency(10*60.0); // 10 minutes } catch { updateJavaXAndRestart(); } doEvery(10*60*1000, r { blockedIPs.clear() }); ai_useThoughtSpaces(true); cachedNodeIndex_autoMake = false; releaseDBLockOnTimeoutEval(); ai_prepLoadFunctions(); //set postToStefansChat_printStackTrace; db(); load('selectedWord); load('inputNr); //autoRestart(5); //typicalDownload(); O webSocketFactory = f makeWebSocket; if (canOccupyPort80()) serveHttpWithWebsockets_multiplePorts(webSocketFactory, myPort, 80); else serveHttpWithWebsockets(myPort, webSocketFactory); pcall { serveHttps_botCompany(); } bot("Smart Bot.", func(S s) -> S { S x = "Input line " + (inputNr++); print(x); save("inputNr"); ai_postTriple(x, "is", quote(s)); //ai_speculate(x); stefansChat_onLine_fullParams.set(litmap(auth := true)); try { ret actualAnswer(s); } finally { stefansChat_onLine_fullParams.set(null); } }); loadPage_forcedTimeout = 70000; thoughtBots.add(mc()); indexMakingTime = sysNow(); ai_fillTripleIndex(); //tripleIndex().addWeb(web_setGlobalID("abcdefghijklmnop", webFromTriple("It's", "a", "test"))); indexMakingTime = sysNow()-indexMakingTime; // TODO ai_onNewIndexedText_do(func(S s) { speculationQueue.add(s) }); //thoughtBots.add(memoryBot = runSubBot(#1001951)); handleStefansChat(); handleSmartBotsChat(); //stefansChat_post("Smart Bot Upgraded! Boot took: " + formatDouble(fromMS(sysNow()-started), 1) + " s"); if (greetCookies) runInNewThread(#1010793); // Post on UAIP ai_onNewWeb(f ai_spec_moveToMiddle); ai_onNewWeb(f addToLatestWebs); ai_extendKnownVerbs(); // Do the slow stuff addVirtualNodeIndex(hugeEnglishDictionary_virtualNodeIndex()); loadTheory(); thread "Speculator" { speculatorLoop(); } doneLoading(); bootTime = sysNow()-started; if (cloned) postToChatNamed(postStartUpMessageToChat, infoBoxAndReturn( "Smart Bot cloned in " + formatSeconds(bootTime, 1) + "s (" + formatSeconds(sysNow()-clonedSince, 1) + "s full)")); else infoBox("Smart Bot booted in " + formatSeconds(bootTime, 1) + "s"); } sS actualAnswer(S s) { ret scanMultipleBots(thoughtBots, s); } svoid loadTheory { lock theoryLock; cleanUp(theoryModule); theoryModule = null; if (!theoryOn) ret; theoryModule = run(#1010963); setOpt(theoryModule, 'onUpdate, r { call(theoryModule, 'react) }); call(theoryModule, 'react); print("Theory module loaded."); } static int lineCount; sbool authed() { ret isTrue(mapGet(stefansChat_onLine_fullParams!, 'auth)) || webAuthed(); } sbool byBot() { ret isTrue(mapGet(stefansChat_onLine_fullParams!, 'botMark)); } answer ctex { if (byBot()) null; /*temp tempSetThreadLocal(answering, true); try {*/ selectWord(quote(s)); S a = answer_2(s); //callAll(getAndClearThreadLocal(afterAnswering)); try answer a; /*} on fail { clearThreadLocal(afterAnswering); }*/ } sS answer_2(S s) { // repeat while ConcurrentModificationException // (should not occur anymore anyway) while licensed { try { ret trim(answer_go(s)); } catch print e { S a = exceptionToStringShort(e); if (eq(a, "ConcurrentModificationException")) { sleep(50); continue; } ret a; } } null; } sS answer_go(S s) { ++lineCount; bool authed = authed(); lock dbLock(); S std = ai_standardAnswer(s); if (std == null) std = ai_standardAnswer_dollarVars(s); // TODO: might get slow eventually if (!startsWith(s, "!")) s = ai_dropDroppableStuff(s); int safety = 0; replaceloop: while (safety++ < 10) { s = trim(s); try answer answer_inner(s, lineCount); for (WebNode node : indexedNodes(s)) { S x = web_operandText(node, "replace with"); if (x != null && neq(s, x)) { print("Replacing with " + x); s = x; continue replaceloop; } } break; } //if (ai_isQuestion_1(s)) ret "No idea"; ret std; } sS chatName() { ret or2((S) mapGet(stefansChat_onLine_fullParams!, 'chatName), "Unknown Chat"); } sS chatLineSymbol() { ret (S) mapGet(stefansChat_onLine_fullParams!, "Chat line symbol"); } sS answer_inner(S s, int lineCount) { S chatName = chatName(); final new Matches m; if (eqic(s, "!eval ps")) ret backtick("ps"); if (swic_trim(s, "!eval ps ", m)) ret backtick("ps " + noUnixTricks(m.rest())); if (authed()) { /*if (lineCount >= stefansChat_onLine_lookback)*/ { if (eqic(s, "!restart")) { restart(); ret "Yo"; } if (eqic(s, "!kill")) { cleanKillIn1Second(); ret "Yo"; } if (eqic(s, "!soft-restart 1")) { softRestart_level1(); ret "Hold on..."; } if (eqicOneOf(s, "!soft-restart", "!auto-restart")) { softRestart_level2(); ret "Hold on..."; } if (eqic(s, "!theory")) ret "OK" with loadTheory(); if (swic_trim(s, "!theory ", m)) ret callAnswerFunction(theoryModule, m.rest()); if (eqic(s, "!peep")) { runAndCleanUp(#1010980); ret "OK, got " + fileLength(ai_chatAnalysis_peepHoleFile()) + " bytes"; } if (swic_trim(s, "!subst-web ", m)) { L tok = javaTokC(m.rest()); if (l(tok) == 2) ret ai_subst_web_charBasedReplace(first(tok), selectWord(unquote(last(tok)))); else ret ai_subst_web(m.rest()); } if (eqic(s, "!idle-patterns")) { time2 { Either e = (Either) evalWithTimeout(60.0, f ai_idle_matchPatterns); } ret e.isA() ? "Made " + nWebs(e.a()) + " in " + toSeconds(lastTiming(), 1) + "s" : "Timeout"; } if (swic_trim(s, "!experiment ", m)) { S code = m.rest(); if (!isSnippetID(code)) code = psI(#1013002) + " " + bashQuote(code); File outFile = directNohupJavax(code); ret "OK, " + f2s(outFile); } if (swic_trim(s, "!experiment ", m)) { File outFile = directNohupJavax(m.rest()); ret "OK, " + f2s(outFile); } if (eqic(s, "!rotate")) { rotateSoftwareMadeWebs(); ret "OK"; } if (swic_trim(s, "!speculate-all ", m)) { time2 { Either e = (Either) evalWithTimeout(10.0, r { ai_speculate_all(m.rest()) }); } int n = 0; pcall { n = e.isA() ? e.a() : websMadeInThread(e.b()); } ret "Made " + nWebs(n) + " in " + toSeconds(lastTiming(), 1) + "s"; } if (eqic(s, "!quick-transpile yourself")) ret transpileMyself('quick); if (eqic(s, "!medium-transpile yourself")) ret transpileMyself('medium); } if "unlearn * *" ret "OK, was: " + uniq(MatchLearner, pattern := $1).examples.put($2, 'rejected); if (swic_trim(s, "!sf ", m)) ret sfu(callAndMake_orDirect(m.rest())); if (swic_trim(s, "!specf ", m)) { S sf = m.rest(); print("specf " + sf); Class c = loadFunctionsWithInclude(ll(sf), #1011841); try { callOpt(c, 'ai_spec_init); ret sfu(call(c, sf)); } finally { cleanUp(c); } } if (swicOneOf_trim(s, m, "!eval ", "!j ")) ret smartBotEval(m.rest()); if (swic_trim(s, "!fresh ", m)) { dynClear(); ret smartBotEval(m.rest()); } if (eqicOneOf(s, "!fresh", "!dyn-clear")) { dynClear(); ret "OK, refreshed"; } if (swic_trim(s, "!spec ", m)) { Pair p = splitAtFirstSpace(m.rest()); S f = startsWith(p.a, "ai_") ? p.a : "ai_spec_" + p.a; ret smartBotEval("ai_callSpeculationFunction(f " + f + ", " + p.b + ");"); } if (swic_trim(s, "!spec-all ", m)) { S f = m.rest(); f = startsWith(f, "ai_") ? f : "ai_spec_" + f; fS _f = f; ret smartBotEval("ai_callSpeculationFunctionOnAllTerms(f " + f + ");"); } if (swic_trim(s, "!run ", m)) { runAndCleanUp(m.rest()); ret "OK"; } if (swic_trim(s, "!match ", m)) { L tok = javaTokC(m.rest()); if (l(tok) != 2) ret "need 2 parameters"; S pat = get(tok, 0), input = unquote(get(tok, 1)); Matches mm = ai_matchPattern(pat, input); ret mm == null ? "No match" : sfu(toList(mm.m)); } if (eqic(s, "!compact")) { thread "Compacting" { startedLoading(); try { time { ai_compactLiveDB(true); } postToSmartBotsChat("Tripelized in " + toSeconds(lastTiming()) + " s"); } finally { doneLoading(); } } ret "OK, compacting"; } if (eqic(s, "!sort-lists")) { time { tripleIndex().sortAllLists(); } ret "OK [" + lastTiming() + " ms]"; } if (swic_trim(s, "!var ", m)) ret sfu(get(mc(), m.rest()); if (eqic(s, "!mtm")) { ai_spec_moveToMiddle_all(); ret "OK"; } if (eqic(s, "!gc")) ret ai_gc_scan("The most important word"); if (eqic(s, "!num-invalid")) ret lstr(ai_allInvalidWebs()); if (swic_trim(s, "!load-subspace ", m)) { AI_SubSpace ss = ai_swapInSubSpace($1); ret "OK, size=" + l(ss); } if (eqic(s, "!assume")) { assumeSmartBotURL(); ret "OK"; } if "done making that" ret ai_doneMakingThat(chatName); S c = "are making in " + chatName; if (flexMatchIC("let's make a *", s, m) || flexMatchIC("let's make an *", s, m)) { S id = ai_text_verified("We", c, "$X"); if (id != null) ret "We're still making " + id; S aThing = a(m.rest()); id = selectWord(aGlobalID()); post("We", c, id); post(id, "is", aThing); S answer = "OK, ID for new " + m.rest() + ": " + id + "."; pcall { answer = appendWithSpaceIfNempty(answer, ai_makePartQuestion(chatName, id)); } ret answer; } WebNode openQuestion = first(ai_search_dollarX_verified("Open question in " + chatName, "is", "$X")); if (openQuestion != null) { post(web_text(openQuestion), "is", s); ai_invalidateWeb(openQuestion); S answer = "OK, stored: " + web_text(openQuestion) + " is " + quoteUnlessWordsAndSpaces(s) + "."; S id = ai_text("We", c, "$X"); // What we're making S q = ai_makePartQuestion(chatName, id); if (q == null) { ai_doneMakingThat(chatName); q = "I think we're done here. Made " + id + ", " + ai_renderThingDescriptionWithParts(id); } answer = appendWithSpaceIfNempty(answer, q); ret answer; } for (S sf : ai_texts_verified("$X", "is a good function to call when user says", quote(s))) { sf = unquote(sf); if (endsWith(sf, "()", m)) if (isIdentifier(m.rest())) ret sfu(makeAndCall(m.rest())); } // end of priviledged commands } if (ai_isQuestion_1(s) && !byBot()) { selectWord(s); ai_postTriple(s, "should be", "answered in the chat"); } if "Are you online?" ret "Yes"; if (eqicOneOf(s, "!question", "!gac")) ret random_gac36k(); if (swic_trim(s, "!word ", m)) { selectWord(m.rest()); ret "OK " + unicode_rightPointingTriangle() + unicode_rightPointingTriangle(); } if (swic_trim(s, "!image ", m)) { S x = m.rest(); print("Googling " + x); BufferedImage img = quickVisualize(x); ret "[IMAGE] " + uploadJPEGToImageServer(img, x); } if "memory stats|full memory stats" ret nWeb(ai_allWebsCount()) + ". " + diskSpaceEtcBot_answer(s) + ". " + diskSpaceInfo(); try answer diskSpaceEtcBot_answer(s); if (swic_trim(s, "!search ", m)) { selectWord("[search] " + m.rest()); ret "OK " + unicode_rightPointingTriangle() + unicode_rightPointingTriangle(); } if (swic_trim(s, "!solve ", m)) { S a; time "Solve in subspace" { a = ai_solveQuestionInSubSpace(m.rest()); } ret "[" + lastTiming() + " ms] " + (a != null ? a : "I don't know"); } if (eqic(s, "!loaded-subspaces")) ret sfu(ai_subSpaceNames()); if (eqic(s, "!subspaces")) ret sfu(ai_subSpaceNamesOnDisk()); if (eqic(s, "!index-time")) ret toS(indexMakingTime, 1) + " s"; if (eqic(s, "!boot-time")) ret toS(bootTime, 1) + " s (" + toS(bootTime+started-vmStarted(), 1) + "s full)"; if (swic_trim(s, "!bench-search", m)) { T3 t = ai_parseArrowTriple(m.rest()); time2 { int n = l(ai_search_dollarX(t)); } ret n(n, "result") + ", " + lastTiming() + " ms"; } if (swic_trim(s, "!vary ", m)) ret ifEq(ai_nlVary(m.rest()), m.rest(), "Sorry, no variation found"); if (swic_trim(s, "!google ", m)) ret join(" - ", swapPair(first(quickGoogle($1)))); if (swic_trim(s, "!google-texts", m)) ret lines(uniquify(map tripleC(quickGoogle2($1)))); if (swic_trim(s, "!google-define", m)) ret lines(uniquify(map(func(T3 t) { t.b + " ~ " + t.c }, quickGoogle2($1)))); if (swic_trim(s, "!google-complete ", m)) ret lines(googleAutoComplete($1)); if (swic_trim(s, "!antonyms ", m)) ret join(", ", antonymsFromSynonymDotCom($1)); if (swic_trim(s, "!has-triple ", m)) { Triple t = ai_parseArrowTriple(m.rest()); ret yn(ai_cache_hasTriple(t)); } if (swic_trim(s, "!triple ", m) || swic_trim(s, "!triples ", m)) { L elements = trimAll(splitAt(m.rest(), "->")); if (l(elements) != 3) ret "3 parts please"; ret "[IMAGE] " + "http://ai1.space/1007546?triples=" + urlencode(lines(elements)); } if (swic_trim(s, "!answer ", m)) { time2 { S a = ai_specReturn_answerToExternalQuestion(10.0, m.rest()); } ret "[" + lastTiming() + " ms] " + (a != null ? a : "I don't know"); } if (swic_trim(s, "!web ", m)) { S id = $1; Web web = indexedWebWithGlobalID(id); if (web == null) ret "Not found"; ret "[IMAGE] " + smartBotURL() + "/diagram?id=" + id; } if (swic_trim(s, "!parse ", m)) ret ai_renderTriple(ai_tripelize(m.rest())); if (eqic(s, "!worst-case")) ret sfu(getOptMC('ai_hasTriple_vary_worstCase)); if (eqic(s, "!uptime")) ret n(secondsSinceSysTime(started), "second"); if (eqic(s, "!typical-set")) ret sfu(diagramServer_typicalSet()); if (eqic(s, "!num-unverified")) ret lstr(ai_unverifiedWebs()); if (eqic(s, "!num-true")) ret lstr(ai_trueWebs()); if (eqic(s, "!version")) ret autoRestart_localMD5(); if (swic_trim(s, "!blob ", m)) { S a = postNodeFromInput(m.rest(), s); selectWord(m.rest()); ret a; } if (swic_trim(s, "!store ", m)) ret postTripleFromInput(ai_tripelize(m.rest()), s); if (swic_trim(s, "!store-triple ", m)) ret postTripleFromInput(ai_parseArrowTriple(m.rest()), s); if (swic(s, "!nodes ", m)) { if (dropSuffixTrim("...", m.rest(), m)) ret lstr(indexedNodesStartingWith(m.rest())); ret lstr(indexedNodes(m.rest())); } if (eqic(s, "!webs")) ret lstr(allIndexedWebs()); if (swic(s, "!webs ", m)) ret joinWithSpace(collect(indexedWebs($1), 'globalID)); if (swic(s, "!splitAtBaseFormVerb ", m)) ret sfu(splitAtBaseFormVerb($1)); if (swic(s, "!maxRunlengthOfRepeatingChars ", m)) ret str(maxRunlengthOfRepeatingChars($1)); if (swic(s, "!collapseWord ", m)) ret collapseWord($1); if (swic(s, "!gac ", m)) ret or2(first(scoredSearch(m.get(0), keys(gac36k()))), "-"); if (eqic(s, "!vms")) ret computerVMs_text(); if (eqic(s, "!id")) ret aGlobalID(); if (swic_trim(s, "!count-triple ", m)) { T3 t = ai_parseArrowTriple(m.rest()); print("Searching: " + sfu(t)); Pair p = ai_countBoth_dollarX(t); ret eq(p.a, p.b) ? str(p.a) : p.a + " (+" + (p.b-p.a) + " unverified)"; } pcall { try answer ai_sfCommands(s); } if (swic_trim(s, "!macmillan ", m)) try { Pair> p = macmillanDefinitions3(m.rest()); ret toUpper(p.a) + "\n" + lines(prependAll("-", p.b)); } catch e { printShortException(e); ret "Macmillan is quiet today."; } try answer ai_answerFromCache(s); S _s = s; s = ai_dropLeadingAdditions(s); if (neq(_s, s)) try answer ai_answerFromCache(s); if "cache size" ret n2(indexedTerms(), "different term") //+ ", " + n(web_countNodes(allWebs_cached()), "node") //+ ", " + n(allWebs_cached(), "web"); + ", " + nWeb(tripleIndex().numWebs()); if "give me subtypes of ..." ret ai_renderList(ai_subtypesOf(m.rest())); if "give me a third person verb" ret random(thirdPersonVerbs()); if (learnedFlexMatch("give me some *", s, m)) { S query = singular($1); ret ai_renderNodesList(concatLists( ai_index_search_dollarX("$X", "is a", query), ai_index_search_dollarX("$X", "is", a(query)))); } if "authed?" ret authed() ? "You are authed." : "You are not authed."; if "what is the singular of *" ret or2(getSingularFromWordHippo($1), singular($1)); if (learnedFlexMatch("what is the relation between * and *", s, m)) { L l = ai_getRelation($1, $2); //ret ai_renderList(l); if (nempty(l)) ret $1 + " " + first(l) + " " + $2; } if (containsAll(asCISet(javaTokC(s)), "list", "long")) pcall { try answer callAnswerMethod(hotwireOnce(#1013113), s); } if "what unix day is it" ret str(unixDay()); if "show me the ..." ret "What " + $1 + "?"; if (learnedFlexMatch("What do * have?", s, m)) ret ai_renderNodesList(ai_index_search_dollarX($1, "have", "$X")); if (learnedFlexMatch("What does * do?", s, m)) ret ai_renderList(map(f web_nodePairToText, webs_search_dollarXY(webFromTriples($1, "$X", "$Y"), indexedWebs($1)))); if (learnedFlexMatch_multi(s, m, "What is *", "Who is *", "Was ist *", "Wer ist *")) try answer ai_renderList(ai_whatIs($1), ""); S sf = web_text(first(ai_search_dollarX_verified("$X", "implements", quote(s)))); if (startsWith(sf, "sf ", m)) ret str(makeAndCall($1)); if (learnedFlexMatch("* how many visitors *", s) || match("how many visitors", s)) ret str(ai1_cookiesToday_int()); // Once more with generated webs (replacing $ vars) if (learnedFlexMatch("What is *", s, m)) { L extendedWebs = indexedWebsAfterVariableSubstitution($1); print("Have " + n(extendedWebs, "extended web") + " for " + quote($1)); try answer ai_renderNodesList(webs_search_dollarX(webFromTriples($1, "is", "$X"), extendedWebs), null); } try answer ai_tryIfAndInput(s); try answer ai_autoApplyRules(s); if (!ai_isQuestion_1(s) && learnedFlexMatch_multi(s, m, "* is *", "* ist *")) try answer postTripleFromInput(triple(m.get(0), "is", m.get(1)), s); try answer ai_standardAnswer(s); try answer ai_standardAnswer_dollarVars(s); // TODO: might get slow eventually try answer ai_standardAnswerEval(s); pcall { final T3 t = ai_tripelize(s); if (t != null) { try answer evalWithTimeoutOrNull(20.0, func -> S { for (O f : tripleAnswerFunctions) try answer (S) pcallF(f, t); null; }); try answer ai_standardAnswerSF_triple_dollarVars(t); } } // 10 second timeout S a = ai_specReturn_answerToExternalQuestion(10.0, s); if (nempty(a) && !swicOneOf(a, "[", "What is ")) ret a; null; } svoid loadBots(S... botIDs) { for (S id : botIDs) pcall { thoughtBots.add(runSubBot(id)); } } static O html(S uri, SS params) { profilePoint('html_1); S ip = clientIP(); bool bad = eq(uri, "/simulate-bad-client"); Pair pair = simpleSpamClientDetect2(ip, uri); if (pair.b) { if (eq(ip, pcall_myFirewallIP())) print("Not blocking myself."); else { print("Blocking IP " + ip); blockedIPs.add(ip); } } if (blockedIPs.contains(ip)) { bad = true; post_verified(print(t3("an HTTP request from a blocked IP", "came in at", dateWithTimeGMT()))); } if (bad) { NanoHTTPD.IHTTPSession httpSession = NanoHTTPD.currentSession!; if (httpSession == null) { print("No HTML session?"); sleepSeconds(spammerSleep); ret "go away"; } httpSession.badClient(true); null; } print(gmtWithSeconds() + ": Serving HTTP " + quote(uri) + " to " + ip + " (anti-spam count: " + pair.a + "/" + simpleSpamClientDetect2_spamMax + ")"); profilePoint('html_2); S requestID = aGlobalID(); S symbol = "HTTP request " + requestID; if (http_isBot()) symbol = "Bot " + symbol; //S domain = serveHttp_domainName(); { temp temp_ai_startBuffering(); post_verified(symbol, "came in at", dateWithTimeGMT()); post_verified(symbol, "was for path", uri); post_verified(symbol, "had user agent", serveHttp_userAgent()); post_verified(symbol, "came from IP", ip); } profilePoint('html_3); //set serveHttp_cookieHandling_verbose; S cookie = serveHttp_cookieHandling(); S loginUrl = "/"; S pw = params.get("pw"); Pair p = standaloneWebAuth(loginUrl, cookie, pw); print("ip=" + ip + ", cookie=" + l(cookie) + ", authed: " + p.b); if (nempty(p.a)) ret p.a; if (eq(uri, "/login")) ret standaloneWebAuth_showForm(loginUrl, cookie); httpAuthed.set(p.b); try { long time = sysNow(); O html = html_2(uri, params); done2(time, "Making HTML " + uri); ret html; } finally { httpAuthed.set(false); } } static O html_2(S s, SS params) { new Matches m; S domain = serveHttp_domainName(); if (ewic(domain, ".supersrv.de")) ret "Super server!"; if (eqic(s, "/favicon.ico")) ret serveFile(loadLibrary(#1013028), "image/x-icon"); if (nempty(params.get("_pretendAuthed")) || authed()) html_pretendAuthed.set(true); if (eqic(s, "/number-of-threads")) ret str(cachedNumberOfThreads!); if (eqic(s, "/realurl")) ret hrefresh(smartBotDirectURL()); if (swic(domain, "pixelboys.") || eqic(domain, "www.botcompany.de")) ret hrefresh("https://www.botcompany.de:8443/1016323/raw"); S input = params.get("input"); if (nempty(input)) { if (webAuthed()) ret htmlencode(callAnswerMethodVerbose(input)); else ret "Can't send input (not authed)"; } if (swic(s, "/matrix/", m)) { s = "/dyn/" + psI(#1013031); if (nempty(m.rest())) params.put("topic", urldecode(m.rest())); } if (eqicOptSlash(s, "/rules")) s = "/dyn/1013529/ai_rulesTable"; if (eqicOptSlash(s, "/livecount")) s = "/dyn/1013377"; if (eqic(s, "/dyn/fresh")) { if (!webAuthed()) ret "No"; dynClear(); ret "OK"; } if (swic(s, "/dyn/", m)) { if (loading()) ret "LOADING, please try again"; S u = m.rest(); int i = smartIndexOf(u, '/'); S id = fsI(takeFirst(u, i)); if (!has_verified(id, "is", "a safe web module")) ret "Unsafe"; O mod = hotwireCached(id); ret callHtmlMethod2(mod, or2(substring(u, i), "/"), params); } if (swic(s, "/sf/", m)) ret htmlencode2(struct(callSafeSF(m.rest()))); if "random-web" s = str(randomIndexedTriple().globalID()); try { if "threads" { time2 { S text = renderRunnableThreadsWithStackTraces(); } ret hpre(text + "\n\n" + lastTiming() + " ms"); } if (eqic(s, "/livecheck")) ret "Smart Bot"; if (eqic(s, "/load")) ret formatDouble(systemLoad(), 2); if (eqic(s, "/1-sec-profile")) ret html_profile(1); if (eqic(s, "/10-sec-profile")) ret html_profile(10); if (eqic(s, "/deadlocks")) ret htmlencode(solveDeadlocks()); if (eqic(s, "/source-stats")) ret h1_title("Source Stats") + multiSetToUL(ai_sourceStats()); if "thoughts" ret serveHTML(html_thoughts()); if "diagram" { S id = params.get("id"); Web web = indexedWebWithGlobalID(id); ret serveJPEG(webToCAL(web).makeImage(600, 400)); } if "log" ret serveText_direct(printLog()); if "learners" ret serveText_direct(renderConcepts(list(MatchLearner))); if "unreached" ret h3_title("Unreached") + ul(map html_encyclopediaTopic(ai_gc_unreachedWords())); // Serve Web With Global ID s = dropPrefix("/", s); if (possibleGlobalID(s)) { L webs = ai_getWebs(s); if (nempty(webs)) { for (Web web : webs) ai_speculateOnWeb(web); Web web = first(webs); ret h2_title("Web " + s + (ai_isInvalidWeb(web) ? " [INVALID]" : "")) + loadjquery() + pre(htmlencode(renderWeb_multiLine(web))) + p(himg(ai_webImage_link(s), title := "Web " + s)) + (l(webs) > 1 ? p("Warning: Multiple webs") : "") + ai_html_wordThoughts("Web " + web.globalID); } /*if (theoryOn && theoryModule == null) ret serveHTML("Loading theory module"); Map map = (Map) getOpt(theoryModule, 'theoryForLineMap); if (map.containsKey(toLower(s))) ret serveHTML("A line in the chat.");*/ ret serveHTML("Unknown: " + s); } if (swic(s, "json/", m)) { s = m.rest(); if (swic(s, "relations/", m)) { new L out; Map map = litorderedmap(); if (loading()) map.put("loading", true); int max = 1000; for (WebRelation r : indexedRelations(m.rest())) if (l(out) >= max) { map.put("more", true); break; } else { L l = tripleToList(web_relationToTriple(r)); l.add(r.web.globalID()); l.add(r.web.source); if (r.web.verified()) l.add("v"); out.add(l); } map.put("data", out); ret serveText(jsonEncode(map)); } ret "unknown"; } if (swic(s, "e/", m)) { // serve encyclopedia topic S topic = urldecode(m.rest()); ret html_topic(topic, eq("1", params.get("random"))); } if (swic(s, "autocomplete/", m)) { int max = min(100, parseInt(or2(params.get("n"), "10"))); L completed = ai_autoComplete(urldecode(m.rest()), max, autoComplete_timeOut); new L out; for (S c : completed) { new HashMap map; if (startsWith(s, c)) map.put(follow := substring(c, l(s))); else map.put(whole := c); out.add(map); } ret serveText(jsonEncode_breakAtLevel1(out)); } if (eqic(s, "alphabetical")) ret html_alphabetical(params); if (eqic(s, "latest-webs")) { int n = toInt(params.get('n)); if (n == 0) n = 100; ret html_latestWebs(min(1000, max(n, 10))); } if (eqic(s, "the-big-number")) ret formatWithThousandsSeparator(ai_allWebsCount()); if (eqic(s, "random")) ret hrefresh(smartBot_encyclopediaLink(ai_randomString()) + "?random=1"); if (eqic(s, "classes")) ret html_classes(); if (eqic(s, "standard-relations")) ret html_standardRelations(); if (eqic(s, "active")) ret html_active(); if (eqic(s, "all-web-ids")) { L l = allToString(allWebIDs_cloned()); ret serveText( l(l) + " ids follow.\n" + lines(l) + l(l) + " ids written."); } if (eqic(s, "internal-files")) ret serveText(lines(map(func(File f) -> S { quote(f.getName()) + " " + fileSize(f) + " " + fileModificationTime(f) }, listFiles(programDir())))); if (swic(s, "internal-files/", m)) { S name = urldecode(m.rest()); if (!isProperFileName(name)) ret serve404("No"); File f = getProgramFile(name); ret f.isFile() ? serveFile(f) : serve404(); } if (eqic(s, "submit-triple")) { S a = params.get("a"), b = params.get("b"), c = params.get("c"); if (empty(a) || empty(b) || empty(c)) ret "Empty field(s)"; ret htmlencode(postTripleFromInput(t3(a, b, c), null)); } if (swic_trim(s, "texts/", m)) { ret serveText((loading() ? "[LOADING]\n" : "\n") + lines(map quoteBorderless2(ai_texts(ai_parseSlashTriple(urldecode(m.rest())))))); } T3 texts_big_t = null; if (swic_trim(s, "texts-big/", m)) texts_big_t = ai_parseSlashTriple(urldecode(m.rest())); if (eqic(s, "texts-big")) { texts_big_t = t3( params.get("a"), params.get("b"), params.get("c")); } if (swic_trim(s, "rev/", m)) texts_big_t = triple("$X", "is", urldecode(m.rest())); if (texts_big_t != null) { final bool strip = eq("1", params.get('strip)); fS style = or2(params.get("style"), "font-size: 20px"); T3 t = texts_big_t; //L texts = ai_texts(t = ai_parseSlashTriple(urldecode(m.rest()))); L> refs = ai_tripleRefs(t); ret htitle_htmlencode(ai_renderTriple(t)) + (loading() ? "[LOADING]\n" : "\n") + //joinMap(texts, func(S s) -> S { pre(htmlencode_noQuote(s), +style, title := ) }); joinMap(refs, func(TripleRef r) -> S { TripleWeb w = cast r.triple; S title = "Web " + w.globalID(); S source = w.source(); if (nempty(source)) title += ", source: " + source; S text = r!; if (strip) text = unquoteMultiline(text); ret pre(htmlencode_noQuote(text), +style, +title); }); } // Search Results S q = params.get("q"); if (nempty(q)) ret html_searchResults(q, params.get("mode")); if (eqic(s, "popular")) ret html_popular(params); // Default for unknown URL S topic = nempty(s) ? s : params.get("topic"); if (nempty(topic)) ret html_topic(urldecode(topic), false); // Home page ret html_home(); } finally { html_pretendAuthed.set(null); } } static NanoHTTPD.Response html_topic(S topic, bool random) { long time; bool timeout = false; print("User agent: " + serveHttp_userAgent()); if (http_isBot()) { time = -1; print("Bot request"); } else { time2 { timeout = ai_speculateDeepWithActiveAndTimeout(topic, speculationTimeoutForHttp); } time = lastTiming(); } L words = ll(topic); //if (ai_getWeb(topic) != null) words.add("Web " + topic); ret serveHTMLNoCache( htitle(topic + " | Smart Bot") + h1(html_smallSmartBotLogo() + " " + htmlencode_noQuote("Topic: " + topic)) + loadjquery() + (random ? ahref("/random", "Another random term") + " | " : "") + "Search: " + html_searchField(topic) + "

" + ai_html_wordThoughts(words) + ai_html_enterTripleForm(first(words)) + p( (time < 0 ? "" : "Speculated for " + time + " ms" + (timeout ? " (TIMED OUT)" : "") + " ") + ahref(smartBot_directTopicLink(topic), "[Direct link]")) ); } sS html_home() { temp tempProfileBlock('html_home); ret tag('link, "", rel := "search", type := "application/opensearchdescription+xml", title := "Smart Bot", href := "http://tinybrain.de:8080/getraw.php?id=1013357") + hcenter3( hsnippetimg(#1101146, width := 64, height := 64) //#1011942) + h1_title("Smart Bot") + p("by " + ahref("http://BotCompany.de/", "BotCompany.de") + (webAuthed() ? " Authed." : "")) + ahref("/popular", "Most occurring") + " | " + ahref("/alphabetical", "Alphabetical") + " | " + ahref("/latest-webs", "Latest") + " | " + ahref("/random", "Random term") + " | " + html_searchField() + "

" + h3("Triple Search") + form( htextfield("a") + " -> " + htextfield("b") + " -> " + htextfield("c", "$X") + " " + hsubmit("Search triples"), action := "texts-big")); } sS html_popular(SS params) { time "Popularity search" { //L keys = multiMapKeysByPopularity(ai_mainIndex()); L keys = multiSetByPopularity(tripleIndex().wordIndex); } int step = 100, n = toInt(params.get("n")); int count = l(keys); L l = subList(keys, n, n+step); ret hcenter3(hsnippetimg(#1011942)) + h1_title("Smart Bot's Encyclopedia (" + n_fancy(keys, "entry") + ")") + "Most occurring | " + ahref("/alphabetical", "Alphabetical") + " | " + ahref("/latest-webs", "Latest") + " | " + html_searchField() + "

" + pageNav2("/", count, n, step, 'n) + ul(map(func(S s) -> S { ahref(smartBot_encyclopediaLink(s), htmlencode(or2(s, "-"))) + " [" + ai_approximateIndexedNodesCount(s) + "]" }, l)); } sS html_searchField() { ret html_searchField(""); } sS html_searchField(S q) { ret html_searchField(q, ""); } sS html_searchField(S q, S mode) { ret hform( htextinput("q", value := q, autofocus := 'autofocus) + " Mode: " + hselect_list(ll("starts with", "multiple words", "ends with", "contains"), mode, name := "mode") + " " + hsubmit("Search"), style := "display: inline", action := smartBotOfficialURL()); } static O html_profile(int seconds) { if (poorMansProfiling_isOn()) ret "Already on"; poorMansProfiling(100); sleepSeconds(seconds); ret serveText(poorMansProfiling_stopAndRenderResults()); } static S html_searchResults(S q, S mode) { int max = 1000; time2 { L l; if (eqic(mode, "multiple words")) l = indexedTerms_scoredSearch(q, max+1); else if (eqic(mode, "ends with")) l = asList(termsEndingWith(q)); else if (eqic(mode, "contains")) l = asList(indexedTermsContaining(q)); else l = asList(fullIndexedTermsStartingWith(q)); if (possibleGlobalID(q) && !eq(first(l), q)) l.add(0, q); } long time = lastTiming(); bool more = l(l) > max; l = takeFirst(max, l); sortInPlaceAlternativeCI(l); S directHit = ""; S trimmed = trim(q); S direct = ai_findIndexedTerm(trimmed); if (direct != null) directHit = p(unicode_blackRightArrow() + " " + b(html_encyclopediaTopic(direct))); else directHit = p("No direct hit. Create entry: " + b(html_encyclopediaTopic(trimmed))); ret h1_title("Smart Bot Search: " + htmlencode(q) + " (" + n_fancy(l, "result") + (loading() ? ", LOADING" : "") + ")") + "Search again: " + html_searchField(q, mode) + "

" + directHit + p(l(l) > max ? max + "+ search results" : n(l, "search result") + " [" + time + " ms]") + ul(map html_encyclopediaTopic(l)); } static S html_alphabetical(SS params) { int step = 100, n = toInt(params.get("n")); Collection all = indexedTerms(); int count = l(all); L l = subListOfCollection(all, n, n+step); ret h1_title("Smart Bot's Encyclopedia (Alphabetical) :)") + ahref("/popular", "Most occurring") + " | " + "Alphabetical" + " | " + ahref("/latest-webs", "Latest") + " | " + html_searchField() + "

" + pageNav2("/alphabetical", count, n, step, 'n) + ul(map(func(S s) -> S { ahref(smartBot_encyclopediaLink(s), htmlencode(or2(s, "-"))) }, l)); } sS html_classes() { L l = sortedIC(ai_texts_verified("$X", "is", "a standard class")); ret h1_title("Smart Bot Classes") + ul(map(func(S s) -> S { ahref(smartBot_encyclopediaLink(s), htmlencode(or2(s, "-"))) + " [" + ai_approximateIndexedNodesCount(s) + "]" }, l)); } sS html_standardRelations() { L l = sortedIC(unquoteAll(ai_texts_verified("$X", "is", "a standard relation"))); ret h1_title("Smart Bot Standard Relations") + ul(map(func(S s) -> S { ahref(smartBot_encyclopediaLink(s), htmlencode(or2(s, "-"))) + " [" + ai_approximateIndexedNodesCount(s) + "]" }, l)); } sS html_active() { L l = sortedIC(unquoteAll(ai_texts_verified("$X", "is", "an active topic"))); L lRules = sortedIC(unquoteAll(ai_texts_verified("$X", "is", "an active rule"))); ret h1_title("Smart Bot's Active Topics") + ul(map(func(S s) -> S { ahref(smartBot_encyclopediaLink(s), htmlencode(or2(s, "-"))) + " [" + ai_approximateIndexedNodesCount(s) + "]" }, l)) + h2("Active Rules") + ul(map(func(S s) -> S { ahref(smartBot_encyclopediaLink(s), htmlencode(or2(s, "-"))) + " [" + ai_approximateIndexedNodesCount(s) + "]" }, lRules)) ; } static S html_latestWebs(int n) { L l = takeLast(n, cloneList(latestWebs)); S bn = formatWithThousands(ai_theBigNumber()); ret htitle("Latest Webs (" + bn + ") | Smart Bot") + h1(html_smallSmartBotLogo() + " - Latest Webs from " + bn) + ul(mapReversed(func(GlobalID id) -> S { TripleWeb w = ai_getTriple(id); if (w == null) ret "[not found] Web " + id; ret ai_html_linkedWeb(id) + htmlencode( " [" + renderGMTDate(w.created()) + "] " + w.source() + ": ") + ai_html_renderTriple(w); }, l)); } sS html_thoughts() { S html = /*hrefresh(5) +*/ hGoogleFontOswald() + loadjquery(); S status = ""; /*Pair p = evalWithTimeout_numberOfCalculations(); if (p.a > 0) status = p(n(p.a, "calculation") + (p.b == 0 ? "" : ", " + p.b + " timed out"));*/ Pair> p = evalWithTimeout_calculations(); if (nempty(p.a) || nempty(p.b)) status = ul( nempty(p.a) ? "In time calculations" + ul_htmlEncode(map threadName(p.a)) : null, nempty(p.b) ? "Timed out calculations" + ul_htmlEncode(map threadName(p.b)) : null ); ai_html_wordThoughts_nodesMax.set(100); try { ret html + wordThoughts() + status; } finally { ai_html_wordThoughts_nodesMax.set(null); } /* if (theoryModule == null) ret html + "Loading theory module..."; S thoughts = (S) call(theoryModule, 'html_thoughts); if (nempty(selectedWord)) ret html + tag('table, tr(td_top(thoughts, style := "background: #CCC") + td_top(wordThoughts(), style := "padding-left: 20px"))); ret html + thoughts; */ } sS wordThoughts() { try { if (empty(selectedWord)) ret ""; S html = ai_html_wordThoughts(selectedWord); html = html_addLinkToSpan(html, 'title, encyclopediaLink(selectedWord)); ret html_addTargetBlank(html); } catch e { printStackTrace(e); ret "Erreur"; } } sS postTripleFromInput(T3 triple, S input) { if (triple == null) null; if (swic(input, "OK, stored")) null; if (!ai_tripleAllowedToPost(triple)) null; new Matches m; if (!(swic(triple.a, "Web ", m) && possibleGlobalID(m.rest()))) selectWord(triple.a); if (ai_cache_hasTriple(triple)) ret "I know"; else { Web web = webFromTriple(triple); web.unverified = !authed(); postSoftwareMadeWeb(web, +input); if (eqic(triple.b, "is") && eqic(triple.c, "invalid")) ai_invalidateWeb(triple.a); if (eqic(triple.b, "is") && eqic(triple.c, "wrong")) ai_wrongWeb(triple.a); ai_postTriple("Web " + web.globalID, "stored because of", chatLineSymbol()); ret "OK, stored" + (web.unverified ? " (unverified)" : "") + ": " + ai_renderTriple(triple); } } sS postNodeFromInput(S node, S input) { if (!ai_nodeNameAllowedToPost(node)) null; if (hasIndexedNode(node)) ret "I know"; else { Web web = oneNodeWeb(node); web.unverified = !authed(); postSoftwareMadeWeb(web, +input); ret "OK, stored" + (web.unverified ? " (unverified)" : "") + ": " + node; } } // might want to get rid of this; do it in speculation svoid processSelectedWord { fS word = selectedWord; if (empty(word)) ret; ai_withMaker('processSelectedWord, r { //ai_speculate(word); pcall { ai_greetingRule1(word); //ai_greetingRule2(word); if (ai_hasTriple(word, "should be", "answered by me") && ai_postTriple(word, "was", "answered by me") != null) { S text = firstQuoted(web_texts(ai_search_dollarX(word, "is", "$X"))); postToStefansChat((nempty(text) ? text + " << " : "") + "Greetings back to you!"); } } }); } svoid makeChatLinesUnrecent { new Matches m; for (WebNode node : ai_search_dollarX("$X", "is", "recent")) if (web_match("Chat line *", node, m)) pcall { int n = parseInt($1); if (n <= stefansChat_n_value-100) { //print("Unrecenting " + n); ai_invalidateWeb(node.web); } } else if (web_match("Smart Bot's Chat line *", node, m)) pcall { int n = parseInt($1); if (n <= smartBotsChat_n_value-100) { //print("Unrecenting " + n); ai_invalidateWeb(node.web); } } } svoid onHistoryRead { lock dbLock(); print("History read."); processSelectedWord(); pcall { makeChatLinesUnrecent(); } } sS selectWord(S word) { if (nempty(word)) { selectedWord = word; save('selectedWord); processSelectedWord(); } ret word; } sS transpileMyself(S mode) { postToStefansChat("Transpiling..."); Pair p = transpileOnServer(programID(), 'medium); ret p.a ? "OK" : "Not OK"; } svoid speculatorLoop { repeat with sleep 5 { ai_speculateDeepAndActive(selectedWord); for (L words : cloneValues(lastUserLines)) for (S word : words) ai_speculateDeepAndActive(word); S s; while ((s = first_sync(speculationQueue)) != null) { speculationQueue.remove(s); long time = sysNow(); ai_speculateWithActive(s); done2_always(time, "Speculation Queue > " + s); } } } public static ISpec ispec = ai_defaultISpec(); // share ISpec interface with sub-modules static JavaXClassLoader hotwire_makeClassLoader(L files) { ClassLoader cl = myClassLoader(); // Avoid class loader chaining, always reference base class loader if (cloned && cloningSince != 0) { ClassLoader parent = cast getOpt(cl, 'virtualParent); print("Cloned class loader. " + parent); if (parent != null) cl = parent; } ret new JavaXClassLoaderWithParent2(null, files, cl, parseClassesToShareList(classesToShare)); } static Lock aiLock() { ret aiLock; } static bool webAuthed() { ret isTrue(httpAuthed!); } svoid handleStefansChat { stefansChat_n_onChange(r { clearTransientWebs(); addTransientWeb(webFromTriple("Latest chat line", "is", "Chat line " + stefansChat_n_value)); }); stefansChat_onLine_lookback = 1; // 2 does double restarts etc. stefansChat_onLine_onHistoryRead.set(f onHistoryRead); stefansChat_onLine_safe(voidfunc(fS text) ctex { pcall { int nr = toInt(mapGet(stefansChat_onLine_fullParams!, "nr")); print("> [" + nr + "] " + text); if (nr != 0) { S x = "Chat line " + nr; stefansChat_onLine_fullParams->put('chatName, "Stefan's Chat"); stefansChat_onLine_fullParams->put("Chat line symbol", x); post(x, "is", "a chat line"); post(x, "is", "recent"); postChatLineInfo(x, text); stefansChat_n_notify(nr); ai_speculateWithActiveAndTimeout(x, speculationTimeoutForNewChatLine); if (!byBot()) lastUserLines.put("Stefan's Chat", ll(text, quote(text), x)); } } temp tempSetThreadLocal(answering, true); try { S a = actualAnswer(text); a = shortenAnswerForChatAndUploadFull(text, a); postToStefansChat(a); callAll(getAndClearThreadLocal(afterAnswering)); } on fail { clearThreadLocal(afterAnswering); } }); } svoid handleSmartBotsChat { smartBotsChat_onLine_lookback = 1; smartBotsChat_onLine_onHistoryRead.set(f onHistoryRead); smartBotsChat_onLine_safe(voidfunc(fS text) ctex { pcall { int nr = toInt(mapGet(stefansChat_onLine_fullParams!, "nr")); print("> [" + nr + "] " + text); if (nr != 0) { S x = "Smart Bot's Chat line " + nr; stefansChat_onLine_fullParams->put('chatName, "Smart Bot's Chat"); stefansChat_onLine_fullParams->put("Chat line symbol", x); post(x, "is", "a Smart Bot's chat line"); post(x, "is", "recent"); postChatLineInfo(x, text); smartBotsChat_n_notify(nr); ai_speculateWithActiveAndTimeout(x, speculationTimeoutForNewChatLine); if (!byBot()) lastUserLines.put("Smart Bot's Chat", ll(text, quote(text), x)); } } temp tempSetThreadLocal(answering, true); try { S a = actualAnswer(text); a = shortenAnswerForChatAndUploadFull(text, a); postToSmartBotsChat(a); callAll(getAndClearThreadLocal(afterAnswering)); } on fail { clearThreadLocal(afterAnswering); } }); } sS handleArchiveMsg(S msgSymbol) { S text = firstQuoted(ai_texts(msgSymbol, "is", "$X")); if (text == null) ret "No text found for " + msgSymbol; text = unquote(text); SS oldParams = setThreadLocal(stefansChat_onLine_fullParams, lithashmap("Chat line symbol", msgSymbol)); try { ret actualAnswer(text); } finally { stefansChat_onLine_fullParams.set(oldParams); } } sS shortenAnswerForChatAndUploadFull(S text, S a) { a = shorten(a, ultimateAnswerLimit); if (l(a) > stefansChat_messageLimit()) { S title = "Smart Bot's answer to: " + text; S id = ntUpload("smart-bot-for-user", title, unSlackSnippet(a)); a = snippetURL(id) + " | " + a; } ret a; } static bool ai_enabled() { true; } sbool http_isBot() { ret userAgentIsBot(serveHttp_userAgent()); } // UNUSED svoid softRestart_level1 { startedLoading(); cloningSince = sysNow(); classesToShare = "T3, TripleWeb, Symbol, GlobalID, MultiSet"; Class c = hotwire(programID()); set(c, ai_fillTripleIndex_useThese := asList(ai_allTriples())); softRestart_phase2(c); } svoid softRestart_phase2(final Class c) { print("Cloning phase 2"); set(c, cloned := true); set(c, clonedSince := cloningSince); set(c, postStartUpMessageToChat := chatName()); addAll((L) getOpt(c, 'latestWebs), latestWebs); removeFirstInjection(); afterAnswering(r { // Create raw thread without any registering/pinging etc. //new Thread("Soft-Restarting") { // public void run() ctex { //Thread.sleep(2000); print("Cloning, new thread"); // copy JavaX translator over copyFields(mc(), c, 'transpileRaw_trans); transpileRaw_trans = null; cleanUp(mc()); // This should end all the threads & the HTTP server System.out.println("Cloning: Cleaned up"); clearAllVariables(); System.out.println("Cloning: Running main"); runMain(c); System.out.println("Cloning: Done!"); // } //}.start(); }); } // also reuse the index svoid softRestart_level2 { startedLoading(); cloningSince = sysNow(); classesToShare = smartBot_sharedClassesForRestart(); Class c = hotwire(programID()); //set(c, ai_fillTripleIndex_useThese := asList(ai_allTriples())); set(c, ai_fillTripleIndex_useTripleIndex := tripleIndex()); softRestart_phase2(c); } svoid afterAnswering(O runnable) { if (isTrue(answering!)) afterAnswering.set(addToOrCreateList(afterAnswering!, runnable)); else callF(runnable); } svoid addToLatestWebs(Web web) { latestWebs.add(web.globalIDObj()); } svoid dynClear { veryQuickJava_refresh(); hotwireCached_clear(); clearAllCaches(); } svoid postChatLineInfo(S x, S text) { post(x, "has text", quote(text)); post(x, "was", byBot() ? "sent by bot" : "sent by human"); post(x, "was sent by IP", (S) lookupPossiblyIgnoreCase(stefansChat_onLine_fullParams!, "ip")); } static WebSocket makeWebSocket(NanoHTTPD.IHTTPSession handshake) { print("New WebSocket."); ret new WebSocket(handshake) { AutoCloseable streamer; @Override protected void onMessage(WebSocketFrame messageFrame) { S s = messageFrame.getTextPayload(); print("WebSocket msg: " + s); if (streamer == null && eq(s, "stream-big-number")) { streamer = timerAsAutocloseable(doEveryStartingNow(100, new Runnable { S lastS = null; public void run() ctex { S s = formatWithThousands(ai_theBigNumber()); if (neq(s, lastS)) { lastS = s; //print("Sending: " + s); send(s); } } })); println("Streaming!"); } } protected void onClose(WebSocketFrame.CloseCode code, String reason, boolean initiatedByRemote) { print("WebSocket close"); _close(streamer); streamer = null; } }; }; sS diskSpaceInfo() { ret toM(fileSize(programFile("triples.gz"))) + " MB (triples.gz) + " + toM(fileSize(programFile("webs-made.txt"))) + " MB (webs-made.txt). " + toM(userDir().getUsableSpace()) + " MB free disk space"; } please include function ai_possibleRuleNames.