Index: src/services/ActivityPubService.js
===================================================================
--- src/services/ActivityPubService.js	(revision 55bc7f95d6ee2d94bdaba55d6ca87265e217dbc4)
+++ src/services/ActivityPubService.js	(revision 3d7312ab39fe3619ae0a9b953d94789dded655a0)
@@ -477,8 +477,30 @@
 }
 
+// Resolve a remote post URL (any fediverse/Klonkt post) into a reply target.
+// Returns a parent-shaped object usable by deliverReply(), or null.
+export async function resolveRemoteNote(url) {
+  if (!/^https?:\/\//i.test(String(url || ''))) return null;
+  const note = await fetchActor(url).catch(() => null); // AP GET (content-negotiates)
+  if (!note || !note.id) return null;
+  const att = note.attributedTo;
+  const actorUri = typeof att === 'string' ? att : (att && att.id);
+  if (!actorUri) return null;
+  const actor = await fetchActor(actorUri).catch(() => null);
+  const ai = actorInfo(actor, actorUri);
+  return {
+    object_uri: note.id,
+    actor_uri: actorUri,
+    actor_url: ai.url,
+    actor_handle: ai.handle,
+    actor_name: ai.name,
+    actor_icon: ai.icon,
+    preview: HtmlSanitizerService.toPlainText(note.content || '').slice(0, 240),
+  };
+}
+
 export default {
   getOrCreateKeys, apWants, sendAP, actorId, noteId,
   buildActor, buildNote, buildCreate, buildOutbox, buildFollowers,
   followerCount, deliver, fetchActor, verifyRequest, handleInbox, deliverCreate, deliverDelete,
-  getInteractions, getInteractionById, buildReplyNote, getOutboxNote, deliverReply,
+  getInteractions, getInteractionById, buildReplyNote, getOutboxNote, deliverReply, resolveRemoteNote,
 };
