import { v } from "convex/values"; import { mutation, query } from "./_generated/server"; export const connect = mutation({ args: { daemonId: v.string(), sessionId: v.string(), hostname: v.string(), platform: v.string(), architecture: v.string(), version: v.string(), }, handler: async (ctx, args) => { const existing = await ctx.db .query("daemonPresence") .withIndex("by_sessionId", (q) => q.eq("sessionId", args.sessionId)) .unique(); const timestamp = Date.now(); if (existing) { await ctx.db.patch("daemonPresence", existing._id, { status: "online", lastHeartbeatAt: timestamp, }); return existing._id; } return await ctx.db.insert("daemonPresence", { ...args, status: "online", startedAt: timestamp, lastHeartbeatAt: timestamp, }); }, }); export const heartbeat = mutation({ args: { daemonId: v.string(), sessionId: v.string(), }, handler: async (ctx, args) => { const presence = await ctx.db .query("daemonPresence") .withIndex("by_sessionId", (q) => q.eq("sessionId", args.sessionId)) .unique(); if (!presence || presence.daemonId !== args.daemonId) { return false; } await ctx.db.patch("daemonPresence", presence._id, { status: "online", lastHeartbeatAt: Date.now(), }); return true; }, }); export const disconnect = mutation({ args: { daemonId: v.string(), sessionId: v.string(), }, handler: async (ctx, args) => { const presence = await ctx.db .query("daemonPresence") .withIndex("by_sessionId", (q) => q.eq("sessionId", args.sessionId)) .unique(); if (!presence || presence.daemonId !== args.daemonId) { return false; } await ctx.db.patch("daemonPresence", presence._id, { status: "offline", lastHeartbeatAt: Date.now(), }); return true; }, }); export const recordEvent = mutation({ args: { daemonId: v.string(), commandId: v.optional(v.id("daemonCommands")), kind: v.string(), data: v.any(), }, handler: async (ctx, args) => { return await ctx.db.insert("daemonCommandEvents", { ...args, createdAt: Date.now(), }); }, }); export const listEvents = query({ args: { daemonId: v.string(), limit: v.optional(v.number()), }, handler: async (ctx, args) => { return await ctx.db .query("daemonCommandEvents") .withIndex("by_daemonId_and_createdAt", (q) => q.eq("daemonId", args.daemonId) ) .order("desc") .take(Math.min(args.limit ?? 100, 500)); }, });