Warning: session_start(): open(/var/lib/php/sessions/sess_9ht4rjem6p4k3git57v3fpg2fp, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning: session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
!7
concept Cmd {
S patterns; // for mmo_parsePattern
S exampleInputs; // line-separated
S cmd; // a star pattern recognized by the backend
S questionsForArguments; // line-separated
int index;
transient MMOPattern parsedPattern;
void change { parsedPattern = null; super.change(); }
MMOPattern parsedPattern() {
if (parsedPattern == null) parsedPattern = mmo_parsePattern(patterns);
ret parsedPattern;
}
sS _fieldOrder = "exampleInputs patterns cmd index";
}
cmodule ChatBotFrontend > DynCRUD {
switchable S backendModuleLibID = "#1027443/Scenarios";
O currentAttractor;
class HandleArgument implements IF1 {
S cmd;
LS argQuestions;
new LS arguments;
*() {}
*(S *cmd, LS *argQuestions) {}
// process an argument
public S get(S arg) {
arguments.add(arg);
if (l(arguments) >= countAsteriskTokens(cmd))
ret sendToBackend(format_quoteAll(cmd, asObjectArray(arguments)));
else
ret handleQuestionWithArguments(this);
}
S currentQuestion() {
ret or2(_get(argQuestions, l(arguments)), "Need argument");
}
}
runnable class Cancel { setField(currentAttractor := null); }
class UndoHandler implements IF1 {
public S get(Bool yes) {
if (!yes) ret "OK"; // user said no
ret (S) sendToBackend("undo");
}
}
start {
dm_watchFieldAndNow backendModuleLibID(r {
dm_setModuleName("Frontend for " + dm_moduleName(backend()))
});
crud.multiLineFields = litset("exampleInputs", "questionsForArguments");
crud.sorter = func(Cl l) -> L { sortByField index(l) };
crud.formFixer = 48;
}
S handleCommand(Cmd cmd) {
if (cmd == null) null;
print("handleCommand " + cmd.cmd);
if (match("undo after confirm", cmd.cmd)) {
O undo = dm_call(backend(), 'lastUndo);
if (undo == null) ret "Nothing to undo";
new WaitForAnswer_YesNo attractor;
attractor.question = "Undo " + undo + "?";
setField(currentAttractor := attractor);
print("Set attractor to: " + attractor);
attractor.processAnswer = new UndoHandler;
attractor.cancelSilently = new Cancel;
ret attractor.question;
}
if (hasAsteriskTokens(cmd.cmd))
ret handleQuestionWithArguments(
new HandleArgument(cmd.cmd, tlft(cmd.questionsForArguments)));
else
ret sendToBackend(cmd.cmd);
}
S handleQuestionWithArguments(HandleArgument handler) {
new WaitForName attractor;
attractor.question = handler.currentQuestion();
setField(currentAttractor := attractor);
print("Set attractor to: " + attractor);
attractor.processName = handler;
attractor.cancelSilently = new Cancel;
ret attractor.question;
}
S sendToBackend(S cmd) {
ret (S) dm_call(backend(), 'answer, cmd);
}
S backend() {
ret dm_require(backendModuleLibID);
}
afterVisualize {
addComponents(crud.buttons,
jbutton("Talk to me", rThread talkToMe),
jPopDownButton_noText("Consistency check", rThread consistencyCheck));
}
void talkToMe enter { dm_showConversationPopupForModule(); }
void consistencyCheck enter {
reindex();
L cmds = list(Cmd);
L errors = mmo_consistencyCheck(
map(cmds, cmd -> pair(cmd.exampleInputs, cmd.patterns)));
if (empty(errors)) infoBox("No consistency problems");
else
dm_showText(n2(errors, "consistency problem"), lines(errors));
}
void reindex {
int index = 1;
for (Cmd cmd : conceptsSortedByField Cmd('index))
cset(cmd, index := index++);
}
// API
void copyCommandsFromBackend() {
for (S cmd : allIfQuotedPatterns(loadSnippet(beforeSlash(backendModuleLibID)))
)
uniqConcept(+cmd);
}
S answer(S s) {
if (currentAttractor != null) {
print("Sending to attractor " + currentAttractor + ": " + s);
S a = strOrNull(call(currentAttractor, 'answer, s));
if (a != null) {
print("Attractor said: " + a);
ret a;
}
}
Cmd cmd = mmo_matchMultiWithTypos(1,
filter(conceptsSortedByField Cmd('index), c -> nempty(c.patterns)),
c -> c.parsedPattern(), s);
if (cmd != null) ret handleCommand(cmd);
ret sendToBackend(s);
}
}