feat: merge schedule_reminder + send_later, add subtype reminder
- Merge send_later into schedule_reminder (optional `to` param — omit for self-reminder) - Add subtype?: "reminder" to WSPushMessage, WSScheduleMessage, ScheduledEntry, InboundPush - Broker handleSend now accepts optional subtype and injects into push envelope - deliver closure passes sm.subtype so reminders surface correctly - MCP channel meta includes subtype field; formatPush tags [REMINDER] in check_messages - MCP server instructions document subtype and schedule_reminder/list_scheduled/cancel_scheduled - client.scheduleMessage accepts isReminder flag, sends subtype: "reminder" on wire Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -103,7 +103,7 @@ const connectionsPerMesh = new Map<string, number>();
|
||||
// Stream subscriptions: "meshId:streamName" → Set of presenceIds
|
||||
const streamSubscriptions = new Map<string, Set<string>>();
|
||||
|
||||
// Scheduled messages: meshId → Map<scheduledId, entry>
|
||||
/// Scheduled messages: meshId → Map<scheduledId, entry>
|
||||
interface ScheduledEntry {
|
||||
id: string;
|
||||
meshId: string;
|
||||
@@ -112,6 +112,7 @@ interface ScheduledEntry {
|
||||
message: string;
|
||||
deliverAt: number;
|
||||
createdAt: number;
|
||||
subtype?: "reminder";
|
||||
timer: ReturnType<typeof setTimeout>;
|
||||
}
|
||||
const scheduledMessages = new Map<string, ScheduledEntry>(); // keyed by scheduledId
|
||||
@@ -652,6 +653,7 @@ async function handleHello(
|
||||
async function handleSend(
|
||||
conn: PeerConn,
|
||||
msg: Extract<WSClientMessage, { type: "send" }>,
|
||||
subtype?: "reminder",
|
||||
): Promise<void> {
|
||||
const messageId = await queueMessage({
|
||||
meshId: conn.meshId,
|
||||
@@ -696,6 +698,7 @@ async function handleSend(
|
||||
nonce: msg.nonce,
|
||||
ciphertext: msg.ciphertext,
|
||||
createdAt: new Date().toISOString(),
|
||||
...(subtype ? { subtype } : {}),
|
||||
};
|
||||
|
||||
for (const [pid, peer] of connections) {
|
||||
@@ -1824,7 +1827,7 @@ function handleConnection(ws: WebSocket): void {
|
||||
nonce: "",
|
||||
ciphertext: Buffer.from(sm.message, "utf-8").toString("base64"),
|
||||
};
|
||||
handleSend(conn2, presenceId, fakeMsg).catch((e) =>
|
||||
handleSend(conn2, fakeMsg, sm.subtype).catch((e) =>
|
||||
log.warn("scheduled delivery error", { scheduled_id: scheduledId, error: String(e) }),
|
||||
);
|
||||
log.info("ws schedule deliver", { scheduled_id: scheduledId, to: sm.to });
|
||||
@@ -1838,6 +1841,7 @@ function handleConnection(ws: WebSocket): void {
|
||||
message: sm.message,
|
||||
deliverAt: sm.deliverAt,
|
||||
createdAt: now,
|
||||
...(sm.subtype ? { subtype: sm.subtype } : {}),
|
||||
timer: setTimeout(deliver, delay),
|
||||
};
|
||||
scheduledMessages.set(scheduledId, entry);
|
||||
|
||||
@@ -86,6 +86,8 @@ export interface WSPushMessage {
|
||||
nonce: string;
|
||||
ciphertext: string;
|
||||
createdAt: string;
|
||||
/** Optional semantic tag — "reminder" when delivered by the scheduler. */
|
||||
subtype?: "reminder";
|
||||
}
|
||||
|
||||
/** Client → broker: manual status override (dnd, forced idle). */
|
||||
@@ -673,6 +675,8 @@ export interface WSScheduleMessage {
|
||||
message: string;
|
||||
/** Unix timestamp (ms) when to deliver. */
|
||||
deliverAt: number;
|
||||
/** Optional semantic tag — "reminder" surfaces differently to the receiver. */
|
||||
subtype?: "reminder";
|
||||
_reqId?: string;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user