Let bots ask multiple-choice questions before acting

ask_user puts up to six questions on one card (radios for one pick,
checkboxes for several, an optional typed Other) as a [question:ID] chip.
The user's answers are checked against the questions, stored in
bot_questions and sent to the bot as their chat message; Skip says so.
Offered in chat replies and user-started tasks, never in routines, hook
calls or chatroom sessions.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2026-10-28 11:10:23 +01:00
co-authored by Claude Opus 5.5
parent 07f87ce4ea
commit d7dfe0e78e
45 changed files with 1448 additions and 6 deletions
+58
View File
@@ -35,6 +35,7 @@ import {
} from "@/src/dict/bot-file-dict";
import type { BUN_SQLITE_DatabaseSchemaType } from "@moduletrace/bun-sqlite/types";
import { EnvParadigms, SecretRequestStatuses } from "@/src/dict/env-dict";
import { BotQuestionStatuses } from "@/src/dict/bot-question-dict";
import { McpServerStatuses, McpTransports } from "@/src/dict/mcp-dict";
import {
CustomToolKinds,
@@ -1652,6 +1653,63 @@ const schema: BUN_SQLITE_DatabaseSchemaType = {
},
],
},
{
tableName: "bot_questions",
tableDescription: `Questions a bot asked a user in their conversation before acting (\`ask_user\`), each answered by picking one option (radios) or several (checkboxes), optionally with a typed "Other". The user answers them in the card, and the answers go to the bot as their chat message`,
fields: [
{
fieldName: "title",
fieldDescription: `A short heading for the card, in the bot's words`,
dataType: "TEXT",
},
{
fieldName: "questions",
fieldDescription: `JSON array of { question, kind (single | multiple), options, allow_other }`,
dataType: "TEXT",
},
{
fieldName: "answers",
fieldDescription: `JSON array, one per question, of { choices (option indexes), other }; null until answered`,
dataType: "TEXT",
},
{
fieldName: "status",
dataType: "TEXT",
options: [...BotQuestionStatuses],
defaultValue: "pending",
},
{
fieldName: "decided_at",
dataType: "INTEGER",
},
{
fieldName: "user_id",
fieldDescription: `The user they were asked of, who alone answers them. Not a foreign key`,
dataType: "INTEGER",
},
{
fieldName: "bot_id",
fieldDescription: `The bot that asked. Not a foreign key`,
dataType: "INTEGER",
},
{
fieldName: "session_id",
fieldDescription: `The conversation they were asked in. Not a foreign key`,
dataType: "INTEGER",
},
{
fieldName: "workspace_id",
fieldDescription: `The session's workspace; null for the bot's own chat. Not a foreign key`,
dataType: "INTEGER",
},
],
indexes: [
{
indexName: "idx_bot_questions_session_id",
indexTableFields: ["session_id"],
},
],
},
{
tableName: "bot_graphics",
tableDescription: `A visual a bot made for a user (a chart, diagram, timeline or report) as one self-contained HTML document. Served by the app at \`/graphics/<id>\` in a sandbox with no network and an origin of its own, so it never runs with the viewer's session. Per user like the conversation it was made in; an edit replaces the HTML and bumps \`version\``,