SDK Server Reference
Complete reference for @zaflun/lumio-sdk/server - the server-side library used in server/functions.ts.
Import
import { action, query, v } from "@zaflun/lumio-sdk/server";
Defining functions
Use query() for reads, mutation() for writes, and action() for work with side effects. Export each handler by name from server/functions.ts; the exported name is the function name that your UI passes to useQuery() or useMutation().
import { action, query } from "@zaflun/lumio-sdk/server";
export const getVotes = query({
args: {},
handler: async (ctx) => ctx.db.list("votes"),
});
export const clearVotes = action({
args: {},
handler: async (ctx) => {
const votes = await ctx.db.list("votes");
for (const vote of votes) await ctx.db.delete("votes", vote._id);
return { cleared: votes.length };
},
});
See Handler-based Functions for the execution flow, caller permissions, and limits.
Handler context
Server-function handlers can use the install-scoped ctx.db, ctx.cache, ctx.secrets, ctx.defer, and ctx.realtime APIs described in Handler-based Functions. A query() handler is read-only: database writes, cache writes, and deferred jobs are refused.
ctx.fetch() refuses every external host in server functions. The manifest's egress.allowHosts does not change this. To call external APIs, use a bot-module handler and declare its egress hosts.
Bot-module handlers use the Bot Module Context. Their ctx.fetch() follows the declared allowlist; their ctx.db requires a version with a declared data schema.
Validation - v
The v object provides runtime argument validators. All args must be declared with v - undeclared fields are stripped before the handler runs.
// Primitives
v.string()
v.number()
v.boolean()
v.null_()
// Modifiers
v.optional(v.string()) // string | undefined — field may be absent
v.nullable(v.string()) // string | null
// Collections
v.array(v.string())
v.object({ name: v.string(), count: v.number() })
// Union
v.union([v.string(), v.number()])
// Literal
v.literal("active")
Validation happens before the handler is called. Invalid args return a structured error to the caller without invoking the handler.
Exports from server/functions.ts
Every named export from server/functions.ts that is an action() or query() result is automatically registered with the platform at deploy time. No additional registration step is needed.
// server/functions.ts
export const getScore = query({ ... }); // registered as "getScore"
export const setScore = action({ ... }); // registered as "setScore"
// Not registered — not an action or query
export const MULTIPLIER = 2;
The exported name becomes the actionName / queryName used on the client.
Bot module handlers
Bot module extensions (category: "bot_module") use a separate set of handler wrappers for chat interaction. Each wrapper sets a __type discriminant on the exported function, following the same pattern as query() and action().
Handler type reference
| Wrapper | __type | __trigger | Sync/Async | Timeout |
|---|---|---|---|---|
command(name, handler) | "command" | Command name | Sync | 500ms |
keyword(word, handler) | "keyword" | Keyword string | Async | 10s |
pattern(regex, handler) | "pattern" | Regex string | Async | 10s |
event(type, handler) | "event" | Event type | Async | 10s |
timer(name, handler) | "timer" | Timer name | Async | 10s |
moderate(handler) | "moderate" | N/A | Sync | 500ms |
Signatures
function command(
name: string,
handler: (ctx: BotModuleContext, args: string[]) => Promise<HandlerResponse | null>
): CommandDefinition;
function keyword(
word: string,
handler: (ctx: BotModuleContext, message: ChatMessage) => Promise<HandlerResponse | null>
): KeywordDefinition;
function pattern(
regex: string,
handler: (ctx: BotModuleContext, message: ChatMessage, matched: string) => Promise<HandlerResponse | null>
): PatternDefinition;
function event(
eventType: string,
handler: (ctx: BotModuleContext, evt: Record<string, unknown>) => Promise<HandlerResponse | null>
): EventDefinition;
function timer(
name: string,
handler: (ctx: BotModuleContext) => Promise<HandlerResponse | null>
): TimerDefinition;
function moderate(
handler: (ctx: BotModuleContext, message: ChatMessage) => Promise<ModerationResponse>
): ModerateDefinition;
BotModuleContext
See Bot Module Context for the full API reference. In bot-module handlers ctx.cache, ctx.secrets, ctx.fetch and ctx.defer() work; ctx.db requires a version with a declared data schema.
HandlerResponse
interface HandlerResponse {
reply?: string;
actions?: ActionRequest[];
}
interface ActionRequest {
action: string;
params: Record<string, unknown>;
}
ModerationResponse
interface ModerationResponse {
block: boolean;
action?: "delete" | "timeout" | "ban";
duration?: number;
reason?: string;
}
// defineModerate(handler) return value
interface ModerateResult {
action: "allow" | "delete" | "timeout" | "warn" | "ban";
duration?: number;
reason?: string;
message?: string;
}
Lumio acts on the action field only. allow (or no action) lets the message through; delete, timeout, ban and warn become the chat actions chat:delete, chat:timeout (duration seconds, default 600), chat:ban and chat:send (message, else reason). The manifest must declare that action in permissions, or it is refused. block is not read: { block: true } without an action does nothing. The handler has a 500ms budget; a timeout or error lets the message through. See Bot Modules → Moderation.
ChatMessage
interface ChatMessage {
text: string;
platformMessageId: string;
}