Add the agent scaffold, mobile web UI, voice auto-leave, and text notifications

This commit is contained in:
Fisto
2026-09-14 16:38:14 +02:00
parent c7aad7547f
commit eab94132bb
27 changed files with 1521 additions and 73 deletions
+11
View File
@@ -132,6 +132,9 @@ function getSendableChannel(channelId: string) {
/** Shape a Discord message for the daemon. Attachments carry CDN links only. */
function mapMessage(message: any) {
const reference = message.messageReference;
const referenced = message.referencedMessage ?? message.referenced_message;
return {
id: message.id,
author: {
@@ -141,6 +144,14 @@ function mapMessage(message: any) {
},
content: message.content,
timestamp: message.timestamp,
editedAt: message.editedTimestamp ?? message.edited_timestamp ?? null,
replyTo: reference?.message_id
? {
id: reference.message_id,
authorId: referenced?.author?.id ?? null,
authorName: referenced?.author?.username ?? null
}
: null,
attachments: (message.attachments ?? []).map((attachment: any) => ({
filename: attachment.filename,
url: attachment.url ?? null,
+86
View File
@@ -20,6 +20,9 @@ function normalizeMessage(event: any): PuppetEvent | undefined {
const message = event?.message;
if (!message?.author) return undefined;
const reference = message.messageReference;
const referenced = message.referencedMessage ?? message.referenced_message;
return {
type: "MESSAGE_CREATE",
id: message.id,
@@ -34,10 +37,66 @@ function normalizeMessage(event: any): PuppetEvent | undefined {
},
content: message.content ?? "",
mentions: [...(message.mentions ?? []).map((user: any) => user.id), ...(message.mentionIds ?? [])],
replyTo: reference?.message_id
? {
id: reference.message_id,
channelId: reference.channel_id ?? event.channelId,
authorId: referenced?.author?.id ?? null,
authorName: referenced?.author?.username ?? null,
content: String(referenced?.content ?? "").slice(0, 500)
}
: null,
editedAt: message.editedTimestamp ?? message.edited_timestamp ?? null,
timestamp: message.timestamp ?? new Date().toISOString()
};
}
function normalizeMessageUpdate(event: any): PuppetEvent | undefined {
const message = event?.message ?? event;
const id = message?.id;
const channelId = message?.channelId ?? event?.channelId;
if (!id || !channelId) return undefined;
return {
type: "MESSAGE_UPDATE",
id,
channelId,
guildId: event?.guildId ?? message.guildId ?? null,
content: message.content ?? "",
editedAt: message.editedTimestamp ?? message.edited_timestamp ?? new Date().toISOString(),
author: message.author
? {
id: message.author.id,
username: message.author.username,
bot: !!message.author.bot
}
: undefined
};
}
function normalizeMessageDelete(event: any): PuppetEvent | undefined {
if (!event?.id || !event?.channelId) return undefined;
return {
type: "MESSAGE_DELETE",
id: event.id,
channelId: event.channelId,
guildId: event.guildId ?? null
};
}
function normalizeMessageDeleteBulk(event: any): PuppetEvent | undefined {
const ids = event?.ids ?? event?.messages;
if (!Array.isArray(ids) || !event?.channelId) return undefined;
return {
type: "MESSAGE_DELETE_BULK",
ids: ids.map(String),
channelId: event.channelId,
guildId: event.guildId ?? null
};
}
function normalizeReaction(
event: any,
type: "MESSAGE_REACTION_ADD" | "MESSAGE_REACTION_REMOVE"
@@ -91,6 +150,33 @@ export function initPuppetEvents() {
}
});
dispatcher.subscribe("MESSAGE_UPDATE", (event: any) => {
try {
const normalized = normalizeMessageUpdate(event);
if (normalized) VesktopNative.puppet.emit(normalized);
} catch (error) {
console.error("[puppet] message update normalization failed:", error);
}
});
dispatcher.subscribe("MESSAGE_DELETE", (event: any) => {
try {
const normalized = normalizeMessageDelete(event);
if (normalized) VesktopNative.puppet.emit(normalized);
} catch (error) {
console.error("[puppet] message delete normalization failed:", error);
}
});
dispatcher.subscribe("MESSAGE_DELETE_BULK", (event: any) => {
try {
const normalized = normalizeMessageDeleteBulk(event);
if (normalized) VesktopNative.puppet.emit(normalized);
} catch (error) {
console.error("[puppet] bulk delete normalization failed:", error);
}
});
dispatcher.subscribe("MESSAGE_REACTION_ADD", (event: any) => {
try {
const normalized = normalizeReaction(event, "MESSAGE_REACTION_ADD");