The regex matchers in lib/responses.js (isImageRequest, isDanceParty, isPodBayDoor, isLoveYou, isRickroll, isTikTok, dad-joke trigger) are 2018-vintage and increasingly out of place now that Data runs on native Ollama/Gemini SDKs with proper tool support.
Idea
Define a small set of tools and let the model decide when to call them:
generate_image(prompt) — calls Gemini Nano Banana
tell_dad_joke() — fetches from icanhazdadjoke.com
start_dance_party() — emits the emoji rain
show_help() — returns the help text
state_asimovs_laws() — Asimov rule recitation
play_rickroll() / play_tiktok() — the button blocks
Both Ollama (tools: [...] → message.tool_calls) and Gemini (config.tools with function declarations) have native tool calling. Translation happens inside lib/chat-backends.js so handleMessage only deals with the canonical shape.
Biggest immediate win
The IMAGE_REQUEST_GUIDANCE shim where Data has to say "please use the /image command" instead of just generating the image. That whole interaction goes away — user says "Data, picture of a sehlat", Data calls the tool, image appears in the channel.
Plan
- New
lib/tools.js — tool definitions (JSON schemas + implementations).
- Extend the chat-backend adapter interface:
chat({ messages, tools }) → { text, toolCalls? }. Adapters translate to/from each provider's native shape.
handleMessage becomes a small loop: call the model → if toolCalls, execute them and feed the results back as a tool-role message → repeat until plain text. Cap iterations to prevent runaways.
- Delete
isImageRequest/IMAGE_REQUEST_GUIDANCE, the love-you/pod-bay/danceparty/rickroll/tiktok matchers and their call sites in app.js. Keep the rules, help, dad joke matchers as fallbacks for now (or convert them too).
- Tests: adapter translation of tool calls for both Ollama + Gemini, and a fake-tool-calling chat that exercises the multi-turn dispatch loop in
handleMessage.
What this unlocks downstream
Future tools (web search, weather, Slack user lookups, etc.) just slot into lib/tools.js — no new dispatch code, no new regex.
The regex matchers in
lib/responses.js(isImageRequest,isDanceParty,isPodBayDoor,isLoveYou,isRickroll,isTikTok, dad-joke trigger) are 2018-vintage and increasingly out of place now that Data runs on native Ollama/Gemini SDKs with proper tool support.Idea
Define a small set of tools and let the model decide when to call them:
generate_image(prompt)— calls Gemini Nano Bananatell_dad_joke()— fetches from icanhazdadjoke.comstart_dance_party()— emits the emoji rainshow_help()— returns the help textstate_asimovs_laws()— Asimov rule recitationplay_rickroll()/play_tiktok()— the button blocksBoth Ollama (
tools: [...]→message.tool_calls) and Gemini (config.toolswith function declarations) have native tool calling. Translation happens insidelib/chat-backends.jssohandleMessageonly deals with the canonical shape.Biggest immediate win
The
IMAGE_REQUEST_GUIDANCEshim where Data has to say "please use the /image command" instead of just generating the image. That whole interaction goes away — user says "Data, picture of a sehlat", Data calls the tool, image appears in the channel.Plan
lib/tools.js— tool definitions (JSON schemas + implementations).chat({ messages, tools }) → { text, toolCalls? }. Adapters translate to/from each provider's native shape.handleMessagebecomes a small loop: call the model → iftoolCalls, execute them and feed the results back as a tool-role message → repeat until plain text. Cap iterations to prevent runaways.isImageRequest/IMAGE_REQUEST_GUIDANCE, the love-you/pod-bay/danceparty/rickroll/tiktok matchers and their call sites inapp.js. Keepthe rules,help,dad jokematchers as fallbacks for now (or convert them too).handleMessage.What this unlocks downstream
Future tools (web search, weather, Slack user lookups, etc.) just slot into
lib/tools.js— no new dispatch code, no new regex.