pocolobby 0.12.2 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/console.js CHANGED
@@ -1 +1 @@
1
- var Se=Object.defineProperty;var d=(b,g)=>Se(b,"name",{value:g,configurable:!0});import{randomBytes as oe}from"node:crypto";import{setTimeout as $e}from"node:timers/promises";import{z as m,ZodError as Te}from"zod";import{Challenge as ie,Code as Ce,CONSOLE_COOKIE as R,cookieToken as B,LOCAL_COOKIE as V,handoffKey as Oe,newCode as xe,newSessionToken as Y,sessionCookie as J,SIGN_IN as re,tokenHash as T,WindowLimiter as se}from"./auth.js";import{displayName as Ie,isoWeek as Ne,tokenPeriods as Ae}from"./board.js";import{BoardIconSchema as Le,BoardSourceSchema as Ee,BoardVisibility as Re,SummarySettingsSchema as je}from"./board-model.js";import{boardCsp as Me}from"./board-page.js";import{renderActivity as Ue,renderAgents as Be,renderBoardAccess as Pe,renderHome as ae,renderNotice as P,renderOverview as De,renderRooms as We,renderSettings as He,renderMemory as Ve,renderTokens as Ye,renderSignIn as ce,renderSummaries as Ge}from"./console-page.js";import{MailError as Ke}from"./mail.js";import{AgentId as le,Email as F,LobbyError as O,RoomId as X}from"./protocol.js";import{PRICES_AS_OF as ze}from"./prices.js";import{TOKEN_RETENTION_MS as Je}from"./store.js";const Fe=4096,Xe=512*1024,D=m.string().regex(/^[a-z0-9][a-z0-9_-]{0,62}$/u),Ze=6e4,me=re.sessionMs,Qe=d(b=>m.string().max(2e3).transform(g=>g.split(",").map(i=>i.trim()).filter(Boolean)).pipe(m.array(m.string()).max(b)),"list"),h={code:m.object({email:F}).strict(),verify:m.object({email:F,code:Ce,lobby:D.optional(),to:m.string().max(64).optional(),state:m.string().regex(ie).optional()}).strict(),ticket:m.object({ticket:m.string().regex(/^[A-Za-z0-9_-]{43}$/u)}).strict(),empty:m.object({}).strict(),lobby:m.object({lobby_id:m.string().max(64),first_room:X.optional()}).strict(),room:m.object({room_id:X}).strict(),members:m.object({add:le.optional(),remove:le.optional()}).strict().refine(b=>b.add!==void 0||b.remove!==void 0,"Name a member"),source:m.object({repo:m.string().max(201),ref:m.string().max(200).optional(),notes:Qe(20)}).strict(),summary:je,visibility:m.object({visibility:Re}).strict(),viewer:m.object({email:F}).strict(),delete:m.object({confirm:m.string().max(64)}).strict(),icon:Le,displayName:m.object({display_name:m.string().max(200).optional()}).strict(),currency:m.object({currency:m.string().max(8)}).strict(),clearTokens:m.object({before:m.string().max(10)}).strict(),memoryErase:m.object({kind:m.enum(["entry","fragment"]),key:m.string().min(1).max(64)}).strict(),memoryCurator:m.object({room_id:m.string().min(1).max(48),agent_id:m.string().min(1).max(48)}).strict()};class de{static{d(this,"Reply")}status;body;headers;constructor(g,i,x={}){this.status=g,this.body=i,this.headers=x}}const p=d((b={},g={})=>new de(200,{ok:!0,...b},g),"ok"),v=d((b,g,i,x={})=>new de(b,{error:{code:g,message:i}},x),"refuse");function fn(b,g){const{store:i,board:x,keys:W}=g,w=b.origin===null?null:new URL(b.origin),ge=b.responseFloorMs??1e3,be=new se(10,15*6e4),ye=new se(30,15*6e4),j=new Map,M=new Map,G=d((e,n="/")=>`${w.protocol}//${e}.${g.boardDomain}${w.port?`:${w.port}`:""}${n}`,"dashboardUrl"),K=d((e,n)=>w?`${e}.${g.boardDomain}`:`${n}/${e}`,"address"),I=d((e,n="/")=>G(e,`/sign-in${n==="/"?"":`?to=${encodeURIComponent(n)}`}`),"openUrl"),Z=d((e,n,l)=>`${w.origin}/open/${encodeURIComponent(e)}?${n==="/"?"":`to=${encodeURIComponent(n)}&`}state=${l}`,"handoffUrl");function y(e,n,l,o,f,c,t={}){n.writeHead(l,{"content-type":o,"cache-control":"no-store","x-content-type-options":"nosniff","referrer-policy":"same-origin","content-security-policy":o.startsWith("text/html")?Me(c):"default-src 'none'; frame-ancestors 'none'",...t}),n.end(e.method==="HEAD"?void 0:f)}d(y,"send");function Q(e,n){const l=B(e.headers.cookie,R);if(!l)return null;const o=i.consoleSession(T(l));return o?.refresh&&(i.refreshConsoleSession(T(l)),n["set-cookie"]=J(R,l)),o}d(Q,"session");function H(e){if(w)return!1;const n=B(e.headers.cookie,V),l=n===null?void 0:M.get(T(n));return l!==void 0&&l>g.clock()}d(H,"operator");function q(e){const n=B(e.headers.cookie,V);return n&&M.delete(T(n)),{"set-cookie":ue(null)}}d(q,"endOperator");async function C(e,n,l,o,f=Fe){if(e.headers.origin!==l)throw e.resume(),new O(403,"origin_not_allowed","Use the settings page itself.");if(e.headers["content-type"]?.split(";",1)[0]?.trim()!=="application/json")throw e.resume(),new O(415,"content_type","Use application/json.");if(Number(e.headers["content-length"])>f)throw e.resume(),new O(413,"body_too_large","The request is too large.");const c=[];let t=0;for await(const r of e)t+=r.length,t<=f&&c.push(r);if(t>f)throw new O(413,"body_too_large","The request is too large.");if(o&&!o())throw new O(401,"sign_in_required","Your session has ended. Sign in again.");let a;try{a=JSON.parse(Buffer.concat(c).toString("utf8"))}catch{throw new O(400,"invalid_json","The request is not valid JSON.")}return n.parse(a)}d(C,"input");async function he(e){const{email:n}=await C(e,h.code,w.origin),l=Date.now()+ge;if(!b.mailer)return v(503,"sign_in_unavailable","Sign-in is not configured on this server.");const o=be.take(g.clientAddress(e));if(o)return v(429,"too_many_requests",`Too many codes asked from here. Try again in ${Math.ceil(o/60)} min.`,{"retry-after":String(o)});const f=W.emailKey(n),c=xe(),t=i.beginSignIn(n,f,W.codeMac(f,c));if(t.wait)return v(429,"too_many_requests",`Wait ${t.wait<120?`${t.wait} s`:`${Math.ceil(t.wait/60)} min`} before asking for another code.`,{"retry-after":String(t.wait)});let a=null;if(t.send)try{await b.mailer.sendSignInCode(n,c)}catch(s){a=s instanceof Ke?s.message:"The email could not be sent"}const r=l-Date.now();return r>0&&await $e(r),a?v(502,"mail_failed",`We could not send the code: ${a}. Try again in a minute.`):p({message:`If ${n} may sign in, a code is on its way. It works for 10 minutes.`})}d(he,"signInCode");async function pe(e){const{email:n,code:l,lobby:o,to:f,state:c}=await C(e,h.verify,w.origin),t=ye.take(g.clientAddress(e));if(t)return v(429,"too_many_requests",`Too many tries from here. Try again in ${Math.ceil(t/60)} min.`,{"retry-after":String(t)});const a=W.emailKey(n),r=Y(),s=i.finishSignIn(n,a,W.codeMac(a,l),T(r));if("error"in s)return s.error==="budget"?v(429,"too_many_wrong_codes",`Too many wrong codes for this address. Wait ${Math.ceil(s.wait/60)} min, then ask for a new code.`,{"retry-after":String(s.wait)}):v(400,"code_invalid","That code is not right, has expired, or had 5 wrong tries. Check the email, or ask for a new code.");const _=fe(f??null);return p({redirect:o?c?Z(o,_,c):I(o,_):"/"},{"set-cookie":J(R,r)})}d(pe,"signInVerify");async function we(e,n,l,o,f){const{lobby:c}=l,t=d((r,s)=>C(e,r,l.origin,f,s),"body"),a=/^rooms\/([^/]+)\/(members|source|source\/remove|archive|restore)$/u.exec(o);if(o==="rooms"){const{room_id:r}=await t(h.room);return i.createRoom(n,r,c),p()}if(a){const r=X.parse(a[1]);if(a[2]==="members"){const s=await t(h.members);return i.changeRoomMembers(n,r,{...s.add?{add:[s.add]}:{},...s.remove?{remove:[s.remove]}:{}},c),p()}if(a[2]==="source"){const s=await t(h.source);return i.setBoardSource(c,r,Ee.parse(s),n),g.refreshBoards(c),p()}return await t(h.empty),a[2]==="source/remove"?i.removeBoardSource(c,r,n):a[2]==="archive"?i.archiveRoom(n,r,c):i.restoreRoom(n,r,c),p()}if(o==="summaries")return i.setSummarySettings(n,c,await t(h.summary)),p({message:"Saved. The next summary uses these settings."});if(o==="summaries/test")return await t(h.empty),x.runNow(c).catch(()=>{}),p({message:"Writing a test summary now. Reload in a minute to see it."});if(o==="access/visibility"){const{visibility:r}=await t(h.visibility);return i.setBoardVisibility(n,c,r),p()}if(o==="display-name"){const{display_name:r}=await t(h.displayName);return i.setDisplayName(n,c,r??""),p()}if(o==="currency"){const{currency:r}=await t(h.currency);return i.setLobbyCurrency(n,c,r),p({message:`Saved: costs show in ${r} from the next page.`})}if(o==="access/icon"){const{png:r}=await t(h.icon,Xe);return i.setBoardIcon(n,c,Buffer.from(r,"base64")),p()}if(o==="access/icon/remove")return await t(h.empty),i.setBoardIcon(n,c,null),p();if(o==="access/viewers")return i.addBoardViewer(n,c,(await t(h.viewer)).email),p();if(o==="access/viewers/remove")return i.removeBoardViewer(n,c,(await t(h.viewer)).email),p();if(o==="memory/erase"){const{kind:r,key:s}=await t(h.memoryErase);return i.eraseMemory(c,r,s,n),p()}if(o==="memory/curator"){const{room_id:r,agent_id:s}=await t(h.memoryCurator);return i.setMemoryCurator(c,r,s==="none"?null:s,n),p()}if(o==="tokens/clear"){const{before:r}=await t(h.clearTokens),{deleted:s}=i.clearTokens(n,c,r);return p({message:`Deleted ${s} daily total${s===1?"":"s"}.`})}if(o==="delete"){const{confirm:r}=await t(h.delete),s=i.deleteLobby(n,c,r);return g.closeAgents(s.agents),p({redirect:w?`${w.origin}/`:"/"})}return e.resume(),v(404,"not_found","Unknown settings route.")}d(we,"lobbyAction");function _e(e,n,l,o,f,c){const{lobby:t}=n,a={nonce:o,email:e.kind==="account"?e.email:null,home:w?`${w.origin}/`:"/",signOut:`${n.base}/settings/api/sign-out`,section:l,lobby:{id:t,name:i.displayName(t)??t,address:K(t,f),url:n.base||"/",link:`${n.origin}${n.base||"/"}`,icon:i.boardIcon(t)?.sha256??null,settings:`${n.base}/settings`,api:`${n.base}/settings/api`,money:i.lobbyMoney(t)}},r=i.boardConfig(t);switch(l){case"overview":return De(a,{view:x.view(t),config:r,rooms:i.rooms(t),agents:i.agents(t),viewers:i.boardViewers(t).length,sessions:i.boardSessionCount(t),last:i.boardLastAttempt(t)});case"rooms":return We(a,{rooms:i.rooms(t),archived:i.archivedRooms(t),config:r,view:x.view(t),snapshots:i.boardNotes(t),repos:i.lobbyRepos(t),agents:i.agents(t),github:g.github});case"summaries":return Ge(a,{config:r,keySet:g.anthropic,usage:i.boardUsage(t,g.clock()-864e5),last:i.boardLastAttempt(t),good:i.boardSummary(t)});case"access":return Pe(a,{config:r,icon:i.boardIcon(t),viewers:i.boardViewers(t),sessions:i.boardSessionCount(t),owner:e.kind==="account"?e.email:null});case"agents":return Be(a,{agents:i.agents(t),rooms:i.rooms(t),config:r,connected:d(s=>g.isConnected(t,s),"connected"),curates:d(s=>i.curationStatus(t,s).map(_=>_.room_id),"curates")});case"tokens":{const s=c.get("by")==="week"?"week":c.get("by")==="month"?"month":"day",_=s==="week"?Ne:s==="month"?k=>k.slice(0,7):void 0;return Ye(a,{by:s,periods:Ae(i.tokenDays(t),_??(k=>k)).reverse(),prices_as_of:ze,clearable:new Date(g.clock()-Je).toISOString().slice(0,10)})}case"memory":{const s=r.agents;return Ve(a,{rooms:i.rooms(t),memory:i.memoryOverview(t),people:Object.fromEntries(i.agents(t).map(_=>{const k=s[_.agent_id];return[_.agent_id,{name:k?.name??Ie(_.agent_id),emoji:k?.emoji??null}]}))})}case"activity":return Ue(a,{events:i.activity(t)});case"general":return He(a,{display_name:i.displayName(t),agents:i.agents(t).filter(s=>s.enabled).length,created:i.lobbyCreatedAt(t),currency:{chosen:i.lobbyCurrency(t),table:i.exchangeRates(),fetching:g.exchangeRates}})}}d(_e,"lobbyPage");async function ee(e,n,l,o,f){let c;try{c=await f()}catch(t){c=t instanceof O?v(t.status,t.code,t.message):t instanceof Te?v(400,"invalid_request",t.issues.map(a=>a.message).join("; ")):v(500,"internal_error","That could not be done. Nothing is implied to have changed; reload and check.")}y(e,n,c.status,"application/json; charset=utf-8",JSON.stringify(c.body),l,{...o,...c.headers})}return d(ee,"reply"),{openUrl:I,handoffUrl:Z,home:w?`${w.origin}/`:"/",handles:d(e=>e==="/sign-in"||/^\/open\/[^/]+$/u.test(e)||e.startsWith("/api/"),"handles"),ticket(){if(w)throw new O(404,"not_local","This broker signs in by email.");const e=Y(),n=g.clock();for(const[l,o]of j)o<=n&&j.delete(l);return j.set(T(e),n+Ze),e},operator:H,endOperator:q,async account(e,n){const l=new URL(e.url??"/","http://settings.invalid"),o=oe(16).toString("base64"),f={},c=e.method??"GET",t="text/html; charset=utf-8",a=e.headers.host??"";if(w&&a.toLowerCase()!==w.host){e.resume(),y(e,n,404,"text/plain; charset=utf-8","Not found.",o);return}if(g.overRate(g.clientAddress(e))){e.resume(),y(e,n,429,"text/plain; charset=utf-8","Too many requests; wait a minute.",o,{"retry-after":"60"});return}const r=w?w.origin:`http://${a}`;if(l.pathname.startsWith("/api/")){if(c!=="POST"){e.resume(),y(e,n,405,"text/plain; charset=utf-8","Use POST.",o);return}await ee(e,n,o,f,async()=>{const u=l.pathname;if(!w){if(u==="/api/sign-in/ticket"){const{ticket:$}=await C(e,h.ticket,r),A=T($),U=j.get(A);if(j.delete(A),U===void 0||U<=g.clock())return v(400,"ticket_invalid","That sign-in link has expired or was already used. Run pocolobby settings again.");const ne=Y(),te=g.clock();for(const[ke,ve]of M)ve<=te&&M.delete(ke);return M.set(T(ne),te+me),p({redirect:"/"},{"set-cookie":ue(ne)})}if(u==="/api/sign-out")return await C(e,h.empty,r),p({redirect:"/"},q(e));if(!H(e))return e.resume(),v(401,"sign_in_required","Run pocolobby settings to sign in.");if(u==="/api/lobbies"){const $=await C(e,h.lobby,r,()=>H(e)),A=i.createLobby($.lobby_id);return $.first_room&&i.createRoom("owner",$.first_room,A.lobby_id),p({redirect:`/${A.lobby_id}/settings`})}return e.resume(),v(404,"not_found","Unknown settings route.")}if(u==="/api/sign-in/code")return he(e);if(u==="/api/sign-in/verify")return pe(e);if(u==="/api/sign-out"){await C(e,h.empty,r);const $=B(e.headers.cookie,R);return $&&i.endConsoleSession(T($)),p({redirect:"/"},{"set-cookie":J(R,null)})}const E=Q(e,f);if(!E)return e.resume(),v(401,"sign_in_required","Your session has ended. Sign in again.");if(u==="/api/lobbies"){const $=d(()=>{const U=B(e.headers.cookie,R);return U!==null&&i.consoleSession(T(U))?.account_id===E.account_id},"still"),A=i.createOwnedLobby(E.account_id,await C(e,h.lobby,r,$));return p({redirect:I(A.lobby_id,"/settings")})}return e.resume(),v(404,"not_found","Unknown settings route.")});return}if(e.resume(),c!=="GET"&&c!=="HEAD"){y(e,n,405,"text/plain; charset=utf-8","Use GET.",o);return}const s=l.pathname.replace(/\/$/u,"")||"/";if(!w){if(!H(e)){y(e,n,200,t,ce({nonce:o,email:null},{missing:[],lobby:null,local:!0}),o);return}if(s!=="/"){y(e,n,303,"text/plain; charset=utf-8","",o,{location:"/"});return}y(e,n,200,t,ae({nonce:o,email:null,signOut:"/api/sign-out"},{owned:i.operatorLobbies(),viewing:[],open:d(u=>`/${u}/`,"open"),mayCreate:!0,remaining:null,address:d(u=>K(u,a),"address")}),o);return}const _=Q(e,f),k=/^\/open\/([^/]+)$/u.exec(s),L=fe(l.searchParams.get("to")),N=l.searchParams.get("state");if(k&&D.safeParse(k[1]).success&&(N===null||!ie.test(N))){y(e,n,303,"text/plain; charset=utf-8","",o,{...f,location:I(k[1],L)});return}if(!_){const u=k?k[1]:null;if(s==="/"||s==="/sign-in"||k){y(e,n,200,t,ce({nonce:o,email:null},{missing:b.missing,lobby:u!==null&&D.safeParse(u).success?u:null,to:L,state:N,local:!1}),o,f);return}y(e,n,303,"text/plain; charset=utf-8","",o,{location:"/sign-in"});return}const S={nonce:o,email:_.email,signOut:"/api/sign-out"};if(k){const u=k[1],E=Y();if(D.safeParse(u).success&&i.createHandoff(_.account_id,u,Oe(E,N))){y(e,n,303,"text/plain; charset=utf-8","",o,{...f,location:G(u,`/handoff?token=${E}${L==="/"?"":`&to=${encodeURIComponent(L)}`}`)});return}if(D.safeParse(u).success&&i.boardVisibility(u)==="public"){y(e,n,303,"text/plain; charset=utf-8","",o,{...f,location:G(u)});return}y(e,n,404,t,P(S,"No lobby to open",`${_.email} cannot open a lobby named ${u}. Ask its owner to add you as a viewer.`,{href:"/",label:"Your lobbies"}),o,f);return}if(s==="/sign-in"){y(e,n,303,"text/plain; charset=utf-8","",o,{...f,location:"/"});return}if(s!=="/"){y(e,n,404,t,P(S,"Not found","There is no such page.",{href:"/",label:"Your lobbies"}),o,f);return}const z=i.consoleLobbies(_.account_id);y(e,n,200,t,ae(S,{owned:z.owned,viewing:z.viewing.map(u=>({lobby_id:u.lobby_id,display_name:u.display_name,url:I(u.lobby_id)})),open:d(u=>I(u),"open"),mayCreate:_.may_create_lobbies,remaining:re.lobbiesPerAccount-z.owned.length,address:d(u=>K(u,a),"address")}),o,f)},async lobby(e,n,l,o,f,c){const t=new URL(e.url??"/","http://settings.invalid"),a=oe(16).toString("base64"),r=e.method??"GET",s="text/html; charset=utf-8",_=t.pathname.slice(l.base.length).replace(/\/$/u,"")||"/",k=d(S=>S!==null&&(S.kind==="operator"?i.boardVisibility(l.lobby)!==null:i.ownsLobby(S.account_id,l.lobby)),"owns"),L=w?I(l.lobby,_):"/";if(_.startsWith("/settings/api/")){if(r!=="POST"){e.resume(),y(e,n,405,"text/plain; charset=utf-8","Use POST.",a);return}await ee(e,n,a,{},async()=>{if(_==="/settings/api/sign-out")return await C(e,h.empty,l.origin),p({redirect:w?`${w.origin}/`:"/"},c());if(!k(o))return e.resume(),o===null?v(401,"sign_in_required","Your session has ended. Sign in again."):v(404,"lobby_not_found","Unknown lobby");const S=o.kind==="operator"?"owner":{account_id:o.account_id};return we(e,S,l,_.slice(14),()=>f()&&k(o))});return}if(e.resume(),r!=="GET"&&r!=="HEAD"){y(e,n,405,"text/plain; charset=utf-8","Use GET.",a);return}if(o===null){y(e,n,303,"text/plain; charset=utf-8","",a,{location:L});return}if(!k(o)){y(e,n,o.kind==="account"?403:404,s,o.kind==="account"?P({nonce:a,email:o.email},"Settings are for the owner","Only the lobby\u2019s owner can open its settings. Its dashboard is still yours to see.",{href:`${l.base}/`,label:"Dashboard"}):P({nonce:a,email:null},"Not found","There is no lobby by that name.",{href:"/",label:"Your lobbies"}),a);return}if(_==="/settings/icon.png"){const S=i.boardIcon(l.lobby);S?y(e,n,200,"image/png",S.png,a,{"content-length":String(S.png.length),"cache-control":"private, no-cache"}):y(e,n,404,"text/plain; charset=utf-8","Not found.",a);return}const N=/^\/settings(?:\/(rooms|summaries|access|agents|tokens|memory|activity|general))?$/u.exec(_);if(!N){y(e,n,404,s,P({nonce:a,email:o.kind==="account"?o.email:null},"Not found","There is no such settings page.",{href:`${l.base}/settings`,label:"Settings"}),a);return}y(e,n,200,s,_e(o,l,N[1]??"overview",a,e.headers.host??"",t.searchParams),a)}}}d(fn,"createConsole");function ue(b){return b===null?`${V}=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0`:`${V}=${b}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${me/1e3}`}d(ue,"localCookie");function fe(b){return b!==null&&/^\/(settings(\/(rooms|summaries|access|agents|tokens|memory|activity|general))?)?$/u.test(b)?b:"/"}d(fe,"destination");export{fn as createConsole,fe as destination};
1
+ var Se=Object.defineProperty;var m=(h,f)=>Se(h,"name",{value:f,configurable:!0});import{randomBytes as oe}from"node:crypto";import{setTimeout as $e}from"node:timers/promises";import{z as d,ZodError as Te}from"zod";import{Challenge as ie,Code as Ce,CONSOLE_COOKIE as E,cookieToken as P,LOCAL_COOKIE as H,handoffKey as Oe,newCode as xe,newSessionToken as V,sessionCookie as J,SIGN_IN as re,tokenHash as T,WindowLimiter as ae}from"./auth.js";import{displayName as Ie,isoWeek as Ae,tokenPeriods as Ne}from"./board.js";import{BoardIconSchema as Le,BoardSourceSchema as je,BoardVisibility as Ee,SummarySettingsSchema as Re}from"./board-model.js";import{boardCsp as Me}from"./board-page.js";import{renderActivity as Ue,renderAgents as Pe,renderPacing as Be,renderBoardAccess as De,renderHome as se,renderNotice as B,renderOverview as We,renderRooms as Ke,renderSettings as He,renderMemory as Ve,renderTokens as Ye,renderSignIn as ce,renderSummaries as Ge}from"./console-page.js";import{MailError as ze}from"./mail.js";import{AgentId as le,Email as F,LobbyError as O,RoomId as X,qualifyAgent as Je}from"./protocol.js";import{PRICES_AS_OF as Fe}from"./prices.js";import{TOKEN_RETENTION_MS as Xe}from"./store.js";const Ze=4096,Qe=512*1024,D=d.string().regex(/^[a-z0-9][a-z0-9_-]{0,62}$/u),qe=6e4,de=re.sessionMs,en=m(h=>d.string().max(2e3).transform(f=>f.split(",").map(o=>o.trim()).filter(Boolean)).pipe(d.array(d.string()).max(h)),"list"),b={code:d.object({email:F}).strict(),verify:d.object({email:F,code:Ce,lobby:D.optional(),to:d.string().max(64).optional(),state:d.string().regex(ie).optional()}).strict(),ticket:d.object({ticket:d.string().regex(/^[A-Za-z0-9_-]{43}$/u)}).strict(),empty:d.object({}).strict(),lobby:d.object({lobby_id:d.string().max(64),first_room:X.optional()}).strict(),room:d.object({room_id:X}).strict(),members:d.object({add:le.optional(),remove:le.optional()}).strict().refine(h=>h.add!==void 0||h.remove!==void 0,"Name a member"),source:d.object({repo:d.string().max(201),ref:d.string().max(200).optional(),notes:en(20)}).strict(),summary:Re,visibility:d.object({visibility:Ee}).strict(),viewer:d.object({email:F}).strict(),delete:d.object({confirm:d.string().max(64)}).strict(),icon:Le,displayName:d.object({display_name:d.string().max(200).optional()}).strict(),currency:d.object({currency:d.string().max(8)}).strict(),pacing:d.object({mode:d.enum(["off","subscription"]).optional(),hold_at:d.coerce.number().optional(),open_at:d.coerce.number().optional()}).strict(),agentKind:d.object({agent_id:d.string().min(1).max(48),kind:d.enum(["worker","on_demand"])}).strict(),clearTokens:d.object({before:d.string().max(10)}).strict(),memoryErase:d.object({kind:d.enum(["entry","fragment"]),key:d.string().min(1).max(64)}).strict(),memoryCurator:d.object({room_id:d.string().min(1).max(48),agent_id:d.string().min(1).max(48)}).strict()};class me{static{m(this,"Reply")}status;body;headers;constructor(f,o,x={}){this.status=f,this.body=o,this.headers=x}}const y=m((h={},f={})=>new me(200,{ok:!0,...h},f),"ok"),v=m((h,f,o,x={})=>new me(h,{error:{code:f,message:o}},x),"refuse");function bn(h,f){const{store:o,board:x,keys:W}=f,w=h.origin===null?null:new URL(h.origin),ge=h.responseFloorMs??1e3,be=new ae(10,15*6e4),ye=new ae(30,15*6e4),R=new Map,M=new Map,Y=m((e,t="/")=>`${w.protocol}//${e}.${f.boardDomain}${w.port?`:${w.port}`:""}${t}`,"dashboardUrl"),G=m((e,t)=>w?`${e}.${f.boardDomain}`:`${t}/${e}`,"address"),I=m((e,t="/")=>Y(e,`/sign-in${t==="/"?"":`?to=${encodeURIComponent(t)}`}`),"openUrl"),Z=m((e,t,l)=>`${w.origin}/open/${encodeURIComponent(e)}?${t==="/"?"":`to=${encodeURIComponent(t)}&`}state=${l}`,"handoffUrl");function p(e,t,l,i,g,s,n={}){t.writeHead(l,{"content-type":i,"cache-control":"no-store","x-content-type-options":"nosniff","referrer-policy":"same-origin","content-security-policy":i.startsWith("text/html")?Me(s):"default-src 'none'; frame-ancestors 'none'",...n}),t.end(e.method==="HEAD"?void 0:g)}m(p,"send");function Q(e,t){const l=P(e.headers.cookie,E);if(!l)return null;const i=o.consoleSession(T(l));return i?.refresh&&(o.refreshConsoleSession(T(l)),t["set-cookie"]=J(E,l)),i}m(Q,"session");function K(e){if(w)return!1;const t=P(e.headers.cookie,H),l=t===null?void 0:M.get(T(t));return l!==void 0&&l>f.clock()}m(K,"operator");function q(e){const t=P(e.headers.cookie,H);return t&&M.delete(T(t)),{"set-cookie":ue(null)}}m(q,"endOperator");async function C(e,t,l,i,g=Ze){if(e.headers.origin!==l)throw e.resume(),new O(403,"origin_not_allowed","Use the settings page itself.");if(e.headers["content-type"]?.split(";",1)[0]?.trim()!=="application/json")throw e.resume(),new O(415,"content_type","Use application/json.");if(Number(e.headers["content-length"])>g)throw e.resume(),new O(413,"body_too_large","The request is too large.");const s=[];let n=0;for await(const r of e)n+=r.length,n<=g&&s.push(r);if(n>g)throw new O(413,"body_too_large","The request is too large.");if(i&&!i())throw new O(401,"sign_in_required","Your session has ended. Sign in again.");let c;try{c=JSON.parse(Buffer.concat(s).toString("utf8"))}catch{throw new O(400,"invalid_json","The request is not valid JSON.")}return t.parse(c)}m(C,"input");async function he(e){const{email:t}=await C(e,b.code,w.origin),l=Date.now()+ge;if(!h.mailer)return v(503,"sign_in_unavailable","Sign-in is not configured on this server.");const i=be.take(f.clientAddress(e));if(i)return v(429,"too_many_requests",`Too many codes asked from here. Try again in ${Math.ceil(i/60)} min.`,{"retry-after":String(i)});const g=W.emailKey(t),s=xe(),n=o.beginSignIn(t,g,W.codeMac(g,s));if(n.wait)return v(429,"too_many_requests",`Wait ${n.wait<120?`${n.wait} s`:`${Math.ceil(n.wait/60)} min`} before asking for another code.`,{"retry-after":String(n.wait)});let c=null;if(n.send)try{await h.mailer.sendSignInCode(t,s)}catch(a){c=a instanceof ze?a.message:"The email could not be sent"}const r=l-Date.now();return r>0&&await $e(r),c?v(502,"mail_failed",`We could not send the code: ${c}. Try again in a minute.`):y({message:`If ${t} may sign in, a code is on its way. It works for 10 minutes.`})}m(he,"signInCode");async function pe(e){const{email:t,code:l,lobby:i,to:g,state:s}=await C(e,b.verify,w.origin),n=ye.take(f.clientAddress(e));if(n)return v(429,"too_many_requests",`Too many tries from here. Try again in ${Math.ceil(n/60)} min.`,{"retry-after":String(n)});const c=W.emailKey(t),r=V(),a=o.finishSignIn(t,c,W.codeMac(c,l),T(r));if("error"in a)return a.error==="budget"?v(429,"too_many_wrong_codes",`Too many wrong codes for this address. Wait ${Math.ceil(a.wait/60)} min, then ask for a new code.`,{"retry-after":String(a.wait)}):v(400,"code_invalid","That code is not right, has expired, or had 5 wrong tries. Check the email, or ask for a new code.");const _=fe(g??null);return y({redirect:i?s?Z(i,_,s):I(i,_):"/"},{"set-cookie":J(E,r)})}m(pe,"signInVerify");async function we(e,t,l,i,g){const{lobby:s}=l,n=m((r,a)=>C(e,r,l.origin,g,a),"body"),c=/^rooms\/([^/]+)\/(members|source|source\/remove|archive|restore)$/u.exec(i);if(i==="rooms"){const{room_id:r}=await n(b.room);return o.createRoom(t,r,s),y()}if(c){const r=X.parse(c[1]);if(c[2]==="members"){const a=await n(b.members);return o.changeRoomMembers(t,r,{...a.add?{add:[a.add]}:{},...a.remove?{remove:[a.remove]}:{}},s),y()}if(c[2]==="source"){const a=await n(b.source);return o.setBoardSource(s,r,je.parse(a),t),f.refreshBoards(s),y()}return await n(b.empty),c[2]==="source/remove"?o.removeBoardSource(s,r,t):c[2]==="archive"?o.archiveRoom(t,r,s):o.restoreRoom(t,r,s),y()}if(i==="summaries")return o.setSummarySettings(t,s,await n(b.summary)),y({message:"Saved. The next summary uses these settings."});if(i==="summaries/test")return await n(b.empty),x.runNow(s).catch(()=>{}),y({message:"Writing a test summary now. Reload in a minute to see it."});if(i==="access/visibility"){const{visibility:r}=await n(b.visibility);return o.setBoardVisibility(t,s,r),y()}if(i==="display-name"){const{display_name:r}=await n(b.displayName);return o.setDisplayName(t,s,r??""),y()}if(i==="currency"){const{currency:r}=await n(b.currency);return o.setLobbyCurrency(t,s,r),y({message:`Saved: costs show in ${r} from the next page.`})}if(i==="pacing")return o.setLobbyPacing(t,s,await n(b.pacing)),y();if(i==="agent-kind"){const{agent_id:r,kind:a}=await n(b.agentKind);return o.setAgentKind(t,s,r,a),y()}if(i==="access/icon"){const{png:r}=await n(b.icon,Qe);return o.setBoardIcon(t,s,Buffer.from(r,"base64")),y()}if(i==="access/icon/remove")return await n(b.empty),o.setBoardIcon(t,s,null),y();if(i==="access/viewers")return o.addBoardViewer(t,s,(await n(b.viewer)).email),y();if(i==="access/viewers/remove")return o.removeBoardViewer(t,s,(await n(b.viewer)).email),y();if(i==="memory/erase"){const{kind:r,key:a}=await n(b.memoryErase);return o.eraseMemory(s,r,a,t),y()}if(i==="memory/curator"){const{room_id:r,agent_id:a}=await n(b.memoryCurator);return o.setMemoryCurator(s,r,a==="none"?null:a,t),y()}if(i==="tokens/clear"){const{before:r}=await n(b.clearTokens),{deleted:a}=o.clearTokens(t,s,r);return y({message:`Deleted ${a} daily total${a===1?"":"s"}.`})}if(i==="delete"){const{confirm:r}=await n(b.delete),a=o.deleteLobby(t,s,r);return f.closeAgents(a.agents),y({redirect:w?`${w.origin}/`:"/"})}return e.resume(),v(404,"not_found","Unknown settings route.")}m(we,"lobbyAction");function _e(e,t,l,i,g,s){const{lobby:n}=t,c={nonce:i,email:e.kind==="account"?e.email:null,home:w?`${w.origin}/`:"/",signOut:`${t.base}/settings/api/sign-out`,section:l,lobby:{id:n,name:o.displayName(n)??n,address:G(n,g),url:t.base||"/",link:`${t.origin}${t.base||"/"}`,icon:o.boardIcon(n)?.sha256??null,settings:`${t.base}/settings`,api:`${t.base}/settings/api`,money:o.lobbyMoney(n)}},r=o.boardConfig(n);switch(l){case"overview":return We(c,{view:x.view(n),config:r,rooms:o.rooms(n),agents:o.agents(n),viewers:o.boardViewers(n).length,sessions:o.boardSessionCount(n),last:o.boardLastAttempt(n)});case"rooms":return Ke(c,{rooms:o.rooms(n),archived:o.archivedRooms(n),config:r,view:x.view(n),snapshots:o.boardNotes(n),repos:o.lobbyRepos(n),agents:o.agents(n),github:f.github});case"summaries":return Ge(c,{config:r,keySet:f.anthropic,usage:o.boardUsage(n,f.clock()-864e5),last:o.boardLastAttempt(n),good:o.boardSummary(n)});case"access":return De(c,{config:r,icon:o.boardIcon(n),viewers:o.boardViewers(n),sessions:o.boardSessionCount(n),owner:e.kind==="account"?e.email:null});case"agents":return Pe(c,{agents:o.agents(n),rooms:o.rooms(n),config:r,connected:m(a=>f.isConnected(n,a),"connected"),curates:m(a=>o.curationStatus(n,a).map(_=>_.room_id),"curates")});case"pacing":return Be(c,{agents:o.agents(n),config:r,pacing:o.lobbyPacing(n),week:m(a=>o.agentWeek(Je(n,a)),"week"),now:f.clock()});case"tokens":{const a=s.get("by")==="week"?"week":s.get("by")==="month"?"month":"day",_=a==="week"?Ae:a==="month"?k=>k.slice(0,7):void 0;return Ye(c,{by:a,periods:Ne(o.tokenDays(n),_??(k=>k)).reverse(),prices_as_of:Fe,clearable:new Date(f.clock()-Xe).toISOString().slice(0,10)})}case"memory":{const a=r.agents;return Ve(c,{rooms:o.rooms(n),memory:o.memoryOverview(n),people:Object.fromEntries(o.agents(n).map(_=>{const k=a[_.agent_id];return[_.agent_id,{name:k?.name??Ie(_.agent_id),emoji:k?.emoji??null}]}))})}case"activity":return Ue(c,{events:o.activity(n)});case"general":return He(c,{display_name:o.displayName(n),agents:o.agents(n).filter(a=>a.enabled).length,created:o.lobbyCreatedAt(n),currency:{chosen:o.lobbyCurrency(n),table:o.exchangeRates(),fetching:f.exchangeRates}})}}m(_e,"lobbyPage");async function ee(e,t,l,i,g){let s;try{s=await g()}catch(n){s=n instanceof O?v(n.status,n.code,n.message):n instanceof Te?v(400,"invalid_request",n.issues.map(c=>c.message).join("; ")):v(500,"internal_error","That could not be done. Nothing is implied to have changed; reload and check.")}p(e,t,s.status,"application/json; charset=utf-8",JSON.stringify(s.body),l,{...i,...s.headers})}return m(ee,"reply"),{openUrl:I,handoffUrl:Z,home:w?`${w.origin}/`:"/",handles:m(e=>e==="/sign-in"||/^\/open\/[^/]+$/u.test(e)||e.startsWith("/api/"),"handles"),ticket(){if(w)throw new O(404,"not_local","This broker signs in by email.");const e=V(),t=f.clock();for(const[l,i]of R)i<=t&&R.delete(l);return R.set(T(e),t+qe),e},operator:K,endOperator:q,async account(e,t){const l=new URL(e.url??"/","http://settings.invalid"),i=oe(16).toString("base64"),g={},s=e.method??"GET",n="text/html; charset=utf-8",c=e.headers.host??"";if(w&&c.toLowerCase()!==w.host){e.resume(),p(e,t,404,"text/plain; charset=utf-8","Not found.",i);return}if(f.overRate(f.clientAddress(e))){e.resume(),p(e,t,429,"text/plain; charset=utf-8","Too many requests; wait a minute.",i,{"retry-after":"60"});return}const r=w?w.origin:`http://${c}`;if(l.pathname.startsWith("/api/")){if(s!=="POST"){e.resume(),p(e,t,405,"text/plain; charset=utf-8","Use POST.",i);return}await ee(e,t,i,g,async()=>{const u=l.pathname;if(!w){if(u==="/api/sign-in/ticket"){const{ticket:$}=await C(e,b.ticket,r),N=T($),U=R.get(N);if(R.delete(N),U===void 0||U<=f.clock())return v(400,"ticket_invalid","That sign-in link has expired or was already used. Run pocolobby settings again.");const ne=V(),te=f.clock();for(const[ke,ve]of M)ve<=te&&M.delete(ke);return M.set(T(ne),te+de),y({redirect:"/"},{"set-cookie":ue(ne)})}if(u==="/api/sign-out")return await C(e,b.empty,r),y({redirect:"/"},q(e));if(!K(e))return e.resume(),v(401,"sign_in_required","Run pocolobby settings to sign in.");if(u==="/api/lobbies"){const $=await C(e,b.lobby,r,()=>K(e)),N=o.createLobby($.lobby_id);return $.first_room&&o.createRoom("owner",$.first_room,N.lobby_id),y({redirect:`/${N.lobby_id}/settings`})}return e.resume(),v(404,"not_found","Unknown settings route.")}if(u==="/api/sign-in/code")return he(e);if(u==="/api/sign-in/verify")return pe(e);if(u==="/api/sign-out"){await C(e,b.empty,r);const $=P(e.headers.cookie,E);return $&&o.endConsoleSession(T($)),y({redirect:"/"},{"set-cookie":J(E,null)})}const j=Q(e,g);if(!j)return e.resume(),v(401,"sign_in_required","Your session has ended. Sign in again.");if(u==="/api/lobbies"){const $=m(()=>{const U=P(e.headers.cookie,E);return U!==null&&o.consoleSession(T(U))?.account_id===j.account_id},"still"),N=o.createOwnedLobby(j.account_id,await C(e,b.lobby,r,$));return y({redirect:I(N.lobby_id,"/settings")})}return e.resume(),v(404,"not_found","Unknown settings route.")});return}if(e.resume(),s!=="GET"&&s!=="HEAD"){p(e,t,405,"text/plain; charset=utf-8","Use GET.",i);return}const a=l.pathname.replace(/\/$/u,"")||"/";if(!w){if(!K(e)){p(e,t,200,n,ce({nonce:i,email:null},{missing:[],lobby:null,local:!0}),i);return}if(a!=="/"){p(e,t,303,"text/plain; charset=utf-8","",i,{location:"/"});return}p(e,t,200,n,se({nonce:i,email:null,signOut:"/api/sign-out"},{owned:o.operatorLobbies(),viewing:[],open:m(u=>`/${u}/`,"open"),mayCreate:!0,remaining:null,address:m(u=>G(u,c),"address")}),i);return}const _=Q(e,g),k=/^\/open\/([^/]+)$/u.exec(a),L=fe(l.searchParams.get("to")),A=l.searchParams.get("state");if(k&&D.safeParse(k[1]).success&&(A===null||!ie.test(A))){p(e,t,303,"text/plain; charset=utf-8","",i,{...g,location:I(k[1],L)});return}if(!_){const u=k?k[1]:null;if(a==="/"||a==="/sign-in"||k){p(e,t,200,n,ce({nonce:i,email:null},{missing:h.missing,lobby:u!==null&&D.safeParse(u).success?u:null,to:L,state:A,local:!1}),i,g);return}p(e,t,303,"text/plain; charset=utf-8","",i,{location:"/sign-in"});return}const S={nonce:i,email:_.email,signOut:"/api/sign-out"};if(k){const u=k[1],j=V();if(D.safeParse(u).success&&o.createHandoff(_.account_id,u,Oe(j,A))){p(e,t,303,"text/plain; charset=utf-8","",i,{...g,location:Y(u,`/handoff?token=${j}${L==="/"?"":`&to=${encodeURIComponent(L)}`}`)});return}if(D.safeParse(u).success&&o.boardVisibility(u)==="public"){p(e,t,303,"text/plain; charset=utf-8","",i,{...g,location:Y(u)});return}p(e,t,404,n,B(S,"No lobby to open",`${_.email} cannot open a lobby named ${u}. Ask its owner to add you as a viewer.`,{href:"/",label:"Your lobbies"}),i,g);return}if(a==="/sign-in"){p(e,t,303,"text/plain; charset=utf-8","",i,{...g,location:"/"});return}if(a!=="/"){p(e,t,404,n,B(S,"Not found","There is no such page.",{href:"/",label:"Your lobbies"}),i,g);return}const z=o.consoleLobbies(_.account_id);p(e,t,200,n,se(S,{owned:z.owned,viewing:z.viewing.map(u=>({lobby_id:u.lobby_id,display_name:u.display_name,url:I(u.lobby_id)})),open:m(u=>I(u),"open"),mayCreate:_.may_create_lobbies,remaining:re.lobbiesPerAccount-z.owned.length,address:m(u=>G(u,c),"address")}),i,g)},async lobby(e,t,l,i,g,s){const n=new URL(e.url??"/","http://settings.invalid"),c=oe(16).toString("base64"),r=e.method??"GET",a="text/html; charset=utf-8",_=n.pathname.slice(l.base.length).replace(/\/$/u,"")||"/",k=m(S=>S!==null&&(S.kind==="operator"?o.boardVisibility(l.lobby)!==null:o.ownsLobby(S.account_id,l.lobby)),"owns"),L=w?I(l.lobby,_):"/";if(_.startsWith("/settings/api/")){if(r!=="POST"){e.resume(),p(e,t,405,"text/plain; charset=utf-8","Use POST.",c);return}await ee(e,t,c,{},async()=>{if(_==="/settings/api/sign-out")return await C(e,b.empty,l.origin),y({redirect:w?`${w.origin}/`:"/"},s());if(!k(i))return e.resume(),i===null?v(401,"sign_in_required","Your session has ended. Sign in again."):v(404,"lobby_not_found","Unknown lobby");const S=i.kind==="operator"?"owner":{account_id:i.account_id};return we(e,S,l,_.slice(14),()=>g()&&k(i))});return}if(e.resume(),r!=="GET"&&r!=="HEAD"){p(e,t,405,"text/plain; charset=utf-8","Use GET.",c);return}if(i===null){p(e,t,303,"text/plain; charset=utf-8","",c,{location:L});return}if(!k(i)){p(e,t,i.kind==="account"?403:404,a,i.kind==="account"?B({nonce:c,email:i.email},"Settings are for the owner","Only the lobby\u2019s owner can open its settings. Its dashboard is still yours to see.",{href:`${l.base}/`,label:"Dashboard"}):B({nonce:c,email:null},"Not found","There is no lobby by that name.",{href:"/",label:"Your lobbies"}),c);return}if(_==="/settings/icon.png"){const S=o.boardIcon(l.lobby);S?p(e,t,200,"image/png",S.png,c,{"content-length":String(S.png.length),"cache-control":"private, no-cache"}):p(e,t,404,"text/plain; charset=utf-8","Not found.",c);return}const A=/^\/settings(?:\/(rooms|summaries|access|agents|pacing|tokens|memory|activity|general))?$/u.exec(_);if(!A){p(e,t,404,a,B({nonce:c,email:i.kind==="account"?i.email:null},"Not found","There is no such settings page.",{href:`${l.base}/settings`,label:"Settings"}),c);return}p(e,t,200,a,_e(i,l,A[1]??"overview",c,e.headers.host??"",n.searchParams),c)}}}m(bn,"createConsole");function ue(h){return h===null?`${H}=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0`:`${H}=${h}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${de/1e3}`}m(ue,"localCookie");function fe(h){return h!==null&&/^\/(settings(\/(rooms|summaries|access|agents|pacing|tokens|memory|activity|general))?)?$/u.test(h)?h:"/"}m(fe,"destination");export{bn as createConsole,fe as destination};
package/dist/pace.js CHANGED
@@ -1 +1 @@
1
- var _=Object.defineProperty;var t=(n,e)=>_(n,"name",{value:e,configurable:!0});const E=6048e5,u=5;function F(n,e,c){const a=e*1e3-c;if(a<=0)return null;const r=Math.min(100,Math.max(0,(1-a/6048e5)*100)),o=t(i=>Math.round(i*10)/10,"tenth");return{line:o(r),lead:o(n-r),per_day:o(Math.max(0,100-n)/(a/(1440*6e4)))}}t(F,"weeklyPace");function M(n){return n>5?"ahead":n<-5?"behind":"on"}t(M,"paceState");export{u as PACE_OFF,M as paceState,F as weeklyPace};
1
+ var c=Object.defineProperty;var e=(n,t)=>c(n,"name",{value:t,configurable:!0});const p=6048e5,h=5;function x(n,t,o){const r=t*1e3-o;if(r<=0)return null;const i=Math.min(100,Math.max(0,(1-r/6048e5)*100)),a=e(_=>Math.round(_*10)/10,"tenth");return{line:a(i),lead:a(n-i),per_day:a(Math.max(0,100-n)/(r/(1440*6e4)))}}e(x,"weeklyPace");function E(n){return n>5?"ahead":n<-5?"behind":"on"}e(E,"paceState");const f={mode:"subscription",hold_at:0,open_at:-3};function l(n,t,o){return t===null?"open":t>o.hold_at?"no_new_tasks":t<=o.open_at?"open":n}e(l,"nextPacing");export{f as DEFAULT_PACING,h as PACE_OFF,l as nextPacing,E as paceState,x as weeklyPace};
package/dist/protocol.js CHANGED
@@ -1 +1 @@
1
- var H=Object.defineProperty;var n=(t,o)=>H(t,"name",{value:o,configurable:!0});import{z as e}from"zod";import{AttachmentDescriptor as F,MAX_ATTACHMENTS as V}from"./attachments.js";const Se=1,W=64*1024,Ee=80*1024,ve=8*1024,Ae=72*1024,we=32*1024,Re=64*1024,r=e.string().regex(/^[a-z][a-z0-9_-]{0,47}$/),u=r,i=r,G=["admin","agents","api","app","assets","board","console","dashboard","healthz","knock","lobby","mail","open","pocolobby","settings","sign-in","static","status","v1","www"],Z=u.regex(/^[a-z](?:[a-z0-9-]{0,46}[a-z0-9])?$/u,"Use lowercase letters, digits and inner hyphens, starting with a letter").refine(t=>!G.includes(t),"This name is reserved for the service and cannot name a lobby"),Te=e.string().regex(/^[A-Z]{3}$/u,"A three-letter currency code, such as SEK"),Me=e.string().trim().max(40,"Use at most 40 characters").regex(/^[^\p{Cc}]*$/u,"A display name cannot hold control characters");function je(t,o){return`${u.parse(t)}/${r.parse(o)}`}n(je,"qualifyAgent");function Ie(t){const o=t.split("/");if(o.length!==2)throw new be(400,"invalid_principal","Invalid agent identity");return{lobby_id:u.parse(o[0]),agent_id:r.parse(o[1])}}n(Ie,"parsePrincipal");const Oe=e.object({lobby_id:Z}).strict(),h=e.string().max(254).transform(t=>t.trim().toLowerCase()).refine(t=>/^[^\s@<>()",;:\\[\]]+@[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)+$/u.test(t),"Use an email address such as name@example.com"),ke=e.object({email:h,enabled:e.boolean().optional(),may_create_lobbies:e.boolean().optional()}).strict(),Ne=e.object({email:h}).strict(),Ce=e.object({room_id:i}).strict(),De=e.object({members:e.array(r).max(100)}).strict(),$e=e.object({add:e.array(r).max(100).optional(),remove:e.array(r).max(100).optional()}).strict().refine(t=>t.add?.length||t.remove?.length,"Name members to add or remove").refine(t=>!t.add?.some(o=>t.remove?.includes(o)),"An agent cannot be both added and removed"),m=e.string().min(1).max(128),Le="pocolobby:",E=e.string().min(1).refine(t=>Buffer.byteLength(t)<=W,"Content exceeds 64 KiB"),Q=["request","notice","assignment","report","question"],J=e.enum(Q,{error:"kind is one of request, notice, assignment, report or question; an answer is a report, or a question when you need a reply"}),ze=n(t=>t!=="notice"&&t!=="report","defaultReplyExpected"),ee=n(t=>t!=="notice","fingerprintReplyDefault"),v=8*1024,d=n(t=>e.string().min(1).max(t).regex(/^[^\p{Cc}]*$/u,"One line without control characters"),"OneLine"),te={kind:J.optional(),reply_expected:e.boolean().optional(),commit:d(100).optional(),commits:e.array(d(100)).min(1).max(10).optional(),files:e.array(d(300)).min(1).max(50).optional(),evidence:d(500).regex(/^[a-z][a-z0-9+.-]+:\S/u,"Use a logical location each machine resolves itself: a lowercase scheme, a colon and a path, such as dropbox:team/reports/run-42 or repo:docs/report.md, not a local absolute path").optional(),options:e.array(d(500)).min(1).max(10).optional(),recommendation:e.string().min(1).max(2e3).optional(),notify_when_seen:e.boolean().optional()},oe=["commit","commits","files","evidence","options","recommendation"];function ne(t){const o={};for(const a of oe)t[a]!==void 0&&(o[a]=t[a]);return Object.keys(o).length?o:null}n(ne,"messageDetails");const A=n(t=>Buffer.byteLength(JSON.stringify(ne(t)??{}))<=v,"detailsFit"),x=e.string().max(40).regex(/^\d{4}-\d\d-\d\dT\d\d:\d\d(:\d\d(\.\d{1,3})?)?(Z|[+-]\d\d:\d\d)$/u,"Use an ISO 8601 time with Z or an offset, such as 2026-10-16T06:41:00+02:00").refine(t=>Number.isFinite(Date.parse(t)),"Not a valid time"),Ue=e.object({agents:e.array(r).min(1).max(100).describe("The agents to rest or resume"),resting:e.boolean().describe("true rests them, false resumes them"),resume_at:x.optional().describe("With resting true: when they resume by themselves, an ISO time with Z or an offset, such as 2026-10-20T01:05:00+02:00. Without it they rest until resumed")}).strict().refine(t=>t.resting||t.resume_at===void 0,{message:"resume_at goes with resting true"}),Ye=720*60*60*1e3,Xe=300*1e3,re=20,w={path:["to"],message:"A room message uses to: * for every member, or a list of members; a list needs a room"},R=n(t=>t.room===void 0?!Array.isArray(t.to):t.to==="*"||Array.isArray(t.to),"roomAddressed"),T={path:["to"],message:"Name each member once"},M=n(t=>!Array.isArray(t.to)||new Set(t.to).size===t.to.length,"recipientsDistinct"),j={path:["files"],message:`Structured fields exceed ${v} bytes together`},I={client_request_id:m,to:e.union([r,e.literal("*"),e.array(r).min(1).max(re)]),priority:e.enum(["info","important"]).default("info"),content:E,correlation_id:m.optional(),reply_to:m.optional(),room:i.optional(),...te,deliver_at:x.optional(),attachments:e.array(F).min(1).max(V).optional(),supersedes:m.optional()},O={path:["attachments"],message:"Attach each file once"},k=n(t=>!t.attachments||new Set(t.attachments.map(o=>`${o.sha256}/${o.filename}`)).size===t.attachments.length,"attachmentsDistinct"),qe=e.object(I).strict().refine(R,w).refine(M,T).refine(A,j).refine(k,O);function Be(t){const{kind:o,reply_expected:a,notify_when_seen:_,deliver_at:p,...g}=t,c={...g};Array.isArray(g.to)&&(c.to=[...g.to].sort());const b=o??"request";return b!=="request"&&(c.kind=b),a!==void 0&&a!==ee(b)&&(c.reply_expected=a),_&&(c.notify_when_seen=!0),p!==void 0&&(c.deliver_at=new Date(p).toISOString()),c}n(Be,"canonicalSend");function Ke(t){return Array.isArray(t)?[...t].sort():null}n(Ke,"namedMembers");function Pe(t){if(typeof t!="string")return{};const o=JSON.parse(t).addressed_to;return o?{addressed_to:o}:{}}n(Pe,"addressedOf");const N=["mon","tue","wed","thu","fri","sat","sun"],ae=e.enum(N);function C(t){try{return new Intl.DateTimeFormat("en-US",{timeZone:t}).resolvedOptions().timeZone}catch{return null}}n(C,"canonicalTimeZone");const D=e.object({time_zone:e.string().min(1).max(64).refine(t=>C(t)!==null,"Unknown IANA time zone"),times:e.array(e.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/u,"Use HH:MM, 24-hour local time")).min(1).max(24),weekdays:e.array(ae).min(1).max(7).optional()}).strict();function He(t){return{time_zone:C(t.time_zone),times:[...new Set(t.times)].sort(),weekdays:t.weekdays?N.filter(o=>t.weekdays.includes(o)):null}}n(He,"canonicalRepeat");const{reply_to:Fe,deliver_at:Ve,supersedes:We,...ie}=I,Ge=e.object({...ie,repeat:D}).strict().refine(R,w).refine(M,T).refine(A,j).refine(k,O),Ze=e.object({id:e.uuid()}).strict(),Qe=e.object({id:e.uuid(),content:E.optional(),deliver_at:x.optional(),repeat:D.optional()}).strict().refine(t=>t.content!==void 0||t.deliver_at!==void 0||t.repeat!==void 0,{message:"Name what to change: content, deliver_at (a message) or repeat (a schedule)"}),$=e.string().trim().max(300),L=e.string().trim().max(40),Je=e.object({agent_id:r,lobby_id:u.optional(),manage_rooms:e.boolean().default(!1),role:e.string().max(16e3).default(""),work_description:$.default(""),machine:L.default(""),screen:e.boolean().default(!1),can_broadcast:e.boolean().default(!1),allowed_recipients:e.array(r).max(100).nullable().default(null)}).strict(),et=e.object({role:e.string().max(16e3).optional(),work_description:$.optional(),machine:L.optional(),screen:e.boolean().optional(),can_broadcast:e.boolean().optional(),manage_rooms:e.boolean().optional(),allowed_recipients:e.array(r).max(100).nullable().optional(),enabled:e.boolean().optional(),paused:e.boolean().optional()}).strict(),tt=e.object({runtime_id:e.uuid(),generation:e.number().int().nonnegative().optional()}).strict(),ot=e.object({message_ids:e.array(e.uuid()).min(1).max(100)}).strict(),nt=e.object({expected_revision:e.number().int().nonnegative(),content:e.string().max(32e3),covered_receipt_seq:e.number().int().nonnegative(),acknowledge_message_ids:e.array(e.uuid()).max(100).default([])}).strict(),rt=e.object({context_revision:e.number().int().nonnegative(),probe_nonce:e.string().min(1).max(128)}).strict(),se=20,at=e.object({count:e.number().int().min(0).max(se),text:e.string().max(300).regex(/^[^\p{Cc}]*$/u,"One line without control characters").default("")}).strict().refine(t=>t.count===0||t.text.trim()!=="",{path:["text"],message:"Say what you need from the owner"}),it=e.object({text:e.string().max(300).regex(/^[^\p{Cc}]*$/u,"One line without control characters")}).strict(),ce=["gotcha","fix","procedure"],z=e.enum(ce),f={gotcha:500,fix:800,procedure:2e3},s=e.string().regex(/^[a-z][a-z0-9_-]{0,47}-[1-9][0-9]{0,5}$/),st=e.object({client_request_id:m,room_id:i,kind:z,text:e.string().trim().min(1).max(f.procedure),evidence:e.string().trim().max(300).default(""),about:e.union([s,e.uuid()]).optional()}).strict(),ct=e.object({room_id:i.optional(),query:e.string().trim().max(200).default(""),ids:e.string().max(1200).transform(t=>t.split(",").map(o=>o.trim()).filter(Boolean)).pipe(e.array(s).max(20)).optional(),mine:e.enum(["true","false"]).transform(t=>t==="true").optional()}).strict(),me=250,U=e.string().trim().min(1).max(me),Y=e.string().trim().max(200),y=e.string().trim().min(1).max(300),X=e.array(e.uuid()).max(20),de=500,le=e.discriminatedUnion("op",[e.object({op:e.literal("add"),kind:z,title:U,text:e.string().trim().min(1).max(f.procedure),keywords:Y.default(""),sources:X.min(1)}).strict(),e.object({op:e.literal("update"),entry:s,title:U.optional(),text:e.string().trim().min(1).max(f.procedure).optional(),keywords:Y.optional(),sources:X.default([]),resolves:y.optional()}).strict(),e.object({op:e.literal("verify"),entry:s}).strict(),e.object({op:e.literal("archive"),entry:s,reason:y,into:s.optional()}).strict(),e.object({op:e.literal("refuse"),fragment:e.uuid(),reason:y,erase:e.boolean().default(!1),dispute:s.optional(),unlanded:e.boolean().default(!1)}).strict()]),q=e.object({attempt:e.uuid().optional(),model:e.string().max(80).optional(),cost_usd:e.number().nonnegative().max(1e3).optional(),input_tokens:e.number().int().nonnegative().optional(),cache_write_tokens:e.number().int().nonnegative().optional(),cache_read_tokens:e.number().int().nonnegative().optional(),output_tokens:e.number().int().nonnegative().optional(),duration_ms:e.number().int().nonnegative().optional()}).strict(),mt=e.object({room_id:i,revision:e.number().int().nonnegative(),commit:e.string().regex(/^[0-9a-f]{7,64}$/),review:e.boolean().default(!1),ops:e.array(le).max(de),summary:e.string().trim().max(1e3).default(""),usage:q.optional()}).strict(),dt=e.object({room_id:i,error:e.string().trim().min(1).max(500),usage:q.optional()}).strict(),lt=e.object({room_id:i,client_request_id:m,to:r,priority:e.enum(["info","important"]).default("info"),content:e.string().trim().min(1).max(8e3)}).strict(),B=e.object({lines:e.number().int().nonnegative(),new:e.number().int().nonnegative(),changed:e.number().int().nonnegative(),removed:e.number().int().nonnegative()}).strict(),pe=28,pt=e.object({room_id:i,head:e.string().regex(/^[0-9a-f]{40,64}$/),computed_at:x,baseline:e.object({code:e.number().int().nonnegative(),tests:e.number().int().nonnegative()}).strict(),days:e.array(e.object({day:e.string().regex(/^\d{4}-\d\d-\d\d$/),commits:e.number().int().nonnegative(),authors:e.array(e.object({name:e.string().trim().min(1).max(100),commits:e.number().int().positive()}).strict()).max(12),code:B,tests:B}).strict()).length(pe)}).strict(),K=e.object({used_percentage:e.number().min(0).max(100),resets_at:e.number().int().positive()}).strict(),P=e.string().max(80).regex(/^[\w.[\]-]+$/u),ue=e.enum(["low","medium","high","xhigh","max"]),xe=e.object({name:e.string().min(1).max(40).regex(/^[\w .-]+$/u),used_percentage:e.number().min(0).max(100),resets_at:e.number().int().positive()}).strict();function ut(t,o){const a=o.trim().toLowerCase().replace(/[ .]+/gu,"-");return a!==""&&`-${t.toLowerCase().replace(/\[.*$/u,"")}-`.includes(`-${a}-`)}n(ut,"windowCovers");const xt=e.object({five_hour:K.optional(),seven_day:K.optional(),account:h.optional(),plan:e.string().max(40).regex(/^[\w .-]*$/u).optional(),model:P.optional(),effort:ue.optional(),context:e.number().int().positive().max(1e8).optional(),model_windows:e.array(xe).max(8).optional()}).strict(),S=e.number().int().positive().max(1e4),_e=e.object({shell:S.optional(),monitor:S.optional(),mcp_task:S.optional()}).strict().refine(t=>Object.keys(t).length>0,"Name at least one kind, or leave it out"),_t=e.object({event:e.enum(["start","stop","failed","waiting"]),at:e.number().int().positive(),background_tasks:e.number().int().nonnegative().max(1e4).optional(),running:_e.optional()}).strict(),l=e.number().int().nonnegative().max(1e8),ge=500,gt=e.object({calls:e.array(e.object({id:e.string().regex(/^[0-9a-f]{32}$/),at:e.number().int().positive(),model:P,speed:e.enum(["standard","fast"]).optional(),geo:e.string().max(40).regex(/^[\w-]+$/u).optional(),input:l,cache_write_5m:l,cache_write_1h:l,cache_read:l,output:l}).strict()).min(1).max(ge)}).strict(),bt=5,ht="x-pocolobby-event-version",ft="x-pocolobby-bridge-version",yt="0.12.2",St=e.string().regex(/^[a-z][a-z0-9_]{0,63}$/),Et=32,vt=4*1024,At=192*1024,wt=["id","lobby_id","room_id","sequence","from","to","priority","content","correlation_id","reply_to","created_at","agent_seen_at","receipt_seq","delivery_state","held_reason","kind","reply_expected","commit","files","evidence","options","recommendation","notify_when_seen","deliver_at","delivered_at","late","schedule_id","cancelled_at"],Rt=["id","from","to","room_id","priority","created_at","kind"],Tt=["message_id","seen_by","seen_at","kind","to","room_id","excerpt"],Mt=e.object({type:e.enum(["adapter_received","notification_attempted"]),notification_id:e.uuid()}).strict(),jt=e.string().regex(/^[0-9a-fA-F]{8}[0-9a-fA-F-]{0,28}$/u,"A message ID, or its first 8 or more characters"),It=20;class be extends Error{static{n(this,"LobbyError")}status;code;details;constructor(o,a,_,p){super(_),this.status=o,this.code=a,this.details=p,this.name="LobbyError"}}export{ke as AccountSettingsSchema,ot as AckSchema,_t as ActivityReportSchema,r as AgentId,Ae as BRIDGE_MAX_PUSH_BYTES,ft as BRIDGE_VERSION_HEADER,pe as CODE_STATS_DAYS,Ze as CancelScheduledSchema,nt as CheckpointSchema,pt as CodeStatsSchema,E as Content,dt as CurationFailureSchema,le as CurationOpSchema,lt as CurationReportSchema,mt as CurationSchema,q as CurationUsageSchema,Te as Currency,we as DEFAULT_PUSH_BYTES,oe as DETAIL_FIELDS,Me as DisplayName,bt as EVENT_VERSION,ht as EVENT_VERSION_HEADER,ue as Effort,h as Email,St as ExtensionKey,Rt as HEADER_KEYS,x as Instant,be as LobbyError,u as LobbyId,Oe as LobbySchema,W as MAX_CONTENT_BYTES,v as MAX_DETAILS_BYTES,At as MAX_EVENT_FRAME_BYTES,vt as MAX_EXTENSION_BYTES,Et as MAX_EXTENSION_KEYS,It as MAX_MESSAGE_IDS,re as MAX_NAMED_RECIPIENTS,se as MAX_OWNER_REQUESTS,Ee as MAX_PAGE_BYTES,Re as MAX_PUSH_BYTES,Ye as MAX_SCHEDULE_AHEAD_MS,ge as MAX_TOKEN_CALLS,ce as MEMORY_KINDS,de as MEMORY_OPS_LIMIT,f as MEMORY_TEXT_LIMITS,me as MEMORY_TITLE_LIMIT,wt as MESSAGE_KEYS,Q as MESSAGE_KINDS,ve as MIN_PUSH_BYTES,z as MemoryKind,s as MemoryRef,te as MessageDetailsShape,jt as MessageIdPrefix,J as MessageKind,P as ModelId,xe as ModelWindowSchema,Z as NewLobbyId,at as OwnerRequestsSchema,Ne as OwnerSchema,yt as PACKAGE_VERSION,Se as PROTOCOL_VERSION,Je as ProvisionSchema,Tt as RECEIPT_KEYS,G as RESERVED_LOBBY_IDS,Le as RESERVED_REQUEST_PREFIX,rt as ReadySchema,ct as RecallQuerySchema,st as RememberSchema,D as RepeatSchema,m as RequestId,Ue as RestAgentsSchema,i as RoomId,$e as RoomMemberChangesSchema,De as RoomMembersSchema,Ce as RoomSchema,_e as RunningSchema,tt as RuntimeSchema,Xe as SCHEDULE_PAST_TOLERANCE_MS,Ge as ScheduleSchema,qe as SendSchema,it as StatusSchema,gt as TokenReportSchema,Mt as TransportReceiptSchema,et as UpdateAgentSchema,Qe as UpdateScheduledSchema,xt as UsageReportSchema,N as WEEKDAYS,ae as Weekday,Pe as addressedOf,He as canonicalRepeat,Be as canonicalSend,C as canonicalTimeZone,ze as defaultReplyExpected,ne as messageDetails,Ke as namedMembers,Ie as parsePrincipal,je as qualifyAgent,ut as windowCovers};
1
+ var V=Object.defineProperty;var n=(t,o)=>V(t,"name",{value:o,configurable:!0});import{z as e}from"zod";import{AttachmentDescriptor as W,MAX_ATTACHMENTS as G}from"./attachments.js";const ve=1,Z=64*1024,Ae=80*1024,we=8*1024,Re=72*1024,Te=32*1024,Me=64*1024,r=e.string().regex(/^[a-z][a-z0-9_-]{0,47}$/),u=r,i=r,Q=["admin","agents","api","app","assets","board","console","dashboard","healthz","knock","lobby","mail","open","pocolobby","settings","sign-in","static","status","v1","www"],J=u.regex(/^[a-z](?:[a-z0-9-]{0,46}[a-z0-9])?$/u,"Use lowercase letters, digits and inner hyphens, starting with a letter").refine(t=>!Q.includes(t),"This name is reserved for the service and cannot name a lobby"),E=e.enum(["worker","on_demand"]),v=e.number().finite().min(-100).max(100),je=e.object({mode:e.enum(["off","subscription"]),hold_at:v,open_at:v}).strict().refine(t=>t.open_at<t.hold_at,{message:"New tasks again must be below no new tasks"}),Ie=e.string().regex(/^[A-Z]{3}$/u,"A three-letter currency code, such as SEK"),ke=e.string().trim().max(40,"Use at most 40 characters").regex(/^[^\p{Cc}]*$/u,"A display name cannot hold control characters");function Oe(t,o){return`${u.parse(t)}/${r.parse(o)}`}n(Oe,"qualifyAgent");function Ne(t){const o=t.split("/");if(o.length!==2)throw new fe(400,"invalid_principal","Invalid agent identity");return{lobby_id:u.parse(o[0]),agent_id:r.parse(o[1])}}n(Ne,"parsePrincipal");const Ce=e.object({lobby_id:J}).strict(),h=e.string().max(254).transform(t=>t.trim().toLowerCase()).refine(t=>/^[^\s@<>()",;:\\[\]]+@[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)+$/u.test(t),"Use an email address such as name@example.com"),De=e.object({email:h,enabled:e.boolean().optional(),may_create_lobbies:e.boolean().optional()}).strict(),Le=e.object({email:h}).strict(),$e=e.object({room_id:i}).strict(),ze=e.object({members:e.array(r).max(100)}).strict(),Ue=e.object({add:e.array(r).max(100).optional(),remove:e.array(r).max(100).optional()}).strict().refine(t=>t.add?.length||t.remove?.length,"Name members to add or remove").refine(t=>!t.add?.some(o=>t.remove?.includes(o)),"An agent cannot be both added and removed"),m=e.string().min(1).max(128),Ye="pocolobby:",A=e.string().min(1).refine(t=>Buffer.byteLength(t)<=Z,"Content exceeds 64 KiB"),ee=["request","notice","assignment","report","question"],te=e.enum(ee,{error:"kind is one of request, notice, assignment, report or question; an answer is a report, or a question when you need a reply"}),Pe=n(t=>t!=="notice"&&t!=="report","defaultReplyExpected"),oe=n(t=>t!=="notice","fingerprintReplyDefault"),w=8*1024,d=n(t=>e.string().min(1).max(t).regex(/^[^\p{Cc}]*$/u,"One line without control characters"),"OneLine"),ne={kind:te.optional(),reply_expected:e.boolean().optional(),commit:d(100).optional(),commits:e.array(d(100)).min(1).max(10).optional(),files:e.array(d(300)).min(1).max(50).optional(),evidence:d(500).regex(/^[a-z][a-z0-9+.-]+:\S/u,"Use a logical location each machine resolves itself: a lowercase scheme, a colon and a path, such as dropbox:team/reports/run-42 or repo:docs/report.md, not a local absolute path").optional(),options:e.array(d(500)).min(1).max(10).optional(),recommendation:e.string().min(1).max(2e3).optional(),notify_when_seen:e.boolean().optional()},re=["commit","commits","files","evidence","options","recommendation"];function ae(t){const o={};for(const a of re)t[a]!==void 0&&(o[a]=t[a]);return Object.keys(o).length?o:null}n(ae,"messageDetails");const R=n(t=>Buffer.byteLength(JSON.stringify(ae(t)??{}))<=w,"detailsFit"),x=e.string().max(40).regex(/^\d{4}-\d\d-\d\dT\d\d:\d\d(:\d\d(\.\d{1,3})?)?(Z|[+-]\d\d:\d\d)$/u,"Use an ISO 8601 time with Z or an offset, such as 2026-10-16T06:41:00+02:00").refine(t=>Number.isFinite(Date.parse(t)),"Not a valid time"),Xe=e.object({agents:e.array(r).min(1).max(100).describe("The agents to rest or resume"),resting:e.boolean().describe("true rests them, false resumes them"),resume_at:x.optional().describe("With resting true: when they resume by themselves, an ISO time with Z or an offset, such as 2026-10-20T01:05:00+02:00. Without it they rest until resumed")}).strict().refine(t=>t.resting||t.resume_at===void 0,{message:"resume_at goes with resting true"}),qe=720*60*60*1e3,Be=300*1e3,ie=20,T={path:["to"],message:"A room message uses to: * for every member, or a list of members; a list needs a room"},M=n(t=>t.room===void 0?!Array.isArray(t.to):t.to==="*"||Array.isArray(t.to),"roomAddressed"),j={path:["to"],message:"Name each member once"},I=n(t=>!Array.isArray(t.to)||new Set(t.to).size===t.to.length,"recipientsDistinct"),k={path:["files"],message:`Structured fields exceed ${w} bytes together`},O={client_request_id:m,to:e.union([r,e.literal("*"),e.array(r).min(1).max(ie)]),priority:e.enum(["info","important"]).default("info"),content:A,correlation_id:m.optional(),reply_to:m.optional(),room:i.optional(),...ne,deliver_at:x.optional(),attachments:e.array(W).min(1).max(G).optional(),supersedes:m.optional()},N={path:["attachments"],message:"Attach each file once"},C=n(t=>!t.attachments||new Set(t.attachments.map(o=>`${o.sha256}/${o.filename}`)).size===t.attachments.length,"attachmentsDistinct"),Ke=e.object(O).strict().refine(M,T).refine(I,j).refine(R,k).refine(C,N);function He(t){const{kind:o,reply_expected:a,notify_when_seen:_,deliver_at:p,...g}=t,c={...g};Array.isArray(g.to)&&(c.to=[...g.to].sort());const b=o??"request";return b!=="request"&&(c.kind=b),a!==void 0&&a!==oe(b)&&(c.reply_expected=a),_&&(c.notify_when_seen=!0),p!==void 0&&(c.deliver_at=new Date(p).toISOString()),c}n(He,"canonicalSend");function Fe(t){return Array.isArray(t)?[...t].sort():null}n(Fe,"namedMembers");function Ve(t){if(typeof t!="string")return{};const o=JSON.parse(t).addressed_to;return o?{addressed_to:o}:{}}n(Ve,"addressedOf");const D=["mon","tue","wed","thu","fri","sat","sun"],se=e.enum(D);function L(t){try{return new Intl.DateTimeFormat("en-US",{timeZone:t}).resolvedOptions().timeZone}catch{return null}}n(L,"canonicalTimeZone");const $=e.object({time_zone:e.string().min(1).max(64).refine(t=>L(t)!==null,"Unknown IANA time zone"),times:e.array(e.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/u,"Use HH:MM, 24-hour local time")).min(1).max(24),weekdays:e.array(se).min(1).max(7).optional()}).strict();function We(t){return{time_zone:L(t.time_zone),times:[...new Set(t.times)].sort(),weekdays:t.weekdays?D.filter(o=>t.weekdays.includes(o)):null}}n(We,"canonicalRepeat");const{reply_to:Ge,deliver_at:Ze,supersedes:Qe,...ce}=O,Je=e.object({...ce,repeat:$}).strict().refine(M,T).refine(I,j).refine(R,k).refine(C,N),et=e.object({id:e.uuid()}).strict(),tt=e.object({id:e.uuid(),content:A.optional(),deliver_at:x.optional(),repeat:$.optional()}).strict().refine(t=>t.content!==void 0||t.deliver_at!==void 0||t.repeat!==void 0,{message:"Name what to change: content, deliver_at (a message) or repeat (a schedule)"}),z=e.string().trim().max(300),U=e.string().trim().max(40),ot=e.object({agent_id:r,lobby_id:u.optional(),manage_rooms:e.boolean().default(!1),role:e.string().max(16e3).default(""),work_description:z.default(""),machine:U.default(""),screen:e.boolean().default(!1),kind:E.default("worker"),can_broadcast:e.boolean().default(!1),allowed_recipients:e.array(r).max(100).nullable().default(null)}).strict(),nt=e.object({role:e.string().max(16e3).optional(),work_description:z.optional(),machine:U.optional(),screen:e.boolean().optional(),kind:E.optional(),can_broadcast:e.boolean().optional(),manage_rooms:e.boolean().optional(),allowed_recipients:e.array(r).max(100).nullable().optional(),enabled:e.boolean().optional(),paused:e.boolean().optional()}).strict(),rt=e.object({runtime_id:e.uuid(),generation:e.number().int().nonnegative().optional()}).strict(),at=e.object({message_ids:e.array(e.uuid()).min(1).max(100)}).strict(),it=e.object({expected_revision:e.number().int().nonnegative(),content:e.string().max(32e3),covered_receipt_seq:e.number().int().nonnegative(),acknowledge_message_ids:e.array(e.uuid()).max(100).default([])}).strict(),st=e.object({context_revision:e.number().int().nonnegative(),probe_nonce:e.string().min(1).max(128)}).strict(),me=20,ct=e.object({count:e.number().int().min(0).max(me),text:e.string().max(300).regex(/^[^\p{Cc}]*$/u,"One line without control characters").default("")}).strict().refine(t=>t.count===0||t.text.trim()!=="",{path:["text"],message:"Say what you need from the owner"}),mt=e.object({text:e.string().max(300).regex(/^[^\p{Cc}]*$/u,"One line without control characters")}).strict(),de=["gotcha","fix","procedure"],Y=e.enum(de),f={gotcha:500,fix:800,procedure:2e3},s=e.string().regex(/^[a-z][a-z0-9_-]{0,47}-[1-9][0-9]{0,5}$/),dt=e.object({client_request_id:m,room_id:i,kind:Y,text:e.string().trim().min(1).max(f.procedure),evidence:e.string().trim().max(300).default(""),about:e.union([s,e.uuid()]).optional()}).strict(),lt=e.object({room_id:i.optional(),query:e.string().trim().max(200).default(""),ids:e.string().max(1200).transform(t=>t.split(",").map(o=>o.trim()).filter(Boolean)).pipe(e.array(s).max(20)).optional(),mine:e.enum(["true","false"]).transform(t=>t==="true").optional()}).strict(),le=250,P=e.string().trim().min(1).max(le),X=e.string().trim().max(200),y=e.string().trim().min(1).max(300),q=e.array(e.uuid()).max(20),pe=500,ue=e.discriminatedUnion("op",[e.object({op:e.literal("add"),kind:Y,title:P,text:e.string().trim().min(1).max(f.procedure),keywords:X.default(""),sources:q.min(1)}).strict(),e.object({op:e.literal("update"),entry:s,title:P.optional(),text:e.string().trim().min(1).max(f.procedure).optional(),keywords:X.optional(),sources:q.default([]),resolves:y.optional()}).strict(),e.object({op:e.literal("verify"),entry:s}).strict(),e.object({op:e.literal("archive"),entry:s,reason:y,into:s.optional()}).strict(),e.object({op:e.literal("refuse"),fragment:e.uuid(),reason:y,erase:e.boolean().default(!1),dispute:s.optional(),unlanded:e.boolean().default(!1)}).strict()]),B=e.object({attempt:e.uuid().optional(),model:e.string().max(80).optional(),cost_usd:e.number().nonnegative().max(1e3).optional(),input_tokens:e.number().int().nonnegative().optional(),cache_write_tokens:e.number().int().nonnegative().optional(),cache_read_tokens:e.number().int().nonnegative().optional(),output_tokens:e.number().int().nonnegative().optional(),duration_ms:e.number().int().nonnegative().optional()}).strict(),pt=e.object({room_id:i,revision:e.number().int().nonnegative(),commit:e.string().regex(/^[0-9a-f]{7,64}$/),review:e.boolean().default(!1),ops:e.array(ue).max(pe),summary:e.string().trim().max(1e3).default(""),usage:B.optional()}).strict(),ut=e.object({room_id:i,error:e.string().trim().min(1).max(500),usage:B.optional()}).strict(),xt=e.object({room_id:i,client_request_id:m,to:r,priority:e.enum(["info","important"]).default("info"),content:e.string().trim().min(1).max(8e3)}).strict(),K=e.object({lines:e.number().int().nonnegative(),new:e.number().int().nonnegative(),changed:e.number().int().nonnegative(),removed:e.number().int().nonnegative()}).strict(),xe=28,_t=e.object({room_id:i,head:e.string().regex(/^[0-9a-f]{40,64}$/),computed_at:x,baseline:e.object({code:e.number().int().nonnegative(),tests:e.number().int().nonnegative()}).strict(),days:e.array(e.object({day:e.string().regex(/^\d{4}-\d\d-\d\d$/),commits:e.number().int().nonnegative(),authors:e.array(e.object({name:e.string().trim().min(1).max(100),commits:e.number().int().positive()}).strict()).max(12),code:K,tests:K}).strict()).length(xe)}).strict(),H=e.object({used_percentage:e.number().min(0).max(100),resets_at:e.number().int().positive()}).strict(),F=e.string().max(80).regex(/^[\w.[\]-]+$/u),_e=e.enum(["low","medium","high","xhigh","max"]),ge=e.object({name:e.string().min(1).max(40).regex(/^[\w .-]+$/u),used_percentage:e.number().min(0).max(100),resets_at:e.number().int().positive()}).strict();function gt(t,o){const a=o.trim().toLowerCase().replace(/[ .]+/gu,"-");return a!==""&&`-${t.toLowerCase().replace(/\[.*$/u,"")}-`.includes(`-${a}-`)}n(gt,"windowCovers");const bt=e.object({five_hour:H.optional(),seven_day:H.optional(),account:h.optional(),plan:e.string().max(40).regex(/^[\w .-]*$/u).optional(),model:F.optional(),effort:_e.optional(),context:e.number().int().positive().max(1e8).optional(),model_windows:e.array(ge).max(8).optional()}).strict(),S=e.number().int().positive().max(1e4),be=e.object({shell:S.optional(),monitor:S.optional(),mcp_task:S.optional()}).strict().refine(t=>Object.keys(t).length>0,"Name at least one kind, or leave it out"),ht=e.object({event:e.enum(["start","stop","failed","waiting"]),at:e.number().int().positive(),background_tasks:e.number().int().nonnegative().max(1e4).optional(),running:be.optional()}).strict(),l=e.number().int().nonnegative().max(1e8),he=500,ft=e.object({calls:e.array(e.object({id:e.string().regex(/^[0-9a-f]{32}$/),at:e.number().int().positive(),model:F,speed:e.enum(["standard","fast"]).optional(),geo:e.string().max(40).regex(/^[\w-]+$/u).optional(),input:l,cache_write_5m:l,cache_write_1h:l,cache_read:l,output:l}).strict()).min(1).max(he)}).strict(),yt=5,St="x-pocolobby-event-version",Et="x-pocolobby-bridge-version",vt="0.14.0",At=e.string().regex(/^[a-z][a-z0-9_]{0,63}$/),wt=32,Rt=4*1024,Tt=192*1024,Mt=["id","lobby_id","room_id","sequence","from","to","priority","content","correlation_id","reply_to","created_at","agent_seen_at","receipt_seq","delivery_state","held_reason","kind","reply_expected","commit","files","evidence","options","recommendation","notify_when_seen","deliver_at","delivered_at","late","schedule_id","cancelled_at"],jt=["id","from","to","room_id","priority","created_at","kind"],It=["message_id","seen_by","seen_at","kind","to","room_id","excerpt"],kt=e.object({type:e.enum(["adapter_received","notification_attempted"]),notification_id:e.uuid()}).strict(),Ot=e.string().regex(/^[0-9a-fA-F]{8}[0-9a-fA-F-]{0,28}$/u,"A message ID, or its first 8 or more characters"),Nt=20;class fe extends Error{static{n(this,"LobbyError")}status;code;details;constructor(o,a,_,p){super(_),this.status=o,this.code=a,this.details=p,this.name="LobbyError"}}export{De as AccountSettingsSchema,at as AckSchema,ht as ActivityReportSchema,r as AgentId,E as AgentKind,Re as BRIDGE_MAX_PUSH_BYTES,Et as BRIDGE_VERSION_HEADER,xe as CODE_STATS_DAYS,et as CancelScheduledSchema,it as CheckpointSchema,_t as CodeStatsSchema,A as Content,ut as CurationFailureSchema,ue as CurationOpSchema,xt as CurationReportSchema,pt as CurationSchema,B as CurationUsageSchema,Ie as Currency,Te as DEFAULT_PUSH_BYTES,re as DETAIL_FIELDS,ke as DisplayName,yt as EVENT_VERSION,St as EVENT_VERSION_HEADER,_e as Effort,h as Email,At as ExtensionKey,jt as HEADER_KEYS,x as Instant,fe as LobbyError,u as LobbyId,Ce as LobbySchema,Z as MAX_CONTENT_BYTES,w as MAX_DETAILS_BYTES,Tt as MAX_EVENT_FRAME_BYTES,Rt as MAX_EXTENSION_BYTES,wt as MAX_EXTENSION_KEYS,Nt as MAX_MESSAGE_IDS,ie as MAX_NAMED_RECIPIENTS,me as MAX_OWNER_REQUESTS,Ae as MAX_PAGE_BYTES,Me as MAX_PUSH_BYTES,qe as MAX_SCHEDULE_AHEAD_MS,he as MAX_TOKEN_CALLS,de as MEMORY_KINDS,pe as MEMORY_OPS_LIMIT,f as MEMORY_TEXT_LIMITS,le as MEMORY_TITLE_LIMIT,Mt as MESSAGE_KEYS,ee as MESSAGE_KINDS,we as MIN_PUSH_BYTES,Y as MemoryKind,s as MemoryRef,ne as MessageDetailsShape,Ot as MessageIdPrefix,te as MessageKind,F as ModelId,ge as ModelWindowSchema,J as NewLobbyId,ct as OwnerRequestsSchema,Le as OwnerSchema,vt as PACKAGE_VERSION,ve as PROTOCOL_VERSION,je as PacingSettingsSchema,ot as ProvisionSchema,It as RECEIPT_KEYS,Q as RESERVED_LOBBY_IDS,Ye as RESERVED_REQUEST_PREFIX,st as ReadySchema,lt as RecallQuerySchema,dt as RememberSchema,$ as RepeatSchema,m as RequestId,Xe as RestAgentsSchema,i as RoomId,Ue as RoomMemberChangesSchema,ze as RoomMembersSchema,$e as RoomSchema,be as RunningSchema,rt as RuntimeSchema,Be as SCHEDULE_PAST_TOLERANCE_MS,Je as ScheduleSchema,Ke as SendSchema,mt as StatusSchema,ft as TokenReportSchema,kt as TransportReceiptSchema,nt as UpdateAgentSchema,tt as UpdateScheduledSchema,bt as UsageReportSchema,D as WEEKDAYS,se as Weekday,Ve as addressedOf,We as canonicalRepeat,He as canonicalSend,L as canonicalTimeZone,Pe as defaultReplyExpected,ae as messageDetails,Fe as namedMembers,Ne as parsePrincipal,Oe as qualifyAgent,gt as windowCovers};
package/dist/server.js CHANGED
@@ -1,8 +1,8 @@
1
- var wt=Object.defineProperty;var c=(a,d)=>wt(a,"name",{value:d,configurable:!0});import{createHash as Ge,randomBytes as vt,timingSafeEqual as _t}from"node:crypto";import{createReadStream as Tt,readFileSync as Et}from"node:fs";import{createServer as St}from"node:http";import{pipeline as It}from"node:stream";import{fileURLToPath as kt}from"node:url";import{WebSocket as ve,WebSocketServer as Ot}from"ws";import{ZodError as Pt,z as v}from"zod";import{DEFAULT_MAX_IMAGE_BYTES as At,DEFAULT_MAX_TEXT_BYTES as Rt,DEFAULT_UPLOAD_INFLIGHT_BYTES as xt,formatBytes as $t}from"./attachments.js";import{argumentList as Bt,buildCatalog as Nt,defaultTools as Ut,permitted as Lt,toolGuide as Ct,ToolName as Dt,validateTools as Me}from"./catalog.js";import{BOARD_COOKIE as re,HANDOFF_COOKIE as je,handoffCookie as Ht,handoffKey as Gt,clientKey as Mt,cookieToken as _e,newSessionToken as ze,sessionCookie as Te,SignInKeys as jt,tokenHash as G}from"./auth.js";import{ActivityTracker as zt}from"./activity.js";import{BoardService as Yt}from"./board.js";import{ExchangeRateService as Ft}from"./exchange-rates.js";import{BoardAgentsSchema as Kt,BoardIconSchema as Jt,RepoName as Vt}from"./board-model.js";import{BOARD_PAGE as Xt,boardCsp as Wt,renderBoardBody as Zt,renderBoardNotice as Qt,renderBoardPage as qt}from"./board-page.js";import{MASCOT_HEADERS as Ye,mascotFile as Fe}from"./mascots.js";import{iconFile as Ke,iconVersion as Je}from"./icons.js";import{createConsole as en,destination as Ve}from"./console.js";import{acquireDatabaseLock as tn}from"./lock.js";import{presentActivity as nn,presentMessage as Xe,presentReceipts as on}from"./presentation.js";import{LobbyStore as an}from"./store.js";import{AccountSettingsSchema as rn,AckSchema as sn,AgentId as We,DEFAULT_PUSH_BYTES as cn,MIN_PUSH_BYTES as Ze,MAX_PUSH_BYTES as Qe,CancelScheduledSchema as qe,UpdateScheduledSchema as un,CheckpointSchema as dn,EVENT_VERSION as et,ActivityReportSchema as ln,BRIDGE_VERSION_HEADER as mn,EVENT_VERSION_HEADER as fn,ExtensionKey as hn,LobbyId as se,LobbySchema as pn,LobbyError as p,HEADER_KEYS as bn,MAX_EXTENSION_BYTES as gn,MAX_EXTENSION_KEYS as yn,MESSAGE_KEYS as wn,OwnerSchema as tt,PACKAGE_VERSION as vn,PROTOCOL_VERSION as nt,ProvisionSchema as _n,ReadySchema as Tn,RESERVED_LOBBY_IDS as ot,RoomId as ie,RoomSchema as En,RestAgentsSchema as Sn,RoomMembersSchema as In,RoomMemberChangesSchema as kn,RuntimeSchema as On,ScheduleSchema as Pn,SendSchema as An,OwnerRequestsSchema as Rn,StatusSchema as xn,TokenReportSchema as $n,UsageReportSchema as Bn,TransportReceiptSchema as Nn,UpdateAgentSchema as Un,MAX_MESSAGE_IDS as Ln,MessageIdPrefix as Cn,qualifyAgent as Z,parsePrincipal as Ee,RECEIPT_KEYS as Dn}from"./protocol.js";const Hn=256*1024,Gn=2*1024*1024,Mn=128*1024,jn=3e3,at=v.object({mode:v.enum(["pending","history","reconciliation"]).default("pending"),cursor:v.coerce.number().int().min(0).max(Number.MAX_SAFE_INTEGER).default(0),limit:v.coerce.number().int().min(1).max(100).default(30),query:v.string().min(1).max(200).optional(),unanswered:v.stringbool().optional(),awaiting:v.stringbool().optional(),ids:v.string().transform(a=>a.split(",")).pipe(v.array(Cn).min(1).max(Ln)).optional(),headers:v.stringbool().optional()}).strict(),zn=v.object({arguments:v.record(v.string(),v.unknown()).default({})}).strict(),Yn=[["GET",/^\/v1\/agents$/],["POST",/^\/v1\/agents\/rest$/],["GET",/^\/v1\/rooms$/],["POST",/^\/v1\/rooms$/],["PUT",/^\/v1\/rooms\/[a-z][a-z0-9_-]{0,47}\/members$/],["PATCH",/^\/v1\/rooms\/[a-z][a-z0-9_-]{0,47}\/members$/],["DELETE",/^\/v1\/rooms\/[a-z][a-z0-9_-]{0,47}$/],["GET",/^\/v1\/messages$/],["POST",/^\/v1\/messages$/],["PUT",/^\/v1\/owner-requests$/],["PUT",/^\/v1\/status$/],["GET",/^\/v1\/memory$/],["POST",/^\/v1\/memory$/],["GET",/^\/v1\/schedules$/],["POST",/^\/v1\/schedules$/],["POST",/^\/v1\/schedules\/cancel$/],["POST",/^\/v1\/schedules\/update$/],["GET",/^\/v1\/context$/],["GET",/^\/v1\/checkpoint$/]],Fn=v.object({cursor:v.coerce.number().int().min(0).max(Number.MAX_SAFE_INTEGER).default(0),limit:v.coerce.number().int().min(1).max(100).default(50)}).strict(),Kn=new URL("../site/index.html",import.meta.url),Jn="default-src 'none'; style-src 'unsafe-inline' https://fonts.googleapis.com; font-src https://fonts.gstatic.com; img-src 'self' data:; base-uri 'none'; form-action 'none'; frame-ancestors 'none'";function Vn(a){try{return JSON.parse(a)}catch{return}}c(Vn,"parseJson");function rt(a,d,h){if(!d||!a||a.startsWith("["))return{kind:"api"};const g=a.toLowerCase().replace(/:\d+$/u,"").replace(/\.$/u,""),E=`.${d.toLowerCase()}`;if(!g.endsWith(E))return{kind:"api"};const k=g.slice(0,-E.length);return ot.includes(k)?g===h?{kind:"api"}:{kind:"none"}:{kind:"board",label:k}}c(rt,"hostKind");function Xn(a){const d=a.headers[mn];return typeof d=="string"&&/^\d{1,4}\.\d{1,4}\.\d{1,6}(-[0-9A-Za-z.-]{1,32})?$/.test(d)?d:null}c(Xn,"bridgeVersion");function Wn(a){const d=a.headers[fn];return typeof d=="string"&&/^\d{1,3}$/.test(d)&&Number(d)>=et}c(Wn,"currentBridge");const Zn=c(a=>a.attachments?{...a,attachments:a.attachments.map(({id:d,filename:h,mime_type:g,size:E})=>({id:d,filename:h,mime_type:g,size:E}))}:a,"compactAttachments"),Qn=["kind","reply_expected"],qn=c((a,d)=>Object.fromEntries(Object.entries(a).filter(([h,g])=>d.includes(h)&&!(g===null&&Qn.includes(h)))),"pick");function eo(a,d){const h={};for(const[g,E]of Object.entries(a))if(!(d.includes(g)||g==="deliveries"||E===void 0)&&hn.safeParse(g).success){if(Object.keys(h).length>=yn)break;Buffer.byteLength(JSON.stringify({...h,[g]:E}))>gn||(h[g]=E)}return Object.keys(h).length?h:null}c(eo,"extensionsOf");function Se(a,d,h){const g=eo(Zn(a),d);return{...qn(a,d),...g?{extensions:g}:{},...h?{presentation:h}:{}}}c(Se,"envelope");function st(a,d){if(a.type==="activity")return{...a,presentation:nn(a.agents)};if(a.type==="receipts")return{...a,receipts:a.receipts.map(O=>Se(O,Dn)),presentation:on(a.receipts,a.remaining)};const{covered:h,covered_count:g,...E}=a,k=c(O=>({...E,messages:a.messages.map(n=>Se(n,wn,O?Xe(n,d):void 0)),...h===void 0?{}:{covered:h.map(n=>Se(n,bn,O?Xe(n,d):void 0)),covered_count:g}}),"shape"),N=k(!0);return Buffer.byteLength(JSON.stringify(N))<=Mn?N:k(!1)}c(st,"wireEvent");function it(a){const d=a.headers["x-pocolobby-runtime-id"],h=a.headers["x-pocolobby-generation"],g=a.headers["x-pocolobby-incarnation"];if(typeof d!="string"||typeof h!="string"||typeof g!="string"||!/^\d+$/.test(h)||!Number.isSafeInteger(Number(h)))throw new p(409,"runtime_required","Claim a runtime and supply its current binding headers.");return{runtime_id:d,generation:Number(h),incarnation:g}}c(it,"runtimeHeaders");function to(a){const d=a.headers.authorization;if(!d||!/^Bearer [A-Za-z0-9_-]{32,512}$/.test(d))throw new p(401,"unauthorized","A valid Bearer credential is required.");return d.slice(7)}c(to,"bearer");function no(a,d){return _t(Ge("sha256").update(a).digest(),d)}c(no,"equalToken");function Ie(a,d,h){a.writeHead(d,{"content-type":"application/json; charset=utf-8","cache-control":"no-store","x-content-type-options":"nosniff"}),a.end(JSON.stringify(h))}c(Ie,"json");function ct(a){return a.issues.map(d=>`${d.path.join(".")||"request"}: ${d.message}`).join("; ")}c(ct,"zodMessage");function ut(a){return a instanceof p?{status:a.status,body:{error:{...a.details,code:a.code,message:a.message}}}:a instanceof URIError?{status:400,body:{error:{code:"invalid_request",message:"The path has a malformed escape."}}}:a instanceof Pt?{status:400,body:{error:{code:"invalid_request",message:ct(a)}}}:{status:500,body:{error:{code:"internal_error",message:"The request failed. No success is implied; retry sends with the same request ID."}}}}c(ut,"errorResponse");function dt(a,d,h,g){return new Promise((E,k)=>{const N=[];let O=0,n=!1;const F=c(U=>{if(n)return;n=!0;const L=U?null:Buffer.concat(N,O);N.length=0,L?E(L):k(U)},"settle");a.on("data",U=>{n||(O+=U.length,O>d?F(h()):N.push(U))}),a.on("end",()=>F());const T=c(()=>F(new p(400,"request_aborted",g)),"abort");a.on("error",T),a.on("aborted",T)})}c(dt,"readBody");async function oo(a,d=Hn){if(a.headers["content-type"]?.split(";",1)[0]?.trim()!=="application/json")throw a.resume(),new p(415,"content_type","Use application/json.");const h=c(()=>new p(413,"body_too_large",`Request exceeds ${Math.round(d/1024)} KiB.`),"tooLarge");if(Number(a.headers["content-length"])>d)throw a.resume(),h();const g=await dt(a,d,h,"Request body was interrupted.");try{return JSON.parse(g.toString("utf8"))}catch{throw new p(400,"invalid_json","Request body must be valid JSON.")}}c(oo,"body");async function ao(a,d,h){if(a.headers["content-type"]?.split(";",1)[0]?.trim()!=="application/octet-stream")throw a.resume(),new p(415,"content_type","Upload with application/octet-stream.");const g=c(()=>new p(413,"attachment_too_large",`The upload exceeds ${$t(d)}, the largest attachment this broker accepts. Nothing was stored.`),"tooLarge"),E=a.headers["content-length"];if(E===void 0)throw a.resume(),new p(411,"length_required","Upload with a Content-Length header.");if(Number(E)>d)throw a.resume(),g();try{h(Number(E))}catch(k){throw a.resume(),k}return await dt(a,d,g,"Upload was interrupted.")}c(ao,"rawBody");async function xo(a){if(!/^[A-Za-z0-9_-]{32,512}$/.test(a.adminToken))throw new Error("Admin token must be 32\u2013512 URL-safe characters. Generate a random token with pocolobby init.");const d=a.host??"127.0.0.1";if(!["127.0.0.1","::1","localhost"].includes(d)&&!a.allowRemote)throw new Error("Remote listeners require --allow-remote and a TLS reverse proxy.");if(a.console?.origin&&!a.board?.domain)throw new Error("A settings origin needs a dashboard domain: set POCOLOBBY_DASHBOARD_DOMAIN too.");let h=a.tools??Ut();Me(h);const g=a.pushBytes??cn;if(!Number.isSafeInteger(g)||g<Ze||g>Qe)throw new Error(`The push size must be between ${Ze} and ${Qe} bytes.`);const E=a.uploadInflightBytes??xt,k=Math.max(a.storeOptions?.maxImageBytes??At,a.storeOptions?.maxTextBytes??Rt);if(!Number.isSafeInteger(E)||E<k)throw new Error(`The in-flight upload budget must be at least the largest attachment, ${k} bytes.`);const N=Et(kt(Kn)),O=tn(a.database);let n;try{n=new an(a.database,a.storeOptions)}catch(e){throw O(),e}const F=Ge("sha256").update(a.adminToken).digest(),T=new Map,U=new Set,L=new Map;let Q=!1;const q=new Ot({noServer:!0,maxPayload:4096,perMessageDeflate:!1});q.on("headers",e=>e.push(`X-PocoLobby-Event-Version: ${et}`));const K=a.storeOptions?.now??Date.now,j=(a.board?.domain??"").toLowerCase(),M=new zt({open:c((e,t)=>n.openTurn(e,t),"open"),close:c((e,t,o)=>n.closeTurn(e,t,o),"close")});for(const e of n.latestTurns())e.ended_ms===null?M.restore(e.agent_id,"working",e.started_ms):e.ended_state&&M.restore(e.agent_id,e.ended_state,e.ended_ms);const ce=a.exchangeRates?new Ft(n,a.exchangeRates.fetch??fetch,K,e=>process.stderr.write(`${e}
2
- `)):null,R=new Yt(n,{...a.board,domain:j},(e,t)=>T.has(Z(e,t)),K,(e,t)=>M.view(Z(e,t))),ke=new jt(a.adminToken),J=j?a.console?.origin??`https://${j}`:void 0,ue=J?new URL(J).hostname.toLowerCase().replace(/\.$/u,""):void 0,V=!J&&["127.0.0.1","::1","localhost"].includes(d),C=J||V?en({origin:J??null,mailer:a.console?.mailer??null,missing:a.console?.mailer||V?[]:a.console?.missing??["POSTMARK_TOKEN","POCOLOBBY_MAIL_FROM"],responseFloorMs:a.console?.responseFloorMs},{store:n,board:R,keys:ke,boardDomain:j,clientAddress:c(e=>le(e),"clientAddress"),overRate:c(e=>de(e),"overRate"),isConnected:c((e,t)=>T.has(Z(e,t)),"isConnected"),closeAgents:c(e=>{for(const t of e)z(t,4401,"Lobby deleted")},"closeAgents"),refreshBoards:c(e=>setImmediate(()=>{R.request(e)}),"refreshBoards"),github:!!a.board?.githubToken,anthropic:!!(a.board?.summaryClient??a.board?.anthropicApiKey),exchangeRates:ce!==null,clock:K}):null;function Oe(e){const t=A.address();if(!t||typeof t=="string")return!1;const o=t.port===80?["",":80"]:[`:${t.port}`],r=(e.headers.host??"").toLowerCase();return["localhost","127.0.0.1","[::1]"].some(i=>o.some(u=>r===`${i}${u}`))}c(Oe,"loopbackHost");function de(e){const t=Date.now(),o=L.get(e);return!o||t-o.start>6e4?(!o&&L.size>=1024&&L.delete(L.keys().next().value),L.set(e,{start:t,count:1}),!1):++o.count>1200}c(de,"overRate");function Pe(e){if(e.headers.origin)throw new p(403,"origin_not_allowed","Browser origins are not enabled on this API.");const t=new URL(e.url??"/","http://lobby.invalid");if(t.searchParams.has("token")||t.searchParams.has("access_token"))throw new p(400,"credential_location","Credentials belong in the Authorization header.");if(de(le(e)))throw new p(429,"request_rate_limit","Too many requests; wait before retrying.");return t}c(Pe,"checkRequest");function le(e){const t=a.board?.clientIpHeader,o=t?e.headers[t.toLowerCase()]:void 0,r=typeof o=="string"&&o.trim()?o.split(",")[0].trim():e.socket.remoteAddress??"unknown";return Mt(r)}c(le,"clientAddress");async function Ae(e,t,o,r,i){const u=e.method??"GET",m=new URL(e.url??"/","http://board.invalid").pathname.slice(i.length)||"/",s=i!=="",l=vt(16).toString("base64"),b=c((S,B,H,yt={})=>{t.writeHead(S,{"content-type":B,"cache-control":"no-store","x-content-type-options":"nosniff","referrer-policy":"same-origin","content-security-policy":B.startsWith("text/html")?Wt(l):"default-src 'none'; frame-ancestors 'none'",...yt}),t.end(u==="HEAD"?void 0:H)},"send"),f="text/html; charset=utf-8",y=c((S,B={})=>b(303,"text/plain; charset=utf-8","",{location:S,...B}),"redirect");if(de(le(e))){b(429,"text/plain; charset=utf-8","Too many requests; wait a minute.",{"retry-after":"60"});return}const w=s?void 0:Fe(m);if((u==="GET"||u==="HEAD")&&w){t.writeHead(200,{...Ye,"content-length":String(w.length)}),t.end(u==="HEAD"?void 0:w);return}const I=s?void 0:Ke(m);if((u==="GET"||u==="HEAD")&&I){t.writeHead(200,I.headers),t.end(u==="HEAD"?void 0:I.body);return}if(!s&&(u==="GET"||u==="HEAD")&&m==="/healthz"){n.healthy(),b(200,"application/json; charset=utf-8",JSON.stringify({status:"ok",protocol_version:nt}));return}const _=se.safeParse(r).success?r:null,x=_===null?null:n.boardVisibility(_),$=s?null:_e(e.headers.cookie,re),D=x!==null&&$!==null?n.boardSession(_,G($)):null,Ue=s&&o.operator(e),oe=D?{kind:"account",account_id:D.account_id,email:D.email}:Ue?{kind:"operator"}:null,Le=D?.email??null,W={};D?.refresh&&(n.refreshBoardSession(G($)),W["set-cookie"]=Te(re,$));const ae=x!==null&&(x==="public"||oe!==null),ye=s?"/":o.openUrl(r),Ce=c((S,B,H={})=>b(S,f,Qt(r,l,B,ye),H),"notice"),De=`${!s&&(e.headers["x-forwarded-proto"]==="https"||a.allowRemote)?"https":"http"}://${e.headers.host}`,gt=e.headers.origin===De,He=s?()=>o.endOperator(e):()=>($&&n.endBoardSession(G($)),{"set-cookie":Te(re,null)});if(m==="/settings"||m.startsWith("/settings/")){const S=D?()=>n.boardSession(_,G($))?.account_id===D.account_id:()=>o.operator(e);for(const[B,H]of Object.entries(W))t.setHeader(B,H);await o.lobby(e,t,{lobby:r,base:i,origin:De},oe,S,He);return}const Y=ae?n.boardIcon(_):null;if((u==="GET"||u==="HEAD")&&m==="/"){ae&&R.request(_),ae?b(200,f,qt(R.view(_),l,Le,Y&&Je(Y.sha256),{home:o.home,dashboard:i||"/",settings:D?.owner||Ue?`${i}/settings`:null,signIn:oe===null?ye:null,lobbies:oe!==null}),W):y(ye);return}if((u==="GET"||u==="HEAD")&&m==="/icon.png"){if(!Y){b(404,"text/plain; charset=utf-8","Not found.");return}const S=new URL(e.url??"/","http://board.invalid").searchParams.get("v")===Je(Y.sha256);t.writeHead(200,{"content-type":"image/png","content-length":String(Y.png.length),"cache-control":S?`${x==="public"?"public":"private"}, max-age=31536000, immutable`:"private, no-cache","x-content-type-options":"nosniff","content-security-policy":"default-src 'none'; frame-ancestors 'none'",...W}),t.end(u==="HEAD"?void 0:Y.png);return}if((u==="GET"||u==="HEAD")&&m==="/dashboard.json"){if(!ae)b(401,"application/json; charset=utf-8",JSON.stringify({error:{code:"unauthorized",message:"Sign in to the dashboard."}}));else{R.request(_);const S=R.view(_);b(200,"application/json; charset=utf-8",JSON.stringify({generated_at:S.generated_at,activity:S.activity,page:Xt,html:Zt(S,Le)}),W)}return}const we=new URL(e.url??"/","http://board.invalid").searchParams;if(!s&&u==="GET"&&m==="/sign-in"){const S=_e(e.headers.cookie,je)??ze();y(o.handoffUrl(r,Ve(we.get("to")),G(S)),{"set-cookie":Ht(S)});return}if(!s&&u==="GET"&&m==="/handoff"){const S=we.get("token"),B=_e(e.headers.cookie,je),H=ze();_!==null&&S!==null&&B!==null&&/^[A-Za-z0-9_-]{43}$/u.test(S)&&n.consumeHandoff(_,Gt(S,G(B)),G(H),$===null?null:G($))?y(Ve(we.get("to")),{"set-cookie":Te(re,H)}):Ce(400,"That sign-in link has expired, was already used, or began in another browser.");return}if(!s&&u==="POST"&&m==="/sign-out"){if(e.resume(),!gt){b(403,"text/plain; charset=utf-8","Sign out from the dashboard page.");return}Ce(200,"You are signed out of this dashboard.",He());return}e.resume(),b(404,"text/plain; charset=utf-8","Not found.")}c(Ae,"lobbyRequest");function Re(e){const t=to(e);return no(t,F)?{owner:!0,agentId:"owner",token:t}:{owner:!1,agentId:n.authenticate(t),token:t}}c(Re,"actor");function lt(e,t){if(n.authenticate(t.token)!==t.agentId)throw new p(401,"unauthorized","Credential revoked.");const o=it(e);return n.assertRuntime(t.agentId,o),o}c(lt,"currentRuntime");let me=0;function mt(e,t){if(me+t>E)throw new p(503,"uploads_busy","The broker is receiving as many uploads as it holds at once (POCOLOBBY_UPLOAD_INFLIGHT_BYTES). Nothing was stored; retry in a few seconds.");me+=t,e.once("close",()=>{me-=t})}c(mt,"admitUpload");function z(e,t=4409,o="Runtime binding changed"){const r=T.get(e);r&&(T.delete(e),r.socket.close(t,o))}c(z,"closePeer");const ee=new Map;function P(e,t){const{name:o,code:r,message:i}=t??{},u=`pocolobby: ${e} failed: ${o??"Error"}${r?` ${r}`:""}: ${i??String(t)}`,m=Date.now();(ee.get(u)??0)>m-6e4||(ee.size>100&&ee.clear(),ee.set(u,m),process.stderr.write(`${u}
3
- `))}c(P,"logFailure");function X(e,t){const o=t instanceof p?t.status:500;o===500&&P("stream",t),T.get(e.agentId)===e&&T.delete(e.agentId),e.socket.close(o===401?4401:o===403?4403:o===409?4409:o===400?1008:1011,o===500?"Broker operation failed; reconnect":o===400?"Invalid transport frame":"Credential or runtime no longer valid")}c(X,"failPeer");const xe=c(e=>{const t=Z(e.lobby_id,e.agent_id),o=T.get(t);return{connected:o!==void 0,bridge_version:o?.bridgeVersion??null,activity:o?M.view(t):null}},"connection"),ft=c((e,t)=>{const o=new Set(n.rooms(e.lobby_id,t==="owner"?void 0:t).map(i=>i.room_id)),r=n.curationStatus(e.lobby_id,e.agent_id).filter(i=>o.has(i.room_id));return r.length?{memory_curation:r}:{}},"curating"),te=c(e=>Nt(h,n.permissions(e),{maxImageBytes:n.maxImageBytes,maxTextBytes:n.maxTextBytes}),"catalogOf");function fe(e){if(e.socket.readyState===ve.OPEN)try{const{revision:t}=te(e.agentId);if(t===e.catalogRevision)return;e.catalogRevision=t;const o={type:"catalog",revision:t};e.socket.send(JSON.stringify(o))}catch{}}c(fe,"announceCatalog");function ne(){if(!Q){try{n.releaseDue(),n.resumeDue()}catch(e){P("scheduled delivery",e)}for(const e of T.values())if(e.socket.readyState===ve.OPEN)try{if(e.socket.bufferedAmount>256*1024){e.socket.terminate();continue}const t=n.nextNotification(e.agentId,e.auth,g)??n.nextReceipts(e.agentId,e.auth);t&&e.socket.send(JSON.stringify(st(t,n.attachmentRetentionDays)))}catch(t){X(e,t)}ht()}}c(ne,"dispatch");function ht(){const e=K();for(const t of T.values())if(t.socket.readyState===ve.OPEN)try{const o=`${Ee(t.agentId).lobby_id}/`,r=M.due(e,t.agentId,m=>m.startsWith(o)&&T.has(m));if(!r.length||!n.permissions(t.agentId).manage_rooms)continue;const i=n.openActivityNotice(t.agentId,t.auth);if(!i)continue;const u={type:"activity",...i,runtime_id:t.auth.runtime_id,generation:t.auth.generation,agents:r.map(({agent:m,turn:s})=>({agent_id:Ee(m).agent_id,...s}))};t.socket.send(JSON.stringify(st(u)));for(const{told:m}of r)m.add(t.agentId)}catch(o){X(t,o)}}c(ht,"tellCoordinators");async function $e(e,t,o){const{method:r,url:i}=e,u=i.pathname,m=o==="owner",s=c(()=>{m||e.runtime()},"fence");if(u===t){if(r==="GET")return{status:200,value:{rooms:n.rooms(e.lobby(),m?void 0:o)}};if(r==="POST"){const w=En.parse(await e.body());return s(),{status:201,value:n.createRoom(o,w.room_id,e.lobby())}}return}if(!u.startsWith(`${t}/`))return;const[l,b,...f]=u.slice(t.length+1).split("/");if(!l||f.length||b!==void 0&&b!=="members")return;const y=ie.parse(decodeURIComponent(l));if(b&&r==="PUT"){const w=In.parse(await e.body());return s(),{status:200,value:n.setRoomMembers(o,y,w.members,e.lobby()),dispatch:!0}}if(b&&r==="PATCH"){const w=kn.parse(await e.body());return s(),{status:200,value:n.changeRoomMembers(o,y,w,e.lobby()),dispatch:!0}}if(!b&&r==="DELETE")return s(),{status:200,value:n.deleteRoom(o,y,e.lobby()),dispatch:!0}}c($e,"roomRoute");async function Be(e){const{method:t,auth:o}=e,r=e.url.pathname;if(r.startsWith("/v1/admin/")){if(!o.owner)throw new p(403,"owner_required","Owner credentials are required.");if(r==="/v1/admin/lobbies"){if(t==="GET")return{status:200,value:{lobbies:n.lobbies()}};if(t==="POST"){const f=pn.parse(await e.body());return{status:201,value:n.createLobby(f.lobby_id)}}}const i=/^\/v1\/admin\/lobbies\/([^/]+)$/.exec(r);if(i&&t==="PATCH"){const f=v.object({display_name:v.string().max(200).nullable()}).strict().parse(await e.body());return{status:200,value:n.setDisplayName("owner",se.parse(decodeURIComponent(i[1])),f.display_name??"")}}if(r==="/v1/admin/attachments"&&t==="GET")return{status:200,value:n.attachments(e.lobby(),Fn.parse(Object.fromEntries([...e.url.searchParams].filter(([f])=>f!=="lobby"))))};if(r==="/v1/admin/attachments/usage"&&t==="GET")return{status:200,value:n.attachmentUsage(e.lobby())};if(r.startsWith("/v1/admin/dashboard")){if(!n.hasLobby(e.lobby()))throw new p(404,"lobby_not_found","Unknown lobby");if(r==="/v1/admin/dashboard"&&t==="GET")return{status:200,value:R.status(e.lobby())};const f=/^\/v1\/admin\/dashboard\/sources\/([^/]+)$/.exec(r);if(f&&t==="PUT"){const y=n.setBoardSource(e.lobby(),ie.parse(decodeURIComponent(f[1])),await e.body(),"owner");return setImmediate(()=>{R.request(e.lobby())}),{status:200,value:y}}if(f&&t==="DELETE")return{status:200,value:n.removeBoardSource(e.lobby(),ie.parse(decodeURIComponent(f[1])),"owner")};if(r==="/v1/admin/dashboard/agents"&&t==="PUT")return{status:200,value:n.setBoardAgents(e.lobby(),Kt.parse(await e.body()))};if(r==="/v1/admin/dashboard/icon"&&t==="PUT"){const{png:y}=Jt.parse(await e.body());return{status:200,value:n.setBoardIcon("owner",e.lobby(),Buffer.from(y,"base64"))}}if(r==="/v1/admin/dashboard/icon"&&t==="DELETE")return{status:200,value:n.setBoardIcon("owner",e.lobby(),null)}}if(r==="/v1/admin/settings/ticket"&&t==="POST"){if(!C)throw new p(404,"not_local","This broker has no settings pages.");return{status:200,value:{ticket:C.ticket(),expires_in_seconds:60}}}if(r==="/v1/admin/settings/accounts"){if(t==="GET")return{status:200,value:{accounts:n.accounts()}};if(t==="POST"){const f=rn.parse(await e.body());return{status:200,value:n.setAccount(f,ke.emailKey(f.email))}}}if(r==="/v1/admin/settings/owner"&&t==="PUT")return{status:200,value:n.grantLobby(tt.parse(await e.body()).email,e.lobby())};if(r==="/v1/admin/settings/owner/revoke"&&t==="POST")return{status:200,value:n.ungrantLobby(tt.parse(await e.body()).email,e.lobby())};if(r==="/v1/admin/settings/repos"){if(t==="GET")return{status:200,value:{lobby_id:e.lobby(),repos:n.lobbyRepos(e.lobby())}};if(t==="POST"){const{repo:f}=v.object({repo:Vt}).strict().parse(await e.body());return{status:200,value:{lobby_id:e.lobby(),repos:n.approveRepo(e.lobby(),f)}}}}const u=/^\/v1\/admin\/settings\/repos\/([^/]+)\/([^/]+)$/.exec(r);if(u&&t==="DELETE")return{status:200,value:{lobby_id:e.lobby(),repos:n.removeRepo(e.lobby(),`${decodeURIComponent(u[1])}/${decodeURIComponent(u[2])}`)}};const m=await $e(e,"/v1/admin/rooms","owner");if(m)return m;if(r==="/v1/admin/memory"&&t==="GET")return{status:200,value:{rooms:n.memoryOverview(e.lobby())}};const s=/^\/v1\/admin\/memory\/rooms\/([a-z][a-z0-9_-]{0,47})\/curator$/.exec(r);if(s&&t==="PUT"){const f=v.object({agent_id:We.nullable()}).strict().parse(await e.body());return{status:200,value:n.setMemoryCurator(e.lobby(),s[1],f.agent_id)}}const l=/^\/v1\/admin\/memory\/(?:entries\/([a-z][a-z0-9_-]{0,47}-[1-9][0-9]{0,5})|fragments\/([0-9a-f-]{36}))$/.exec(r);if(l&&t==="DELETE")return n.eraseMemory(e.lobby(),l[1]?"entry":"fragment",l[1]??l[2]),{status:200,value:{erased:!0}};if(r==="/v1/admin/agents"){if(t==="GET")return{status:200,value:{agents:n.agents(e.lobby()).map(f=>({...f,...xe(f)}))}};if(t==="POST"){const f=_n.parse(await e.body());if(f.lobby_id!==void 0&&e.url.searchParams.has("lobby")&&f.lobby_id!==e.lobby())throw new p(400,"lobby_mismatch","Provisioning lobby must match the administrative selector.");return{status:201,value:n.provision({...f,lobby_id:f.lobby_id??e.lobby()})}}}const b=/^\/v1\/admin\/agents\/([^/]+)(?:\/(rotate|reset-runtime|retry|messages|context|schedules|schedules\/cancel))?$/.exec(r);if(b){const f=Z(e.lobby(),We.parse(decodeURIComponent(b[1]))),y=b[2];if(!y&&t==="PATCH"){const w=Un.parse(await e.body()),I=n.updateAgent(f,w);w.enabled===!1&&z(f,4403,"Agent disabled");const _=T.get(f);return _&&fe(_),{status:200,value:I,dispatch:!0}}if(y==="messages"&&t==="GET"){const{headers:w,...I}=at.parse(Object.fromEntries([...e.url.searchParams].filter(([x])=>x!=="lobby"))),_={...I,includeHeldContent:!0};return{status:200,value:w?n.messageLines(f,_):n.messages(f,_)}}if(y==="context"&&t==="GET")return{status:200,value:n.context(f)};if(y==="schedules"&&t==="GET")return{status:200,value:n.scheduled(f)};if(y==="schedules/cancel"&&t==="POST"){const w=qe.parse(await e.body());return{status:200,value:n.cancelScheduled(f,null,w.id)}}if(t==="POST"&&["rotate","reset-runtime","retry"].includes(y??"")){if(v.object({}).strict().parse(await e.body()),y==="rotate"){const w=n.rotateToken(f);return z(f,4401,"Credential rotated"),{status:200,value:w}}return y==="reset-runtime"&&(n.resetRuntime(f),z(f)),y==="retry"&&n.retryNotifications(f),{status:200,value:{ok:!0},dispatch:!0}}}}else if(r==="/v1/agents/rest"&&t==="POST"){if(o.owner)throw new p(400,"owner_pauses","The owner pauses agents with PATCH /v1/admin/agents.");const i=Sn.parse(await e.body());return e.runtime(),{status:200,value:n.restAgents(o.agentId,i.agents,i.resting,i.resume_at),dispatch:!0}}else{if(r==="/v1/agents"&&t==="GET")return{status:200,value:{agents:n.agents(e.lobby()).filter(i=>i.enabled).map(i=>({agent_id:i.agent_id,lobby_id:i.lobby_id,work_description:i.work_description,machine:i.machine,screen:i.screen,...xe(i),...ft(i,o.agentId),enabled:i.enabled,paused:i.paused,resume_at:i.resume_at,ready:i.ready,last_seen_at:i.last_seen_at,last_agent_seen_at:i.last_agent_seen_at,notification_attention_required:i.notification_attention_required,unseen_notified_count:i.unseen_notified_count,oldest_unseen_notified_at:i.oldest_unseen_notified_at,last_message_at:i.last_message_at,owner_requests:i.owner_requests,status:i.status,usage:R.agentUsage(i.lobby_id,i.agent_id)}))}};if(r==="/v1/messages"&&t==="POST"){const i=An.parse(await e.body());return o.owner||e.runtime(),{status:200,value:n.send(o.agentId,i,e.lobby()),dispatch:!0}}else{if(o.owner)throw new p(403,"agent_required","Use an agent credential or the owner administrative route.");const i=await $e(e,"/v1/rooms",o.agentId);if(i)return i;if(r==="/v1/runtime"&&t==="POST"){const s=On.parse(await e.body());n.authenticate(o.token);const l=n.claimRuntime(o.agentId,s.runtime_id,s.generation);s.generation===void 0&&M.forget(o.agentId,K());const b=T.get(o.agentId);return b&&b.auth.generation!==l.generation&&z(o.agentId,4409,"Runtime resumed by a newer process"),{status:200,value:l}}if(r==="/v1/context"&&t==="GET"){const s=te(o.agentId);return{status:200,value:{...n.context(o.agentId),tool_guide:Ct(s.tools,s.revision),broker:{host:e.host,version:vn}}}}const u=/^\/v1\/attachments\/([0-9a-f]{64})$/.exec(r);if(u&&t==="PUT"){const s=e.runtime(),l=await e.rawBody(Math.max(n.maxImageBytes,n.maxTextBytes));return{status:200,value:n.uploadAttachment(o.agentId,s,u[1],l)}}const m=/^\/v1\/attachments\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(\/content)?$/.exec(r);if(m&&t==="GET"&&!e.url.search){if(!m[2])return{status:200,value:n.attachment(o.agentId,m[1])};const{info:s,path:l,size:b}=n.attachmentFile(o.agentId,m[1]);return{status:200,value:null,raw:{path:l,size:b,headers:{"content-type":"application/octet-stream","content-disposition":"attachment","x-pocolobby-sha256":s.sha256,"x-pocolobby-mime-type":s.mime_type,"x-pocolobby-filename":encodeURIComponent(s.filename)}}}}if(r==="/v1/messages"&&t==="GET"){const{headers:s,...l}=at.parse(Object.fromEntries(e.url.searchParams));return{status:200,value:s?n.messageLines(o.agentId,l):n.messages(o.agentId,l)}}if(r==="/v1/memory"&&t==="GET")return{status:200,value:n.recall(o.agentId,Object.fromEntries(e.url.searchParams))};if(r==="/v1/memory"&&t==="POST"){const s=n.remember(o.agentId,e.runtime(),await e.body());return{status:s.duplicate?200:201,value:s}}if(r==="/v1/acknowledgments"&&t==="POST"){const s=sn.parse(await e.body());return{status:200,value:n.acknowledge(o.agentId,e.runtime(),s.message_ids)}}if(r==="/v1/schedules"){if(t==="GET")return{status:200,value:n.scheduled(o.agentId)};if(t==="POST"){const s=Pn.parse(await e.body());return{status:200,value:n.createSchedule(o.agentId,e.runtime(),s)}}}if(r==="/v1/schedules/cancel"&&t==="POST"){const s=qe.parse(await e.body());return{status:200,value:n.cancelScheduled(o.agentId,e.runtime(),s.id)}}if(r==="/v1/schedules/update"&&t==="POST"){const s=un.parse(await e.body());return{status:200,value:n.updateScheduled(o.agentId,e.runtime(),s)}}if(r==="/v1/checkpoint"&&t==="GET")return{status:200,value:n.checkpointView(o.agentId)};if(r==="/v1/checkpoint"&&t==="PUT"){const s=dn.parse(await e.body());return{status:200,value:n.checkpoint(o.agentId,e.runtime(),s)}}if(r==="/v1/memory/brief"&&t==="GET"){n.authenticate(o.token);const{part:s}=v.object({part:v.enum(["1","2","3"])}).strict().parse(Object.fromEntries(e.url.searchParams));return{status:200,value:{text:n.memoryBrief(o.agentId,Number(s))}}}if(r==="/v1/memory/curation/failures"&&t==="POST"){const s=await e.body();return n.authenticate(o.token),{status:200,value:n.curationFailed(o.agentId,s)}}if(r==="/v1/code-stats"&&t==="POST"){const s=await e.body();return n.authenticate(o.token),{status:200,value:n.saveCodeStats(o.agentId,s)}}if(r==="/v1/memory/curation/report"&&t==="POST"){const s=await e.body();return n.authenticate(o.token),{status:200,value:n.curationReport(o.agentId,s),dispatch:!0}}if(r==="/v1/memory/curation"){if(n.authenticate(o.token),t==="GET"){const{room:s,review:l}=v.object({room:ie,review:v.literal("all").optional()}).strict().parse(Object.fromEntries(e.url.searchParams));return{status:200,value:n.curationSnapshot(o.agentId,s,l==="all")}}if(t==="POST"){const s=await e.body(Gn);return n.authenticate(o.token),{status:200,value:n.curate(o.agentId,s)}}}if(r==="/v1/usage"&&t==="PUT"){const s=Bn.parse(await e.body());return n.authenticate(o.token),R.recordUsage(o.agentId,s),{status:200,value:{recorded:!0}}}if(r==="/v1/activity"&&t==="PUT"){const s=ln.parse(await e.body());return n.authenticate(o.token),M.record(o.agentId,s),{status:200,value:{recorded:!0}}}if(r==="/v1/tokens"&&t==="POST"){const s=$n.parse(await e.body());return n.authenticate(o.token),{status:200,value:n.recordTokens(o.agentId,s.calls)}}if(r==="/v1/owner-requests"&&t==="PUT"){const s=Rn.parse(await e.body());return{status:200,value:{owner_requests:n.setOwnerRequests(o.agentId,e.runtime(),s)}}}if(r==="/v1/status"&&t==="PUT"){const s=xn.parse(await e.body());return{status:200,value:{status:n.setStatus(o.agentId,e.runtime(),s)}}}if(r==="/v1/ready"&&t==="POST"){const s=Tn.parse(await e.body());return n.ready(o.agentId,e.runtime(),s),{status:200,value:{ready:!0},dispatch:!0}}}}throw new p(404,"not_found","Unknown API route.")}c(Be,"route");function pt(e){return{async call(t,o,r){const i=new URL(o,"http://operation.invalid");if(i.origin!=="http://operation.invalid"||!o.startsWith("/v1/")||o.includes("..")||o.includes("\\")||i.hash||i.search&&!(t==="GET"&&["/v1/messages","/v1/memory"].includes(i.pathname))||!Yn.some(([s,l])=>s===t&&l.test(i.pathname)))throw new p(403,"operation_not_dispatchable","A tool may only run registered agent operations.");const u=r===void 0?{}:JSON.parse(JSON.stringify(r)),m=await Be({...e,method:t,url:i,body:c(async()=>u,"body"),rawBody:c(async()=>{throw new p(403,"operation_not_dispatchable","Uploads are not tools.")},"rawBody")});return m.dispatch&&setImmediate(ne),m.value}}}c(pt,"toolContext");async function bt(e){if(e.auth.owner)throw new p(403,"agent_required","Tools belong to agents; the owner uses the CLI.");const t=e.url.pathname;if(t==="/v1/tools"&&e.method==="GET"&&!e.url.search)return{status:200,value:te(e.auth.agentId)};const o=/^\/v1\/tools\/([^/]+)$/.exec(t);if(o&&e.method==="POST"&&!e.url.search){const r=zn.parse(await e.body());if(n.authenticate(e.auth.token)!==e.auth.agentId)throw new p(401,"unauthorized","Credential revoked.");const i=Dt.safeParse(decodeURIComponent(o[1])),u=i.success?h.find(s=>s.name===i.data):void 0;if(!u)throw new p(404,"unknown_tool","This broker offers no tool by that name.");if(!Lt(u,n.permissions(e.auth.agentId)))throw new p(403,"tool_forbidden",`${u.name} needs a permission this agent does not have.`);const m=u.input.safeParse(r.arguments);if(!m.success){const s=te(e.auth.agentId).tools.find(l=>l.name===u.name);throw new p(400,"invalid_request",`${ct(m.error)}. ${s?`${Bt(s)}.`:""}`.trim())}return{status:200,value:{result:await u.run(pt(e),m.data)}}}throw new p(404,"not_found","Unknown API route.")}c(bt,"toolRoute");const A=St(async(e,t)=>{try{e.headers["x-forwarded-proto"]==="https"&&t.setHeader("strict-transport-security","max-age=31536000");const o=rt(e.headers.host,j,ue);if(o.kind==="none"){e.resume(),t.writeHead(404,{"content-type":"text/plain; charset=utf-8"}),t.end("Not found.");return}if(o.kind==="board"&&C){await Ae(e,t,C,o.label,"");return}if(C){const I=new URL(e.url??"/","http://lobby.invalid").pathname,_=V?/^\/([^/]+)/u.exec(I)?.[1]:void 0,x=_!==void 0&&se.safeParse(_).success&&!ot.includes(_)?_:null,$=I==="/"&&(V?Oe(e):(e.headers.host??"").toLowerCase().replace(/:\d+$/u,"")===ue);if(C.handles(I)||$||x!==null){V&&!Oe(e)?(e.resume(),t.writeHead(421,{"content-type":"text/plain; charset=utf-8"}),t.end("Open this broker at its own address, such as http://localhost:8787.")):x!==null?await Ae(e,t,C,x,`/${x}`):await C.account(e,t);return}}const r=Pe(e),i=e.method??"GET",u=r.pathname;if(i==="GET"&&u==="/healthz"){n.healthy(),Ie(t,200,{status:"ok",protocol_version:nt});return}if((i==="GET"||i==="HEAD")&&u==="/"){t.writeHead(200,{"content-type":"text/html; charset=utf-8","content-length":String(N.length),"cache-control":"public, max-age=300","content-security-policy":Jn,"x-content-type-options":"nosniff"}),t.end(i==="HEAD"?void 0:N);return}const m=Fe(u);if((i==="GET"||i==="HEAD")&&m){t.writeHead(200,{...Ye,"content-length":String(m.length)}),t.end(i==="HEAD"?void 0:m);return}const s=Ke(u);if((i==="GET"||i==="HEAD")&&s){t.writeHead(200,s.headers),t.end(i==="HEAD"?void 0:s.body);return}const l=Re(e);if(!l.owner&&(r.searchParams.has("lobby")||r.searchParams.has("lobby_id")))throw new p(403,"scope_selection_forbidden","Your credential selects your private lobby; it cannot be changed by a request.");const b=r.searchParams.get("lobby");let f;const y={method:i,url:r,auth:l,lobby:c(()=>f??=l.owner?b===null?n.soleLobby():se.parse(b):Ee(l.agentId).lobby_id,"lobby"),host:e.headers.host??null,body:c(I=>oo(e,I),"body"),rawBody:c(I=>ao(e,I,_=>mt(t,_)),"rawBody"),runtime:c(()=>lt(e,l),"runtime")},w=u==="/v1/tools"||u.startsWith("/v1/tools/")?await bt(y):await Be(y);w.raw?(t.writeHead(w.status,{...w.raw.headers,"content-length":String(w.raw.size),"cache-control":"no-store","x-content-type-options":"nosniff"}),It(Tt(w.raw.path),t,()=>{})):Ie(t,w.status,w.value),w.dispatch&&setImmediate(ne)}catch(o){const r=ut(o);r.status===500&&P(`${e.method} ${e.url?.split("?",1)[0]}`,o),!t.headersSent&&!t.destroyed&&(r.status===413&&t.setHeader("connection","close"),r.status===429&&t.setHeader("retry-after","60"),r.status===503&&t.setHeader("retry-after","5"),Ie(t,r.status,r.body))}});A.requestTimeout=12e4,A.headersTimeout=1e4,A.keepAliveTimeout=5e3,A.maxRequestsPerSocket=1e3,A.on("connection",e=>{U.add(e),e.on("close",()=>U.delete(e))}),A.on("upgrade",(e,t,o)=>{const r=c(()=>t.destroy(),"dropSocket");t.on("error",r);try{if(rt(e.headers.host,j,ue).kind!=="api")throw new p(404,"not_found","Unknown stream route.");const i=Pe(e);if(i.pathname!=="/v1/events"||i.search)throw new p(404,"not_found","Unknown stream route.");if(!Wn(e))throw new p(426,"bridge_outdated","This PocoLobby bridge is older than the broker: install the current package.");const u=Re(e);if(u.owner)throw new p(403,"agent_required","Only an agent can consume an inbox.");const m=it(e);n.assertRuntime(u.agentId,m),t.off("error",r),q.handleUpgrade(e,t,o,s=>{z(u.agentId,4409,"Connection replaced by the same runtime");const l={agentId:u.agentId,auth:m,socket:s,bridgeVersion:Xn(e),alive:!0,frames:0,frameWindow:Date.now()};T.set(u.agentId,l),s.on("error",()=>{}),s.on("close",()=>{T.get(u.agentId)===l&&T.delete(u.agentId)}),s.on("pong",()=>{l.alive=!0;try{n.heartbeat(l.agentId,l.auth)}catch(b){X(l,b)}}),s.on("message",(b,f)=>{try{if(Date.now()-l.frameWindow>6e4&&(l.frames=0,l.frameWindow=Date.now()),++l.frames>jn)throw new Error("Too many transport frames in a minute");const y=f?void 0:Nn.safeParse(Vn(b.toString())).data;if(!y)throw new p(400,"invalid_frame","Invalid transport frame.");n.recordTransport(l.agentId,l.auth,y)}catch(y){X(l,y)}});try{n.heartbeat(l.agentId,l.auth)}catch(b){X(l,b);return}fe(l),setImmediate(ne)})}catch(i){const{status:u,body:m}=ut(i),s=JSON.stringify(m);t.end(`HTTP/1.1 ${u} Rejected\r
1
+ var wt=Object.defineProperty;var c=(a,d)=>wt(a,"name",{value:d,configurable:!0});import{createHash as Ge,randomBytes as vt,timingSafeEqual as _t}from"node:crypto";import{createReadStream as Tt,readFileSync as Et}from"node:fs";import{createServer as St}from"node:http";import{pipeline as It}from"node:stream";import{fileURLToPath as kt}from"node:url";import{WebSocket as _e,WebSocketServer as Ot}from"ws";import{ZodError as Pt,z as v}from"zod";import{DEFAULT_MAX_IMAGE_BYTES as At,DEFAULT_MAX_TEXT_BYTES as Rt,DEFAULT_UPLOAD_INFLIGHT_BYTES as xt,formatBytes as $t}from"./attachments.js";import{argumentList as Bt,buildCatalog as Nt,defaultTools as Ut,permitted as Lt,toolGuide as Ct,ToolName as Dt,validateTools as Me}from"./catalog.js";import{BOARD_COOKIE as re,HANDOFF_COOKIE as je,handoffCookie as Ht,handoffKey as Gt,clientKey as Mt,cookieToken as Te,newSessionToken as ze,sessionCookie as Ee,SignInKeys as jt,tokenHash as G}from"./auth.js";import{ActivityTracker as zt}from"./activity.js";import{BoardService as Yt}from"./board.js";import{ExchangeRateService as Ft}from"./exchange-rates.js";import{BoardAgentsSchema as Kt,BoardIconSchema as Jt,RepoName as Vt}from"./board-model.js";import{BOARD_PAGE as Wt,boardCsp as Xt,renderBoardBody as Zt,renderBoardNotice as Qt,renderBoardPage as qt}from"./board-page.js";import{MASCOT_HEADERS as Ye,mascotFile as Fe}from"./mascots.js";import{iconFile as Ke,iconVersion as Je}from"./icons.js";import{createConsole as en,destination as Ve}from"./console.js";import{acquireDatabaseLock as tn}from"./lock.js";import{presentActivity as nn,presentMessage as We,presentReceipts as on}from"./presentation.js";import{LobbyStore as an}from"./store.js";import{AccountSettingsSchema as rn,AckSchema as sn,AgentId as Xe,DEFAULT_PUSH_BYTES as cn,MIN_PUSH_BYTES as Ze,MAX_PUSH_BYTES as Qe,CancelScheduledSchema as qe,UpdateScheduledSchema as un,CheckpointSchema as dn,EVENT_VERSION as et,ActivityReportSchema as ln,BRIDGE_VERSION_HEADER as mn,EVENT_VERSION_HEADER as fn,ExtensionKey as hn,LobbyId as se,LobbySchema as pn,LobbyError as p,HEADER_KEYS as bn,MAX_EXTENSION_BYTES as gn,MAX_EXTENSION_KEYS as yn,MESSAGE_KEYS as wn,OwnerSchema as tt,PACKAGE_VERSION as vn,PROTOCOL_VERSION as nt,ProvisionSchema as _n,ReadySchema as Tn,RESERVED_LOBBY_IDS as ot,RoomId as ie,RoomSchema as En,RestAgentsSchema as Sn,RoomMembersSchema as In,RoomMemberChangesSchema as kn,RuntimeSchema as On,ScheduleSchema as Pn,SendSchema as An,OwnerRequestsSchema as Rn,StatusSchema as xn,TokenReportSchema as $n,UsageReportSchema as Bn,TransportReceiptSchema as Nn,UpdateAgentSchema as Un,MAX_MESSAGE_IDS as Ln,MessageIdPrefix as Cn,qualifyAgent as Z,parsePrincipal as Se,RECEIPT_KEYS as Dn}from"./protocol.js";const Hn=256*1024,Gn=2*1024*1024,Mn=128*1024,jn=3e3,at=v.object({mode:v.enum(["pending","history","reconciliation"]).default("pending"),cursor:v.coerce.number().int().min(0).max(Number.MAX_SAFE_INTEGER).default(0),limit:v.coerce.number().int().min(1).max(100).default(30),query:v.string().min(1).max(200).optional(),unanswered:v.stringbool().optional(),awaiting:v.stringbool().optional(),ids:v.string().transform(a=>a.split(",")).pipe(v.array(Cn).min(1).max(Ln)).optional(),headers:v.stringbool().optional()}).strict(),zn=v.object({arguments:v.record(v.string(),v.unknown()).default({})}).strict(),Yn=[["GET",/^\/v1\/agents$/],["POST",/^\/v1\/agents\/rest$/],["GET",/^\/v1\/rooms$/],["POST",/^\/v1\/rooms$/],["PUT",/^\/v1\/rooms\/[a-z][a-z0-9_-]{0,47}\/members$/],["PATCH",/^\/v1\/rooms\/[a-z][a-z0-9_-]{0,47}\/members$/],["DELETE",/^\/v1\/rooms\/[a-z][a-z0-9_-]{0,47}$/],["GET",/^\/v1\/messages$/],["POST",/^\/v1\/messages$/],["PUT",/^\/v1\/owner-requests$/],["PUT",/^\/v1\/status$/],["GET",/^\/v1\/memory$/],["POST",/^\/v1\/memory$/],["GET",/^\/v1\/schedules$/],["POST",/^\/v1\/schedules$/],["POST",/^\/v1\/schedules\/cancel$/],["POST",/^\/v1\/schedules\/update$/],["GET",/^\/v1\/context$/],["GET",/^\/v1\/checkpoint$/]],Fn=v.object({cursor:v.coerce.number().int().min(0).max(Number.MAX_SAFE_INTEGER).default(0),limit:v.coerce.number().int().min(1).max(100).default(50)}).strict(),Kn=new URL("../site/index.html",import.meta.url),Jn="default-src 'none'; style-src 'unsafe-inline' https://fonts.googleapis.com; font-src https://fonts.gstatic.com; img-src 'self' data:; base-uri 'none'; form-action 'none'; frame-ancestors 'none'";function Vn(a){try{return JSON.parse(a)}catch{return}}c(Vn,"parseJson");function rt(a,d,h){if(!d||!a||a.startsWith("["))return{kind:"api"};const g=a.toLowerCase().replace(/:\d+$/u,"").replace(/\.$/u,""),E=`.${d.toLowerCase()}`;if(!g.endsWith(E))return{kind:"api"};const O=g.slice(0,-E.length);return ot.includes(O)?g===h?{kind:"api"}:{kind:"none"}:{kind:"board",label:O}}c(rt,"hostKind");function Wn(a){const d=a.headers[mn];return typeof d=="string"&&/^\d{1,4}\.\d{1,4}\.\d{1,6}(-[0-9A-Za-z.-]{1,32})?$/.test(d)?d:null}c(Wn,"bridgeVersion");function Xn(a){const d=a.headers[fn];return typeof d=="string"&&/^\d{1,3}$/.test(d)&&Number(d)>=et}c(Xn,"currentBridge");const Zn=c(a=>a.attachments?{...a,attachments:a.attachments.map(({id:d,filename:h,mime_type:g,size:E})=>({id:d,filename:h,mime_type:g,size:E}))}:a,"compactAttachments"),Qn=["kind","reply_expected"],qn=c((a,d)=>Object.fromEntries(Object.entries(a).filter(([h,g])=>d.includes(h)&&!(g===null&&Qn.includes(h)))),"pick");function eo(a,d){const h={};for(const[g,E]of Object.entries(a))if(!(d.includes(g)||g==="deliveries"||E===void 0)&&hn.safeParse(g).success){if(Object.keys(h).length>=yn)break;Buffer.byteLength(JSON.stringify({...h,[g]:E}))>gn||(h[g]=E)}return Object.keys(h).length?h:null}c(eo,"extensionsOf");function Ie(a,d,h){const g=eo(Zn(a),d);return{...qn(a,d),...g?{extensions:g}:{},...h?{presentation:h}:{}}}c(Ie,"envelope");function st(a,d){if(a.type==="activity")return{...a,presentation:nn(a.agents)};if(a.type==="receipts")return{...a,receipts:a.receipts.map(P=>Ie(P,Dn)),presentation:on(a.receipts,a.remaining)};const{covered:h,covered_count:g,...E}=a,O=c(P=>({...E,messages:a.messages.map(n=>Ie(n,wn,P?We(n,d):void 0)),...h===void 0?{}:{covered:h.map(n=>Ie(n,bn,P?We(n,d):void 0)),covered_count:g}}),"shape"),N=O(!0);return Buffer.byteLength(JSON.stringify(N))<=Mn?N:O(!1)}c(st,"wireEvent");function it(a){const d=a.headers["x-pocolobby-runtime-id"],h=a.headers["x-pocolobby-generation"],g=a.headers["x-pocolobby-incarnation"];if(typeof d!="string"||typeof h!="string"||typeof g!="string"||!/^\d+$/.test(h)||!Number.isSafeInteger(Number(h)))throw new p(409,"runtime_required","Claim a runtime and supply its current binding headers.");return{runtime_id:d,generation:Number(h),incarnation:g}}c(it,"runtimeHeaders");function to(a){const d=a.headers.authorization;if(!d||!/^Bearer [A-Za-z0-9_-]{32,512}$/.test(d))throw new p(401,"unauthorized","A valid Bearer credential is required.");return d.slice(7)}c(to,"bearer");function no(a,d){return _t(Ge("sha256").update(a).digest(),d)}c(no,"equalToken");function ke(a,d,h){a.writeHead(d,{"content-type":"application/json; charset=utf-8","cache-control":"no-store","x-content-type-options":"nosniff"}),a.end(JSON.stringify(h))}c(ke,"json");function ct(a){return a.issues.map(d=>`${d.path.join(".")||"request"}: ${d.message}`).join("; ")}c(ct,"zodMessage");function ut(a){return a instanceof p?{status:a.status,body:{error:{...a.details,code:a.code,message:a.message}}}:a instanceof URIError?{status:400,body:{error:{code:"invalid_request",message:"The path has a malformed escape."}}}:a instanceof Pt?{status:400,body:{error:{code:"invalid_request",message:ct(a)}}}:{status:500,body:{error:{code:"internal_error",message:"The request failed. No success is implied; retry sends with the same request ID."}}}}c(ut,"errorResponse");function dt(a,d,h,g){return new Promise((E,O)=>{const N=[];let P=0,n=!1;const F=c(U=>{if(n)return;n=!0;const C=U?null:Buffer.concat(N,P);N.length=0,C?E(C):O(U)},"settle");a.on("data",U=>{n||(P+=U.length,P>d?F(h()):N.push(U))}),a.on("end",()=>F());const T=c(()=>F(new p(400,"request_aborted",g)),"abort");a.on("error",T),a.on("aborted",T)})}c(dt,"readBody");async function oo(a,d=Hn){if(a.headers["content-type"]?.split(";",1)[0]?.trim()!=="application/json")throw a.resume(),new p(415,"content_type","Use application/json.");const h=c(()=>new p(413,"body_too_large",`Request exceeds ${Math.round(d/1024)} KiB.`),"tooLarge");if(Number(a.headers["content-length"])>d)throw a.resume(),h();const g=await dt(a,d,h,"Request body was interrupted.");try{return JSON.parse(g.toString("utf8"))}catch{throw new p(400,"invalid_json","Request body must be valid JSON.")}}c(oo,"body");async function ao(a,d,h){if(a.headers["content-type"]?.split(";",1)[0]?.trim()!=="application/octet-stream")throw a.resume(),new p(415,"content_type","Upload with application/octet-stream.");const g=c(()=>new p(413,"attachment_too_large",`The upload exceeds ${$t(d)}, the largest attachment this broker accepts. Nothing was stored.`),"tooLarge"),E=a.headers["content-length"];if(E===void 0)throw a.resume(),new p(411,"length_required","Upload with a Content-Length header.");if(Number(E)>d)throw a.resume(),g();try{h(Number(E))}catch(O){throw a.resume(),O}return await dt(a,d,g,"Upload was interrupted.")}c(ao,"rawBody");async function xo(a){if(!/^[A-Za-z0-9_-]{32,512}$/.test(a.adminToken))throw new Error("Admin token must be 32\u2013512 URL-safe characters. Generate a random token with pocolobby init.");const d=a.host??"127.0.0.1";if(!["127.0.0.1","::1","localhost"].includes(d)&&!a.allowRemote)throw new Error("Remote listeners require --allow-remote and a TLS reverse proxy.");if(a.console?.origin&&!a.board?.domain)throw new Error("A settings origin needs a dashboard domain: set POCOLOBBY_DASHBOARD_DOMAIN too.");let h=a.tools??Ut();Me(h);const g=a.pushBytes??cn;if(!Number.isSafeInteger(g)||g<Ze||g>Qe)throw new Error(`The push size must be between ${Ze} and ${Qe} bytes.`);const E=a.uploadInflightBytes??xt,O=Math.max(a.storeOptions?.maxImageBytes??At,a.storeOptions?.maxTextBytes??Rt);if(!Number.isSafeInteger(E)||E<O)throw new Error(`The in-flight upload budget must be at least the largest attachment, ${O} bytes.`);const N=Et(kt(Kn)),P=tn(a.database);let n;try{n=new an(a.database,a.storeOptions)}catch(e){throw P(),e}const F=Ge("sha256").update(a.adminToken).digest(),T=new Map,U=new Set,C=new Map;let Q=!1;const q=new Ot({noServer:!0,maxPayload:4096,perMessageDeflate:!1});q.on("headers",e=>e.push(`X-PocoLobby-Event-Version: ${et}`));const K=a.storeOptions?.now??Date.now,j=(a.board?.domain??"").toLowerCase(),M=new zt({open:c((e,t)=>n.openTurn(e,t),"open"),close:c((e,t,o)=>n.closeTurn(e,t,o),"close")});for(const e of n.latestTurns())e.ended_ms===null?M.restore(e.agent_id,"working",e.started_ms):e.ended_state&&M.restore(e.agent_id,e.ended_state,e.ended_ms);const ce=a.exchangeRates?new Ft(n,a.exchangeRates.fetch??fetch,K,e=>process.stderr.write(`${e}
2
+ `)):null,R=new Yt(n,{...a.board,domain:j},(e,t)=>T.has(Z(e,t)),K,(e,t)=>M.view(Z(e,t))),Oe=new jt(a.adminToken),J=j?a.console?.origin??`https://${j}`:void 0,ue=J?new URL(J).hostname.toLowerCase().replace(/\.$/u,""):void 0,V=!J&&["127.0.0.1","::1","localhost"].includes(d),D=J||V?en({origin:J??null,mailer:a.console?.mailer??null,missing:a.console?.mailer||V?[]:a.console?.missing??["POSTMARK_TOKEN","POCOLOBBY_MAIL_FROM"],responseFloorMs:a.console?.responseFloorMs},{store:n,board:R,keys:Oe,boardDomain:j,clientAddress:c(e=>le(e),"clientAddress"),overRate:c(e=>de(e),"overRate"),isConnected:c((e,t)=>T.has(Z(e,t)),"isConnected"),closeAgents:c(e=>{for(const t of e)z(t,4401,"Lobby deleted")},"closeAgents"),refreshBoards:c(e=>setImmediate(()=>{R.request(e)}),"refreshBoards"),github:!!a.board?.githubToken,anthropic:!!(a.board?.summaryClient??a.board?.anthropicApiKey),exchangeRates:ce!==null,clock:K}):null;function Pe(e){const t=A.address();if(!t||typeof t=="string")return!1;const o=t.port===80?["",":80"]:[`:${t.port}`],r=(e.headers.host??"").toLowerCase();return["localhost","127.0.0.1","[::1]"].some(i=>o.some(u=>r===`${i}${u}`))}c(Pe,"loopbackHost");function de(e){const t=Date.now(),o=C.get(e);return!o||t-o.start>6e4?(!o&&C.size>=1024&&C.delete(C.keys().next().value),C.set(e,{start:t,count:1}),!1):++o.count>1200}c(de,"overRate");function Ae(e){if(e.headers.origin)throw new p(403,"origin_not_allowed","Browser origins are not enabled on this API.");const t=new URL(e.url??"/","http://lobby.invalid");if(t.searchParams.has("token")||t.searchParams.has("access_token"))throw new p(400,"credential_location","Credentials belong in the Authorization header.");if(de(le(e)))throw new p(429,"request_rate_limit","Too many requests; wait before retrying.");return t}c(Ae,"checkRequest");function le(e){const t=a.board?.clientIpHeader,o=t?e.headers[t.toLowerCase()]:void 0,r=typeof o=="string"&&o.trim()?o.split(",")[0].trim():e.socket.remoteAddress??"unknown";return Mt(r)}c(le,"clientAddress");async function Re(e,t,o,r,i){const u=e.method??"GET",m=new URL(e.url??"/","http://board.invalid").pathname.slice(i.length)||"/",s=i!=="",l=vt(16).toString("base64"),b=c((S,B,H,yt={})=>{t.writeHead(S,{"content-type":B,"cache-control":"no-store","x-content-type-options":"nosniff","referrer-policy":"same-origin","content-security-policy":B.startsWith("text/html")?Xt(l):"default-src 'none'; frame-ancestors 'none'",...yt}),t.end(u==="HEAD"?void 0:H)},"send"),f="text/html; charset=utf-8",y=c((S,B={})=>b(303,"text/plain; charset=utf-8","",{location:S,...B}),"redirect");if(de(le(e))){b(429,"text/plain; charset=utf-8","Too many requests; wait a minute.",{"retry-after":"60"});return}const w=s?void 0:Fe(m);if((u==="GET"||u==="HEAD")&&w){t.writeHead(200,{...Ye,"content-length":String(w.length)}),t.end(u==="HEAD"?void 0:w);return}const I=s?void 0:Ke(m);if((u==="GET"||u==="HEAD")&&I){t.writeHead(200,I.headers),t.end(u==="HEAD"?void 0:I.body);return}if(!s&&(u==="GET"||u==="HEAD")&&m==="/healthz"){n.healthy(),b(200,"application/json; charset=utf-8",JSON.stringify({status:"ok",protocol_version:nt}));return}const _=se.safeParse(r).success?r:null,x=_===null?null:n.boardVisibility(_),$=s?null:Te(e.headers.cookie,re),L=x!==null&&$!==null?n.boardSession(_,G($)):null,ye=s&&o.operator(e),oe=L?{kind:"account",account_id:L.account_id,email:L.email}:ye?{kind:"operator"}:null,Le=L?.email??null,X={};L?.refresh&&(n.refreshBoardSession(G($)),X["set-cookie"]=Ee(re,$));const ae=x!==null&&(x==="public"||oe!==null),we=s?"/":o.openUrl(r),Ce=c((S,B,H={})=>b(S,f,Qt(r,l,B,we),H),"notice"),De=`${!s&&(e.headers["x-forwarded-proto"]==="https"||a.allowRemote)?"https":"http"}://${e.headers.host}`,gt=e.headers.origin===De,He=s?()=>o.endOperator(e):()=>($&&n.endBoardSession(G($)),{"set-cookie":Ee(re,null)});if(m==="/settings"||m.startsWith("/settings/")){const S=L?()=>n.boardSession(_,G($))?.account_id===L.account_id:()=>o.operator(e);for(const[B,H]of Object.entries(X))t.setHeader(B,H);await o.lobby(e,t,{lobby:r,base:i,origin:De},oe,S,He);return}const Y=ae?n.boardIcon(_):null;if((u==="GET"||u==="HEAD")&&m==="/"){ae&&R.request(_),ae?b(200,f,qt(R.view(_),l,Le,Y&&Je(Y.sha256),{home:o.home,dashboard:i||"/",settings:L?.owner||ye?`${i}/settings`:null,signIn:oe===null?we:null,lobbies:oe!==null}),X):y(we);return}if((u==="GET"||u==="HEAD")&&m==="/icon.png"){if(!Y){b(404,"text/plain; charset=utf-8","Not found.");return}const S=new URL(e.url??"/","http://board.invalid").searchParams.get("v")===Je(Y.sha256);t.writeHead(200,{"content-type":"image/png","content-length":String(Y.png.length),"cache-control":S?`${x==="public"?"public":"private"}, max-age=31536000, immutable`:"private, no-cache","x-content-type-options":"nosniff","content-security-policy":"default-src 'none'; frame-ancestors 'none'",...X}),t.end(u==="HEAD"?void 0:Y.png);return}if((u==="GET"||u==="HEAD")&&m==="/dashboard.json"){if(!ae)b(401,"application/json; charset=utf-8",JSON.stringify({error:{code:"unauthorized",message:"Sign in to the dashboard."}}));else{R.request(_);const S=R.view(_);b(200,"application/json; charset=utf-8",JSON.stringify({generated_at:S.generated_at,activity:S.activity,page:Wt,html:Zt(S,Le,L?.owner||ye?`${i}/settings`:null)}),X)}return}const ve=new URL(e.url??"/","http://board.invalid").searchParams;if(!s&&u==="GET"&&m==="/sign-in"){const S=Te(e.headers.cookie,je)??ze();y(o.handoffUrl(r,Ve(ve.get("to")),G(S)),{"set-cookie":Ht(S)});return}if(!s&&u==="GET"&&m==="/handoff"){const S=ve.get("token"),B=Te(e.headers.cookie,je),H=ze();_!==null&&S!==null&&B!==null&&/^[A-Za-z0-9_-]{43}$/u.test(S)&&n.consumeHandoff(_,Gt(S,G(B)),G(H),$===null?null:G($))?y(Ve(ve.get("to")),{"set-cookie":Ee(re,H)}):Ce(400,"That sign-in link has expired, was already used, or began in another browser.");return}if(!s&&u==="POST"&&m==="/sign-out"){if(e.resume(),!gt){b(403,"text/plain; charset=utf-8","Sign out from the dashboard page.");return}Ce(200,"You are signed out of this dashboard.",He());return}e.resume(),b(404,"text/plain; charset=utf-8","Not found.")}c(Re,"lobbyRequest");function xe(e){const t=to(e);return no(t,F)?{owner:!0,agentId:"owner",token:t}:{owner:!1,agentId:n.authenticate(t),token:t}}c(xe,"actor");function lt(e,t){if(n.authenticate(t.token)!==t.agentId)throw new p(401,"unauthorized","Credential revoked.");const o=it(e);return n.assertRuntime(t.agentId,o),o}c(lt,"currentRuntime");let me=0;function mt(e,t){if(me+t>E)throw new p(503,"uploads_busy","The broker is receiving as many uploads as it holds at once (POCOLOBBY_UPLOAD_INFLIGHT_BYTES). Nothing was stored; retry in a few seconds.");me+=t,e.once("close",()=>{me-=t})}c(mt,"admitUpload");function z(e,t=4409,o="Runtime binding changed"){const r=T.get(e);r&&(T.delete(e),r.socket.close(t,o))}c(z,"closePeer");const ee=new Map;function k(e,t){const{name:o,code:r,message:i}=t??{},u=`pocolobby: ${e} failed: ${o??"Error"}${r?` ${r}`:""}: ${i??String(t)}`,m=Date.now();(ee.get(u)??0)>m-6e4||(ee.size>100&&ee.clear(),ee.set(u,m),process.stderr.write(`${u}
3
+ `))}c(k,"logFailure");function W(e,t){const o=t instanceof p?t.status:500;o===500&&k("stream",t),T.get(e.agentId)===e&&T.delete(e.agentId),e.socket.close(o===401?4401:o===403?4403:o===409?4409:o===400?1008:1011,o===500?"Broker operation failed; reconnect":o===400?"Invalid transport frame":"Credential or runtime no longer valid")}c(W,"failPeer");const $e=c(e=>{const t=Z(e.lobby_id,e.agent_id),o=T.get(t);return{connected:o!==void 0,bridge_version:o?.bridgeVersion??null,activity:o?M.view(t):null}},"connection"),ft=c((e,t)=>{const o=new Set(n.rooms(e.lobby_id,t==="owner"?void 0:t).map(i=>i.room_id)),r=n.curationStatus(e.lobby_id,e.agent_id).filter(i=>o.has(i.room_id));return r.length?{memory_curation:r}:{}},"curating"),te=c(e=>Nt(h,n.permissions(e),{maxImageBytes:n.maxImageBytes,maxTextBytes:n.maxTextBytes}),"catalogOf");function fe(e){if(e.socket.readyState===_e.OPEN)try{const{revision:t}=te(e.agentId);if(t===e.catalogRevision)return;e.catalogRevision=t;const o={type:"catalog",revision:t};e.socket.send(JSON.stringify(o))}catch{}}c(fe,"announceCatalog");function ne(){if(!Q){try{n.releaseDue(),n.resumeDue()}catch(e){k("scheduled delivery",e)}for(const e of T.values())if(e.socket.readyState===_e.OPEN)try{if(e.socket.bufferedAmount>256*1024){e.socket.terminate();continue}const t=n.nextNotification(e.agentId,e.auth,g)??n.nextReceipts(e.agentId,e.auth);t&&e.socket.send(JSON.stringify(st(t,n.attachmentRetentionDays)))}catch(t){W(e,t)}ht()}}c(ne,"dispatch");function ht(){const e=K();for(const t of T.values())if(t.socket.readyState===_e.OPEN)try{const o=`${Se(t.agentId).lobby_id}/`,r=M.due(e,t.agentId,m=>m.startsWith(o)&&T.has(m));if(!r.length||!n.permissions(t.agentId).manage_rooms)continue;const i=n.openActivityNotice(t.agentId,t.auth);if(!i)continue;const u={type:"activity",...i,runtime_id:t.auth.runtime_id,generation:t.auth.generation,agents:r.map(({agent:m,turn:s})=>({agent_id:Se(m).agent_id,...s}))};t.socket.send(JSON.stringify(st(u)));for(const{told:m}of r)m.add(t.agentId)}catch(o){W(t,o)}}c(ht,"tellCoordinators");async function Be(e,t,o){const{method:r,url:i}=e,u=i.pathname,m=o==="owner",s=c(()=>{m||e.runtime()},"fence");if(u===t){if(r==="GET")return{status:200,value:{rooms:n.rooms(e.lobby(),m?void 0:o)}};if(r==="POST"){const w=En.parse(await e.body());return s(),{status:201,value:n.createRoom(o,w.room_id,e.lobby())}}return}if(!u.startsWith(`${t}/`))return;const[l,b,...f]=u.slice(t.length+1).split("/");if(!l||f.length||b!==void 0&&b!=="members")return;const y=ie.parse(decodeURIComponent(l));if(b&&r==="PUT"){const w=In.parse(await e.body());return s(),{status:200,value:n.setRoomMembers(o,y,w.members,e.lobby()),dispatch:!0}}if(b&&r==="PATCH"){const w=kn.parse(await e.body());return s(),{status:200,value:n.changeRoomMembers(o,y,w,e.lobby()),dispatch:!0}}if(!b&&r==="DELETE")return s(),{status:200,value:n.deleteRoom(o,y,e.lobby()),dispatch:!0}}c(Be,"roomRoute");async function Ne(e){const{method:t,auth:o}=e,r=e.url.pathname;if(r.startsWith("/v1/admin/")){if(!o.owner)throw new p(403,"owner_required","Owner credentials are required.");if(r==="/v1/admin/lobbies"){if(t==="GET")return{status:200,value:{lobbies:n.lobbies()}};if(t==="POST"){const f=pn.parse(await e.body());return{status:201,value:n.createLobby(f.lobby_id)}}}const i=/^\/v1\/admin\/lobbies\/([^/]+)$/.exec(r);if(i&&t==="PATCH"){const f=v.object({display_name:v.string().max(200).nullable()}).strict().parse(await e.body());return{status:200,value:n.setDisplayName("owner",se.parse(decodeURIComponent(i[1])),f.display_name??"")}}if(r==="/v1/admin/attachments"&&t==="GET")return{status:200,value:n.attachments(e.lobby(),Fn.parse(Object.fromEntries([...e.url.searchParams].filter(([f])=>f!=="lobby"))))};if(r==="/v1/admin/attachments/usage"&&t==="GET")return{status:200,value:n.attachmentUsage(e.lobby())};if(r.startsWith("/v1/admin/dashboard")){if(!n.hasLobby(e.lobby()))throw new p(404,"lobby_not_found","Unknown lobby");if(r==="/v1/admin/dashboard"&&t==="GET")return{status:200,value:R.status(e.lobby())};const f=/^\/v1\/admin\/dashboard\/sources\/([^/]+)$/.exec(r);if(f&&t==="PUT"){const y=n.setBoardSource(e.lobby(),ie.parse(decodeURIComponent(f[1])),await e.body(),"owner");return setImmediate(()=>{R.request(e.lobby())}),{status:200,value:y}}if(f&&t==="DELETE")return{status:200,value:n.removeBoardSource(e.lobby(),ie.parse(decodeURIComponent(f[1])),"owner")};if(r==="/v1/admin/dashboard/agents"&&t==="PUT")return{status:200,value:n.setBoardAgents(e.lobby(),Kt.parse(await e.body()))};if(r==="/v1/admin/dashboard/icon"&&t==="PUT"){const{png:y}=Jt.parse(await e.body());return{status:200,value:n.setBoardIcon("owner",e.lobby(),Buffer.from(y,"base64"))}}if(r==="/v1/admin/dashboard/icon"&&t==="DELETE")return{status:200,value:n.setBoardIcon("owner",e.lobby(),null)}}if(r==="/v1/admin/settings/ticket"&&t==="POST"){if(!D)throw new p(404,"not_local","This broker has no settings pages.");return{status:200,value:{ticket:D.ticket(),expires_in_seconds:60}}}if(r==="/v1/admin/settings/accounts"){if(t==="GET")return{status:200,value:{accounts:n.accounts()}};if(t==="POST"){const f=rn.parse(await e.body());return{status:200,value:n.setAccount(f,Oe.emailKey(f.email))}}}if(r==="/v1/admin/settings/owner"&&t==="PUT")return{status:200,value:n.grantLobby(tt.parse(await e.body()).email,e.lobby())};if(r==="/v1/admin/settings/owner/revoke"&&t==="POST")return{status:200,value:n.ungrantLobby(tt.parse(await e.body()).email,e.lobby())};if(r==="/v1/admin/settings/repos"){if(t==="GET")return{status:200,value:{lobby_id:e.lobby(),repos:n.lobbyRepos(e.lobby())}};if(t==="POST"){const{repo:f}=v.object({repo:Vt}).strict().parse(await e.body());return{status:200,value:{lobby_id:e.lobby(),repos:n.approveRepo(e.lobby(),f)}}}}const u=/^\/v1\/admin\/settings\/repos\/([^/]+)\/([^/]+)$/.exec(r);if(u&&t==="DELETE")return{status:200,value:{lobby_id:e.lobby(),repos:n.removeRepo(e.lobby(),`${decodeURIComponent(u[1])}/${decodeURIComponent(u[2])}`)}};const m=await Be(e,"/v1/admin/rooms","owner");if(m)return m;if(r==="/v1/admin/memory"&&t==="GET")return{status:200,value:{rooms:n.memoryOverview(e.lobby())}};const s=/^\/v1\/admin\/memory\/rooms\/([a-z][a-z0-9_-]{0,47})\/curator$/.exec(r);if(s&&t==="PUT"){const f=v.object({agent_id:Xe.nullable()}).strict().parse(await e.body());return{status:200,value:n.setMemoryCurator(e.lobby(),s[1],f.agent_id)}}const l=/^\/v1\/admin\/memory\/(?:entries\/([a-z][a-z0-9_-]{0,47}-[1-9][0-9]{0,5})|fragments\/([0-9a-f-]{36}))$/.exec(r);if(l&&t==="DELETE")return n.eraseMemory(e.lobby(),l[1]?"entry":"fragment",l[1]??l[2]),{status:200,value:{erased:!0}};if(r==="/v1/admin/agents"){if(t==="GET")return{status:200,value:{agents:n.agents(e.lobby()).map(f=>({...f,...$e(f)}))}};if(t==="POST"){const f=_n.parse(await e.body());if(f.lobby_id!==void 0&&e.url.searchParams.has("lobby")&&f.lobby_id!==e.lobby())throw new p(400,"lobby_mismatch","Provisioning lobby must match the administrative selector.");return{status:201,value:n.provision({...f,lobby_id:f.lobby_id??e.lobby()})}}}const b=/^\/v1\/admin\/agents\/([^/]+)(?:\/(rotate|reset-runtime|retry|messages|context|schedules|schedules\/cancel))?$/.exec(r);if(b){const f=Z(e.lobby(),Xe.parse(decodeURIComponent(b[1]))),y=b[2];if(!y&&t==="PATCH"){const w=Un.parse(await e.body()),I=n.updateAgent(f,w);w.enabled===!1&&z(f,4403,"Agent disabled");const _=T.get(f);return _&&fe(_),{status:200,value:I,dispatch:!0}}if(y==="messages"&&t==="GET"){const{headers:w,...I}=at.parse(Object.fromEntries([...e.url.searchParams].filter(([x])=>x!=="lobby"))),_={...I,includeHeldContent:!0};return{status:200,value:w?n.messageLines(f,_):n.messages(f,_)}}if(y==="context"&&t==="GET")return{status:200,value:n.context(f)};if(y==="schedules"&&t==="GET")return{status:200,value:n.scheduled(f)};if(y==="schedules/cancel"&&t==="POST"){const w=qe.parse(await e.body());return{status:200,value:n.cancelScheduled(f,null,w.id)}}if(t==="POST"&&["rotate","reset-runtime","retry"].includes(y??"")){if(v.object({}).strict().parse(await e.body()),y==="rotate"){const w=n.rotateToken(f);return z(f,4401,"Credential rotated"),{status:200,value:w}}return y==="reset-runtime"&&(n.resetRuntime(f),z(f)),y==="retry"&&n.retryNotifications(f),{status:200,value:{ok:!0},dispatch:!0}}}}else if(r==="/v1/agents/rest"&&t==="POST"){if(o.owner)throw new p(400,"owner_pauses","The owner pauses agents with PATCH /v1/admin/agents.");const i=Sn.parse(await e.body());return e.runtime(),{status:200,value:n.restAgents(o.agentId,i.agents,i.resting,i.resume_at),dispatch:!0}}else{if(r==="/v1/agents"&&t==="GET")return{status:200,value:{agents:n.agents(e.lobby()).filter(i=>i.enabled).map(i=>({agent_id:i.agent_id,lobby_id:i.lobby_id,work_description:i.work_description,machine:i.machine,screen:i.screen,kind:i.manage_rooms?"coordinator":i.kind,pacing:i.pacing,...$e(i),...ft(i,o.agentId),enabled:i.enabled,paused:i.paused,resume_at:i.resume_at,ready:i.ready,last_seen_at:i.last_seen_at,last_agent_seen_at:i.last_agent_seen_at,notification_attention_required:i.notification_attention_required,unseen_notified_count:i.unseen_notified_count,oldest_unseen_notified_at:i.oldest_unseen_notified_at,last_message_at:i.last_message_at,owner_requests:i.owner_requests,status:i.status,usage:R.agentUsage(i.lobby_id,i.agent_id)}))}};if(r==="/v1/messages"&&t==="POST"){const i=An.parse(await e.body());return o.owner||e.runtime(),{status:200,value:n.send(o.agentId,i,e.lobby()),dispatch:!0}}else{if(o.owner)throw new p(403,"agent_required","Use an agent credential or the owner administrative route.");const i=await Be(e,"/v1/rooms",o.agentId);if(i)return i;if(r==="/v1/runtime"&&t==="POST"){const s=On.parse(await e.body());n.authenticate(o.token);const l=n.claimRuntime(o.agentId,s.runtime_id,s.generation);s.generation===void 0&&M.forget(o.agentId,K());const b=T.get(o.agentId);return b&&b.auth.generation!==l.generation&&z(o.agentId,4409,"Runtime resumed by a newer process"),{status:200,value:l}}if(r==="/v1/context"&&t==="GET"){const s=te(o.agentId);return{status:200,value:{...n.context(o.agentId),tool_guide:Ct(s.tools,s.revision),broker:{host:e.host,version:vn}}}}const u=/^\/v1\/attachments\/([0-9a-f]{64})$/.exec(r);if(u&&t==="PUT"){const s=e.runtime(),l=await e.rawBody(Math.max(n.maxImageBytes,n.maxTextBytes));return{status:200,value:n.uploadAttachment(o.agentId,s,u[1],l)}}const m=/^\/v1\/attachments\/([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(\/content)?$/.exec(r);if(m&&t==="GET"&&!e.url.search){if(!m[2])return{status:200,value:n.attachment(o.agentId,m[1])};const{info:s,path:l,size:b}=n.attachmentFile(o.agentId,m[1]);return{status:200,value:null,raw:{path:l,size:b,headers:{"content-type":"application/octet-stream","content-disposition":"attachment","x-pocolobby-sha256":s.sha256,"x-pocolobby-mime-type":s.mime_type,"x-pocolobby-filename":encodeURIComponent(s.filename)}}}}if(r==="/v1/messages"&&t==="GET"){const{headers:s,...l}=at.parse(Object.fromEntries(e.url.searchParams));return{status:200,value:s?n.messageLines(o.agentId,l):n.messages(o.agentId,l)}}if(r==="/v1/memory"&&t==="GET")return{status:200,value:n.recall(o.agentId,Object.fromEntries(e.url.searchParams))};if(r==="/v1/memory"&&t==="POST"){const s=n.remember(o.agentId,e.runtime(),await e.body());return{status:s.duplicate?200:201,value:s}}if(r==="/v1/acknowledgments"&&t==="POST"){const s=sn.parse(await e.body());return{status:200,value:n.acknowledge(o.agentId,e.runtime(),s.message_ids)}}if(r==="/v1/schedules"){if(t==="GET")return{status:200,value:n.scheduled(o.agentId)};if(t==="POST"){const s=Pn.parse(await e.body());return{status:200,value:n.createSchedule(o.agentId,e.runtime(),s)}}}if(r==="/v1/schedules/cancel"&&t==="POST"){const s=qe.parse(await e.body());return{status:200,value:n.cancelScheduled(o.agentId,e.runtime(),s.id)}}if(r==="/v1/schedules/update"&&t==="POST"){const s=un.parse(await e.body());return{status:200,value:n.updateScheduled(o.agentId,e.runtime(),s)}}if(r==="/v1/checkpoint"&&t==="GET")return{status:200,value:n.checkpointView(o.agentId)};if(r==="/v1/checkpoint"&&t==="PUT"){const s=dn.parse(await e.body());return{status:200,value:n.checkpoint(o.agentId,e.runtime(),s)}}if(r==="/v1/memory/brief"&&t==="GET"){n.authenticate(o.token);const{part:s}=v.object({part:v.enum(["1","2","3"])}).strict().parse(Object.fromEntries(e.url.searchParams));return{status:200,value:{text:n.memoryBrief(o.agentId,Number(s))}}}if(r==="/v1/memory/curation/failures"&&t==="POST"){const s=await e.body();return n.authenticate(o.token),{status:200,value:n.curationFailed(o.agentId,s)}}if(r==="/v1/code-stats"&&t==="POST"){const s=await e.body();return n.authenticate(o.token),{status:200,value:n.saveCodeStats(o.agentId,s)}}if(r==="/v1/memory/curation/report"&&t==="POST"){const s=await e.body();return n.authenticate(o.token),{status:200,value:n.curationReport(o.agentId,s),dispatch:!0}}if(r==="/v1/memory/curation"){if(n.authenticate(o.token),t==="GET"){const{room:s,review:l}=v.object({room:ie,review:v.literal("all").optional()}).strict().parse(Object.fromEntries(e.url.searchParams));return{status:200,value:n.curationSnapshot(o.agentId,s,l==="all")}}if(t==="POST"){const s=await e.body(Gn);return n.authenticate(o.token),{status:200,value:n.curate(o.agentId,s)}}}if(r==="/v1/usage"&&t==="PUT"){const s=Bn.parse(await e.body());return n.authenticate(o.token),R.recordUsage(o.agentId,s),{status:200,value:{recorded:!0}}}if(r==="/v1/activity"&&t==="PUT"){const s=ln.parse(await e.body());return n.authenticate(o.token),M.record(o.agentId,s),{status:200,value:{recorded:!0}}}if(r==="/v1/tokens"&&t==="POST"){const s=$n.parse(await e.body());return n.authenticate(o.token),{status:200,value:n.recordTokens(o.agentId,s.calls)}}if(r==="/v1/owner-requests"&&t==="PUT"){const s=Rn.parse(await e.body());return{status:200,value:{owner_requests:n.setOwnerRequests(o.agentId,e.runtime(),s)}}}if(r==="/v1/status"&&t==="PUT"){const s=xn.parse(await e.body());return{status:200,value:{status:n.setStatus(o.agentId,e.runtime(),s)}}}if(r==="/v1/ready"&&t==="POST"){const s=Tn.parse(await e.body());return n.ready(o.agentId,e.runtime(),s),{status:200,value:{ready:!0},dispatch:!0}}}}throw new p(404,"not_found","Unknown API route.")}c(Ne,"route");function pt(e){return{async call(t,o,r){const i=new URL(o,"http://operation.invalid");if(i.origin!=="http://operation.invalid"||!o.startsWith("/v1/")||o.includes("..")||o.includes("\\")||i.hash||i.search&&!(t==="GET"&&["/v1/messages","/v1/memory"].includes(i.pathname))||!Yn.some(([s,l])=>s===t&&l.test(i.pathname)))throw new p(403,"operation_not_dispatchable","A tool may only run registered agent operations.");const u=r===void 0?{}:JSON.parse(JSON.stringify(r)),m=await Ne({...e,method:t,url:i,body:c(async()=>u,"body"),rawBody:c(async()=>{throw new p(403,"operation_not_dispatchable","Uploads are not tools.")},"rawBody")});return m.dispatch&&setImmediate(ne),m.value}}}c(pt,"toolContext");async function bt(e){if(e.auth.owner)throw new p(403,"agent_required","Tools belong to agents; the owner uses the CLI.");const t=e.url.pathname;if(t==="/v1/tools"&&e.method==="GET"&&!e.url.search)return{status:200,value:te(e.auth.agentId)};const o=/^\/v1\/tools\/([^/]+)$/.exec(t);if(o&&e.method==="POST"&&!e.url.search){const r=zn.parse(await e.body());if(n.authenticate(e.auth.token)!==e.auth.agentId)throw new p(401,"unauthorized","Credential revoked.");const i=Dt.safeParse(decodeURIComponent(o[1])),u=i.success?h.find(s=>s.name===i.data):void 0;if(!u)throw new p(404,"unknown_tool","This broker offers no tool by that name.");if(!Lt(u,n.permissions(e.auth.agentId)))throw new p(403,"tool_forbidden",`${u.name} needs a permission this agent does not have.`);const m=u.input.safeParse(r.arguments);if(!m.success){const s=te(e.auth.agentId).tools.find(l=>l.name===u.name);throw new p(400,"invalid_request",`${ct(m.error)}. ${s?`${Bt(s)}.`:""}`.trim())}return{status:200,value:{result:await u.run(pt(e),m.data)}}}throw new p(404,"not_found","Unknown API route.")}c(bt,"toolRoute");const A=St(async(e,t)=>{try{e.headers["x-forwarded-proto"]==="https"&&t.setHeader("strict-transport-security","max-age=31536000");const o=rt(e.headers.host,j,ue);if(o.kind==="none"){e.resume(),t.writeHead(404,{"content-type":"text/plain; charset=utf-8"}),t.end("Not found.");return}if(o.kind==="board"&&D){await Re(e,t,D,o.label,"");return}if(D){const I=new URL(e.url??"/","http://lobby.invalid").pathname,_=V?/^\/([^/]+)/u.exec(I)?.[1]:void 0,x=_!==void 0&&se.safeParse(_).success&&!ot.includes(_)?_:null,$=I==="/"&&(V?Pe(e):(e.headers.host??"").toLowerCase().replace(/:\d+$/u,"")===ue);if(D.handles(I)||$||x!==null){V&&!Pe(e)?(e.resume(),t.writeHead(421,{"content-type":"text/plain; charset=utf-8"}),t.end("Open this broker at its own address, such as http://localhost:8787.")):x!==null?await Re(e,t,D,x,`/${x}`):await D.account(e,t);return}}const r=Ae(e),i=e.method??"GET",u=r.pathname;if(i==="GET"&&u==="/healthz"){n.healthy(),ke(t,200,{status:"ok",protocol_version:nt});return}if((i==="GET"||i==="HEAD")&&u==="/"){t.writeHead(200,{"content-type":"text/html; charset=utf-8","content-length":String(N.length),"cache-control":"public, max-age=300","content-security-policy":Jn,"x-content-type-options":"nosniff"}),t.end(i==="HEAD"?void 0:N);return}const m=Fe(u);if((i==="GET"||i==="HEAD")&&m){t.writeHead(200,{...Ye,"content-length":String(m.length)}),t.end(i==="HEAD"?void 0:m);return}const s=Ke(u);if((i==="GET"||i==="HEAD")&&s){t.writeHead(200,s.headers),t.end(i==="HEAD"?void 0:s.body);return}const l=xe(e);if(!l.owner&&(r.searchParams.has("lobby")||r.searchParams.has("lobby_id")))throw new p(403,"scope_selection_forbidden","Your credential selects your private lobby; it cannot be changed by a request.");const b=r.searchParams.get("lobby");let f;const y={method:i,url:r,auth:l,lobby:c(()=>f??=l.owner?b===null?n.soleLobby():se.parse(b):Se(l.agentId).lobby_id,"lobby"),host:e.headers.host??null,body:c(I=>oo(e,I),"body"),rawBody:c(I=>ao(e,I,_=>mt(t,_)),"rawBody"),runtime:c(()=>lt(e,l),"runtime")},w=u==="/v1/tools"||u.startsWith("/v1/tools/")?await bt(y):await Ne(y);w.raw?(t.writeHead(w.status,{...w.raw.headers,"content-length":String(w.raw.size),"cache-control":"no-store","x-content-type-options":"nosniff"}),It(Tt(w.raw.path),t,()=>{})):ke(t,w.status,w.value),w.dispatch&&setImmediate(ne)}catch(o){const r=ut(o);r.status===500&&k(`${e.method} ${e.url?.split("?",1)[0]}`,o),!t.headersSent&&!t.destroyed&&(r.status===413&&t.setHeader("connection","close"),r.status===429&&t.setHeader("retry-after","60"),r.status===503&&t.setHeader("retry-after","5"),ke(t,r.status,r.body))}});A.requestTimeout=12e4,A.headersTimeout=1e4,A.keepAliveTimeout=5e3,A.maxRequestsPerSocket=1e3,A.on("connection",e=>{U.add(e),e.on("close",()=>U.delete(e))}),A.on("upgrade",(e,t,o)=>{const r=c(()=>t.destroy(),"dropSocket");t.on("error",r);try{if(rt(e.headers.host,j,ue).kind!=="api")throw new p(404,"not_found","Unknown stream route.");const i=Ae(e);if(i.pathname!=="/v1/events"||i.search)throw new p(404,"not_found","Unknown stream route.");if(!Xn(e))throw new p(426,"bridge_outdated","This PocoLobby bridge is older than the broker: install the current package.");const u=xe(e);if(u.owner)throw new p(403,"agent_required","Only an agent can consume an inbox.");const m=it(e);n.assertRuntime(u.agentId,m),t.off("error",r),q.handleUpgrade(e,t,o,s=>{z(u.agentId,4409,"Connection replaced by the same runtime");const l={agentId:u.agentId,auth:m,socket:s,bridgeVersion:Wn(e),alive:!0,frames:0,frameWindow:Date.now()};T.set(u.agentId,l),s.on("error",()=>{}),s.on("close",()=>{T.get(u.agentId)===l&&T.delete(u.agentId)}),s.on("pong",()=>{l.alive=!0;try{n.heartbeat(l.agentId,l.auth)}catch(b){W(l,b)}}),s.on("message",(b,f)=>{try{if(Date.now()-l.frameWindow>6e4&&(l.frames=0,l.frameWindow=Date.now()),++l.frames>jn)throw new Error("Too many transport frames in a minute");const y=f?void 0:Nn.safeParse(Vn(b.toString())).data;if(!y)throw new p(400,"invalid_frame","Invalid transport frame.");n.recordTransport(l.agentId,l.auth,y)}catch(y){W(l,y)}});try{n.heartbeat(l.agentId,l.auth)}catch(b){W(l,b);return}fe(l),setImmediate(ne)})}catch(i){const{status:u,body:m}=ut(i),s=JSON.stringify(m);t.end(`HTTP/1.1 ${u} Rejected\r
4
4
  Connection: close\r
5
5
  Content-Type: application/json\r
6
6
  Content-Length: ${Buffer.byteLength(s)}\r
7
7
  \r
8
- ${s}`)}});const he=setInterval(ne,a.dispatchIntervalMs??250);he.unref();const Ne=c(()=>{if(!Q){try{n.pruneMessages()}catch(e){P("message sweep",e)}try{n.collectAttachments()}catch(e){P("attachment sweep",e)}try{n.pruneSignIn()}catch(e){P("sign-in sweep",e)}try{n.pruneAdminEvents()}catch(e){P("audit sweep",e)}try{n.pruneNotificationAttempts()}catch(e){P("notification sweep",e)}try{n.pruneTokens()}catch(e){P("token sweep",e)}try{n.pruneTurns()}catch(e){P("turn sweep",e)}try{n.pruneMemory()}catch(e){P("memory sweep",e)}try{ce?.refreshIfDue()}catch(e){P("exchange-rate refresh",e)}}},"sweep"),pe=setInterval(Ne,a.attachmentSweepIntervalMs??6e4);pe.unref(),setImmediate(Ne);const be=setInterval(()=>{for(const e of T.values()){if(!e.alive){e.socket.terminate();continue}e.alive=!1,e.socket.ping()}},15e3);be.unref();try{await new Promise((e,t)=>{A.once("error",t),A.listen(a.port??8787,d,()=>{A.off("error",t),e()})})}catch(e){throw clearInterval(he),clearInterval(be),clearInterval(pe),q.close(),n.close(),O(),e}const ge=A.address();if(!ge||typeof ge=="string")throw new Error("Could not determine listening address.");return{url:`http://${d.includes(":")?`[${d}]`:d}:${ge.port}`,setTools(e){Me(e),h=e;for(const t of T.values())fe(t)},async close(){if(Q)return;Q=!0,clearInterval(he),clearInterval(be),clearInterval(pe);for(const t of T.values())t.socket.close(1001,"Broker restarting");const e=setTimeout(()=>{for(const t of U)t.destroy()},250);e.unref(),await new Promise(t=>A.close(()=>t()));for(const t of T.values())t.socket.terminate();q.close(),clearTimeout(e),await R.close(),await ce?.close(),n.close(),O()}}}c(xo,"startServer");export{rt as hostKind,xo as startServer,st as wireEvent};
8
+ ${s}`)}});const he=setInterval(ne,a.dispatchIntervalMs??250);he.unref();const Ue=c(()=>{if(!Q){try{n.pruneMessages()}catch(e){k("message sweep",e)}try{n.collectAttachments()}catch(e){k("attachment sweep",e)}try{n.pruneSignIn()}catch(e){k("sign-in sweep",e)}try{n.pruneAdminEvents()}catch(e){k("audit sweep",e)}try{n.pruneNotificationAttempts()}catch(e){k("notification sweep",e)}try{n.pruneTokens()}catch(e){k("token sweep",e)}try{n.pruneTurns()}catch(e){k("turn sweep",e)}try{n.pruneMemory()}catch(e){k("memory sweep",e)}try{ce?.refreshIfDue()}catch(e){k("exchange-rate refresh",e)}try{n.paceAll(),n.pruneAccountWeeks()}catch(e){k("pacing",e)}}},"sweep"),pe=setInterval(Ue,a.attachmentSweepIntervalMs??6e4);pe.unref(),setImmediate(Ue);const be=setInterval(()=>{for(const e of T.values()){if(!e.alive){e.socket.terminate();continue}e.alive=!1,e.socket.ping()}},15e3);be.unref();try{await new Promise((e,t)=>{A.once("error",t),A.listen(a.port??8787,d,()=>{A.off("error",t),e()})})}catch(e){throw clearInterval(he),clearInterval(be),clearInterval(pe),q.close(),n.close(),P(),e}const ge=A.address();if(!ge||typeof ge=="string")throw new Error("Could not determine listening address.");return{url:`http://${d.includes(":")?`[${d}]`:d}:${ge.port}`,setTools(e){Me(e),h=e;for(const t of T.values())fe(t)},async close(){if(Q)return;Q=!0,clearInterval(he),clearInterval(be),clearInterval(pe);for(const t of T.values())t.socket.close(1001,"Broker restarting");const e=setTimeout(()=>{for(const t of U)t.destroy()},250);e.unref(),await new Promise(t=>A.close(()=>t()));for(const t of T.values())t.socket.terminate();q.close(),clearTimeout(e),await R.close(),await ce?.close(),n.close(),P()}}}c(xo,"startServer");export{rt as hostKind,xo as startServer,st as wireEvent};
@@ -1,7 +1,7 @@
1
- var O=Object.defineProperty;var d=(s,i)=>O(s,"name",{value:i,configurable:!0});import{execFile as $,spawn as k}from"node:child_process";import{createHash as v}from"node:crypto";import{readFile as x,rename as N,writeFile as T}from"node:fs/promises";import{tmpdir as P}from"node:os";import{join as W}from"node:path";import{LobbyClient as b}from"./client.js";import{Effort as D,ModelId as j,ModelWindowSchema as E,UsageReportSchema as R,windowCovers as I}from"./protocol.js";import{newCalls as J}from"./transcripts.js";const U=5*6e4,A=5*6e4,y=3e3,C=5*6e4,q=1e4,z=15*6e4,F=6e4;function M(s,i,o){const t=s??{},n=t.rate_limits,u=j.safeParse(t.model?.id),a=D.safeParse(t.effort?.level),e=t.context_window?.context_window_size,r=d(m=>{const{used_percentage:_,resets_at:w}=m??{};return typeof _=="number"&&typeof w=="number"?{used_percentage:Math.min(100,Math.max(0,_)),resets_at:Math.round(w)}:void 0},"window"),l=R.safeParse({five_hour:r(n?.five_hour),seven_day:r(n?.seven_day),account:i?.email,plan:i?.plan,model:u.success?u.data:void 0,effort:a.success?a.data:void 0,context:typeof e=="number"&&Number.isInteger(e)&&e>0?e:void 0,model_windows:o});if(!l.success)return null;const c=Object.fromEntries(Object.entries(l.data).filter(([,m])=>m!==void 0));return c.five_hour||c.seven_day||c.model?c:null}d(M,"usageReport");function H(s){if(!s)return"";const i=d(t=>`${Math.max(0,Math.round(100-t))}% left`,"left"),o=[];if(s.five_hour){const t=new Date(s.five_hour.resets_at*1e3),n=`${String(t.getHours()).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}`;o.push(`5h ${i(s.five_hour.used_percentage)}, resets ${n}`)}s.seven_day&&o.push(`week ${i(s.seven_day.used_percentage)}`);for(const t of s.model_windows??[])s.model&&I(s.model,t.name)&&o.push(`${t.name.toLowerCase()} ${i(t.used_percentage)}`);return o.join(", ")}d(H,"statusText");function L(){return new Promise(s=>{$("claude",["auth","status","--json"],{timeout:y,windowsHide:!0,shell:process.platform==="win32"},(i,o)=>{if(i)return s(null);try{const t=JSON.parse(o);s({email:typeof t.email=="string"?t.email:void 0,plan:typeof t.subscriptionType=="string"?t.subscriptionType:void 0})}catch{s(null)}})})}d(L,"claudeAccount");function G(s){const i=s??{},o=i.response?.rate_limits?.model_scoped;return i.subtype!=="success"||!Array.isArray(o)?null:o.flatMap(t=>{const{display_name:n,utilization:u,resets_at:a}=t??{},e=typeof a=="string"?Date.parse(a):NaN,r=E.safeParse({name:typeof n=="string"?n.trim():void 0,used_percentage:typeof u=="number"?Math.min(100,Math.max(0,u)):void 0,resets_at:Number.isFinite(e)?Math.round(e/1e3):void 0});return r.success?[r.data]:[]}).slice(0,8)}d(G,"modelWindows");function K(){return new Promise(s=>{const i=k("claude",["--safe-mode","--no-session-persistence","--print","--input-format","stream-json","--output-format","stream-json","--verbose"],{stdio:["pipe","pipe","ignore"],windowsHide:!0,shell:process.platform==="win32"});let o=!1,t="";const n=d(e=>{o||(o=!0,clearTimeout(u),i.stdin.end(),i.kill(),s(e))},"finish"),u=setTimeout(()=>n(null),q),a=d((e,r)=>i.stdin.write(`${JSON.stringify({type:"control_request",request_id:e,request:r})}
2
- `),"send");i.on("error",()=>n(null)),i.on("exit",()=>n(null)),i.stdin.on("error",()=>n(null)),i.stdout.on("data",e=>{t+=e.toString("utf8");for(let r=t.indexOf(`
1
+ var x=Object.defineProperty;var d=(s,o)=>x(s,"name",{value:o,configurable:!0});import{execFile as T,spawn as P}from"node:child_process";import{createHash as W}from"node:crypto";import{readFile as D,rename as E,writeFile as j}from"node:fs/promises";import{tmpdir as R}from"node:os";import{join as J}from"node:path";import{LobbyClient as N}from"./client.js";import{Effort as C,ModelId as I,ModelWindowSchema as U,UsageReportSchema as A,windowCovers as q}from"./protocol.js";import{newCalls as z}from"./transcripts.js";const F=5*6e4,H=5*6e4,L=3e4,b=3e3,K=5*6e4,B=1e4,G=15*6e4,Q=6e4;function h(s,o,i){const t=s??{},n=t.rate_limits,u=I.safeParse(t.model?.id),a=C.safeParse(t.effort?.level),e=t.context_window?.context_window_size,r=d(w=>{const{used_percentage:p,resets_at:_}=w??{};return typeof p=="number"&&typeof _=="number"?{used_percentage:Math.min(100,Math.max(0,p)),resets_at:Math.round(_)}:void 0},"window"),f=A.safeParse({five_hour:r(n?.five_hour),seven_day:r(n?.seven_day),account:o?.email,plan:o?.plan,model:u.success?u.data:void 0,effort:a.success?a.data:void 0,context:typeof e=="number"&&Number.isInteger(e)&&e>0?e:void 0,model_windows:i});if(!f.success)return null;const c=Object.fromEntries(Object.entries(f.data).filter(([,w])=>w!==void 0));return c.five_hour||c.seven_day||c.model?c:null}d(h,"usageReport");function V(s){if(!s)return"";const o=d(t=>`${Math.max(0,Math.round(100-t))}% left`,"left"),i=[];if(s.five_hour){const t=new Date(s.five_hour.resets_at*1e3),n=`${String(t.getHours()).padStart(2,"0")}:${String(t.getMinutes()).padStart(2,"0")}`;i.push(`5h ${o(s.five_hour.used_percentage)}, resets ${n}`)}s.seven_day&&i.push(`week ${o(s.seven_day.used_percentage)}`);for(const t of s.model_windows??[])s.model&&q(s.model,t.name)&&i.push(`${t.name.toLowerCase()} ${o(t.used_percentage)}`);return i.join(", ")}d(V,"statusText");function X(){return new Promise(s=>{T("claude",["auth","status","--json"],{timeout:b,windowsHide:!0,shell:process.platform==="win32"},(o,i)=>{if(o)return s(null);try{const t=JSON.parse(i);s({email:typeof t.email=="string"?t.email:void 0,plan:typeof t.subscriptionType=="string"?t.subscriptionType:void 0})}catch{s(null)}})})}d(X,"claudeAccount");function Y(s){const o=s??{},i=o.response?.rate_limits?.model_scoped;return o.subtype!=="success"||!Array.isArray(i)?null:i.flatMap(t=>{const{display_name:n,utilization:u,resets_at:a}=t??{},e=typeof a=="string"?Date.parse(a):NaN,r=U.safeParse({name:typeof n=="string"?n.trim():void 0,used_percentage:typeof u=="number"?Math.min(100,Math.max(0,u)):void 0,resets_at:Number.isFinite(e)?Math.round(e/1e3):void 0});return r.success?[r.data]:[]}).slice(0,8)}d(Y,"modelWindows");function Z(){return new Promise(s=>{const o=P("claude",["--safe-mode","--no-session-persistence","--print","--input-format","stream-json","--output-format","stream-json","--verbose"],{stdio:["pipe","pipe","ignore"],windowsHide:!0,shell:process.platform==="win32"});let i=!1,t="";const n=d(e=>{i||(i=!0,clearTimeout(u),o.stdin.end(),o.kill(),s(e))},"finish"),u=setTimeout(()=>n(null),B),a=d((e,r)=>o.stdin.write(`${JSON.stringify({type:"control_request",request_id:e,request:r})}
2
+ `),"send");o.on("error",()=>n(null)),o.on("exit",()=>n(null)),o.stdin.on("error",()=>n(null)),o.stdout.on("data",e=>{t+=e.toString("utf8");for(let r=t.indexOf(`
3
3
  `);r>=0;r=t.indexOf(`
4
- `)){const l=t.slice(0,r);t=t.slice(r+1);let c;try{c=JSON.parse(l)}catch{continue}c.type==="control_response"&&(c.response?.request_id==="initialize"?a("usage",{subtype:"get_usage",skip_behaviors:!0}):c.response?.request_id==="usage"&&n(G(c.response)))}}),a("initialize",{subtype:"initialize"})})}d(K,"claudeModelWindows");async function g(s,i,o,t,n){const u=i?.transcript_path,a=typeof u=="string"&&u.endsWith(".jsonl")?u:null;if(!a&&!Object.keys(o.transcripts??{}).length)return{state:o,note:""};if(!n.dryRun&&!o.tokens_more&&o.tokens_at&&t-o.tokens_at<F)return{state:o,note:""};const{calls:e,read:r,more:l}=await J(a,o.transcripts??{},t);if(n.dryRun)return{state:o,note:`Dry run, not sent: POST /v1/tokens with ${e.length} model call${e.length===1?"":"s"}`};const c=n.client??new b({...s,timeoutMs:y});try{return e.length&&await c.request("POST","/v1/tokens",{calls:e}),{state:{...o,transcripts:r,tokens_at:t,tokens_more:l},note:""}}catch{return{state:{...o,tokens_at:t,tokens_more:!1},note:""}}}d(g,"reportTokens");async function se(s,i,o,t={}){const n=t.now??Date.now,u=t.statePath??W(P(),`pocolobby-usage-${v("sha256").update(i).digest("hex").slice(0,16)}.json`);let a=null;try{a=JSON.parse(o)}catch{return""}let e={};try{e=JSON.parse(await x(u,"utf8"))}catch{}const r=d(async()=>{try{await T(`${u}.tmp`,JSON.stringify(e),{mode:384}),await N(`${u}.tmp`,u)}catch{}},"save");if(M(a,null)===null){const f=await g(s,a,e,n(),t);return t.dryRun?f.note?`${f.note}
5
- Dry run: this input has no rate_limits and no model, so no usage would be sent.`:"Dry run: this input has no rate_limits and no model, so nothing would be sent.":(e=f.state,await r(),"")}const l=!e.account_tried_at||n()-e.account_tried_at>=A,c=!e.windows_tried_at||n()-e.windows_tried_at>=C;(l||c)&&!t.dryRun&&(l&&(e={...e,account_tried_at:n()}),c&&(e={...e,windows_tried_at:n()}),await r());const[m,_]=await Promise.all([l?(t.account??L)():null,c?(t.windows??K)():null]);m&&(e={...e,account:m,account_at:n()}),_&&(e={...e,windows:_,windows_at:n()});const w=e.windows&&e.windows_at&&n()-e.windows_at<z?e.windows:void 0,p=M(a,e.account??null,w),S=H(p),h=JSON.stringify(p);if(t.dryRun){const f=await g(s,a,e,n(),t);return`${S}
6
- Dry run, not sent: PUT /v1/usage ${h}${f.note?`
7
- ${f.note}`:""}`}if(p&&(h!==e.sent||n()-(e.sent_at??0)>=U)){const f=t.client??new b({...s,timeoutMs:y});try{await f.request("PUT","/v1/usage",p),e={...e,sent:h,sent_at:n()}}catch{}}return await r(),e=(await g(s,a,e,n(),t)).state,await r(),S}d(se,"runStatusLine");export{U as USAGE_RESEND_MS,G as modelWindows,se as runStatusLine,H as statusText,M as usageReport};
4
+ `)){const f=t.slice(0,r);t=t.slice(r+1);let c;try{c=JSON.parse(f)}catch{continue}c.type==="control_response"&&(c.response?.request_id==="initialize"?a("usage",{subtype:"get_usage",skip_behaviors:!0}):c.response?.request_id==="usage"&&n(Y(c.response)))}}),a("initialize",{subtype:"initialize"})})}d(Z,"claudeModelWindows");async function O(s,o,i,t,n){const u=o?.transcript_path,a=typeof u=="string"&&u.endsWith(".jsonl")?u:null;if(!a&&!Object.keys(i.transcripts??{}).length)return{state:i,note:""};if(!n.dryRun&&!i.tokens_more&&i.tokens_at&&t-i.tokens_at<Q)return{state:i,note:""};const{calls:e,read:r,more:f}=await z(a,i.transcripts??{},t);if(n.dryRun)return{state:i,note:`Dry run, not sent: POST /v1/tokens with ${e.length} model call${e.length===1?"":"s"}`};const c=n.client??new N({...s,timeoutMs:b});try{return e.length&&await c.request("POST","/v1/tokens",{calls:e}),{state:{...i,transcripts:r,tokens_at:t,tokens_more:f},note:""}}catch{return{state:{...i,tokens_at:t,tokens_more:!1},note:""}}}d(O,"reportTokens");async function ce(s,o,i,t={}){const n=t.now??Date.now,u=t.statePath??J(R(),`pocolobby-usage-${W("sha256").update(o).digest("hex").slice(0,16)}.json`);let a=null;try{a=JSON.parse(i)}catch{return""}let e={};try{e=JSON.parse(await D(u,"utf8"))}catch{}const r=d(async()=>{try{await j(`${u}.tmp`,JSON.stringify(e),{mode:384}),await E(`${u}.tmp`,u)}catch{}},"save");if(h(a,null)===null){const l=await O(s,a,e,n(),t);return t.dryRun?l.note?`${l.note}
5
+ Dry run: this input has no rate_limits and no model, so no usage would be sent.`:"Dry run: this input has no rate_limits and no model, so nothing would be sent.":(e=l.state,await r(),"")}const f=d(()=>e.windows&&e.windows_at&&n()-e.windows_at<G&&e.windows_email===e.account?.email?e.windows:void 0,"fresh"),c=d(l=>l!==null&&(JSON.stringify(l)!==e.sent||n()-(e.sent_at??0)>=F),"due"),w=h(a,null)?.seven_day!==void 0,p=e.account_tried_at===void 0?1/0:n()-e.account_tried_at,_=!e.windows_tried_at||n()-e.windows_tried_at>=K,g=_||p>=H||w&&p>=L&&c(h(a,e.account??null,f()));(g||_)&&!t.dryRun&&(g&&(e={...e,account_tried_at:n()}),_&&(e={...e,windows_tried_at:n()}),await r());let S=!1;const M=g?await(t.account??X)():null;M&&(e={...e,account:M,account_at:n()},S=!!M.email,t.dryRun||await r());const v=_?await(t.windows??Z)():null;v&&(e={...e,windows:v,windows_at:n(),windows_email:S?e.account?.email:void 0});const m=h(a,e.account??null,f()),k=V(m),y=m?.seven_day&&!S?c(m)?{...m,seven_day:void 0}:null:m,$=JSON.stringify(y);if(t.dryRun){const l=await O(s,a,e,n(),t);return`${k}
6
+ Dry run, not sent: PUT /v1/usage ${JSON.stringify(y??m)}${l.note?`
7
+ ${l.note}`:""}`}if(c(y)){const l=t.client??new N({...s,timeoutMs:b});try{await l.request("PUT","/v1/usage",y),e={...e,sent:$,sent_at:n()}}catch{}}return await r(),e=(await O(s,a,e,n(),t)).state,await r(),k}d(ce,"runStatusLine");export{F as USAGE_RESEND_MS,Y as modelWindows,ce as runStatusLine,V as statusText,h as usageReport};