fix(tlon): use HTTP-only poke for outbound to avoid SSE conflict

The monitor already maintains an SSE connection for inbound messages.
Opening another EventSource for outbound pokes causes conflicts.
This uses a simple HTTP PUT to the channel endpoint instead.
This commit is contained in:
Hunter Miller 2026-01-25 09:23:20 -06:00
parent 885167dd58
commit ddc29261c2

View File

@ -17,6 +17,48 @@ import { buildMediaText, sendDm, sendGroupMessage } from "./urbit/send.js";
import { monitorTlonProvider } from "./monitor/index.js";
import { tlonChannelConfigSchema } from "./config-schema.js";
import { tlonOnboardingAdapter } from "./onboarding.js";
import { authenticate } from "./urbit/auth.js";
// Simple HTTP-only poke that doesn't open an EventSource (avoids conflict with monitor's SSE)
async function createHttpPokeApi(params: { url: string; code: string; ship: string }) {
const cookie = await authenticate(params.url, params.code);
const channelId = `${Math.floor(Date.now() / 1000)}-${Math.random().toString(36).substring(2, 8)}`;
const channelUrl = `${params.url}/~/channel/${channelId}`;
const shipName = params.ship.replace(/^~/, "");
return {
poke: async (pokeParams: { app: string; mark: string; json: unknown }) => {
const pokeId = Date.now();
const pokeData = {
id: pokeId,
action: "poke",
ship: shipName,
app: pokeParams.app,
mark: pokeParams.mark,
json: pokeParams.json,
};
const response = await fetch(channelUrl, {
method: "PUT",
headers: {
"Content-Type": "application/json",
Cookie: cookie.split(";")[0],
},
body: JSON.stringify([pokeData]),
});
if (!response.ok && response.status !== 204) {
const errorText = await response.text();
throw new Error(`Poke failed: ${response.status} - ${errorText}`);
}
return pokeId;
},
delete: async () => {
// No-op for HTTP-only client
},
};
}
const TLON_CHANNEL_ID = "tlon" as const;
@ -118,12 +160,11 @@ const tlonOutbound: ChannelOutboundAdapter = {
throw new Error(`Invalid Tlon target. Use ${formatTargetHint()}`);
}
ensureUrbitConnectPatched();
const api = await Urbit.authenticate({
ship: account.ship.replace(/^~/, ""),
// Use HTTP-only poke (no EventSource) to avoid conflicts with monitor's SSE connection
const api = await createHttpPokeApi({
url: account.url,
ship: account.ship,
code: account.code,
verbose: false,
});
try {