@scp-dev/dashboard 0.2.0 → 0.4.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/public/index.html +1 -1
- package/dist/public/selfhost.js +35 -32
- package/dist/server.js +1 -1
- package/package.json +1 -1
package/dist/public/index.html
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>scp relay</title><link rel="stylesheet" href="/app.css?v=1oq5q70"><script src="/selfhost.js?v=
|
|
1
|
+
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>scp relay</title><link rel="stylesheet" href="/app.css?v=1oq5q70"><script src="/selfhost.js?v=6h9eza" defer></script></head><body></body></html>
|
package/dist/public/selfhost.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(()=>{var f=((e)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var U=86400000;var ot=(e)=>{let t=2166136261;for(let n=0;n<e.length;n++)t=Math.imul(t^e.charCodeAt(n),16777619);return t>>>0};function at(e){let t=e.split(/[^\p{L}\p{N}]+/u).filter(Boolean);return(t.length>1?t[0][0]+t[1][0]:(t[0]??e).slice(0,1)).toUpperCase()||"?"}function ee(e){let t=(
|
|
1
|
+
(()=>{var f=((e)=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(t,n)=>(typeof require<"u"?require:t)[n]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+e+'" is not supported')});var U=86400000;var ot=(e)=>{let t=2166136261;for(let n=0;n<e.length;n++)t=Math.imul(t^e.charCodeAt(n),16777619);return t>>>0};function at(e){let t=e.split(/[^\p{L}\p{N}]+/u).filter(Boolean);return(t.length>1?t[0][0]+t[1][0]:(t[0]??e).slice(0,1)).toUpperCase()||"?"}function ee(e){let t=(d)=>d.split("@")[0]||d,n=new Map;for(let d of e)n.set(t(d.email),(n.get(t(d.email))??0)+1);let o=e.map((d)=>({id:d.user_id,name:n.get(t(d.email))>1?d.email:t(d.email)}));o.sort((d,l)=>d.name.localeCompare(l.name));let i=new Set,s=new Map;for(let{id:d,name:l}of o){let a=ot(l)%8;for(let c=0;c<8&&i.has(a);c++)a=(a+1)%8;i.add(a),s.set(d,{name:l,initials:at(l),tone:a})}return s}function B(e,t){return{...e,machines:e.machines.map(({actor:n,...o})=>({...o,identity:n!==null&&t.get(n)||null}))}}var dt=["inbox.wait","ask","scopes","groups"],pn=[...dt,"peek","judge","holds"],te={bodyBytes:65536,recipients:16,attachments:16,ttlDefaultS:604800,ttlMaxS:2592000,purgeAfterS:604800,inboxMax:1000,inboxPage:100,waitMaxS:50,causalWindowS:120,pairBurstWindowS:10,onlineWithinS:60,hookOnlineS:300,hookIdleS:1800,hookEndedGraceS:30,restartGraceS:60,injectMessages:5,injectBytes:7168,pushBytes:20480,pushes:20,pushGapS:30,pushQuietS:3,pushGraceS:6,stopBlocks:3,directiveHolds:5,injectHoldS:10,deferredShowS:600,deferredSettleMs:2000,listOfflineWithinS:86400,historicAfterS:3600,handleBoundS:2592000,endpointRetireS:86400,endpointRetireMax:1000,idempotencyS:86400,auditKeepS:2592000,noteChars:280,handbackBytes:16384,stderrBytes:1024,activityKeep:5000,activitySummaryChars:200,textField:512,lineageMax:16,depthMax:32,fanOutMax:32,fanOutTotal:64,grantTtlS:604800,groupIdleS:86400,policyLoadsKept:8,titleRefreshTurns:5,wakeDebounceS:60,wakeBackoffMaxS:900,wakeRefChars:512,wakeEtaMaxS:3600};var Re=["codex-queue"];var Se=new Set(["cli","hook","mcp","shell"]);var Ln=`harness IN (${[...Se].map((e)=>`'${e}'`).join(", ")})`;var ne="_gone_",On=[`CREATE TABLE IF NOT EXISTS endpoints (
|
|
2
2
|
id TEXT PRIMARY KEY,
|
|
3
3
|
handle TEXT NOT NULL UNIQUE,
|
|
4
4
|
kind TEXT NOT NULL,
|
|
@@ -77,7 +77,10 @@
|
|
|
77
77
|
spent_cwd TEXT,
|
|
78
78
|
title TEXT,
|
|
79
79
|
bound_process TEXT
|
|
80
|
-
)`,"CREATE TABLE IF NOT EXISTS groups (name TEXT PRIMARY KEY, owner TEXT NOT NULL, tree TEXT, rules TEXT, pinned INTEGER NOT NULL DEFAULT 0, created_at INTEGER NOT NULL, id TEXT)","CREATE TABLE IF NOT EXISTS group_members (name TEXT NOT NULL, endpoint TEXT NOT NULL, added_by TEXT NOT NULL, at INTEGER NOT NULL, PRIMARY KEY (name, endpoint))","CREATE TABLE IF NOT EXISTS policy_binds (policy TEXT NOT NULL, name TEXT NOT NULL, grp TEXT NOT NULL, PRIMARY KEY (policy, name))","CREATE TABLE IF NOT EXISTS policy_loads (policy TEXT PRIMARY KEY, at INTEGER NOT NULL)","CREATE INDEX IF NOT EXISTS group_members_endpoint ON group_members (endpoint)","CREATE TABLE IF NOT EXISTS admins (subject TEXT NOT NULL, scope_kind TEXT NOT NULL, scope TEXT NOT NULL, scope_id TEXT, granted_at INTEGER NOT NULL, revoked_at INTEGER)","CREATE TABLE IF NOT EXISTS tree_events (tree TEXT NOT NULL, at INTEGER NOT NULL)","CREATE INDEX IF NOT EXISTS tree_events_tree ON tree_events (tree, at)"
|
|
80
|
+
)`,"CREATE TABLE IF NOT EXISTS groups (name TEXT PRIMARY KEY, owner TEXT NOT NULL, tree TEXT, rules TEXT, pinned INTEGER NOT NULL DEFAULT 0, created_at INTEGER NOT NULL, id TEXT)","CREATE TABLE IF NOT EXISTS group_members (name TEXT NOT NULL, endpoint TEXT NOT NULL, added_by TEXT NOT NULL, at INTEGER NOT NULL, PRIMARY KEY (name, endpoint))","CREATE TABLE IF NOT EXISTS policy_binds (policy TEXT NOT NULL, name TEXT NOT NULL, grp TEXT NOT NULL, PRIMARY KEY (policy, name))","CREATE TABLE IF NOT EXISTS policy_loads (policy TEXT PRIMARY KEY, at INTEGER NOT NULL)","CREATE INDEX IF NOT EXISTS group_members_endpoint ON group_members (endpoint)","CREATE TABLE IF NOT EXISTS admins (subject TEXT NOT NULL, scope_kind TEXT NOT NULL, scope TEXT NOT NULL, scope_id TEXT, granted_at INTEGER NOT NULL, revoked_at INTEGER)","CREATE TABLE IF NOT EXISTS tree_events (tree TEXT NOT NULL, at INTEGER NOT NULL)","CREATE INDEX IF NOT EXISTS tree_events_tree ON tree_events (tree, at)",`CREATE TABLE IF NOT EXISTS spawn_via (
|
|
81
|
+
spawner TEXT NOT NULL, name TEXT NOT NULL, runner TEXT NOT NULL, address TEXT, machine TEXT, ref TEXT, attach TEXT,
|
|
82
|
+
created_at INTEGER NOT NULL, ended_at INTEGER, PRIMARY KEY (spawner, name)
|
|
83
|
+
)`,"CREATE INDEX IF NOT EXISTS spawn_via_address ON spawn_via(address)","CREATE TABLE IF NOT EXISTS relay_migrations (name TEXT PRIMARY KEY, at INTEGER NOT NULL)",`CREATE TABLE IF NOT EXISTS activity (
|
|
81
84
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
82
85
|
at INTEGER NOT NULL,
|
|
83
86
|
endpoint TEXT NOT NULL,
|
|
@@ -87,7 +90,7 @@
|
|
|
87
90
|
agent TEXT
|
|
88
91
|
)`,"CREATE TABLE IF NOT EXISTS peek_turns (id INTEGER PRIMARY KEY AUTOINCREMENT, endpoint TEXT NOT NULL, at INTEGER NOT NULL, role TEXT NOT NULL, text TEXT NOT NULL)","CREATE INDEX IF NOT EXISTS peek_turns_endpoint ON peek_turns (endpoint, id)","CREATE TRIGGER IF NOT EXISTS audit_no_update BEFORE UPDATE ON audit BEGIN SELECT RAISE(ABORT, 'audit is append-only'); END",`CREATE TRIGGER IF NOT EXISTS audit_no_delete BEFORE DELETE ON audit
|
|
89
92
|
WHEN OLD.at > CAST(strftime('%s', 'now') AS INTEGER) * 1000 - ${te.auditKeepS*1000}
|
|
90
|
-
BEGIN SELECT RAISE(ABORT, 'audit is append-only'); END`];var
|
|
93
|
+
BEGIN SELECT RAISE(ABORT, 'audit is append-only'); END`];var xn=`stderr (last ${te.stderrBytes/1024} KB):`,lt=4,Dn=new RegExp(`^[0-9a-z]{${lt},}$`);var In=`COALESCE(wake IN (${Re.map((e)=>`'${e}'`).join(", ")}), 0)`;class k{value;constructor(e){this.value=e}toString(){return this.value}}var ht={"&":"&","<":"<",">":">",'"':""","'":"'"};function Ne(e){if(e instanceof k)return e.value;if(Array.isArray(e))return e.map(Ne).join("");if(e===null||e===void 0||e===!1)return"";return String(e).replace(/[&<>"']/g,(t)=>ht[t])}function r(e,...t){let n=e[0];for(let o=0;o<t.length;o++)n+=Ne(t[o])+e[o+1];return new k(n)}function R(e){let t=2166136261;for(let n=0;n<e.length;n++)t=Math.imul(t^e.charCodeAt(n),16777619);return(t>>>0).toString(36)}function re(e,t){let n=e.email?r`<nav class="nav" aria-label="Main">
|
|
91
94
|
<a href="/orgs" ${e.nav==="orgs"?r`aria-current="page"`:""}>Orgs</a>
|
|
92
95
|
<a href="/device" ${e.nav==="device"?r`aria-current="page"`:""}>Device</a>
|
|
93
96
|
<form method="post" action="/sign-out"><input type="hidden" name="csrf" value="${e.csrf}"><button class="linkish" type="submit">Sign out</button></form>
|
|
@@ -302,16 +305,16 @@ table.orgs td.end,table.orgs th.end{text-align:right}
|
|
|
302
305
|
.harnesses .more{line-height:1}
|
|
303
306
|
.foot-in{display:flex;flex-wrap:wrap;justify-content:space-between;gap:1rem;padding-block:2rem}
|
|
304
307
|
@media (prefers-reduced-motion:reduce){*,*::before,*::after{transition:none!important;animation:none!important}}
|
|
305
|
-
`;var vs=30*U;var _s=["default-src 'none'","style-src 'self' https://fonts.googleapis.com","font-src https://fonts.gstatic.com","script-src 'self' https://challenges.cloudflare.com","frame-src https://challenges.cloudflare.com","connect-src 'self' https://challenges.cloudflare.com","img-src 'self' data:","form-action 'self'","frame-ancestors 'none'","base-uri 'none'"].join("; ");var L=8000;function O(e,t){if(!e)return"never";let n=Math.max(0,Math.round((t-Date.parse(e))/1000));if(n<5)return"just now";if(n<60)return`${n}s ago`;if(n<3600)return`${Math.floor(n/60)}m ago`;if(n<86400)return`${Math.floor(n/3600)}h ago`;return`${Math.floor(n/86400)}d ago`}function E(e){let[,t="",...n]=e.split("/");return{machine:t,handle:n.join("/")||t}}function X(e,t=!1){let n=new Map(e.machines.map((s)=>[s.name,{name:s.name,machine:s,endpoints:[],away:0}])),o=(s)=>{let l=n.get(s);if(!l)l={name:s,machine:null,endpoints:[],away:0},n.set(s,l);return l},i=new Map(e.endpoints.filter((s)=>s.kind==="agent").map((s)=>[s.address,s]));for(let s of i.values()){let l=s,d=new Set([s.address]);for(let p=t?i.get(l.parent??""):void 0;p&&!d.has(p.address);p=i.get(p.parent??""))d.add(p.address),l=p;let a=E(s.address).machine,c=t?E(l.address).machine:a;if(o(c).endpoints.push(s),c!==a)o(a).away++}return[...n.values()]}var x=(e)=>e.wake&&e.wake!=="none"?e.wake:null,bt=r`<svg class="bolt" viewBox="0 0 16 16" aria-hidden="true"><path d="M9.5 1 3 9h4.5L6.5 15 13 7H8.5z" fill="currentColor"/></svg>`;function G(e){if(e.startsWith("hook:"))return`a message runs its ${e.slice(5)} wake hook`;if(e==="spawn-resume")return"a message resumes it through its spawn";return`a message wakes it via ${e}`}function wt(e){let t=x(e),n=e.waking?"hibernated, its machine is waking":t?`${e.presence}, ${G(t)}`:e.presence==="idle"?"idle, reads messages at its next turn":e.presence;return{cell:r`<span class="dot ${e.presence}${t?" wake":""}" aria-hidden="true"></span><span class="mini">${e.waking?"waking":e.presence}</span>${t?r` <span class="wake-badge">${bt}<span class="sr">${G(t)}</span></span>`:""}`,tip:n}}var de={claude:'<path d="m4.7144 15.9555 4.7174-2.6471.079-.2307-.079-.1275h-.2307l-.7893-.0486-2.6956-.0729-2.3375-.0971-2.2646-.1214-.5707-.1215-.5343-.7042.0546-.3522.4797-.3218.686.0608 1.5179.1032 2.2767.1578 1.6514.0972 2.4468.255h.3886l.0546-.1579-.1336-.0971-.1032-.0972L6.973 9.8356l-2.55-1.6879-1.3356-.9714-.7225-.4918-.3643-.4614-.1578-1.0078.6557-.7225.8803.0607.2246.0607.8925.686 1.9064 1.4754 2.4893 1.8336.3643.3035.1457-.1032.0182-.0728-.164-.2733-1.3539-2.4467-1.445-2.4893-.6435-1.032-.17-.6194c-.0607-.255-.1032-.4674-.1032-.7285L6.287.1335 6.6997 0l.9957.1336.419.3642.6192 1.4147 1.0018 2.2282 1.5543 3.0296.4553.8985.2429.8318.091.255h.1579v-.1457l.1275-1.706.2368-2.0947.2307-2.6957.0789-.7589.3764-.9107.7468-.4918.5828.2793.4797.686-.0668.4433-.2853 1.8517-.5586 2.9021-.3643 1.9429h.2125l.2429-.2429.9835-1.3053 1.6514-2.0643.7286-.8196.85-.9046.5464-.4311h1.0321l.759 1.1293-.34 1.1657-1.0625 1.3478-.8804 1.1414-1.2628 1.7-.7893 1.36.0729.1093.1882-.0183 2.8535-.607 1.5421-.2794 1.8396-.3157.8318.3886.091.3946-.3278.8075-1.967.4857-2.3072.4614-3.4364.8136-.0425.0304.0486.0607 1.5482.1457.6618.0364h1.621l3.0175.2247.7892.522.4736.6376-.079.4857-1.2142.6193-1.6393-.3886-3.825-.9107-1.3113-.3279h-.1822v.1093l1.0929 1.0686 2.0035 1.8092 2.5075 2.3314.1275.5768-.3218.4554-.34-.0486-2.2039-1.6575-.85-.7468-1.9246-1.621h-.1275v.17l.4432.6496 2.3436 3.5214.1214 1.0807-.17.3521-.6071.2125-.6679-.1214-1.3721-1.9246L14.38 17.959l-1.1414-1.9428-.1397.079-.674 7.2552-.3156.3703-.7286.2793-.6071-.4614-.3218-.7468.3218-1.4753.3886-1.9246.3157-1.53.2853-1.9004.17-.6314-.0121-.0425-.1397.0182-1.4328 1.9672-2.1796 2.9446-1.7243 1.8456-.4128.164-.7164-.3704.0667-.6618.4008-.5889 2.386-3.0357 1.4389-1.882.929-1.0868-.0062-.1579h-.0546l-6.3385 4.1164-1.1293.1457-.4857-.4554.0608-.7467.2307-.2429 1.9064-1.3114Z" fill="currentColor"/>',codex:'<path d="M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z" fill="currentColor"/>',opencode:'<path d="M21.6 24H2.4V0h19.2zM16.8 4.8H7.2v14.4h9.6z" fill="currentColor"/><path d="M16.8 9.6H7.2v9.6h9.6z" fill="currentColor" opacity=".45"/>',gemini:'<path d="M11.04 19.32Q12 21.51 12 24q0-2.49.93-4.68.96-2.19 2.58-3.81t3.81-2.55Q21.51 12 24 12q-2.49 0-4.68-.93a12.3 12.3 0 0 1-3.81-2.58 12.3 12.3 0 0 1-2.58-3.81Q12 2.49 12 0q0 2.49-.96 4.68-.93 2.19-2.55 3.81a12.3 12.3 0 0 1-3.81 2.58Q2.49 12 0 12q2.49 0 4.68.96 2.19.93 3.81 2.55t2.55 3.81" fill="currentColor"/>',agy:'<path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" fill="currentColor"/>',grok:'<g transform="translate(1.2 1.2) scale(.9)"><path d="M6.469 8.776 16.512 23h-4.464L2.005 8.776H6.47zm-.004 7.9 2.233 3.164L6.467 23H2l4.465-6.324zM22 2.582V23h-3.659V7.764L22 2.582zM22 1l-9.952 14.095-2.233-3.163L17.533 1H22z" fill="currentColor"/></g>',muse:'<g transform="translate(-1.2 -1.2) scale(1.1)"><path d="M6.915 4.03c-1.968 0-3.683 1.28-4.871 3.113C.704 9.208 0 11.883 0 14.449c0 .706.07 1.369.21 1.973a6.624 6.624 0 0 0 .265.86 5.297 5.297 0 0 0 .371.761c.696 1.159 1.818 1.927 3.593 1.927 1.497 0 2.633-.671 3.965-2.444.76-1.012 1.144-1.626 2.663-4.32l.756-1.339.186-.325c.061.1.121.196.183.3l2.152 3.595c.724 1.21 1.665 2.556 2.47 3.314 1.046.987 1.992 1.22 3.06 1.22 1.075 0 1.876-.355 2.455-.843a3.743 3.743 0 0 0 .81-.973c.542-.939.861-2.127.861-3.745 0-2.72-.681-5.357-2.084-7.45-1.282-1.912-2.957-2.93-4.716-2.93-1.047 0-2.088.467-3.053 1.308-.652.57-1.257 1.29-1.82 2.05-.69-.875-1.335-1.547-1.958-2.056-1.182-.966-2.315-1.303-3.454-1.303zm10.16 2.053c1.147 0 2.188.758 2.992 1.999 1.132 1.748 1.647 4.195 1.647 6.4 0 1.548-.368 2.9-1.839 2.9-.58 0-1.027-.23-1.664-1.004-.496-.601-1.343-1.878-2.832-4.358l-.617-1.028a44.908 44.908 0 0 0-1.255-1.98c.07-.109.141-.224.211-.327 1.12-1.667 2.118-2.602 3.358-2.602zm-10.201.553c1.265 0 2.058.791 2.675 1.446.307.327.737.871 1.234 1.579l-1.02 1.566c-.757 1.163-1.882 3.017-2.837 4.338-1.191 1.649-1.81 1.817-2.486 1.817-.524 0-1.038-.237-1.383-.794-.263-.426-.464-1.13-.464-2.046 0-2.221.63-4.535 1.66-6.088.454-.687.964-1.226 1.533-1.533a2.264 2.264 0 0 1 1.088-.285z" fill="currentColor"/></g>',pi:'<path d="M0 0h18v6H0zM0 6h6v18H0zM12 6h6v6h-6zM6 12h6v6H6zM18 12h6v12h-6z" fill="currentColor"/>',t3code:'<path d="M5.177,18.414V7.823H1V5.362H12.374V7.823H8.197V18.414H5.177ZM17.593,18.638C16.686,18.638 15.784,18.52 14.889,18.283C13.994,18.035 13.236,17.687 12.615,17.239L13.789,14.927C14.287,15.288 14.865,15.574 15.523,15.785C16.182,15.996 16.847,16.102 17.518,16.102C18.277,16.102 18.873,15.953 19.308,15.654C19.743,15.356 19.961,14.946 19.961,14.424C19.961,13.927 19.768,13.535 19.383,13.249C18.998,12.963 18.376,12.82 17.518,12.82H16.139V10.825L19.774,6.705L20.11,7.786H13.267V5.362H22.403V7.32L18.786,11.441L17.257,10.564H18.134C19.737,10.564 20.949,10.925 21.769,11.646C22.59,12.367 23,13.293 23,14.424C23,15.157 22.807,15.847 22.422,16.494C22.037,17.127 21.446,17.643 20.651,18.041C19.855,18.439 18.836,18.638 17.593,18.638Z" fill="currentColor"/>',generic:'<g transform="scale(1.5)"><rect x="1.75" y="2.75" width="12.5" height="10.5" rx="1.5" fill="none" stroke="currentColor" stroke-width="1.4"/><path d="M4.5 6.25 6.5 8l-2 1.75M8 10h3" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></g>'},yt={"claude-code":"claude","claude-desktop":"claude","claude-cowork":"claude","claude-desktop-chat":"claude","codex-desktop":"codex",claude:"claude",codex:"codex",opencode:"opencode",gemini:"gemini",agy:"agy",antigravity:"agy",grok:"grok",muse:"muse",xai:"grok",pi:"pi",t3code:"t3code",t3:"t3code"},J=(e)=>yt[(e??"").toLowerCase()]??"generic",q=(e)=>{let t=J(e);return r`<svg class="hicon h-${t}" width="12" height="12" viewBox="0 0 24 24" role="img" aria-label="${e??"unknown harness"}">${new k(de[t])}</svg>`},vt=r`<svg width="8" height="8" viewBox="0 0 8 8" aria-hidden="true"><path d="M2 .75 6.5 4 2 7.25z" fill="currentColor"/></svg>`,V=(e)=>e.startsWith(ne)?"(ended)":e,S=(e)=>V(E(e).handle),_t=(e)=>Object.entries(e).filter(([t])=>t!=="machine"),Oe={online:0,idle:1,hibernated:1,offline:2},oe=(e,t)=>(Oe[e.presence]??3)-(Oe[t.presence]??3)||E(e.address).handle.localeCompare(E(t.address).handle);function xe(e){let t=new Set(e.map((a)=>a.address)),n=new Map,o=[];for(let a of e)if(a.parent&&a.parent!==a.address&&t.has(a.parent))n.set(a.parent,[...n.get(a.parent)??[],a]);else o.push(a);let i=[],s=new Set,l=(a,c)=>{for(let p of a.sort(oe)){if(s.has(p.address))continue;s.add(p.address),i.push({e:p,depth:c.length,anc:c,kids:0}),l(n.get(p.address)??[],[...c,p.address])}};l(o,[]),l(e.filter((a)=>!s.has(a.address)),[]);let d=new Map(i.map((a)=>[a.e.address,a]));for(let a of i)if(a.anc.length)d.get(a.anc.at(-1)).kids++;return i}var ae=(e)=>e.presence!=="offline";function kt(e){let t=e.filter((a)=>a.kind==="agent"),n=new Set(t.map((a)=>a.address)),o=new Map,i=[];for(let a of t)if(a.parent&&a.parent!==a.address&&n.has(a.parent))o.set(a.parent,[...o.get(a.parent)??[],a]);else i.push(a);let s=new Set,l=(a)=>{s.add(a.address);let c=[],p=[...o.get(a.address)??[]];while(p.length){let b=p.pop();if(s.has(b.address))continue;s.add(b.address),c.push(b),p.push(...o.get(b.address)??[])}return{root:a,kids:c.filter(ae).sort(oe)}},d=i.map(l);for(let a of t)if(!s.has(a.address))d.push(l(a));return d.filter((a)=>ae(a.root)||a.kids.length).sort((a,c)=>c.kids.length-a.kids.length||oe(a.root,c.root))}var Rt=3,le=(e)=>r`<span class="cell ${e.presence}${x(e)?" wake":""}" title="${S(e.address)}, ${e.presence}"></span>`;function De({root:e,kids:t}){let{machine:n}=E(e.address);return r`<div class="strip-row"><span class="strip-who" title="${e.address}">${q(e.harness)}<span class="mono strip-name">${S(e.address)}</span><span class="mini">${n}</span></span>
|
|
306
|
-
<span class="cells">${ae(e)?
|
|
307
|
-
<span class="cells">${t.map((n)=>
|
|
308
|
-
<td class="agent" title="${rt}">${it}${q(e.harness)}<span class="mono">${
|
|
308
|
+
`;var ks=30*U;var Rs=["default-src 'none'","style-src 'self' https://fonts.googleapis.com","font-src https://fonts.gstatic.com","script-src 'self' https://challenges.cloudflare.com","frame-src https://challenges.cloudflare.com","connect-src 'self' https://challenges.cloudflare.com","img-src 'self' data:","form-action 'self'","frame-ancestors 'none'","base-uri 'none'"].join("; ");var L=8000;function O(e,t){if(!e)return"never";let n=Math.max(0,Math.round((t-Date.parse(e))/1000));if(n<5)return"just now";if(n<60)return`${n}s ago`;if(n<3600)return`${Math.floor(n/60)}m ago`;if(n<86400)return`${Math.floor(n/3600)}h ago`;return`${Math.floor(n/86400)}d ago`}function E(e){let[,t="",...n]=e.split("/");return{machine:t,handle:n.join("/")||t}}function X(e,t=!1){let n=new Map(e.machines.map((s)=>[s.name,{name:s.name,machine:s,endpoints:[],away:0}])),o=(s)=>{let d=n.get(s);if(!d)d={name:s,machine:null,endpoints:[],away:0},n.set(s,d);return d},i=new Map(e.endpoints.filter((s)=>s.kind==="agent").map((s)=>[s.address,s]));for(let s of i.values()){let d=s,l=new Set([s.address]);for(let u=t?i.get(d.parent??""):void 0;u&&!l.has(u.address);u=i.get(u.parent??""))l.add(u.address),d=u;let a=E(s.address).machine,c=t?E(d.address).machine:a;if(o(c).endpoints.push(s),c!==a)o(a).away++}return[...n.values()]}var x=(e)=>e.wake&&e.wake!=="none"?e.wake:null,wt=r`<svg class="bolt" viewBox="0 0 16 16" aria-hidden="true"><path d="M9.5 1 3 9h4.5L6.5 15 13 7H8.5z" fill="currentColor"/></svg>`;function G(e){if(e.startsWith("hook:"))return`a message runs its ${e.slice(5)} wake hook`;if(e==="spawn-resume")return"a message resumes it through its spawn";return`a message wakes it via ${e}`}function bt(e){let t=x(e),n=e.waking?"hibernated, its machine is waking":t?`${e.presence}, ${G(t)}`:e.presence==="idle"?"idle, reads messages at its next turn":e.presence;return{cell:r`<span class="dot ${e.presence}${t?" wake":""}" aria-hidden="true"></span><span class="mini">${e.waking?"waking":e.presence}</span>${t?r` <span class="wake-badge">${wt}<span class="sr">${G(t)}</span></span>`:""}`,tip:n}}var le={claude:'<path d="m4.7144 15.9555 4.7174-2.6471.079-.2307-.079-.1275h-.2307l-.7893-.0486-2.6956-.0729-2.3375-.0971-2.2646-.1214-.5707-.1215-.5343-.7042.0546-.3522.4797-.3218.686.0608 1.5179.1032 2.2767.1578 1.6514.0972 2.4468.255h.3886l.0546-.1579-.1336-.0971-.1032-.0972L6.973 9.8356l-2.55-1.6879-1.3356-.9714-.7225-.4918-.3643-.4614-.1578-1.0078.6557-.7225.8803.0607.2246.0607.8925.686 1.9064 1.4754 2.4893 1.8336.3643.3035.1457-.1032.0182-.0728-.164-.2733-1.3539-2.4467-1.445-2.4893-.6435-1.032-.17-.6194c-.0607-.255-.1032-.4674-.1032-.7285L6.287.1335 6.6997 0l.9957.1336.419.3642.6192 1.4147 1.0018 2.2282 1.5543 3.0296.4553.8985.2429.8318.091.255h.1579v-.1457l.1275-1.706.2368-2.0947.2307-2.6957.0789-.7589.3764-.9107.7468-.4918.5828.2793.4797.686-.0668.4433-.2853 1.8517-.5586 2.9021-.3643 1.9429h.2125l.2429-.2429.9835-1.3053 1.6514-2.0643.7286-.8196.85-.9046.5464-.4311h1.0321l.759 1.1293-.34 1.1657-1.0625 1.3478-.8804 1.1414-1.2628 1.7-.7893 1.36.0729.1093.1882-.0183 2.8535-.607 1.5421-.2794 1.8396-.3157.8318.3886.091.3946-.3278.8075-1.967.4857-2.3072.4614-3.4364.8136-.0425.0304.0486.0607 1.5482.1457.6618.0364h1.621l3.0175.2247.7892.522.4736.6376-.079.4857-1.2142.6193-1.6393-.3886-3.825-.9107-1.3113-.3279h-.1822v.1093l1.0929 1.0686 2.0035 1.8092 2.5075 2.3314.1275.5768-.3218.4554-.34-.0486-2.2039-1.6575-.85-.7468-1.9246-1.621h-.1275v.17l.4432.6496 2.3436 3.5214.1214 1.0807-.17.3521-.6071.2125-.6679-.1214-1.3721-1.9246L14.38 17.959l-1.1414-1.9428-.1397.079-.674 7.2552-.3156.3703-.7286.2793-.6071-.4614-.3218-.7468.3218-1.4753.3886-1.9246.3157-1.53.2853-1.9004.17-.6314-.0121-.0425-.1397.0182-1.4328 1.9672-2.1796 2.9446-1.7243 1.8456-.4128.164-.7164-.3704.0667-.6618.4008-.5889 2.386-3.0357 1.4389-1.882.929-1.0868-.0062-.1579h-.0546l-6.3385 4.1164-1.1293.1457-.4857-.4554.0608-.7467.2307-.2429 1.9064-1.3114Z" fill="currentColor"/>',codex:'<path d="M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.02 1.1686a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4945 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0201 1.1685a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.872zm16.5963 3.8558L13.1038 8.364 15.1192 7.2a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.407-.667zm2.0107-3.0231l-.142-.0852-4.7735-2.7818a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1638a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654l2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z" fill="currentColor"/>',opencode:'<path d="M21.6 24H2.4V0h19.2zM16.8 4.8H7.2v14.4h9.6z" fill="currentColor"/><path d="M16.8 9.6H7.2v9.6h9.6z" fill="currentColor" opacity=".45"/>',gemini:'<path d="M11.04 19.32Q12 21.51 12 24q0-2.49.93-4.68.96-2.19 2.58-3.81t3.81-2.55Q21.51 12 24 12q-2.49 0-4.68-.93a12.3 12.3 0 0 1-3.81-2.58 12.3 12.3 0 0 1-2.58-3.81Q12 2.49 12 0q0 2.49-.96 4.68-.93 2.19-2.55 3.81a12.3 12.3 0 0 1-3.81 2.58Q2.49 12 0 12q2.49 0 4.68.96 2.19.93 3.81 2.55t2.55 3.81" fill="currentColor"/>',agy:'<path d="M12.48 10.92v3.28h7.84c-.24 1.84-.853 3.187-1.787 4.133-1.147 1.147-2.933 2.4-6.053 2.4-4.827 0-8.6-3.893-8.6-8.72s3.773-8.72 8.6-8.72c2.6 0 4.507 1.027 5.907 2.347l2.307-2.307C18.747 1.44 16.133 0 12.48 0 5.867 0 .307 5.387.307 12s5.56 12 12.173 12c3.573 0 6.267-1.173 8.373-3.36 2.16-2.16 2.84-5.213 2.84-7.667 0-.76-.053-1.467-.173-2.053H12.48z" fill="currentColor"/>',grok:'<g transform="translate(1.2 1.2) scale(.9)"><path d="M6.469 8.776 16.512 23h-4.464L2.005 8.776H6.47zm-.004 7.9 2.233 3.164L6.467 23H2l4.465-6.324zM22 2.582V23h-3.659V7.764L22 2.582zM22 1l-9.952 14.095-2.233-3.163L17.533 1H22z" fill="currentColor"/></g>',muse:'<g transform="translate(-1.2 -1.2) scale(1.1)"><path d="M6.915 4.03c-1.968 0-3.683 1.28-4.871 3.113C.704 9.208 0 11.883 0 14.449c0 .706.07 1.369.21 1.973a6.624 6.624 0 0 0 .265.86 5.297 5.297 0 0 0 .371.761c.696 1.159 1.818 1.927 3.593 1.927 1.497 0 2.633-.671 3.965-2.444.76-1.012 1.144-1.626 2.663-4.32l.756-1.339.186-.325c.061.1.121.196.183.3l2.152 3.595c.724 1.21 1.665 2.556 2.47 3.314 1.046.987 1.992 1.22 3.06 1.22 1.075 0 1.876-.355 2.455-.843a3.743 3.743 0 0 0 .81-.973c.542-.939.861-2.127.861-3.745 0-2.72-.681-5.357-2.084-7.45-1.282-1.912-2.957-2.93-4.716-2.93-1.047 0-2.088.467-3.053 1.308-.652.57-1.257 1.29-1.82 2.05-.69-.875-1.335-1.547-1.958-2.056-1.182-.966-2.315-1.303-3.454-1.303zm10.16 2.053c1.147 0 2.188.758 2.992 1.999 1.132 1.748 1.647 4.195 1.647 6.4 0 1.548-.368 2.9-1.839 2.9-.58 0-1.027-.23-1.664-1.004-.496-.601-1.343-1.878-2.832-4.358l-.617-1.028a44.908 44.908 0 0 0-1.255-1.98c.07-.109.141-.224.211-.327 1.12-1.667 2.118-2.602 3.358-2.602zm-10.201.553c1.265 0 2.058.791 2.675 1.446.307.327.737.871 1.234 1.579l-1.02 1.566c-.757 1.163-1.882 3.017-2.837 4.338-1.191 1.649-1.81 1.817-2.486 1.817-.524 0-1.038-.237-1.383-.794-.263-.426-.464-1.13-.464-2.046 0-2.221.63-4.535 1.66-6.088.454-.687.964-1.226 1.533-1.533a2.264 2.264 0 0 1 1.088-.285z" fill="currentColor"/></g>',pi:'<path d="M0 0h18v6H0zM0 6h6v18H0zM12 6h6v6h-6zM6 12h6v6H6zM18 12h6v12h-6z" fill="currentColor"/>',t3code:'<path d="M5.177,18.414V7.823H1V5.362H12.374V7.823H8.197V18.414H5.177ZM17.593,18.638C16.686,18.638 15.784,18.52 14.889,18.283C13.994,18.035 13.236,17.687 12.615,17.239L13.789,14.927C14.287,15.288 14.865,15.574 15.523,15.785C16.182,15.996 16.847,16.102 17.518,16.102C18.277,16.102 18.873,15.953 19.308,15.654C19.743,15.356 19.961,14.946 19.961,14.424C19.961,13.927 19.768,13.535 19.383,13.249C18.998,12.963 18.376,12.82 17.518,12.82H16.139V10.825L19.774,6.705L20.11,7.786H13.267V5.362H22.403V7.32L18.786,11.441L17.257,10.564H18.134C19.737,10.564 20.949,10.925 21.769,11.646C22.59,12.367 23,13.293 23,14.424C23,15.157 22.807,15.847 22.422,16.494C22.037,17.127 21.446,17.643 20.651,18.041C19.855,18.439 18.836,18.638 17.593,18.638Z" fill="currentColor"/>',generic:'<g transform="scale(1.5)"><rect x="1.75" y="2.75" width="12.5" height="10.5" rx="1.5" fill="none" stroke="currentColor" stroke-width="1.4"/><path d="M4.5 6.25 6.5 8l-2 1.75M8 10h3" fill="none" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></g>'},yt={"claude-code":"claude","claude-desktop":"claude","claude-cowork":"claude","claude-desktop-chat":"claude","codex-desktop":"codex",claude:"claude",codex:"codex",opencode:"opencode",gemini:"gemini",agy:"agy",antigravity:"agy",grok:"grok",muse:"muse",xai:"grok",pi:"pi",t3code:"t3code",t3:"t3code"},V=(e)=>yt[(e??"").toLowerCase()]??"generic",q=(e)=>{let t=V(e);return r`<svg class="hicon h-${t}" width="12" height="12" viewBox="0 0 24 24" role="img" aria-label="${e??"unknown harness"}">${new k(le[t])}</svg>`},_t=r`<svg width="8" height="8" viewBox="0 0 8 8" aria-hidden="true"><path d="M2 .75 6.5 4 2 7.25z" fill="currentColor"/></svg>`,J=(e)=>e.startsWith(ne)?"(ended)":e,S=(e)=>J(E(e).handle),vt=(e)=>Object.entries(e).filter(([t])=>t!=="machine"),Oe={online:0,idle:1,hibernated:1,offline:2},oe=(e,t)=>(Oe[e.presence]??3)-(Oe[t.presence]??3)||E(e.address).handle.localeCompare(E(t.address).handle);function xe(e){let t=new Set(e.map((a)=>a.address)),n=new Map,o=[];for(let a of e)if(a.parent&&a.parent!==a.address&&t.has(a.parent))n.set(a.parent,[...n.get(a.parent)??[],a]);else o.push(a);let i=[],s=new Set,d=(a,c)=>{for(let u of a.sort(oe)){if(s.has(u.address))continue;s.add(u.address),i.push({e:u,depth:c.length,anc:c,kids:0}),d(n.get(u.address)??[],[...c,u.address])}};d(o,[]),d(e.filter((a)=>!s.has(a.address)),[]);let l=new Map(i.map((a)=>[a.e.address,a]));for(let a of i)if(a.anc.length)l.get(a.anc.at(-1)).kids++;return i}var ae=(e)=>e.presence!=="offline";function kt(e){let t=e.filter((a)=>a.kind==="agent"),n=new Set(t.map((a)=>a.address)),o=new Map,i=[];for(let a of t)if(a.parent&&a.parent!==a.address&&n.has(a.parent))o.set(a.parent,[...o.get(a.parent)??[],a]);else i.push(a);let s=new Set,d=(a)=>{s.add(a.address);let c=[],u=[...o.get(a.address)??[]];while(u.length){let w=u.pop();if(s.has(w.address))continue;s.add(w.address),c.push(w),u.push(...o.get(w.address)??[])}return{root:a,kids:c.filter(ae).sort(oe)}},l=i.map(d);for(let a of t)if(!s.has(a.address))l.push(d(a));return l.filter((a)=>ae(a.root)||a.kids.length).sort((a,c)=>c.kids.length-a.kids.length||oe(a.root,c.root))}var Rt=3,de=(e)=>r`<span class="cell ${e.presence}${x(e)?" wake":""}" title="${S(e.address)}, ${e.presence}"></span>`;function De({root:e,kids:t}){let{machine:n}=E(e.address);return r`<div class="strip-row"><span class="strip-who" title="${e.address}">${q(e.harness)}<span class="mono strip-name">${S(e.address)}</span><span class="mini">${n}</span></span>
|
|
309
|
+
<span class="cells">${ae(e)?de(e):""}${t.map(de)}</span>${t.length?r`<span class="mini push">${t.length}</span>`:""}</div>`}function St(e){let t=e.filter((n)=>!n.kids.length);if(t.length<=Rt)return e.map(De);return[...e.filter((n)=>n.kids.length).map(De),r`<div class="strip-row"><span class="strip-who"><span class="mono strip-name">${t.length} solo agents</span></span>
|
|
310
|
+
<span class="cells">${t.map((n)=>de(n.root))}</span></div>`]}function Me(e,t){return r`<div class="strip" aria-label="Agents per orchestrator">${St(kt(e.endpoints))}</div><p class="mini strip-key"><span class="cell online"></span>online <span class="cell idle wake"></span>wakeable <span class="cell idle"></span>next turn <a class="mini-link push" href="/orgs/${t}/graph">Graph</a></p>`}function Tt({e,depth:t,anc:n,kids:o},i,s,d){let l=S(e.address),{machine:a}=E(e.address),c=e.parent?S(e.parent):null,u=vt(e.labels),w=e.status?e.status.note?`${e.status.state}: ${e.status.note}`:e.status.state:"none",st=e.presence==="online"?"now":O(e.last_seen,s),_e=bt(e),it=o?r`<button class="caret" type="button" data-tree="${e.address}" aria-expanded="${String(!i.has(e.address))}" aria-label="${o} under ${l}">${_t}</button>`:r`<span class="caret" aria-hidden="true"></span>`,rt=[l,e.harness??"unknown harness",c?`sub of ${c}`:""].filter(Boolean).join(", ");return r`<tr${t?r` class="sub d${Math.min(t,4)}" data-anc="${n.join(" ")}"${n.some((C)=>i.has(C))?" hidden":""}`:""}>
|
|
311
|
+
<td class="agent" title="${rt}">${it}${q(e.harness)}<span class="mono">${l}</span>${a!==d?r` <span class="tag" title="runs on ${a}">${a}</span>`:""}${c&&!t?r` <span class="mini">sub of ${c}</span>`:""}</td>
|
|
309
312
|
<td class="small" title="${e.title??""}">${e.title??""}</td>
|
|
310
|
-
<td title="${
|
|
311
|
-
<td title="${
|
|
312
|
-
<td title="${
|
|
313
|
+
<td title="${_e.tip}">${_e.cell}</td>
|
|
314
|
+
<td title="${w}">${e.status?r`<span class="role">${e.status.state}</span>${e.status.note?r` <span class="small">${e.status.note}</span>`:""}`:r`<span class="mini">none</span>`}</td>
|
|
315
|
+
<td title="${u.map(([C,Q])=>`${C}=${Q}`).join(", ")}">${u.map(([C,Q])=>r`<span class="tag">${C}=${Q}</span>`)}</td>
|
|
313
316
|
<td class="mono end" title="${e.last_seen??"never"}">${st}</td>
|
|
314
|
-
</tr>`}var Nt=r`<colgroup><col class="c-agent"><col class="c-title"><col class="c-presence"><col class="c-status"><col class="c-labels"><col class="c-seen"></colgroup>`,Ie=(e,t,n,o)=>{let i=new Set(e.filter((s)=>s.kids&&s.e.presence==="offline").map((s)=>s.e.address));return r`<div class="table"><table class="agents">${Nt}${n?r`<thead><tr><th>Agent</th><th>Title</th><th>Presence</th><th>Status</th><th>Labels</th><th class="end">Seen</th></tr></thead>`:""}<tbody>${e.map((s)=>Tt(s,i,t,o))}</tbody></table></div>`};function At(e,t){let n=e.machine,o=n?n.online?"online":"offline":e.endpoints.some((
|
|
317
|
+
</tr>`}var Nt=r`<colgroup><col class="c-agent"><col class="c-title"><col class="c-presence"><col class="c-status"><col class="c-labels"><col class="c-seen"></colgroup>`,Ie=(e,t,n,o)=>{let i=new Set(e.filter((s)=>s.kids&&s.e.presence==="offline").map((s)=>s.e.address));return r`<div class="table"><table class="agents">${Nt}${n?r`<thead><tr><th>Agent</th><th>Title</th><th>Presence</th><th>Status</th><th>Labels</th><th class="end">Seen</th></tr></thead>`:""}<tbody>${e.map((s)=>Tt(s,i,t,o))}</tbody></table></div>`};function At(e,t){let n=e.machine,o=n?n.online?"online":"offline":e.endpoints.some((d)=>d.presence==="online")?"online":"offline",i=xe(e.endpoints.filter((d)=>d.presence!=="offline")),s=xe(e.endpoints.filter((d)=>d.presence==="offline"));return r`<div class="machine">
|
|
315
318
|
<div class="machine-head">
|
|
316
319
|
<span class="dot ${o}" aria-hidden="true"></span><h3 class="mono">${e.name}</h3>
|
|
317
320
|
${n?r`<span class="role">${n.kind}</span>`:""}
|
|
@@ -319,9 +322,9 @@ table.orgs td.end,table.orgs th.end{text-align:right}
|
|
|
319
322
|
<span class="mini push">${e.endpoints.length} ${e.endpoints.length===1?"agent":"agents"}</span>
|
|
320
323
|
</div>
|
|
321
324
|
${e.endpoints.length?r`${i.length?Ie(i,t,!0,e.name):""}${s.length?r`<details class="offline" data-key="${e.name}"><summary class="mini"><span class="when-shut">show</span><span class="when-open">hide</span> ${s.length} offline</summary>${Ie(s,t,!i.length,e.name)}</details>`:""}`:r`<p class="empty">${e.away?`Its ${e.away===1?"agent shows":"agents show"} under a parent on another machine.`:"No agents on this machine right now."}</p>`}
|
|
322
|
-
</div>`}function z(e){switch(e.kind){case"session_start":return"started a session";case"session_end":return"ended its session";case"stop":return e.summary?`finished a turn: ${e.summary}`:"finished a turn";case"tool":return[e.tool,e.summary].filter(Boolean).join(": ")||"used a tool";default:return e.summary??e.kind}}var ce=(e)=>[...e].sort((t,n)=>n.at.localeCompare(t.at));function
|
|
325
|
+
</div>`}function z(e){switch(e.kind){case"session_start":return"started a session";case"session_end":return"ended its session";case"stop":return e.summary?`finished a turn: ${e.summary}`:"finished a turn";case"tool":return[e.tool,e.summary].filter(Boolean).join(": ")||"used a tool";default:return e.summary??e.kind}}var ce=(e)=>[...e].sort((t,n)=>n.at.localeCompare(t.at));function ue(e,t){return r`<section class="block"><div class="block-head"><h2>Recent activity</h2>${Y(t)}</div>
|
|
323
326
|
${e.length?r`<div class="table"><table class="activity"><colgroup><col class="c-when"><col class="c-who"><col></colgroup><thead><tr><th>When</th><th>Agent</th><th>What</th></tr></thead>
|
|
324
|
-
<tbody>${ce(e).map((n)=>{let{machine:o,handle:i}=E(n.endpoint),s=`${o}/${
|
|
327
|
+
<tbody>${ce(e).map((n)=>{let{machine:o,handle:i}=E(n.endpoint),s=`${o}/${J(i)}`,d=z(n);return r`<tr><td class="mono" title="${n.at}">${O(n.at,t)}</td><td class="mono" title="${n.agent?`${s} ${n.agent}`:s}">${s}${n.agent?r` <span class="mini">${n.agent}</span>`:""}</td><td class="small" title="${d}">${d}</td></tr>`})}</tbody></table></div>`:r`<p class="empty">No activity yet. Hooks report tool use and turns as agents work.</p>`}</section>`}var j=(e)=>r`<div class="cmd"><code><span class="prompt" aria-hidden="true">$ </span>${e}</code><button class="btn btn-ghost btn-small" type="button" data-copy="${e}">Copy</button></div>`,Y=(e)=>r`<span class="mini push live-stamp"><span class="dot online pulse" aria-hidden="true"></span><span data-feed>polling</span>, updated ${new Date(e).toISOString().slice(11,19)} UTC</span>`;function pe(e){return r`<section class="block onboard"><h2>Connect your first machine</h2>
|
|
325
328
|
<p class="small">No machines have joined this hub yet. Run these on the machine your agents work on. The page updates on its own once it connects.</p>
|
|
326
329
|
<ol class="steps">
|
|
327
330
|
<li><p class="label">Install the CLI</p>${j("npm i -g @scp-dev/cli")}</li>
|
|
@@ -334,10 +337,10 @@ table.orgs td.end,table.orgs th.end{text-align:right}
|
|
|
334
337
|
${j("swarm up --token <token> --machine <name>")}
|
|
335
338
|
<p class="small">Or set <code>SCP_TOKEN</code> in its environment. Its agents show the label <span class="tag">token=<name></span>.</p>
|
|
336
339
|
</div>
|
|
337
|
-
</section>`}var P=()=>
|
|
340
|
+
</section>`}var P=()=>_("The hub did not answer. This page retries on its own.",!0)||r``;function he(e,t,n){if(!e)return P();let o=X(e,!0);if(!o.length)return pe(t);let i=o.reduce((d,l)=>d+l.endpoints.length,0),s=o.filter((d)=>d.machine?.online||d.endpoints.some((l)=>l.presence==="online")).length;return r`<section class="block"><div class="block-head"><h2>Machines</h2>
|
|
338
341
|
<span class="mini">${o.length} ${o.length===1?"machine":"machines"}, ${s} online, ${i} ${i===1?"agent":"agents"}</span>
|
|
339
342
|
${Y(n)}</div>
|
|
340
|
-
${o.map((
|
|
343
|
+
${o.map((d)=>At(d,n))}
|
|
341
344
|
</section>`}var K=`
|
|
342
345
|
const chosen = new Map();
|
|
343
346
|
const fold = (root) => {
|
|
@@ -418,22 +421,22 @@ if (live) {
|
|
|
418
421
|
}
|
|
419
422
|
const tab = document.querySelector('.tabs [aria-current="page"]');
|
|
420
423
|
if (tab) tab.scrollIntoView({ block: "nearest", inline: "nearest" });
|
|
421
|
-
`;var
|
|
424
|
+
`;var Zs=7*U;var $e=[["overview","Overview",""],["activity","Activity","/activity"],["sessions","Sessions","/sessions"],["graph","Graph","/graph"],["tokens","Tokens and devices","/tokens"],["members","Members","/members"]],Mt=(e,t,n)=>r`<nav class="tabs" aria-label="${e}">${t.map(([o,i])=>r`<a href="${o}"${o===n?r` aria-current="page"`:""}>${i}</a>`)}</nav>`;function ge(e,t){let n=`/orgs/${e.org.handle}`;return r`<div class="org-head">
|
|
422
425
|
<p class="label"><a class="mini-link" href="/orgs">Orgs</a> / ${e.org.handle}</p>
|
|
423
426
|
<div class="org-title"><h1>${e.org.name}</h1><span class="mini">you are <span class="role">${e.role}</span></span></div>
|
|
424
427
|
</div>
|
|
425
|
-
${Mt("Organization",$e.map(([,o,i])=>[n+i,o]),n+$e.find(([o])=>o===t)[2])}`}function Ue(e,t,n,o={}){let i=r`<script src="/app.js?v=${R(K)}" defer></script>`,s=o.live?r`${i}<noscript><meta http-equiv="refresh" content="${Math.round(L/1000)}"></noscript>`:i,
|
|
428
|
+
${Mt("Organization",$e.map(([,o,i])=>[n+i,o]),n+$e.find(([o])=>o===t)[2])}`}function Ue(e,t,n,o={}){let i=r`<script src="/app.js?v=${R(K)}" defer></script>`,s=o.live?r`${i}<noscript><meta http-equiv="refresh" content="${Math.round(L/1000)}"></noscript>`:i,d=o.live?r`<div class="tab-body" data-live="${L}" data-events="/orgs/${e.org.handle}/events">${n}</div>`:r`<div class="tab-body">${n}</div>`;return{head:s,nav:"orgs",body:r`${ge(e,t)}${d}`}}var _=(e,t=!1)=>e?r`<p class="notice${t?" err":""}" role="${t?"alert":"status"}">${e}</p>`:"";function Ut(e,t){let n=e.endpoints.filter((s)=>s.kind==="agent"),o=n.filter((s)=>s.presence==="idle"),i=X(e);return{online:n.filter((s)=>s.presence==="online").length,wakeable:o.filter((s)=>x(s)).length,nextTurn:o.filter((s)=>!x(s)).length,offline:n.filter((s)=>s.presence==="offline").length,machines:i.length,machinesOnline:i.filter((s)=>s.machine?.online||s.endpoints.some((d)=>d.presence==="online")).length,messages:t?t.edges.filter((s)=>s.kind==="message").reduce((s,d)=>s+(d.count??0),0):null,minutes:t?.minutes??15}}var W=(e,t,n,o="")=>r`<div class="tile${o?` ${o}`:""}"><p class="tile-label">${e}</p><p class="tile-value">${t}</p><p class="mini">${n}</p></div>`;function Ht(e){return r`<div class="tiles">
|
|
426
429
|
${W("Online",e.online,e.online===1?"agent working":"agents working","on")}
|
|
427
430
|
${W("Idle, wakeable",e.wakeable,"a message wakes them")}
|
|
428
431
|
${W("Idle, next turn",e.nextTurn,"read at their next turn")}
|
|
429
432
|
${W("Machines",e.machines,`${e.machinesOnline} online`)}
|
|
430
433
|
${W("Messages",e.messages??"-",`last ${e.minutes} min`)}
|
|
431
|
-
</div>`}function qt(e,t){if(e.status)return{lead:r`<span class="role">${e.status.state}</span>`,text:e.status.note??""};let n=t.get(e.address);if(n?.summary)return{lead:r`<span class="mini">tl;dr</span>`,text:n.summary};if(e.title)return{lead:"",text:e.title};return null}var me=6,qe={online:0,idle:1,hibernated:1,offline:2};function Pt(e,t,n){let o=new Map,i=ce(e.activity);for(let a of i)if(a.kind==="stop"&&a.summary&&!o.has(a.endpoint))o.set(a.endpoint,a);let s=e.endpoints.filter((a)=>a.kind==="agent"&&a.presence!=="offline").map((a)=>({e:a,g:qt(a,o)})).sort((a,c)=>(qe[a.e.presence]??3)-(qe[c.e.presence]??3)||Number(!a.g)-Number(!c.g)||(c.e.last_seen??"").localeCompare(a.e.last_seen??"")),
|
|
432
|
-
${
|
|
434
|
+
</div>`}function qt(e,t){if(e.status)return{lead:r`<span class="role">${e.status.state}</span>`,text:e.status.note??""};let n=t.get(e.address);if(n?.summary)return{lead:r`<span class="mini">tl;dr</span>`,text:n.summary};if(e.title)return{lead:"",text:e.title};return null}var me=6,qe={online:0,idle:1,hibernated:1,offline:2};function Pt(e,t,n){let o=new Map,i=ce(e.activity);for(let a of i)if(a.kind==="stop"&&a.summary&&!o.has(a.endpoint))o.set(a.endpoint,a);let s=e.endpoints.filter((a)=>a.kind==="agent"&&a.presence!=="offline").map((a)=>({e:a,g:qt(a,o)})).sort((a,c)=>(qe[a.e.presence]??3)-(qe[c.e.presence]??3)||Number(!a.g)-Number(!c.g)||(c.e.last_seen??"").localeCompare(a.e.last_seen??"")),d=s.slice(0,me),l=i[0];return r`<section class="panel now"><div class="panel-head"><h2>Happening now</h2><a class="mini-link push" href="/orgs/${n}/sessions">All sessions</a></div>
|
|
435
|
+
${d.length?r`<ul class="now-list">${d.map(({e:a,g:c})=>{let u=x(a);return r`<li><div class="now-who">${q(a.harness)}<span class="mono">${S(a.address)}</span><span class="mini">${E(a.address).machine}</span><span class="push mini"><span class="dot ${a.presence}${u?" wake":""}" aria-hidden="true"></span>${a.presence}</span></div>
|
|
433
436
|
<p class="now-what small" title="${c?.text??""}">${c?r`${c.lead}${c.lead&&c.text?" ":""}${c.text}`:r`<span class="mini">no status yet</span>`}</p></li>`})}</ul>${s.length>me?r`<p class="mini more-line">and ${s.length-me} more on the <a class="mini-link" href="/orgs/${n}/sessions">Sessions</a> tab</p>`:""}`:r`<p class="empty">No agent is online or idle right now.</p>`}
|
|
434
|
-
${
|
|
435
|
-
</section>`}var F=(e,t,n=`${t}s`)=>`${e} ${e===1?t:n}`;function Pe(e,t,n,o,i){if(!e)return P();if(!e.machines.length&&!e.endpoints.length)return
|
|
436
|
-
${
|
|
437
|
+
${l?r`<p class="mini last-line"><span class="what" title="${z(l)}">Last activity ${O(l.at,t)}: ${S(l.endpoint)}, ${z(l)}</span><a class="mini-link" href="/orgs/${n}/activity">All activity</a></p>`:""}
|
|
438
|
+
</section>`}var F=(e,t,n=`${t}s`)=>`${e} ${e===1?t:n}`;function Pe(e,t,n,o,i){if(!e)return P();if(!e.machines.length&&!e.endpoints.length)return pe(o);let s=Ut(e,t),d=n.holds?r`<p class="notice held" role="status">${F(n.holds,"message")} held by the relay judge, waiting for review. <a href="/orgs/${o}/members#judge">Review</a></p>`:"";return r`<div class="block-head summary-head"><p class="mini">${F(s.online+s.wakeable+s.nextTurn,"agent")} live, ${s.offline} offline</p>${Y(i)}</div>
|
|
439
|
+
${d}
|
|
437
440
|
${Ht(s)}
|
|
438
441
|
<div class="panels">
|
|
439
442
|
${Pt(e,i,o)}
|
|
@@ -441,7 +444,7 @@ if (tab) tab.scrollIntoView({ block: "nearest", inline: "nearest" });
|
|
|
441
444
|
${Me(e,o)}
|
|
442
445
|
<p class="small fleet-line">${F(s.machines,"machine")}, ${s.machinesOnline} online. ${F(n.devices,"device")} and ${F(n.tokens,"API token")} signed in. <a class="mini-link" href="/orgs/${o}/tokens">Manage</a></p>
|
|
443
446
|
</section>
|
|
444
|
-
</div>`}var Wt=["claude","codex","opencode","gemini","agy","grok","muse","pi","t3code"],Ft='<g transform="scale(1.5)"><circle cx="8" cy="5.25" r="2.75" fill="none" stroke="currentColor" stroke-width="1.4"/><path d="M2.75 14c.5-3 2.6-4.75 5.25-4.75S12.75 11 13.25 14" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></g>',Bt='<path d="M3 3h10v4H7v6H3zM29 29H19v-4h6v-6h4z"/><rect x="11" y="11" width="10" height="10"/>';function We(e){let t=e.split("/");return t.length>=3?{machine:t[1],handle:t.slice(2).join("/")}:{machine:"",handle:""}}function jt(e,t){if(!t||e.length<=t.length+1||!e.startsWith(t))return e;return"-_./:".includes(e[t.length])?e.slice(t.length+1):e}function Fe(e){if(!e)return r``;let t=e.nodes.map((i)=>{let{machine:s,handle:
|
|
447
|
+
</div>`}var Wt=["claude","codex","opencode","gemini","agy","grok","muse","pi","t3code"],Ft='<g transform="scale(1.5)"><circle cx="8" cy="5.25" r="2.75" fill="none" stroke="currentColor" stroke-width="1.4"/><path d="M2.75 14c.5-3 2.6-4.75 5.25-4.75S12.75 11 13.25 14" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></g>',Bt='<path d="M3 3h10v4H7v6H3zM29 29H19v-4h6v-6h4z"/><rect x="11" y="11" width="10" height="10"/>';function We(e){let t=e.split("/");return t.length>=3?{machine:t[1],handle:t.slice(2).join("/")}:{machine:"",handle:""}}function jt(e,t){if(!t||e.length<=t.length+1||!e.startsWith(t))return e;return"-_./:".includes(e[t.length])?e.slice(t.length+1):e}function Fe(e){if(!e)return r``;let t=e.nodes.map((i)=>{let{machine:s,handle:d}=We(i.address),l=i.kind==="human"?"human":J(d),a=i.parent?We(i.parent):null;return{address:i.address,kind:i.kind,machine:s,name:l,label:l===d&&a&&a.machine===s?jt(d,a.handle):l,icon:i.kind==="human"?"human":V(i.harness),harness:i.harness,title:i.title,presence:i.presence,status:i.status,wake:i.wake&&i.wake!=="none"?i.wake:null,how:i.waking?"its machine is waking":i.wake&&i.wake!=="none"?G(i.wake):null,parent:i.parent,historic:i.historic===!0}}),n=e.machines.filter((i)=>i.kind!=="revoked").map((i)=>({name:i.name,online:i.online,identity:i.identity??null})),o=JSON.stringify({minutes:e.minutes,machines:n,nodes:t,edges:e.edges}).replace(/</g,"\\u003c");return r`<script type="application/json" data-graph-data>${new k(o)}</script>`}var Be=r`<div class="graph-canvas"><svg class="graph-svg" role="group" aria-label="Agents by machine"></svg><div class="graph-tip" role="tooltip" hidden></div></div>`,je=r`<span class="trails" role="group" aria-label="Message trail speed">trails <span class="seg">${["1","0.5","0.25"].map((e)=>r`<button type="button" data-trail="${e}" aria-pressed="${e==="1"?"true":"false"}">${e}x</button>`)}</span></span>`,Ge=(e)=>r`<label class="mini"><input type="checkbox" data-graph-nextturn> show next-turn idle</label><label class="mini"><input type="checkbox" data-graph-offline> show offline</label>${e?r`<label class="mini"><input type="checkbox" data-graph-historic> show historic</label>`:""}`,Xe=r`<p class="mini graph-legend"><span class="key spawn" aria-hidden="true"></span>spawned <span class="key msg" aria-hidden="true"></span>messages, last <span data-graph-minutes>15</span> min</p>`,fe=()=>r`<script src="/app.js?v=${R(K)}" defer></script><script src="/graph.js?v=${R(Kt())}" defer></script><link rel="stylesheet" href="/graph.css?v=${R(Gt)}">`;function Ve(e,t,n={}){return r`<div class="graph gfull" data-graph data-full data-events="/orgs/${e.handle}/events" aria-label="Live graph of agents and their links">
|
|
445
448
|
${Be}
|
|
446
449
|
<header class="g-over g-left">
|
|
447
450
|
<a class="mini-link" href="/orgs/${e.handle}/graph">Back to the dashboard</a>
|
|
@@ -456,7 +459,7 @@ if (tab) tab.scrollIntoView({ block: "nearest", inline: "nearest" });
|
|
|
456
459
|
</div>
|
|
457
460
|
<div hidden data-live="${L}">${Fe(t)}</div>
|
|
458
461
|
${t?"":r`<p class="g-empty mini">The hub did not answer. This page retries on its own.</p>`}
|
|
459
|
-
</div>`}function
|
|
462
|
+
</div>`}function Je(e,t,n={}){return r`${ge(e,"graph")}
|
|
460
463
|
<div class="graph gfull gtab" data-graph data-full data-events="/orgs/${e.org.handle}/events" aria-label="Live graph of agents and their links">
|
|
461
464
|
${Be}
|
|
462
465
|
<div class="g-over g-left">
|
|
@@ -560,9 +563,9 @@ body.bare{overflow:hidden;height:100dvh;min-height:0}
|
|
|
560
563
|
if (n.presence === "offline") return o.offline || (n.kind === "human" && talks.has(n.address));
|
|
561
564
|
if (n.presence === "idle" && n.kind === "agent" && !n.wake) return o.nextTurn;
|
|
562
565
|
return true;
|
|
563
|
-
}`,
|
|
566
|
+
}`,Vt=`function slot(e, w, h, min) {
|
|
564
567
|
return { x0: e.x0, x1: Math.max(e.x1, e.x0 + w, e.x0 + min), y0: e.y0 - h, y1: e.y1 };
|
|
565
|
-
}`,
|
|
568
|
+
}`,Jt=`function bands(items, o) {
|
|
566
569
|
const byKey = new Map();
|
|
567
570
|
for (const it of items) { if (!byKey.has(it.key)) byKey.set(it.key, { key: it.key, items: [] }); byKey.get(it.key).items.push(it); }
|
|
568
571
|
const groups = [...byKey.values()];
|
|
@@ -696,16 +699,16 @@ if (!root || !live) return;
|
|
|
696
699
|
const bar = document.querySelector("[data-view-bar]");
|
|
697
700
|
const full = root.hasAttribute("data-full");
|
|
698
701
|
const NS = "http://www.w3.org/2000/svg";
|
|
699
|
-
const ICONS = ${JSON.stringify({...
|
|
702
|
+
const ICONS = ${JSON.stringify({...le,human:Ft})};
|
|
700
703
|
const MARK = ${JSON.stringify(Bt)};
|
|
701
704
|
const COLORED = new Set(${JSON.stringify(Wt)});
|
|
702
705
|
const BOLT = "M9.5 1 3 9h4.5L6.5 15 13 7H8.5z";
|
|
703
706
|
const R = 16, PAD = 20, HEAD = 26, ID_LINE = 14, GAP = 26, BAND_GAP = 44, LABEL_MAX = 176, NAME_MAX = 220, ID_MAX = 200, MIN_W = 96, CAP = 1.6;
|
|
704
707
|
const TRAILS = [1, 0.5, 0.25];
|
|
705
708
|
const LAYOUT = ${JSON.stringify(zt)};
|
|
706
|
-
${Jt}
|
|
707
|
-
${Yt}
|
|
708
709
|
${Vt}
|
|
710
|
+
${Yt}
|
|
711
|
+
${Jt}
|
|
709
712
|
${Xt}
|
|
710
713
|
const svg = root.querySelector(".graph-svg");
|
|
711
714
|
const canvas = root.querySelector(".graph-canvas");
|
|
@@ -1297,9 +1300,9 @@ setStream(false);
|
|
|
1297
1300
|
update();
|
|
1298
1301
|
connect();
|
|
1299
1302
|
})();
|
|
1300
|
-
`;var ze={overview:"",agents:"/sessions",devices:"/tokens",machines:"/tokens",settings:"/members",judge:"/members"};function Ye(e){if(!e?.startsWith("/")||/[\u0000-\u001f\u007f\\]/.test(e))return"/";let t="https://relay.invalid";try{let n=new URL(e,t);return n.origin===t&&n.pathname.replace(/\/+$/,"")!=="/sign-in"?n.pathname+n.search+n.hash:"/"}catch{return"/"}}function Ke(e,t){let n=e.replace(/\/+$/,"")||"/",o=`/orgs/${t.org.handle}`;if(n==="/"||n==="/orgs"||n==="/sign-in")return{redirect:o};if(n==="/device")return{page:"device"};if(n===o)return{tab:"overview"};if(!n.startsWith(`${o}/`))return{page:"not-found"};let i=n.slice(o.length+1);if(Object.hasOwn(ze,i))return{redirect:o+ze[i]};if(["activity","sessions","graph","graph/full","tokens","members"].includes(i))return{tab:i};return{page:"not-found"}}function T(e,t,n){return re({...t,email:e.signedIn?e.member.name:null,csrf:e.csrf},n)}function Zt(e,t,n,o){let i=n.graph?B(n.graph,ee(e.members.map((s)=>({user_id:s.id,email:s.name})))):null;switch(t){case"overview":{let s={devices:e.devices,tokens:e.tokens,holds:null};return Pe(n.overview,i,s,e.org.handle,o)}case"activity":return n.overview?
|
|
1303
|
+
`;var ze={overview:"",agents:"/sessions",devices:"/tokens",machines:"/tokens",settings:"/members",judge:"/members"};function Ye(e){if(!e?.startsWith("/")||/[\u0000-\u001f\u007f\\]/.test(e))return"/";let t="https://relay.invalid";try{let n=new URL(e,t);return n.origin===t&&n.pathname.replace(/\/+$/,"")!=="/sign-in"?n.pathname+n.search+n.hash:"/"}catch{return"/"}}function Ke(e,t){let n=e.replace(/\/+$/,"")||"/",o=`/orgs/${t.org.handle}`;if(n==="/"||n==="/orgs"||n==="/sign-in")return{redirect:o};if(n==="/device")return{page:"device"};if(n===o)return{tab:"overview"};if(!n.startsWith(`${o}/`))return{page:"not-found"};let i=n.slice(o.length+1);if(Object.hasOwn(ze,i))return{redirect:o+ze[i]};if(["activity","sessions","graph","graph/full","tokens","members"].includes(i))return{tab:i};return{page:"not-found"}}function T(e,t,n){return re({...t,email:e.signedIn?e.member.name:null,csrf:e.csrf},n)}function Zt(e,t,n,o){let i=n.graph?B(n.graph,ee(e.members.map((s)=>({user_id:s.id,email:s.name})))):null;switch(t){case"overview":{let s={devices:e.devices,tokens:e.tokens,holds:null};return Pe(n.overview,i,s,e.org.handle,o)}case"activity":return n.overview?ue(n.overview.activity,o):P();case"sessions":return he(n.overview,e.org.handle,o);case"tokens":return r`${_("Tokens and devices are managed with the scp-relay token CLI.")}`;case"members":return r`${_("Members are managed with the scp-relay account CLI.")}`;case"graph":return Je({org:e.org,role:e.member.role},i,{historic:!0})}}function Ze(e,t,n,o){let i={org:e.org,role:e.member.role},s=t==="overview"?e.org.name:`${e.org.name} ${t==="graph/full"?"graph":t}`;if(t==="graph/full"){let u=n.graph?B(n.graph,ee(e.members.map((w)=>({user_id:w.id,email:w.name})))):null;return T(e,{title:s,bare:!0,head:fe()},Ve(e.org,u,{historic:!0}))}let d=Zt(e,t,n,o);if(t==="graph")return T(e,{title:s,nav:"orgs",head:fe()},d);let l=t==="overview"||t==="activity"||t==="sessions",{body:a,...c}=Ue(i,t,d,{live:l});return T(e,{...c,title:s},a)}function N(e,t="",n){return T(e,{title:"Sign in",narrow:!0},r`<p class="label">Self-hosted relay</p><h1>Sign in</h1>
|
|
1301
1304
|
<p class="lead">Use a relay token or sign in with a device code.</p>
|
|
1302
|
-
${
|
|
1305
|
+
${_(t,!0)}
|
|
1303
1306
|
<form class="form" data-sign-in method="post" action="/v1/dashboard/sign-in">
|
|
1304
1307
|
<input type="hidden" name="csrf" value="${e.csrf}">
|
|
1305
1308
|
<label class="field"><span>Token</span><input type="password" name="token" placeholder="scp_t_... or scp_d_..." required autofocus autocomplete="off"></label>
|
|
@@ -1312,4 +1315,4 @@ connect();
|
|
|
1312
1315
|
${n?r`<section class="block"><h2>Approve this device</h2><p class="small">Run this command on the relay, replacing the account and member placeholders:</p><pre><code>scp-relay device approve ${n.user_code} --account <handle> --member <name></code></pre><p class="mini" role="status">Waiting for approval.</p></section>`:""}`)}var Ee=(e)=>`'${e.replace(/'/g,"'\\''")}'`;function Qe(e,t="<user_code>"){return T(e,{title:"Device",nav:"device",narrow:!0},r`<p class="label">Device sign-in</p><h1>Approve a device</h1>
|
|
1313
1316
|
<p class="lead">Approve the code shown on the device by running this command on the relay:</p>
|
|
1314
1317
|
<pre><code>scp-relay device approve ${Ee(t)} --account ${Ee(e.org.handle)} --member ${Ee(e.member.name)}</code></pre>
|
|
1315
|
-
<p class="small">Only approve a code for a device you recognize.</p>`)}function et(e){return T(e,{title:"Not found",narrow:!0},r`<h1>Not found</h1><p class="lead">This page does not exist.</p><a href="/">Return home</a>`)}function
|
|
1318
|
+
<p class="small">Only approve a code for a device you recognize.</p>`)}function et(e){return T(e,{title:"Not found",narrow:!0},r`<h1>Not found</h1><p class="lead">This page does not exist.</p><a href="/">Return home</a>`)}function we(e,t){return T(e,{title:"Dashboard unavailable",narrow:!0},r`<h1>Dashboard unavailable</h1>${_(t,!0)}<a href="">Reload</a>`)}var m={signedIn:!1,csrf:""},D=0,be=!1;class M extends Error{}async function I(e,t){let n=await fetch(`/v1/dashboard/${e}`,{method:t?"POST":"GET",credentials:"same-origin",cache:"no-store",headers:t?{accept:"application/json","content-type":"application/json"}:{accept:"application/json"},...t?{body:JSON.stringify({...t,csrf:m.csrf})}:{}}),o=await n.json();if(!n.ok){let i=o&&typeof o==="object"?o:{};if(n.status===401&&i.error==="signed_out")throw new M;throw Error(typeof i.message==="string"?i.message:i.error==="invalid_token"?"The token is not valid.":"The relay could not complete the request.")}return o}function b(e){let t=new DOMParser().parseFromString(e,"text/html"),n=[...t.querySelectorAll("script[src]")];document.head.replaceWith(t.head),document.body.replaceWith(t.body);for(let o of n){let i=document.createElement("script");for(let s of o.attributes)i.setAttribute(s.name,s.value);i.async=!1,o.replaceWith(i)}}function ye(){location.replace(`/sign-in?next=${encodeURIComponent(location.pathname+location.search)}`)}async function tt(e){try{return await I(e)}catch(t){if(t instanceof M)throw t;return null}}function Qt(){try{return localStorage.getItem("scp.graph.historic")==="1"}catch{return!1}}async function en(e){let t=["overview","activity","sessions","graph","graph/full"].includes(e),n=["overview","graph","graph/full"].includes(e),[o,i]=await Promise.all([t?tt("overview"):null,n?tt(Qt()?"graph?historic=1":"graph"):null]);return{overview:o,graph:i}}var Z=(e)=>e instanceof Error?e.message:"The relay could not complete the request.",nt=()=>location.replace(Ye(new URLSearchParams(location.search).get("next")));async function tn(e,t){let n=Date.now()+e.expires_in*1000,o=Math.max(1,e.interval)*1000;while(t===D){if(await new Promise((s)=>setTimeout(s,o)),t!==D)return;if(Date.now()>=n)break;let i=await I("device/poll",{device_code:e.device_code});if(t!==D)return;if(i.status==="ok"){nt();return}if(i.status!=="pending"){b(N(m,i.status==="denied"?"Device sign-in was denied.":"The device code expired. Try again."));return}}if(t===D)b(N(m,"The device code expired. Try again."))}document.addEventListener("submit",(e)=>{let t=e.target;if(!(t instanceof HTMLFormElement))return;let n=t.getAttribute("action")==="/sign-out",o=t.hasAttribute("data-sign-in"),i=t.hasAttribute("data-device");if(!n&&!o&&!i)return;if(e.preventDefault(),be)return;be=!0;let s=++D;for(let d of t.querySelectorAll("button"))d.disabled=!0;(async()=>{try{if(n)await I("sign-out",{}),location.replace("/sign-in");else if(o){let d=new FormData(t).get("token");await I("sign-in",{token:typeof d==="string"?d:""}),nt()}else{let d=await I("device",{});b(N(m,"",d)),tn(d,s).catch((l)=>{if(s===D)b(N(m,Z(l)))})}}catch(d){if(d instanceof M)ye();else b(m.signedIn?we(m,Z(d)):N(m,Z(d)))}finally{be=!1}})()});async function nn(){if(m=await I("session"),!m.signedIn){b(N(m));return}let e=m,t=Ke(location.pathname,e);if("redirect"in t){location.replace(t.redirect);return}if("page"in t){b(t.page==="device"?Qe(e,new URLSearchParams(location.search).get("user_code")??void 0):et(e));return}let n=async()=>Ze(e,t.tab,await en(t.tab),Date.now());window.scpRegion=async()=>{try{return new DOMParser().parseFromString(await n(),"text/html").querySelector("[data-live]")}catch(o){if(o instanceof M)ye();return null}},b(await n())}nn().catch((e)=>{if(e instanceof M)ye();else b(we(m,Z(e)))});})();
|
package/dist/server.js
CHANGED