pi-straw-boss 0.5.2 → 0.6.1
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/README.md +1 -1
- package/dist/gui/assets/ask-Dpo9zn5X.js +1 -0
- package/dist/gui/assets/{chat-jdyprBMu.js → chat-BO71QXXf.js} +3 -2
- package/dist/gui/assets/{index-C_WFzbRO.js → index-5qCqN1sA.js} +1 -1
- package/dist/gui/assets/{index-BccsK_Zr.css → index-D8pxo5hc.css} +1 -1
- package/dist/gui/assets/{layer-CdS6Zpfk.js → layer-DhF1EBxx.js} +2 -2
- package/dist/gui/assets/views-U9D50TDD.js +2 -0
- package/dist/gui/index.html +2 -2
- package/package.json +1 -1
- package/src/ask.ts +24 -14
- package/src/bridge.ts +170 -0
- package/src/control.ts +23 -8
- package/src/dialogs.ts +153 -0
- package/src/gui.ts +16 -11
- package/src/index.ts +11 -4
- package/src/items.ts +11 -5
- package/src/net.ts +6 -6
- package/src/owners.ts +116 -0
- package/dist/gui/assets/ask-DLinwCcp.js +0 -1
- package/dist/gui/assets/views-BjEPS-ZH.js +0 -2
package/README.md
CHANGED
|
@@ -45,7 +45,7 @@ You need pi running inside Herdr 0.9.4 or newer, and [pi-intercom](https://www.n
|
|
|
45
45
|
| `boss_broadcast` | Message a tab, a workspace, all towers, or every session. |
|
|
46
46
|
| `/boss` | Take over as this tab's main agent. |
|
|
47
47
|
| `/boss status`, `/boss tower` | Show the status; open and focus the tower. |
|
|
48
|
-
| `/boss gui`, `/boss gui stop` | Open the net in the browser (any session, joins nothing); stop its server. Type into a session from its comms view; a
|
|
48
|
+
| `/boss gui`, `/boss gui stop` | Open the net in the browser (any session, joins nothing); stop its server. Type into a session from its comms view; answer a waiting `robot_hand` selector or `ask_user_question` questionnaire there or in its alert (other dialogs show read-only, to answer in the terminal; `secret_drop` stays terminal-only). |
|
|
49
49
|
| `/boss gui remote`, `/boss gui remote off` | Reach the GUI from your phone over your tailnet (`tailscale serve`, never Funnel): pair by QR code; off removes only its own serve entry. |
|
|
50
50
|
|
|
51
51
|
Subagents and sessions in Herdr worktree workspaces never join: the session that launched them speaks for them. Outside Herdr the extension does nothing.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{n as e}from"./post-B39ywXKd.js";var t=e=>e.multiple?`It takes several choices.`:e.freeform&&e.options.length?`It also takes your own words.`:``,n=(n,r)=>e(`div`,{class:`ask-one`},n.header&&e(`b`,{class:`ask-head`},n.header),e(`p`,{class:`ask-q`},n.question),n.context&&e(`div`,{class:`ask-ctx`},n.context),n.options.length>0&&e(`ol`,{class:`ask-opts`,"aria-label":`Options`},...n.options.map(t=>e(`li`,{class:`ask-opt`},e(`b`,null,t.title),t.description&&e(`small`,null,t.description)))),r&&t(n)&&e(`small`,{class:`ask-how`},t(n))),r=e=>e.replace(/[\u0000-\u0008\u000b-\u001f\u007f-\u009f]/g,`�`),i=(e,t)=>(e.select?.choices??[]).map((e,t)=>({...e,i:t})).filter(e=>!(t&&e.localOnly)),a=(e,t,n)=>({...e.size?{choices:[...e].sort((e,t)=>e-t)}:{},...t.trim()?{text:t}:{},...n.trim()?{note:n}:{}}),o=(e,t,n)=>({dialog:e.dialog,digest:e.digest,answerId:n,...t}),s={digest:`The question changed; read it again.`,"not-allowed":`That answer does not fit the question.`,malformed:`The session could not read that answer.`};function c(e){let{outcome:t,reason:n,by:r}=e.body;return t===`accepted`?[`ok`,`Answered.`]:t===`stale`?[`error`,r===`local`?`It was already answered in the terminal.`:r===`cancel`?`It was dismissed in the terminal.`:`It is no longer open.`]:t===`rejected`?[`error`,s[String(n)]??`The session refused that answer.`]:t===`busy`?[`error`,`Another answer is on its way; check the terminal.`]:t===`unknown`||e.status===504?[`error`,`Not confirmed. Check the terminal.`,!0]:[`error`,n??`Refused (${e.status}).`]}var l=e=>[`accepted`,`stale`,`busy`,`unknown`].includes(String(e.body.outcome))||e.status===504,u=e=>e.answer?`d\n${e.answer.dialog}\n${e.answer.digest}`:`c\n${e.callId}\n${e.why??``}`;function d(s,d,f=location.hostname!==`127.0.0.1`){let p,m,h,g=!1,_=!1,v;for(let e of[`focusin`,`pointerdown`])document.addEventListener(e,e=>m&&!m.el.contains(e.target)&&(m.lost=void 0));let y=(e,t,n,...r)=>(e.dataset.tone=t,e.replaceChildren(n,...r)),b=()=>{if(!m)return;let e=document.activeElement;e&&e!==document.body&&e!==m.lost&&(m.lost=void 0),m.go.disabled=!g||_,m.controls.forEach(e=>e.disabled=!g||_||m.done),m.send&&(m.send.disabled=!g||_||m.done||!m.pick()),e&&m.el.contains(e)&&e.disabled&&(m.lost=e);let t=m.lost;t&&!t.disabled&&m.el.contains(t)&&(!document.activeElement||document.activeElement===document.body)&&(t.focus(),m.lost=void 0)};async function x(t,n){[t.sending,_,t.spell]=[!0,!0,!1],b(),y(t.note,``,`Sending…`);let r=await d(`answer`,n).catch(()=>void 0),i=e(`button`,{type:`button`,class:`cmp-link`},`Check again`);i.onclick=()=>void x(t,n);let[a,o,s]=r?c(r):[`error`,`Not confirmed. Check the terminal.`,!0];[t.done,t.sending,_,t.busy]=[!r||l(r),!1,!1,r?.body.outcome===`busy`],y(t.note,a,o,...s?[i]:[]),b(),t.note.scrollIntoView?.({block:`nearest`})}let S=(t,n,r,i,a)=>{let o=e(`button`,{type:`button`,class:`ask-opt`,role:t,"aria-checked":`false`},e(`b`,a?{"data-n":String(a)}:null,n),...r.filter(Boolean).map(t=>e(`small`,null,t)));return o.onclick=i,o};function C(t,n){let a,o=i(n,f).map(e=>S(`radio`,e.label,[e.note],()=>(a=e.i,o.forEach((t,r)=>t.setAttribute(`aria-checked`,String(i(n,f)[r].i===e.i))),b()),e.i+1)),s=n.select?.copy!==void 0&&e(`button`,{type:`button`,class:`cmp-link`},`Copy command`);return s&&(s.disabled=!navigator.clipboard,s.onclick=()=>void navigator.clipboard.writeText(n.select.copy).then(()=>y(t.note,`ok`,`Copied to this device's clipboard.`),()=>y(t.note,`error`,`The browser refused the clipboard.`))),t.pick=()=>a===void 0?void 0:{choice:a},t.controls=o,[e(`pre`,{class:`ask-title`},r(n.select.title)),e(`div`,{class:`ask-opts`,role:`radiogroup`,"aria-label":`Choices`},...o),e(`div`,{class:`ask-acts`},t.send,s,t.go)]}function w(t,n){let r=n.questions.map(()=>({picks:new Set,text:e(`input`,{type:`text`,maxlength:`8192`,class:`ask-own`,placeholder:`Or type your own answer`,"aria-label":`Your own answer`}),note:e(`input`,{type:`text`,maxlength:`2048`,class:`ask-own ask-memo`,placeholder:`Note (optional)`,"aria-label":`Note`})})),i=n.questions.map((n,i)=>{let a=r[i],o=n.multiple?`checkbox`:`radio`,s=n.options.map((e,t)=>S(o,e.title,[e.description,e.preview&&`It has a preview; see it in the terminal.`],()=>{n.multiple||(a.picks.clear(),a.text.value=``),a.picks.has(t)?a.picks.delete(t):a.picks.add(t),s.forEach((e,t)=>e.setAttribute(`aria-checked`,String(a.picks.has(t)))),b()}));return a.text.oninput=()=>(n.multiple||(a.picks.clear(),s.forEach(e=>e.setAttribute(`aria-checked`,`false`))),b()),t.controls.push(...s,a.text,a.note),e(`div`,{class:`ask-one`},n.header&&e(`b`,{class:`ask-head`},n.header),e(`p`,{class:`ask-q`},n.question),e(`div`,{class:`ask-opts`,role:n.multiple?`group`:`radiogroup`,"aria-label":`Options`},...s),a.text,a.note)});return t.pick=()=>r.every(e=>e.picks.size||e.text.value.trim())?{answers:r.map(e=>a(e.picks,e.text.value,e.note.value))}:void 0,[...i,e(`div`,{class:`ask-acts`},t.send,t.go)]}function T(r){let i=r.asks??(r.ask?[r.ask]:[]),a=i.length>1,s=r.answer,c={key:u(r),el:e(`section`,{class:`ask`}),note:e(`p`,{class:`ask-note`,role:`status`,"aria-live":`polite`}),go:e(`button`,{type:`button`,class:`cmp-link`},`Focus terminal`),controls:[],pick:()=>void 0,done:!1,sending:!1};c.go.onclick=async()=>{_=!0,b();let e=await d(`focus`,{}).catch(()=>void 0);y(c.note,e?.ok?``:`error`,e?.ok?``:e?.body.reason??`Herdr could not be reached.`),_=!1,b()},s&&((c.send=e(`button`,{type:`button`,class:`ask-send`},`Send answer`)).onclick=()=>void(c.pick()&&x(c,o(s,c.pick(),crypto.randomUUID()))));let l=e(`p`,{class:`ask-term`},r.why&&i.length?r.why:`${a?`Answer them`:`Answer it`} in the terminal. ${a||!i[0]?``:t(i[0])}`.trim());return c.el.append(...s?s.select?C(c,s):w(c,s):[...i.length?i.map(e=>n(e,a)):[e(`p`,{class:`ask-why`},r.why??`It waits on a dialog.`)],e(`div`,{class:`ask-acts`},l,c.go)],c.note),c}let E=(e,t)=>{let n=document.activeElement;m&&m!==t&&(m.focus=m.el.contains(n)?n:void 0),[p,m,h]=[e,t,t?.send?t:h],s.replaceChildren(...t?[t.el]:[]),b(),t?.focus&&(!document.activeElement||document.activeElement===document.body)&&t.focus.focus()};return{update(e,t){g=t,e&&(v=void clearTimeout(v)),!e&&(m?.done||m?.sending)?v??=setTimeout(()=>(v=void 0,E()),6e3):e?m&&(u(e)===m.key||!e.answer&&(m.done||m.sending)&&e.callId===p?.callId)?((m.busy||m.sending)&&!e.answer?m.spell=!0:m.busy&&m.spell&&e.answer&&([m.done,m.busy]=[!1,!1],y(m.note,``,`The other answer was not taken; this one can go.`)),p=e):E(e,h?.key===u(e)&&!h.done?h:T(e)):E(),b()}}}export{d as t};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import{l as e,n as t}from"./index-
|
|
1
|
+
import{l as e,n as t}from"./index-5qCqN1sA.js";import{n}from"./post-B39ywXKd.js";function r(){let e=!0,t=0;return{get pinned(){return e},scrolled(n){e=n,n&&(t=0)},hold:()=>void(e=!1),arrived(n){return e||(t+=n),e},jump:()=>void(e=!0,t=0),button:n=>e&&!n?void 0:t&&!n?`${t} new`:`jump to latest`}}async function i(e,t,n,r){let i=()=>e.items.some(e=>e.id===n);for(;!i()&&e.before;)r(e.prepend(await t.older(e.before)));return i()?!0:(r(e.reset(await t.latest())),!1)}var a=(e,t,n)=>({tag:e,kids:t,attrs:n}),o=/^(?:https?:\/\/|mailto:)[^\s\u0000-\u001f]+$/i,s=(e,t)=>a(`a`,t,{href:e,rel:`noopener noreferrer`,target:`_blank`}),c=/(`+)([^`]|[^`][^]{0,1000}?[^`])\1(?!`)|\*\*([^*][^]{0,1000}?)\*\*|~~([^~][^]{0,1000}?)~~|\*([^\s*][^*]{0,500}?)\*|(?<![\w])_([^\s_][^_]{0,500}?)_(?![\w])|\[([^\]]{1,500})\]\(([^)\s]{1,2000})(?:\s+"[^"]*")?\)|(https?:\/\/[^\s<>)\]]+)/g;function l(e){let t=[],n=0;for(let r of e.matchAll(c))r.index>n&&t.push(e.slice(n,r.index)),n=r.index+r[0].length,r[2]===void 0?r[3]===void 0?r[4]===void 0?r[5]!==void 0||r[6]!==void 0?t.push(a(`em`,l(r[5]??r[6]))):r[7]===void 0?t.push(s(r[9],[r[9]])):t.push(o.test(r[8])?s(r[8],l(r[7])):r[0]):t.push(a(`del`,l(r[4]))):t.push(a(`strong`,l(r[3]))):t.push(a(`code`,[r[2]]));return n<e.length&&t.push(e.slice(n)),t}var u=/^(\s*)([-*+]|\d+[.)])\s+(.*)$/,d=/^\s*([-*_])(\s*\1){2,}\s*$/,f=/^\s*\|?\s*:?-+:?\s*(\|\s*:?-+:?\s*)*\|?\s*$/,p=e=>e.trim().replace(/^\|/,``).replace(/\|$/,``).split(`|`).map(e=>e.trim()),m=(e,t)=>/^\s*(`{3,}|~{3,}|#{1,6}\s|>)/.test(e)||d.test(e)||u.test(e)||e.includes(`|`)&&t!==void 0&&f.test(t)&&t.includes(`-`);function h(e,t=0){if(t>=16)return[a(`p`,[e])];let n=e.replace(/\r\n?/g,`
|
|
2
2
|
`).split(`
|
|
3
3
|
`),r=[];for(let e=0;e<n.length;){let i=n[e],o=n[e+1],s=i.match(/^\s*(`{3,}|~{3,})\s*([\w+-]*)/),c=i.match(/^\s*(#{1,6})\s+(.*?)\s*#*\s*$/),g=i.match(u);if(!i.trim())e++;else if(s){let t=[];for(e++;e<n.length&&!n[e].trim().startsWith(s[1]);e++)t.push(n[e]);e++,r.push(a(`pre`,[a(`code`,[t.join(`
|
|
4
4
|
`)],s[2]?{"data-lang":s[2]}:void 0)]))}else if(c)r.push(a(`h${c[1].length}`,l(c[2]))),e++;else if(d.test(i))r.push(a(`hr`,[])),e++;else if(/^\s*>/.test(i)){let i=[];for(;e<n.length&&/^\s*>/.test(n[e]);e++)i.push(n[e].replace(/^\s*> ?/,``));r.push(a(`blockquote`,h(i.join(`
|
|
5
5
|
`),t+1)))}else if(i.includes(`|`)&&o!==void 0&&f.test(o)&&o.includes(`-`)){let t=[];for(e+=2;e<n.length&&n[e].trim()&&n[e].includes(`|`);e++)t.push(p(n[e]));r.push(a(`table`,[a(`thead`,[a(`tr`,p(i).map(e=>a(`th`,l(e))))]),a(`tbody`,t.map(e=>a(`tr`,e.map(e=>a(`td`,l(e))))))]))}else if(g){let i=g[1].length,o=[];for(;e<n.length;){let r=n[e].match(u);if(!r||r[1].length!==i||/\d/.test(r[2])!==/\d/.test(g[2]))break;let s=[r[3]],c=r[3].match(/^\[([ xX])\]\s+(.*)$/);for(c&&(s[0]=c[2]),e++;e<n.length&&n[e].trim()&&n[e].search(/\S/)>i;e++)s.push(n[e].replace(RegExp(`^ {0,${i+2}}`),``));let l=h(s.join(`
|
|
6
6
|
`),t+1),d=l[0],f=c?.[1]!==` `;c&&(typeof d==`object`&&d.tag===`p`?d.kids:l).unshift(a(`i`,f?[`✓`]:[],{class:`check`,"data-done":String(f),"aria-label":f?`done`:`not done`})),o.push(a(`li`,l,c?{class:`task`}:void 0)),!n[e]?.trim()&&n[e+1]?.match(u)?.[1]?.length===i&&e++}r.push(a(/\d/.test(g[2])?`ol`:`ul`,o))}else{let t=[i];for(e++;e<n.length&&n[e].trim()&&!m(n[e],n[e+1]);e++)t.push(n[e]);r.push(a(`p`,l(t.join(`
|
|
7
|
-
`))))}}return r}function g(e){let t=e=>{if(typeof e==`string`)return document.createTextNode(e);let n=document.createElement(e.tag);for(let[t,r]of Object.entries(e.attrs??{}))n.setAttribute(t,r);return n.append(...e.kids.map(t)),n},n=document.createDocumentFragment();return n.append(...e.map(t)),n}function _(e=600){let t=[],n,r=!1,i=new Set,a=new Map,o=new Map,s=e=>e.forEach(e=>(i.delete(e.id),e.tools?.forEach(e=>(o.delete(e.id),a.delete(e.id)))));function c(e,t){let n=[];for(let r of e)i.has(r.id)||(i.add(r.id),r.kind===`result`&&r.callId?(a.set(r.callId,r),o.has(r.callId)&&t.add(o.get(r.callId))):(r.tools?.forEach(e=>o.set(e.id,r.id)),n.push(r)));return n}let l=e=>({rebuild:!1,added:[],touched:[],dropped:[],front:!1,...e});return{get items(){return t},get before(){return n},get detached(){return r},result:e=>a.get(e),reset(e){return[t,n,r]=[[],e.before,!1],i.clear(),a.clear(),o.clear(),t=c(e.items,new Set),l({rebuild:!0,added:t})},append(i){if(r)return l({});let a=new Set,o=c(i,a);t.push(...o);let u=t.length>e?t.splice(0,t.length-e):[];return s(u),u.length&&(n=t[0].id),l({added:o,touched:[...a],dropped:u.map(e=>e.id)})},prepend(i){let a=new Set,o=c(i.items,a);t.unshift(...o),n=i.before;let u=t.length>e?t.splice(e):[];return s(u),u.length&&(r=!0),l({added:o,touched:[...a],dropped:u.map(e=>e.id),front:!0})}}}var v=e=>e?new Date(e).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`,hour12:!1}):``,y=e=>e>=1024?`${(e/1024).toFixed(e>=10240?0:1)} KB`:`${e} B`,b={intercom_message:`message from`,subagent_result:`report from`,subagent_ping:`question from`,subagent_status:`status of`,"pi-loop-monitor":`monitor`,"memory-context":`memory`,"doc-review":`form answers`},x=n=>{let r=e(`<span class="ava"><svg><use/></svg></span>`);return r.querySelector(`use`).setAttribute(`href`,`#i-${t[n]??n}`),r};function S(e){let t=[],r=0;for(let i of e.matchAll(/https?:\/\/[^\s<>)\]]+/g))t.push(e.slice(r,i.index),n(`a`,{href:i[0],rel:`noopener noreferrer`,target:`_blank`},i[0])),r=i.index+i[0].length;return[...t,e.slice(r)]}function C(e,t,{who:a,link:o,openTile:s}){let c=_(),l=new Map,u=n(`div`,{class:`chat-list`}),d=n(`div`,{class:`chat-top`}),f=n(`div`,{class:`chat-live`}),p=n(`button`,{class:`chat-pill`,type:`button`,hidden:``}),m=n(`p`,{class:`chat-empty`},`No transmissions yet.`),C=n(`div`,{class:`chat-scroll`,tabindex:`-1`,"aria-label":`Comms log`},d,u,f);e.replaceChildren(C,p);let w=r(),T=!1,E=!1,D,O,k=0,A=()=>C.scrollHeight-C.scrollTop-C.clientHeight<80,j=(e=w.button(c.detached))=>(p.hidden=!e,p.textContent=e??``),M=()=>(w.jump(),O=void 0,C.scrollTop=C.scrollHeight,j());async function N(e){T=!0;let n=await i(c,t,e,e=>(z(e),B(e))).finally(()=>T=!1),r=l.get(e);if(D===e){if(!n||!r)return M();w.hold(),O=r,r.scrollIntoView({block:`center`}),r.classList.remove(`lit`),r.offsetWidth,r.classList.add(`lit`),clearTimeout(k),k=window.setTimeout(()=>(O=void 0,r.classList.remove(`lit`)),2e3),j()}}let P=()=>D?void N(D):M(),F=(e,n,r,i)=>{e.disabled=!0,t.entry(r).then(t=>{let r=t&&i(t);if(r===void 0)return void(e.textContent=`unavailable`);n.textContent=r,e.remove()},()=>e.textContent=`unavailable`)},I=e=>s({id:`doc:${e}`,title:e.split(`/`).pop()||e,body:()=>{let r=n(`div`,{class:`md`},n(`p`,{class:`chat-empty`},`Loading…`));return t.doc(e).then(e=>r.replaceChildren(e===void 0?`Unavailable.`:g(h(e)))),r}});function L(e){let
|
|
7
|
+
`))))}}return r}function g(e){let t=e=>{if(typeof e==`string`)return document.createTextNode(e);let n=document.createElement(e.tag);for(let[t,r]of Object.entries(e.attrs??{}))n.setAttribute(t,r);return n.append(...e.kids.map(t)),n},n=document.createDocumentFragment();return n.append(...e.map(t)),n}function _(e=600){let t=[],n,r=!1,i=new Set,a=new Map,o=new Map,s=e=>e.forEach(e=>(i.delete(e.id),e.tools?.forEach(e=>(o.delete(e.id),a.delete(e.id)))));function c(e,t){let n=[];for(let r of e)i.has(r.id)||(i.add(r.id),r.kind===`result`&&r.callId?(a.set(r.callId,r),o.has(r.callId)&&t.add(o.get(r.callId))):(r.tools?.forEach(e=>o.set(e.id,r.id)),n.push(r)));return n}let l=e=>({rebuild:!1,added:[],touched:[],dropped:[],front:!1,...e});return{get items(){return t},get before(){return n},get detached(){return r},result:e=>a.get(e),reset(e){return[t,n,r]=[[],e.before,!1],i.clear(),a.clear(),o.clear(),t=c(e.items,new Set),l({rebuild:!0,added:t})},append(i){if(r)return l({});let a=new Set,o=c(i,a);t.push(...o);let u=t.length>e?t.splice(0,t.length-e):[];return s(u),u.length&&(n=t[0].id),l({added:o,touched:[...a],dropped:u.map(e=>e.id)})},prepend(i){let a=new Set,o=c(i.items,a);t.unshift(...o),n=i.before;let u=t.length>e?t.splice(e):[];return s(u),u.length&&(r=!0),l({added:o,touched:[...a],dropped:u.map(e=>e.id),front:!0})}}}var v=e=>e?new Date(e).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`,hour12:!1}):``,y=e=>e>=1024?`${(e/1024).toFixed(e>=10240?0:1)} KB`:`${e} B`,b={intercom_message:`message from`,subagent_result:`report from`,subagent_ping:`question from`,subagent_status:`status of`,"pi-loop-monitor":`monitor`,"memory-context":`memory`,"doc-review":`form answers`},x=n=>{let r=e(`<span class="ava"><svg><use/></svg></span>`);return r.querySelector(`use`).setAttribute(`href`,`#i-${t[n]??n}`),r};function S(e){let t=[],r=0;for(let i of e.matchAll(/https?:\/\/[^\s<>)\]]+/g))t.push(e.slice(r,i.index),n(`a`,{href:i[0],rel:`noopener noreferrer`,target:`_blank`},i[0])),r=i.index+i[0].length;return[...t,e.slice(r)]}function C(e,t,{who:a,link:o,openTile:s}){let c=_(),l=new Map,u=n(`div`,{class:`chat-list`}),d=n(`div`,{class:`chat-top`}),f=n(`div`,{class:`chat-live`}),p=n(`button`,{class:`chat-pill`,type:`button`,hidden:``}),m=n(`p`,{class:`chat-empty`},`No transmissions yet.`),C=n(`div`,{class:`chat-scroll`,tabindex:`-1`,"aria-label":`Comms log`},d,u,f);e.replaceChildren(C,p);let w=r(),T=!1,E=!1,D,O,k=0,A=()=>C.scrollHeight-C.scrollTop-C.clientHeight<80,j=(e=w.button(c.detached))=>(p.hidden=!e,p.textContent=e??``),M=()=>(w.jump(),O=void 0,C.scrollTop=C.scrollHeight,j());async function N(e){T=!0;let n=await i(c,t,e,e=>(z(e),B(e))).finally(()=>T=!1),r=l.get(e);if(D===e){if(!n||!r)return M();w.hold(),O=r,r.scrollIntoView({block:`center`}),r.classList.remove(`lit`),r.offsetWidth,r.classList.add(`lit`),clearTimeout(k),k=window.setTimeout(()=>(O=void 0,r.classList.remove(`lit`)),2e3),j()}}let P=()=>D?void N(D):M(),F=(e,n,r,i)=>{e.disabled=!0,t.entry(r).then(t=>{let r=t&&i(t);if(r===void 0)return void(e.textContent=`unavailable`);n.textContent=r,e.remove()},()=>e.textContent=`unavailable`)},I=e=>s({id:`doc:${e}`,title:e.split(`/`).pop()||e,body:()=>{let r=n(`div`,{class:`md`},n(`p`,{class:`chat-empty`},`Loading…`));return t.doc(e).then(e=>r.replaceChildren(e===void 0?`Unavailable.`:g(h(e)))),r}});function L(e,r){let i=c.result(e.id),a=n(`pre`,{class:`out`},i?.text??``),o=n(`pre`,{class:`args`},e.args??``),s=e.cut?n(`button`,{class:`more`,type:`button`},`show all arguments`):null;s?.addEventListener(`click`,()=>F(s,o,r,t=>(e=>e&&`${e.args??``}${e.cut?`
|
|
8
|
+
… (cut at 1 MB)`:``}`)(t.tools?.find(t=>t.id===e.id))));let l=i?.more?n(`button`,{class:`more`,type:`button`},`show all (${y(i.bytes??0)})`):null;l?.addEventListener(`click`,()=>F(l,a,i.id,e=>e.text));let u=e.name===`show_doc`&&t.doc?n(`button`,{class:`more open`,type:`button`},`open beside`):null;return u?.addEventListener(`click`,t=>(t.preventDefault(),e.summary.split(`, `).forEach(I))),n(`details`,{class:`act`},n(`summary`,{"data-mark":i?i.isError?`error`:`done`:`working`},n(`b`,{class:`badge`}),n(`code`,null,e.name),n(`span`,{class:`sum`},e.summary),u),o,s,i&&n(`div`,{class:`result`},i.images?n(`em`,null,`${i.images} image(s)`):null,a,l))}function R(e){let t=n(`time`,null,v(e.at));switch(e.kind){case`user`:return n(`article`,{class:`tx you`},n(`header`,null,t,n(`b`,null,`you`),x(`user`)),n(`div`,{class:`bubble`},...S(e.text??``),e.images?n(`em`,null,` · ${e.images} image(s)`):null));case`assistant`:{let r=a(),i=n(`pre`,{class:`thought-text`}),o=e.thought?n(`button`,{class:`thought`,type:`button`},e.thought<0?`◇ thought · redacted`:`◇ thought · ${e.thought.toLocaleString()} chars`):null;return e.thought&&e.thought>0&&o?.addEventListener(`click`,()=>F(o,i,e.id,e=>e.thoughtText)),n(`article`,{class:`tx in`},x(r.role),n(`div`,{class:`tx-body`},n(`header`,null,n(`b`,null,r.name),e.model?n(`span`,null,e.model):null,t,e.stop?n(`span`,{class:`stop`,"data-mark":`error`},e.stop):null),o,i,e.text?n(`div`,{class:`md`},g(h(e.text))):null,e.error?n(`p`,{class:`fault`},e.error):null,...(e.tools??[]).map(t=>L(t,e.id))))}case`bash`:return n(`article`,{class:`tx sys`},n(`details`,{class:`act`},n(`summary`,{"data-mark":e.exit?`error`:`done`},n(`b`,{class:`badge`}),n(`code`,null,`shell`),n(`span`,{class:`sum`},`! ${e.command}`),e.exit?n(`span`,{class:`stop`,"data-mark":`error`},`exit ${e.exit}`):null),e.text?n(`pre`,{class:`out`},e.text):null));case`notice`:return n(`article`,{class:`tx sys`},n(`details`,{class:`notice`},n(`summary`,null,x(`comms`),n(`em`,null,`incoming`),b[e.type??``]??e.type??`notice`,` `,e.from&&o(e.from)||(e.from??``),t),n(`pre`,null,e.text??``)));case`divider`:return n(`article`,{class:`tx rule`},n(`details`,null,n(`summary`,null,e.type===`compaction`?`context compacted · ${(e.tokens??0).toLocaleString()} tokens summarized`:`branch summary`),n(`pre`,null,e.text??``)));default:return n(`article`,{class:`tx note`},e.text??``,` `,t)}}function z(e){e.rebuild&&(l.clear(),u.replaceChildren());for(let t of e.dropped)l.get(t)?.remove(),l.delete(t);let t=e.added.map(e=>(l.set(e.id,R(e)),l.get(e.id)));e.front?u.prepend(...t):u.append(...t),m.remove(),c.items.length||u.append(m),d.hidden=!c.before}let B=e=>e.touched.forEach(e=>{let t=l.get(e),n=c.items.find(t=>t.id===e);if(t&&n){let r=R(n);t.replaceWith(r),l.set(e,r)}}),V=async()=>{if(!T&&c.before&&E){T=!0;try{let e=C.scrollHeight,n=c.prepend(await t.older(c.before));z(n),B(n),C.scrollTop+=C.scrollHeight-e}finally{T=!1}c.before&&C.clientHeight&&d.getBoundingClientRect().bottom>=C.getBoundingClientRect().top&&V()}};new IntersectionObserver(e=>e.some(e=>e.isIntersecting)&&void V(),{root:C}).observe(d),p.addEventListener(`click`,()=>{D=void 0,c.detached?t.latest().then(e=>(z(c.reset(e)),M())):M()}),C.addEventListener(`scroll`,()=>(w.scrolled(A()),j()),{passive:!0});for(let e of[`wheel`,`touchstart`,`pointerdown`,`keydown`])C.addEventListener(e,()=>O=D=void 0,{passive:!0});let H=new ResizeObserver(()=>w.pinned&&!c.detached?C.scrollTop=C.scrollHeight:O?.scrollIntoView({block:`center`}));return H.observe(u),H.observe(C),{log:C,apply(e){if(e.reset)z(c.reset({items:e.items??[],before:e.before})),E=!0,P();else if(e.items?.length){let t=c.append(e.items);z(t),B(t),w.arrived(t.added.length)&&!c.detached?M():j()}},reveal(e){D=e,E&&P()},setLive(e,t){f.dataset.mark=t,f.lastChild?.textContent!==e&&f.replaceChildren(...e?[n(`b`,{class:`badge`}),n(`span`,null,e)]:[])}}}export{C as mountChat};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var e={working:`started working`,waiting:`is waiting on a question`,idle:`went idle`,done:`finished`,error:`hit an error`,unknown:`lost its status`};function t(e){let t=new Map;for(let n of e.bases){n.tower&&t.set(`tower:${n.id}`,{name:`${n.label} tower`,mark:n.tower.mark});for(let e of n.tabs.flatMap(e=>e.units))for(let n of[e,...e.subs])t.set(n.id,{name:n.name,mark:n.mark});for(let e of n.outposts)t.set(e.id,{name:e.label,mark:e.mark})}return t}function n(n,r){if(!n)return[];let[i,a]=[t(n),t(r)],o=[];for(let[t,n]of a){let r=i.get(t);r?r.mark!==n.mark&&o.push({text:`${n.name} ${e[n.mark]}`,mark:n.mark}):o.push({text:`${n.name} joined`,mark:n.mark})}for(let[e,t]of i)a.has(e)||o.push({text:`${t.name} left`,mark:`idle`});return o}var r=e=>e===`waiting`||e===`error`?0:1;function i(e,t){let n=new Map;for(let r of e.bases)for(let e of[...r.tower?[{...r.tower,role:`tower`}]:[],...[...r.tabs.flatMap(e=>e.units),...r.outside].flatMap(e=>[e,...e.subs])])n.set(e.key,{key:e.key,ws:r.id,name:e.name,role:e.role,mark:e.mark,note:e.note,at:t,pending:e.pending});return n}function a(e,t){return[...t.values()].filter(t=>e?.get(t.key)?.mark!==t.mark&&(r(t.mark)===0||e!==void 0&&t.mark===`done`))}var o=e=>{try{return decodeURIComponent(e)}catch{return e}},s=e=>/^\.+$/.test(e)?e.replaceAll(`.`,`%2E`):encodeURIComponent(e);function c(e){let[t,n]=e.split(`#`)[0].split(`?`),[r,i,a,s]=t.replace(/^\/+|\/+$/g,``).split(`/`).map(o);if(r!==`w`||!i)return{view:`map`};if(a!==`s`||!s)return{view:`workspace`,ws:i};let c=new URLSearchParams(n).get(`at`);return c?{view:`session`,ws:i,key:s,at:c}:{view:`session`,ws:i,key:s}}var l=e=>e.view===`map`?``:e.view===`workspace`?`w/${s(e.ws)}`:`w/${s(e.ws)}/s/${s(e.key)}${e.at?`?at=${encodeURIComponent(e.at)}`:``}`,u=e=>e.view===`session`?{view:`workspace`,ws:e.ws}:{view:`map`},d=e=>e.view===`session`?e.key:e.view===`workspace`?`w:${e.ws}`:null;function ee(e,t=new URL(document.baseURI).pathname){let n=()=>c(location.pathname.slice(t.length)+location.search),r={route:n,href:e=>l(e)||`./`,go(n){let r=t+l(n);location.pathname+location.search!==r&&history.pushState(null,``,r),e(n)}};return addEventListener(`popstate`,()=>e(n())),document.addEventListener(`click`,e=>{let t=e.target?.closest?.(`a[data-route]`);!t||e.defaultPrevented||e.button!==0||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey||(e.preventDefault(),r.go(c(t.getAttribute(`data-route`))))}),r}var f={main:`main`,member:`member`,subagent:`subagent`,outpost:`outpost`,outside:`outside`,tower:`tower`},p={working:`working`,waiting:`waiting on a question`,idle:`idle`,done:`finished`,error:`error`,unknown:`no status`},m=e=>e===`waiting`||e===`error`,h=e=>{let t=new DOMParser().parseFromString(e.trim(),`text/html`).body.firstElementChild;if(!(t instanceof HTMLElement))throw Error(`bad template`);return document.importNode(t,!0)},g=(e,t)=>{let n=document.getElementById(e);if(!(n instanceof t))throw Error(`#${e} is missing from the page`);return n},_=(e,t,n)=>{let r=e.querySelector(t);r.textContent!==n&&(r.textContent=n)},v=(e,t)=>{if(e.dataset.mark===t)return;let n=e.dataset.mark!==void 0;e.dataset.mark=t,n&&(e.classList.remove(`flash`),e.offsetWidth,e.classList.add(`flash`))},y=(e,t)=>e?e.replace(/^tool:/,`using `):p[t],b=(e,t)=>{e.toggleAttribute(`hidden`,!t),t&&(e.setAttribute(`href`,l(t)||`./`),e.setAttribute(`data-route`,l(t)))},x=`<div class="plate"><i class="ring"></i><svg><use href="#i-main"/></svg><b class="badge"></b></div>`;function S(e,t,n){v(e,n);let r=e.querySelector(`use`),i=`#i-${f[t]??`member`}`;r.getAttribute(`href`)!==i&&r.setAttribute(`href`,i)}function C(e,t,n,r){let i=new Map;for(let t of e.children)!t.classList.contains(`leaving`)&&t.dataset.key&&i.set(t.dataset.key,t);let a=e.firstElementChild;for(let o of t){let t=i.get(o.id);for(t||(t=n(o),t.dataset.key=o.id,t.classList.add(`enter`),setTimeout(()=>t.classList.remove(`enter`),600)),i.delete(o.id);a?.classList.contains(`leaving`);)a=a.nextElementSibling;t===a?a=a.nextElementSibling:e.insertBefore(t,a),r(t,o)}for(let e of i.values())e.classList.add(`leaving`),setTimeout(()=>e.remove(),400)}var w=()=>h(`<div class="unit"><div class="card"><a class="hit"></a>${x}<div class="meta"><span class="name"></span><span class="line"><em class="role"></em><span class="note"></span></span></div></div><div class="subs"></div></div>`);function T(e,t){let n=e.closest(`.base`)?.dataset.key,r=e.querySelector(`.hit`);b(r,t.key&&n?{view:`session`,ws:n,key:t.key}:void 0),r.setAttribute(`aria-label`,`${t.name}: ${y(t.note,t.mark)}`),r.toggleAttribute(`data-alert`,m(t.mark)),v(e,t.mark),S(e.querySelector(`.plate`),t.role,t.mark),_(e,`.name`,t.name),_(e,`.role`,t.role),_(e,`.note`,y(t.note,t.mark)),C(e.querySelector(`.subs`),t.subs??[],w,T)}var te=()=>h(`<section class="base"><header><div class="tower"><i class="sweep"></i><i class="pulse"></i><svg><use href="#i-tower"/></svg><b class="badge"></b></div><div class="title"><span class="crown"><svg><use href="#i-crown"/></svg>head tower</span><h2><a class="enter-base"></a></h2><p></p></div></header><div class="tabs"></div><div class="outposts"></div></section>`);function ne(e,t){v(e,t.mark),e.classList.toggle(`head`,t.head);let n=e.querySelector(`.tower`);n.classList.toggle(`ghost`,!t.tower),v(n,t.tower?.mark??`unknown`),_(e,`h2 a`,t.label),b(e.querySelector(`h2 a`),{view:`workspace`,ws:t.id}),_(e,`.title p`,t.tower?`control tower · ${p[t.tower.mark]}`:`no tower yet`),C(e.querySelector(`.tabs`),t.tabs,()=>h(`<div class="tab"><h3></h3><div class="units"></div></div>`),(e,t)=>{_(e,`h3`,`tab ${t.label}`),C(e.querySelector(`.units`),t.units,w,T)}),C(e.querySelector(`.outposts`),t.outposts.map(e=>({id:e.id,name:e.label,role:`outpost`,mark:e.mark,note:e.mark===`unknown`?`no agent running`:void 0})),w,T)}function re(e,t,n){let r=[...e.querySelectorAll(`.base:not(.leaving) .tower`)],i=e.querySelector(`.base.head:not(.leaving) .tower`),a=e.getBoundingClientRect(),o=e=>{let t=e.getBoundingClientRect();return[Math.round(t.x+t.width/2-a.x),Math.round(t.y+t.height/2-a.y)]},s=i?r.filter(e=>e!==i).map(e=>{let[[t,n],[r,a]]=[o(i),o(e)],s=Math.round((t+r)/2);return`M${t} ${n}C${s} ${n} ${s} ${a} ${r} ${a}`}):[],c=s.join(`|`);if(t.dataset.sig===c)return;t.dataset.sig=c;let l=(e,t,...n)=>{let r=document.createElementNS(`http://www.w3.org/2000/svg`,e);for(let[e,n]of Object.entries(t))r.setAttribute(e,n);return r.append(...n),r};t.replaceChildren(...s.flatMap(e=>[l(`path`,{class:`wire`,d:e}),...n?[]:[l(`circle`,{class:`packet`,r:`3`},l(`animateMotion`,{dur:`5s`,repeatCount:`indefinite`,path:e}))]]))}function ie(){let[e,t,n,r]=[g(`map`,HTMLElement),g(`bases`,HTMLElement),g(`links`,SVGSVGElement),g(`log`,HTMLElement)],i=matchMedia(`(prefers-reduced-motion: reduce)`).matches,a=()=>!e.hidden&&re(e,n,i);return new ResizeObserver(a).observe(e),{layout:a,stats(e){let t=e.bases.flatMap(e=>e.tabs.flatMap(e=>e.units.flatMap(e=>[e,...e.subs]))),n=e=>String(t.filter(t=>!e||t.mark===e).length);for(let[t,r]of[[`s-bases`,String(e.bases.length)],[`s-agents`,n()],[`s-working`,n(`working`)],[`s-waiting`,n(`waiting`)]])g(t,HTMLElement).textContent=r},show(e){C(t,e.bases,te,ne),g(`empty`,HTMLElement).hidden=e.bases.length>0,requestAnimationFrame(a)},log(e){let t=new Date().toLocaleTimeString([],{hour12:!1});for(let n of e){let e=h(`<li><span></span><time></time></li>`);e.dataset.mark=n.mark,_(e,`span`,n.text),_(e,`time`,t),r.prepend(e)}for(;r.children.length>12;)r.lastElementChild.remove()},pause(e){document.documentElement.classList.toggle(`paused`,e)},still(e){e?n.pauseAnimations():n.unpauseAnimations()}}}var E=45e3,ae=1e3,oe=3e4,se=(e,t)=>Math.min(oe,ae*2**(e-1))*(.8+.4*t);function D(e){try{return JSON.parse(e)}catch{return}}function ce(e){let t,n,r,i=0,a={state:`connecting`,attempt:0},o=t=>e.onStatus(a={...a,...t}),s=()=>(e.clearTimeout(n),e.clearTimeout(r),n=r=void 0),c=()=>{let e=t;t=void 0,e?.close()},l=()=>{e.clearTimeout(r),r=e.setTimeout(()=>u(),E),o({state:`live`,attempt:0,lastContact:e.now()})},u=()=>{c(),s();let t=a.attempt+1;if(t>8)return o({state:`offline`,attempt:t});o({state:`reconnecting`,attempt:t}),e.hidden()||(n=e.setTimeout(d,se(t,e.random())))},d=()=>{c(),s(),i=e.now();let n=t=e.open();n.onError(()=>t===n&&u()),n.listen(`message`,r=>{if(t!==n)return;let i=D(r);i&&e.onNet(i),o({problem:i?void 0:`the server sent a snapshot the page cannot read`}),l()}),n.listen(`ping`,()=>t===n&&l()),n.listen(`problem`,e=>{t===n&&(o({problem:D(e)??`the server reported a problem the page cannot read`}),l())}),r=e.setTimeout(()=>u(),E)};return{start(){o({state:`connecting`,attempt:0}),d()},resume(){let n=e.now()-i<2e3||a.lastContact!==void 0&&e.now()-a.lastContact<=2e4;t&&n||(o({attempt:0,state:a.state===`live`?`reconnecting`:a.state}),d())},restart:d,hide(){e.clearTimeout(n),n=void 0},stop(){c(),s()}}}var le=(function(){let e=typeof document<`u`&&document.createElement(`link`).relList;return e&&e.supports&&e.supports(`modulepreload`)?`modulepreload`:`preload`})(),ue=function(e,t){return new URL(e,t).href},de={},fe=function(e){return e.pathname.endsWith(`.css`)},pe=function(e,t,n){if(t in e)return e[t];let r=n();if(!r){e[t]=void 0;return}let i=r.then(()=>{e[t]=void 0},n=>{throw e[t]=void 0,n});return e[t]=i,i},O=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e,i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function s(e){return import.meta.resolve?new URL(import.meta.resolve(e)):new URL(e,import.meta.url)}r=o(t.map(t=>{t=ue(t,n);let r=s(t),i=fe(r);return pe(de,r.href,()=>{if(e===void 0){e={all:new Set,styles:new Set};let t=document.getElementsByTagName(`link`);for(let n=t.length-1;n>=0;n--){let r=t[n];e.all.add(r.href),r.rel===`stylesheet`&&e.styles.add(r.href)}}if((i?e.styles:e.all).has(r.href))return;let t=document.createElement(`link`);if(t.rel=i?`stylesheet`:le,i||(t.as=`script`),t.crossOrigin=``,t.href=r.href,a&&t.setAttribute(`nonce`,a),document.head.appendChild(t),i)return new Promise((e,n)=>{t.addEventListener(`load`,e),t.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${r}`)))})})}).filter(e=>e!==void 0))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},k=ie(),A=e=>document.getElementById(e),me=e=>e?new Date(e).toLocaleTimeString([],{hour12:!1}):`never`,j,M,N,P,F={state:`connecting`,attempt:0},I={view:`map`},L=!1,R,z,he,B=e=>z?e(z):void he?.then(e);function ge(){he??=O(async()=>{let{mountFocus:e}=await import(`./views-BjEPS-ZH.js`);return{mountFocus:e}},[],import.meta.url).then(({mountFocus:e})=>(z=e({data:ve,restart:()=>Q.restart(),openTile:W,online:()=>F.state===`live`}),z.show(I,I),N&&z.net(N),z))}var V,H,U=e=>{if(V)return e(V);H??=O(async()=>{let{mountPanels:e}=await import(`./layer-CdS6Zpfk.js`);return{mountPanels:e}},[],import.meta.url).then(({mountPanels:e})=>V=e({label:e=>N?.bases.find(t=>t.id===e)?.label??e,recent:async e=>(await(Z?Z.data(e).latest():X(e,`?limit=12`))).items,focus:e=>Z&&(()=>Z.data(e).post(`focus`,{}))})),H.then(e)},W=(e,t)=>U(n=>n.tiles.open(e,t));function G(e){if(N=P=e,document.hidden)return;k.stats(e);let t=i(e,Date.now()),r=a(R,t);(r.length||V)&&U(e=>e.alerts(r,t)),R=t,k.log(n(M,e)),M=e,B(t=>t.net(e)),I.view===`map`&&(k.show(e),j=e,P=void 0)}function K(e){let t=I,n=e.view===`workspace`&&t.view===`map`?document.querySelector(`#bases [data-key="${CSS.escape(e.ws)}"]`)?.getBoundingClientRect():void 0;I=e,e.view!==`map`&&ge(),A(`map`).hidden=e.view!==`map`,A(`legend`).hidden=e.view===`session`,k.still(e.view!==`map`),B(r=>r.show(e,t,n)),e.view===`map`&&N&&N!==j&&(G(N),requestAnimationFrame(k.layout)),L&&d(e)!==d(t)&&Q.restart()}function q(e){F=e;let t=e.state===`reconnecting`||e.state===`offline`;document.body.dataset.stale=A(`stage`).dataset.stale=String(t),A(`link`).dataset.state=e.state,A(`link-text`).textContent={connecting:`connecting`,live:`live`,reconnecting:`reconnecting`,offline:`offline`}[e.state],z&&N&&z.net(N),V?.stack.redraw();let n=A(`banner`);n.hidden=!t&&!e.problem;let r=e.state===`offline`?`Disconnected. Gave up after ${e.attempt-1} tries; it reconnects when you return to this tab.`:e.state===`reconnecting`?`Disconnected from the straw net. Reconnecting${e.attempt?` (try ${e.attempt})`:``}… The view shows the last known state.`:`The server is up but cannot read the net: ${e.problem}`,i=document.createElement(`b`);i.textContent=me(e.lastContact),n.replaceChildren(`${r} Last update `,i,`.`)}function J(e,t){try{let n=JSON.parse(t);B(t=>e===`history`?t.history(n):t.cards(n))}catch{}}function _e(e){let t=new EventSource(e?`events?watch=${encodeURIComponent(e)}`:`events`);return{onError:e=>t.onerror=e,listen:(e,n)=>t.addEventListener(e,e=>n(e.data)),close:()=>t.close()}}var Y=e=>fetch(`api/${e}`,{cache:`no-store`}).then(e=>e.ok?e.json():Promise.reject(Error(String(e.status)))),X=(e,t=``)=>Y(`history/${encodeURIComponent(e)}${t}`),Z=void 0,ve=e=>({older:t=>X(e,`?before=${encodeURIComponent(t)}`),latest:()=>X(e),entry:t=>Y(`entry/${encodeURIComponent(e)}/${encodeURIComponent(t)}`).catch(()=>void 0)}),ye=()=>{let e=_e(d(I));return e.listen(`history`,e=>J(`history`,e)),e.listen(`cards`,e=>J(`cards`,e)),e};document.addEventListener(`click`,e=>{let t=e.target?.closest?.(`a[data-alert]`),n=t&&c(t.getAttribute(`data-route`)??``);if(!n||n.view!==`session`||e.button!==0||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;let r=R?.get(n.key);r&&(e.preventDefault(),U(e=>e.stack.show(r)))},!0);var be=ee(e=>K(e)),Q=ce({open:ye,now:Date.now,setTimeout:(e,t)=>window.setTimeout(e,t),clearTimeout:e=>window.clearTimeout(e),random:Math.random,hidden:()=>document.hidden,onNet:G,onStatus:q}),$=()=>Q.resume();document.addEventListener(`visibilitychange`,()=>{if(k.pause(document.hidden),document.hidden)return Q.hide();P&&G(P),B(e=>e.wake()),$()}),addEventListener(`keydown`,e=>{e.key!==`Escape`||e.defaultPrevented||(e.preventDefault(),!V?.stack.close()&&I.view!==`map`&&be.go(u(I)))}),A(`pair`).addEventListener(`click`,()=>void O(async()=>{let{pairTile:e}=await import(`./pair-DDTg3MTR.js`);return{pairTile:e}},[],import.meta.url).then(({pairTile:e})=>W(e(),!0)));for(let e of[`focus`,`pageshow`,`online`])window.addEventListener(e,()=>!document.hidden&&$());q(F),K(be.route()),Q.start(),L=!0;export{b as a,S as c,C as d,_ as f,x as i,h as l,r as m,f as n,g as o,m as p,p as r,y as s,O as t,v as u};
|
|
1
|
+
var e={working:`started working`,waiting:`is waiting on a question`,idle:`went idle`,done:`finished`,error:`hit an error`,unknown:`lost its status`};function t(e){let t=new Map;for(let n of e.bases){n.tower&&t.set(`tower:${n.id}`,{name:`${n.label} tower`,mark:n.tower.mark});for(let e of n.tabs.flatMap(e=>e.units))for(let n of[e,...e.subs])t.set(n.id,{name:n.name,mark:n.mark});for(let e of n.outposts)t.set(e.id,{name:e.label,mark:e.mark})}return t}function n(n,r){if(!n)return[];let[i,a]=[t(n),t(r)],o=[];for(let[t,n]of a){let r=i.get(t);r?r.mark!==n.mark&&o.push({text:`${n.name} ${e[n.mark]}`,mark:n.mark}):o.push({text:`${n.name} joined`,mark:n.mark})}for(let[e,t]of i)a.has(e)||o.push({text:`${t.name} left`,mark:`idle`});return o}var r=e=>e===`waiting`||e===`error`?0:1;function i(e,t){let n=new Map;for(let r of e.bases)for(let e of[...r.tower?[{...r.tower,role:`tower`}]:[],...[...r.tabs.flatMap(e=>e.units),...r.outside].flatMap(e=>[e,...e.subs])])n.set(e.key,{key:e.key,ws:r.id,name:e.name,role:e.role,mark:e.mark,note:e.note,at:t,pending:e.pending});return n}function a(e,t){return[...t.values()].filter(t=>e?.get(t.key)?.mark!==t.mark&&(r(t.mark)===0||e!==void 0&&t.mark===`done`))}var o=e=>{try{return decodeURIComponent(e)}catch{return e}},s=e=>/^\.+$/.test(e)?e.replaceAll(`.`,`%2E`):encodeURIComponent(e);function c(e){let[t,n]=e.split(`#`)[0].split(`?`),[r,i,a,s]=t.replace(/^\/+|\/+$/g,``).split(`/`).map(o);if(r!==`w`||!i)return{view:`map`};if(a!==`s`||!s)return{view:`workspace`,ws:i};let c=new URLSearchParams(n).get(`at`);return c?{view:`session`,ws:i,key:s,at:c}:{view:`session`,ws:i,key:s}}var l=e=>e.view===`map`?``:e.view===`workspace`?`w/${s(e.ws)}`:`w/${s(e.ws)}/s/${s(e.key)}${e.at?`?at=${encodeURIComponent(e.at)}`:``}`,u=e=>e.view===`session`?{view:`workspace`,ws:e.ws}:{view:`map`},d=e=>e.view===`session`?e.key:e.view===`workspace`?`w:${e.ws}`:null;function ee(e,t=new URL(document.baseURI).pathname){let n=()=>c(location.pathname.slice(t.length)+location.search),r={route:n,href:e=>l(e)||`./`,go(n){let r=t+l(n);location.pathname+location.search!==r&&history.pushState(null,``,r),e(n)}};return addEventListener(`popstate`,()=>e(n())),document.addEventListener(`click`,e=>{let t=e.target?.closest?.(`a[data-route]`);!t||e.defaultPrevented||e.button!==0||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey||(e.preventDefault(),r.go(c(t.getAttribute(`data-route`))))}),r}var f={main:`main`,member:`member`,subagent:`subagent`,outpost:`outpost`,outside:`outside`,tower:`tower`},p={working:`working`,waiting:`waiting on a question`,idle:`idle`,done:`finished`,error:`error`,unknown:`no status`},m=e=>e===`waiting`||e===`error`,h=e=>{let t=new DOMParser().parseFromString(e.trim(),`text/html`).body.firstElementChild;if(!(t instanceof HTMLElement))throw Error(`bad template`);return document.importNode(t,!0)},g=(e,t)=>{let n=document.getElementById(e);if(!(n instanceof t))throw Error(`#${e} is missing from the page`);return n},_=(e,t,n)=>{let r=e.querySelector(t);r.textContent!==n&&(r.textContent=n)},v=(e,t)=>{if(e.dataset.mark===t)return;let n=e.dataset.mark!==void 0;e.dataset.mark=t,n&&(e.classList.remove(`flash`),e.offsetWidth,e.classList.add(`flash`))},y=(e,t)=>e?e.replace(/^tool:/,`using `):p[t],b=(e,t)=>{e.toggleAttribute(`hidden`,!t),t&&(e.setAttribute(`href`,l(t)||`./`),e.setAttribute(`data-route`,l(t)))},x=`<div class="plate"><i class="ring"></i><svg><use href="#i-main"/></svg><b class="badge"></b></div>`;function S(e,t,n){v(e,n);let r=e.querySelector(`use`),i=`#i-${f[t]??`member`}`;r.getAttribute(`href`)!==i&&r.setAttribute(`href`,i)}function C(e,t,n,r){let i=new Map;for(let t of e.children)!t.classList.contains(`leaving`)&&t.dataset.key&&i.set(t.dataset.key,t);let a=e.firstElementChild;for(let o of t){let t=i.get(o.id);for(t||(t=n(o),t.dataset.key=o.id,t.classList.add(`enter`),setTimeout(()=>t.classList.remove(`enter`),600)),i.delete(o.id);a?.classList.contains(`leaving`);)a=a.nextElementSibling;t===a?a=a.nextElementSibling:e.insertBefore(t,a),r(t,o)}for(let e of i.values())e.classList.add(`leaving`),setTimeout(()=>e.remove(),400)}var w=()=>h(`<div class="unit"><div class="card"><a class="hit"></a>${x}<div class="meta"><span class="name"></span><span class="line"><em class="role"></em><span class="note"></span></span></div></div><div class="subs"></div></div>`);function T(e,t){let n=e.closest(`.base`)?.dataset.key,r=e.querySelector(`.hit`);b(r,t.key&&n?{view:`session`,ws:n,key:t.key}:void 0),r.setAttribute(`aria-label`,`${t.name}: ${y(t.note,t.mark)}`),r.toggleAttribute(`data-alert`,m(t.mark)),v(e,t.mark),S(e.querySelector(`.plate`),t.role,t.mark),_(e,`.name`,t.name),_(e,`.role`,t.role),_(e,`.note`,y(t.note,t.mark)),C(e.querySelector(`.subs`),t.subs??[],w,T)}var te=()=>h(`<section class="base"><header><div class="tower"><i class="sweep"></i><i class="pulse"></i><svg><use href="#i-tower"/></svg><b class="badge"></b></div><div class="title"><span class="crown"><svg><use href="#i-crown"/></svg>head tower</span><h2><a class="enter-base"></a></h2><p></p></div></header><div class="tabs"></div><div class="outposts"></div></section>`);function ne(e,t){v(e,t.mark),e.classList.toggle(`head`,t.head);let n=e.querySelector(`.tower`);n.classList.toggle(`ghost`,!t.tower),v(n,t.tower?.mark??`unknown`),_(e,`h2 a`,t.label),b(e.querySelector(`h2 a`),{view:`workspace`,ws:t.id}),_(e,`.title p`,t.tower?`control tower · ${p[t.tower.mark]}`:`no tower yet`),C(e.querySelector(`.tabs`),t.tabs,()=>h(`<div class="tab"><h3></h3><div class="units"></div></div>`),(e,t)=>{_(e,`h3`,`tab ${t.label}`),C(e.querySelector(`.units`),t.units,w,T)}),C(e.querySelector(`.outposts`),t.outposts.map(e=>({id:e.id,name:e.label,role:`outpost`,mark:e.mark,note:e.mark===`unknown`?`no agent running`:void 0})),w,T)}function re(e,t,n){let r=[...e.querySelectorAll(`.base:not(.leaving) .tower`)],i=e.querySelector(`.base.head:not(.leaving) .tower`),a=e.getBoundingClientRect(),o=e=>{let t=e.getBoundingClientRect();return[Math.round(t.x+t.width/2-a.x),Math.round(t.y+t.height/2-a.y)]},s=i?r.filter(e=>e!==i).map(e=>{let[[t,n],[r,a]]=[o(i),o(e)],s=Math.round((t+r)/2);return`M${t} ${n}C${s} ${n} ${s} ${a} ${r} ${a}`}):[],c=s.join(`|`);if(t.dataset.sig===c)return;t.dataset.sig=c;let l=(e,t,...n)=>{let r=document.createElementNS(`http://www.w3.org/2000/svg`,e);for(let[e,n]of Object.entries(t))r.setAttribute(e,n);return r.append(...n),r};t.replaceChildren(...s.flatMap(e=>[l(`path`,{class:`wire`,d:e}),...n?[]:[l(`circle`,{class:`packet`,r:`3`},l(`animateMotion`,{dur:`5s`,repeatCount:`indefinite`,path:e}))]]))}function ie(){let[e,t,n,r]=[g(`map`,HTMLElement),g(`bases`,HTMLElement),g(`links`,SVGSVGElement),g(`log`,HTMLElement)],i=matchMedia(`(prefers-reduced-motion: reduce)`).matches,a=()=>!e.hidden&&re(e,n,i);return new ResizeObserver(a).observe(e),{layout:a,stats(e){let t=e.bases.flatMap(e=>e.tabs.flatMap(e=>e.units.flatMap(e=>[e,...e.subs]))),n=e=>String(t.filter(t=>!e||t.mark===e).length);for(let[t,r]of[[`s-bases`,String(e.bases.length)],[`s-agents`,n()],[`s-working`,n(`working`)],[`s-waiting`,n(`waiting`)]])g(t,HTMLElement).textContent=r},show(e){C(t,e.bases,te,ne),g(`empty`,HTMLElement).hidden=e.bases.length>0,requestAnimationFrame(a)},log(e){let t=new Date().toLocaleTimeString([],{hour12:!1});for(let n of e){let e=h(`<li><span></span><time></time></li>`);e.dataset.mark=n.mark,_(e,`span`,n.text),_(e,`time`,t),r.prepend(e)}for(;r.children.length>12;)r.lastElementChild.remove()},pause(e){document.documentElement.classList.toggle(`paused`,e)},still(e){e?n.pauseAnimations():n.unpauseAnimations()}}}var E=45e3,ae=1e3,oe=3e4,se=(e,t)=>Math.min(oe,ae*2**(e-1))*(.8+.4*t);function D(e){try{return JSON.parse(e)}catch{return}}function ce(e){let t,n,r,i=0,a={state:`connecting`,attempt:0},o=t=>e.onStatus(a={...a,...t}),s=()=>(e.clearTimeout(n),e.clearTimeout(r),n=r=void 0),c=()=>{let e=t;t=void 0,e?.close()},l=()=>{e.clearTimeout(r),r=e.setTimeout(()=>u(),E),o({state:`live`,attempt:0,lastContact:e.now()})},u=()=>{c(),s();let t=a.attempt+1;if(t>8)return o({state:`offline`,attempt:t});o({state:`reconnecting`,attempt:t}),e.hidden()||(n=e.setTimeout(d,se(t,e.random())))},d=()=>{c(),s(),i=e.now();let n=t=e.open();n.onError(()=>t===n&&u()),n.listen(`message`,r=>{if(t!==n)return;let i=D(r);i&&e.onNet(i),o({problem:i?void 0:`the server sent a snapshot the page cannot read`}),l()}),n.listen(`ping`,()=>t===n&&l()),n.listen(`problem`,e=>{t===n&&(o({problem:D(e)??`the server reported a problem the page cannot read`}),l())}),r=e.setTimeout(()=>u(),E)};return{start(){o({state:`connecting`,attempt:0}),d()},resume(){let n=e.now()-i<2e3||a.lastContact!==void 0&&e.now()-a.lastContact<=2e4;t&&n||(o({attempt:0,state:a.state===`live`?`reconnecting`:a.state}),d())},restart:d,hide(){e.clearTimeout(n),n=void 0},stop(){c(),s()}}}var le=(function(){let e=typeof document<`u`&&document.createElement(`link`).relList;return e&&e.supports&&e.supports(`modulepreload`)?`modulepreload`:`preload`})(),ue=function(e,t){return new URL(e,t).href},de={},fe=function(e){return e.pathname.endsWith(`.css`)},pe=function(e,t,n){if(t in e)return e[t];let r=n();if(!r){e[t]=void 0;return}let i=r.then(()=>{e[t]=void 0},n=>{throw e[t]=void 0,n});return e[t]=i,i},O=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e,i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function s(e){return import.meta.resolve?new URL(import.meta.resolve(e)):new URL(e,import.meta.url)}r=o(t.map(t=>{t=ue(t,n);let r=s(t),i=fe(r);return pe(de,r.href,()=>{if(e===void 0){e={all:new Set,styles:new Set};let t=document.getElementsByTagName(`link`);for(let n=t.length-1;n>=0;n--){let r=t[n];e.all.add(r.href),r.rel===`stylesheet`&&e.styles.add(r.href)}}if((i?e.styles:e.all).has(r.href))return;let t=document.createElement(`link`);if(t.rel=i?`stylesheet`:le,i||(t.as=`script`),t.crossOrigin=``,t.href=r.href,a&&t.setAttribute(`nonce`,a),document.head.appendChild(t),i)return new Promise((e,n)=>{t.addEventListener(`load`,e),t.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${r}`)))})})}).filter(e=>e!==void 0))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},k=ie(),A=e=>document.getElementById(e),me=e=>e?new Date(e).toLocaleTimeString([],{hour12:!1}):`never`,j,M,N,P,F={state:`connecting`,attempt:0},I={view:`map`},L=!1,R,z,he,B=e=>z?e(z):void he?.then(e);function ge(){he??=O(async()=>{let{mountFocus:e}=await import(`./views-U9D50TDD.js`);return{mountFocus:e}},[],import.meta.url).then(({mountFocus:e})=>(z=e({data:ve,restart:()=>Q.restart(),openTile:W,online:()=>F.state===`live`}),z.show(I,I),N&&z.net(N),z))}var V,H,U=e=>{if(V)return e(V);H??=O(async()=>{let{mountPanels:e}=await import(`./layer-DhF1EBxx.js`);return{mountPanels:e}},[],import.meta.url).then(({mountPanels:e})=>V=e({label:e=>N?.bases.find(t=>t.id===e)?.label??e,recent:async e=>(await(Z?Z.data(e).latest():X(e,`?limit=12`))).items,post:e=>Z&&((t,n)=>Z.data(e).post(t,n))})),H.then(e)},W=(e,t)=>U(n=>n.tiles.open(e,t));function G(e){if(N=P=e,document.hidden)return;k.stats(e);let t=i(e,Date.now()),r=a(R,t);(r.length||V)&&U(e=>e.alerts(r,t)),R=t,k.log(n(M,e)),M=e,B(t=>t.net(e)),I.view===`map`&&(k.show(e),j=e,P=void 0)}function K(e){let t=I,n=e.view===`workspace`&&t.view===`map`?document.querySelector(`#bases [data-key="${CSS.escape(e.ws)}"]`)?.getBoundingClientRect():void 0;I=e,e.view!==`map`&&ge(),A(`map`).hidden=e.view!==`map`,A(`legend`).hidden=e.view===`session`,k.still(e.view!==`map`),B(r=>r.show(e,t,n)),e.view===`map`&&N&&N!==j&&(G(N),requestAnimationFrame(k.layout)),L&&d(e)!==d(t)&&Q.restart()}function q(e){F=e;let t=e.state===`reconnecting`||e.state===`offline`;document.body.dataset.stale=A(`stage`).dataset.stale=String(t),A(`link`).dataset.state=e.state,A(`link-text`).textContent={connecting:`connecting`,live:`live`,reconnecting:`reconnecting`,offline:`offline`}[e.state],z&&N&&z.net(N),V?.stack.redraw();let n=A(`banner`);n.hidden=!t&&!e.problem;let r=e.state===`offline`?`Disconnected. Gave up after ${e.attempt-1} tries; it reconnects when you return to this tab.`:e.state===`reconnecting`?`Disconnected from the straw net. Reconnecting${e.attempt?` (try ${e.attempt})`:``}… The view shows the last known state.`:`The server is up but cannot read the net: ${e.problem}`,i=document.createElement(`b`);i.textContent=me(e.lastContact),n.replaceChildren(`${r} Last update `,i,`.`)}function J(e,t){try{let n=JSON.parse(t);B(t=>e===`history`?t.history(n):t.cards(n))}catch{}}function _e(e){let t=new EventSource(e?`events?watch=${encodeURIComponent(e)}`:`events`);return{onError:e=>t.onerror=e,listen:(e,n)=>t.addEventListener(e,e=>n(e.data)),close:()=>t.close()}}var Y=e=>fetch(`api/${e}`,{cache:`no-store`}).then(e=>e.ok?e.json():Promise.reject(Error(String(e.status)))),X=(e,t=``)=>Y(`history/${encodeURIComponent(e)}${t}`),Z=void 0,ve=e=>({older:t=>X(e,`?before=${encodeURIComponent(t)}`),latest:()=>X(e),entry:t=>Y(`entry/${encodeURIComponent(e)}/${encodeURIComponent(t)}`).catch(()=>void 0)}),ye=()=>{let e=_e(d(I));return e.listen(`history`,e=>J(`history`,e)),e.listen(`cards`,e=>J(`cards`,e)),e};document.addEventListener(`click`,e=>{let t=e.target?.closest?.(`a[data-alert]`),n=t&&c(t.getAttribute(`data-route`)??``);if(!n||n.view!==`session`||e.button!==0||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;let r=R?.get(n.key);r&&(e.preventDefault(),U(e=>e.stack.show(r)))},!0);var be=ee(e=>K(e)),Q=ce({open:ye,now:Date.now,setTimeout:(e,t)=>window.setTimeout(e,t),clearTimeout:e=>window.clearTimeout(e),random:Math.random,hidden:()=>document.hidden,onNet:G,onStatus:q}),$=()=>Q.resume();document.addEventListener(`visibilitychange`,()=>{if(k.pause(document.hidden),document.hidden)return Q.hide();P&&G(P),B(e=>e.wake()),$()}),addEventListener(`keydown`,e=>{e.key!==`Escape`||e.defaultPrevented||(e.preventDefault(),!V?.stack.close()&&I.view!==`map`&&be.go(u(I)))}),A(`pair`).addEventListener(`click`,()=>void O(async()=>{let{pairTile:e}=await import(`./pair-DDTg3MTR.js`);return{pairTile:e}},[],import.meta.url).then(({pairTile:e})=>W(e(),!0)));for(let e of[`focus`,`pageshow`,`online`])window.addEventListener(e,()=>!document.hidden&&$());q(F),K(be.route()),Q.start(),L=!0;export{b as a,S as c,C as d,_ as f,x as i,h as l,r as m,f as n,g as o,m as p,p as r,y as s,O as t,v as u};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
:root{--bg:#060a14;--panel:#0e1628e0;--line:#7a98e033;--text:#dbe6ff;--dim:#8b99ba;--gold:#ffd166;--grid:linear-gradient(#82a0ff0d 1px, transparent 1px) 0 0 / 44px 44px, linear-gradient(90deg, #82a0ff0d 1px, transparent 1px) 0 0 / 44px 44px;--mono:ui-monospace, "SF Mono", Menlo, Consolas, monospace;--sans:ui-rounded, "Avenir Next", "Trebuchet MS", system-ui, -apple-system, "Segoe UI", sans-serif}*{box-sizing:border-box;margin:0}html{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark}body{min-height:100vh;color:var(--text);font:14px/1.4 var(--sans);background:radial-gradient(1100px 640px at 12% -10%, #38e0ff1c, transparent 62%), radial-gradient(900px 600px at 98% 8%, #966eff1c, transparent 60%), linear-gradient(var(--bg), #0a1020);background-attachment:fixed}svg{display:block}[data-mark=working]{--c:#38e0ff}[data-mark=waiting]{--c:#ffb02e}[data-mark=idle]{--c:#7184ad}[data-mark=done]{--c:#3ddc97}[data-mark=error]{--c:#ff5470}[data-mark=unknown]{--c:#4f5c7c}[data-mark]{--c1:color-mix(in srgb, var(--c) 13%, transparent);--c4:color-mix(in srgb, var(--c) 45%, transparent)}:focus-visible{outline-offset:2px;outline:2px solid #38e0ff}.shell{max-width:1480px;margin:0 auto;padding:18px 22px 40px}.hud{border:1px solid var(--line);background:var(--panel);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);z-index:5;border-radius:18px;align-items:center;gap:24px;padding:12px 18px;display:flex;position:sticky;top:12px}.brand{align-items:center;gap:12px;margin-right:auto;display:flex}.logo{color:#38e0ff;border:1px solid var(--line);background:radial-gradient(circle at 30% 25%,#38e0ff4d,#0a1020e6);border-radius:14px;place-items:center;width:44px;height:44px;display:grid}.logo svg{filter:drop-shadow(0 0 6px #38e0ff);width:28px;height:28px}.brand h1{letter-spacing:.14em;text-transform:uppercase;font-size:20px}.brand p{color:var(--dim);font-size:12px}.stats{gap:10px;display:flex}.stats div,.tally div,.alerts{background:#ffffff0a;border:1px solid #ffffff0f;border-radius:12px;min-width:78px;padding:6px 12px}.stats dt,.tally dt{color:var(--dim);letter-spacing:.08em;text-transform:uppercase;font-size:11px}.stats dd,.tally dd{font:600 20px/1.1 var(--mono)}.stats [data-mark] dd,.tally [data-mark] dd,.count b{color:var(--c)}.pair-btn{border:1px solid var(--line);color:var(--dim);font:600 12px var(--sans);letter-spacing:.08em;text-transform:uppercase;cursor:pointer;background:0 0;border-radius:12px;padding:6px 12px}.pair{text-align:center;color:var(--dim);justify-items:center;gap:12px;font-size:13px;display:grid}.qr{shape-rendering:crispedges;border-radius:12px;width:min(100%,300px)}.link{color:var(--dim);text-transform:uppercase;letter-spacing:.08em;align-items:center;gap:8px;font-size:12px;display:flex}.link i{background:#4f5c7c;border-radius:50%;width:9px;height:9px}.link[data-state=live] i{background:#3ddc97;animation:2.4s ease-in-out infinite blink}.link[data-state=live]{color:#3ddc97}.link[data-state=reconnecting] i,.link[data-state=connecting] i{background:#ffb02e;animation:1s ease-in-out infinite blink}.link[data-state=offline] i{background:#ff5470}.banner{color:#c9d6f5;background:#7184ad29;border-radius:14px;margin:14px 0 0;padding:10px 16px;font-size:13px}.banner[hidden]{display:none}.banner b{font-family:var(--mono);font-weight:600}.stage{grid-template-columns:minmax(0,1fr) 300px;align-items:start;gap:20px;margin-top:18px;transition:opacity .4s;display:grid}.stage[data-stale=true] .map,body[data-stale=true] .stats{opacity:.4}.stage[data-stale=true] *{animation-play-state:paused!important}.map{border:1px solid var(--line);background:var(--grid), #080d1a8c;border-radius:22px;min-height:420px;padding:26px;transition:opacity .4s;position:relative}.links{pointer-events:none;width:100%;height:100%;position:absolute;inset:0}.wire{fill:none;stroke:#38e0ff4d;stroke-width:1.5px;stroke-dasharray:3 7;stroke-linecap:round}.packet{fill:#38e0ff;opacity:.9}.bases{grid-template-columns:repeat(auto-fill,minmax(min(100%,300px),1fr));align-items:start;gap:30px;display:grid;position:relative}.empty{color:var(--dim);text-align:center;padding:120px 0;position:relative}.base{border:1px solid var(--line);background:linear-gradient(#16213c,#0c1324);border-radius:18px;padding:16px;position:relative;box-shadow:0 18px 40px #00000059}.base.head{background:linear-gradient(#ffd1661a,#0000 38%),linear-gradient(#16213c,#0c1324)}.base[data-mark=waiting]{box-shadow:0 18px 40px #00000059,inset 0 0 0 999px #ffb02e0b}.base>header{align-items:center;gap:14px;margin-bottom:14px;display:flex}.title{justify-items:start;min-width:0;margin-right:auto;display:grid}.title h2{white-space:nowrap;text-overflow:ellipsis;max-width:100%;font-size:17px;overflow:hidden}.title p{max-width:100%;color:var(--dim);white-space:nowrap;text-overflow:ellipsis;font-size:12px;overflow:hidden}.crown{letter-spacing:.12em;text-transform:uppercase;color:var(--gold);background:#ffd1661f;border-radius:999px;align-items:center;gap:5px;margin-bottom:3px;padding:2px 9px 2px 6px;font-size:10px;display:inline-flex}.crown svg{width:14px;height:14px}.base:not(.head) .crown{display:none}.tower{width:80px;height:80px;color:var(--c);flex:none;place-items:center;display:grid;position:relative}.tower:before{content:"";background:radial-gradient(circle at 35% 30%, color-mix(in srgb, var(--c) 24%, #101a2e), #0b1222 70%);border:1px solid color-mix(in srgb, var(--c) 45%, transparent);border-radius:50%;position:absolute;inset:0}.tower svg{width:48px;height:48px;filter:drop-shadow(0 0 6px color-mix(in srgb, var(--c) 70%, transparent));position:relative}.tower.ghost{opacity:.45}.tower.ghost:before{border-style:dashed}.sweep,.pulse{opacity:0;pointer-events:none;border-radius:50%;position:absolute;inset:0}.sweep{background:conic-gradient(from 0deg, transparent 0 70%, color-mix(in srgb, var(--c) 55%, transparent) 100%)}.pulse{border:2px solid var(--c)}.tower[data-mark=working] .sweep{opacity:1;animation:3.2s linear infinite spin}.tower[data-mark=waiting] .pulse{animation:1.5s ease-out infinite ping}.tower>.badge{--s:40px;position:absolute;bottom:-2px;right:-2px}.tabs{gap:12px;display:grid}.tab{background:#ffffff06;border:1px solid #ffffff0d;border-radius:14px;padding:10px}.tab h3{color:var(--dim);letter-spacing:.12em;text-transform:uppercase;margin-bottom:8px;font-size:11px;font-weight:600}.units,.subs{gap:8px;display:grid}.outposts{gap:8px;margin-top:12px;display:grid}.outposts:empty{display:none}.outposts:before{content:"Outposts";color:var(--dim);letter-spacing:.12em;text-transform:uppercase;font-size:11px}.card{background:#ffffff09;border:1px solid #ffffff0f;border-radius:12px;align-items:center;gap:10px;padding:8px 10px;transition:background-color .4s;display:flex;position:relative}.unit[data-mark=waiting]>.card{background:#ffb02e1c}.unit[data-mark=error]>.card{background:#ff54701c}.unit[data-mark=working]>.card{background:#38e0ff12}.plate{width:var(--s,40px);height:var(--s,40px);color:var(--c);background:radial-gradient(circle at 35% 30%, color-mix(in srgb, var(--c) 26%, #101a2e), #0b1222 72%);border-radius:50%;flex:none;place-items:center;transition:color .4s;display:grid;position:relative}.plate svg{width:calc(var(--s,40px) * .55);height:calc(var(--s,40px) * .55)}.ring,.plate:after{pointer-events:none;border-radius:50%;position:absolute;inset:-3px}.ring{opacity:0;background:conic-gradient(from 0deg, transparent 0 55%, var(--c));-webkit-mask:radial-gradient(farthest-side,#0000 calc(100% - 3px),#000 calc(100% - 2px));mask:radial-gradient(farthest-side,#0000 calc(100% - 3px),#000 calc(100% - 2px))}.plate[data-mark=working]>.ring{opacity:1;animation:1.1s linear infinite spin}.plate:after{content:"";border:2px solid var(--c);opacity:0}.plate[data-mark=waiting]:after{animation:1.5s ease-out infinite ping}.badge{width:clamp(16px, calc(var(--s,40px) * .3), 24px);height:clamp(16px, calc(var(--s,40px) * .3), 24px);font:700 10px/1 var(--mono);color:#06101e;background:var(--c);border-radius:50%;flex:none;place-items:center;transition:background-color .4s;display:grid}.plate>.badge{position:absolute;bottom:-4px;right:-4px}[data-mark=waiting]>.badge:after{content:"?"}[data-mark=idle]>.badge:after{content:"z"}[data-mark=done]>.badge:after{content:"✓"}[data-mark=error]>.badge:after{content:"!"}[data-mark=unknown]>.badge:after{content:"·"}[data-mark=working]>.badge:after{content:"";border:2px solid #06101e;border-right-color:#0000;border-radius:50%;width:8px;height:8px;animation:.8s linear infinite spin}[data-mark=waiting]>.badge{animation:1.2s ease-in-out infinite hop}.meta{min-width:0;display:grid}.name{white-space:nowrap;text-overflow:ellipsis;font-weight:600;overflow:hidden}.line{color:var(--dim);align-items:baseline;gap:8px;min-width:0;font-size:12px;display:flex}.role{letter-spacing:.1em;text-transform:uppercase;color:color-mix(in srgb, var(--c) 70%, var(--dim));font-size:10px;font-style:normal}.note{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.unit[data-mark=idle]>.card{opacity:.85}.subs{margin:6px 0 0 22px;padding-left:18px;position:relative}.subs:empty{display:none}.subs:before{content:"";background:repeating-linear-gradient(#7a98e080 0 4px,#0000 4px 8px);width:1px;position:absolute;top:-4px;bottom:22px;left:3px}.subs>.unit>.card:before{content:"";background:repeating-linear-gradient(90deg,#7a98e080 0 4px,#0000 4px 8px);width:15px;height:1px;position:absolute;top:50%;left:-15px}.subs>.unit{position:relative}.subs .plate{--s:30px}.subs .name{font-size:13px}.side{gap:16px;display:grid;position:sticky;top:96px}.panel{border:1px solid var(--line);background:var(--panel);border-radius:18px;padding:14px 16px}.panel h2{color:var(--dim);letter-spacing:.14em;text-transform:uppercase;margin-bottom:10px;font-size:11px}.net-log summary{cursor:pointer;justify-content:space-between;align-items:center;list-style:none;display:flex}.net-log summary::-webkit-details-marker{display:none}.net-log summary:after{content:"▾";color:var(--dim);transition:transform .2s}.net-log:not([open]) summary:after{transform:rotate(-90deg)}.net-log:not([open]) h2{margin-bottom:0}.log{gap:7px;max-height:360px;padding:0;list-style:none;display:grid;overflow:hidden}.log:empty:before{content:"Waiting for changes…";color:var(--dim);font-size:12px}.log li{grid-template-columns:auto 1fr;gap:2px 8px;font-size:12px;animation:.4s ease-out both slide;display:grid}.log li:before{content:"";background:var(--c);border-radius:50%;width:8px;height:8px;margin-top:5px}.log time{font:11px var(--mono);color:var(--dim);grid-column:2}.credit{color:var(--dim);padding:0 6px;font-size:11px}.legend{gap:8px;padding:0;font-size:12px;list-style:none;display:grid}.legend li{align-items:center;gap:9px;display:flex}.enter{animation:.5s cubic-bezier(.2,.9,.3,1.15) both pop}.leaving{pointer-events:none;animation:.35s ease-in both out}.flash>.card>.plate,.flash.tower{animation:.6s ease-out flash}@keyframes spin{to{transform:rotate(360deg)}}@keyframes ping{0%{opacity:.6;transform:scale(1)}to{opacity:0;transform:scale(1.7)}}@keyframes hop{50%{transform:translateY(-3px)}}@keyframes blink{50%{opacity:.35}}@keyframes pop{0%{opacity:0;transform:scale(.92)translateY(8px)}}@keyframes out{to{opacity:0;transform:scale(.94)}}@keyframes flash{40%{transform:scale(1.12)}}@keyframes slide{0%{opacity:0;transform:translate(10px)}}@keyframes zoom{0%{opacity:0;transform:scale(.45)}}[hidden]{display:none!important}a{color:inherit}.crumbs,.tally dt,.comms-head small,.tx.you>header,.notice em,.rule summary,.dossier-in>.tag,.d-drones h4,.specs dt,.stop,.dialog .tag,.intel h4,.pending b{color:var(--dim);letter-spacing:.14em;text-transform:uppercase;font-size:11px;font-style:normal}.token .name,.drone .note,.count small,.sum,.where,.tile b{white-space:nowrap;text-overflow:ellipsis;max-width:100%;overflow:hidden}.md a,.bubble a,.notice a,.d-note a,.specs a,.crumbs a{color:#38e0ff}.crumbs{gap:10px;margin:14px 6px 0;display:flex}.crumbs>*+:before{content:"›";opacity:.5;margin-right:10px}.crumbs a,.brand{text-decoration:none}.work{align-items:flex-start;gap:20px;min-width:0;display:flex}.view{flex:1 1 0;min-width:0}body[data-stale=true] .work{opacity:.45}.enter-zoom{transform-origin:var(--ox,50%) var(--oy,0);animation:.5s ease-out both zoom}.enter-slide,.dossier{animation:.4s ease-out both slide}.enter-back{animation:.4s ease-out both pop}.hit,.enter-base:after{z-index:1;border-radius:inherit;position:absolute;inset:0}.enter-base:after{content:"";z-index:0}.hit:hover{box-shadow:inset 0 0 0 1px var(--c)}.base>header{position:relative}.enter-base{text-decoration:none}.base>header:hover h2{color:#38e0ff}.alerts{width:230px;color:inherit;font:inherit;text-align:left;cursor:pointer;align-items:center;gap:10px;display:flex;position:relative}.alerts:disabled{cursor:default;opacity:.6}.alerts:not(:disabled){border-color:var(--c4);background:var(--c1)}.faces{flex:none;padding-left:10px;display:flex}.faces .plate{--s:28px;margin-left:-10px;box-shadow:0 0 0 2px #0e1628}.faces .badge{display:none}.count{min-width:0;display:grid}.count b{font:600 18px/1.1 var(--mono)}.count small,.comms-head p,.cmp-note,.where,.queued,.d-line,.who p{color:var(--dim);font-size:12px}.token{border:1px solid #0000;border-radius:16px;justify-items:center;gap:3px;width:100%;padding:10px 8px 9px;text-decoration:none;display:grid;position:relative}a.token:hover{border-color:var(--c4)}.token[data-mark=waiting]{background:#ffb02e1c}.token[data-mark=error]{background:#ff54701c}.token .plate{--s:64px;margin-bottom:4px}.token .name{font-weight:600}.token .line{justify-items:center;max-width:100%;display:grid}.drone{width:94px;padding:6px;font-size:12px}.drone .plate{--s:44px}.drone .role{display:none}.flash.token>.plate{animation:.6s ease-out flash}.zoom-in,.comms-in{border:1px solid var(--line);background:var(--grid), #080d1a8c;border-radius:22px;position:relative}.zoom-in{min-height:420px;padding:24px}.zoom-in.void>:not(.lost){display:none}.lost,.chat-empty{color:var(--dim);text-align:center;padding:60px 0}.keep{align-items:center;gap:20px;padding:18px 22px;display:flex}.keep h2{font-size:24px}.tower.big{width:120px;height:120px}.tower.big svg{width:72px;height:72px}.tower.big>.badge{--s:96px;bottom:4px;right:4px}a.tower:hover:before{border-color:var(--c)}.tally{gap:10px;display:flex}.squads,.camps{grid-template-columns:repeat(auto-fit,minmax(min(100%,430px),1fr));align-items:start;gap:18px;margin-top:20px;display:grid}.squad{background:#0c1324c7;padding:14px 16px 18px}.squad[data-mark=waiting]{background:#262121d9}.squad h3{align-items:center;gap:10px;margin-bottom:14px;display:flex}.squad h3 b,.crumbs b{color:var(--text)}.squad h3 small{margin-left:auto}.squad h3 svg{width:18px;height:18px}.flag{background:var(--c);width:10px;height:10px;box-shadow:0 0 8px var(--c);border-radius:2px;transform:rotate(45deg)}.formation{flex-wrap:wrap;align-items:flex-start;gap:16px 20px;display:flex}.col{justify-items:center;gap:8px;width:196px;display:grid}.say{width:100%;color:var(--dim);background:#111a2f;border-radius:12px;margin-top:4px;padding:7px 10px;font-size:12px;line-height:1.35}.say p{overflow-wrap:anywhere;max-height:4.05em;overflow:hidden}.drones{flex-wrap:wrap;justify-content:center;gap:8px;width:100%;padding-top:16px;display:flex;position:relative}.drones:empty{display:none}.drones:before{content:"";background:repeating-linear-gradient(#7a98e099 0 4px,#0000 4px 8px);width:1px;height:14px;position:absolute;top:0;left:50%}.camp .token{width:156px}[data-group=outside] .plate{filter:saturate(.3);outline-offset:4px;outline:1px dashed #8b99ba8c}.comms-in,.tile{height:calc(var(--vvh,100vh) - 190px);grid-template-rows:auto minmax(0,1fr) auto;min-height:380px;display:grid;overflow:hidden}.comms-head,.tile>header{background:var(--panel);align-items:center;gap:12px;padding:12px 18px;display:flex}.ava{color:#38e0ff;background:radial-gradient(circle at 35% 30%,#38e0ff47,#0b1222 72%);border-radius:50%;flex:none;place-items:center;width:30px;height:30px;display:grid}.ava svg{width:58%;height:58%}.comms-head h2{font-size:16px}.chan{margin-left:auto}.chat-root{min-height:0;display:grid;position:relative}.chat-scroll{overflow-anchor:none;padding:16px 20px;overflow-y:auto}.chat-list{gap:14px;display:grid}.chat-top{height:1px}.chat-live{color:var(--c);align-items:center;gap:10px;margin-top:14px;padding-left:44px;font-size:12px;display:flex}.chat-pill{--c:#38e0ff;border:0;position:absolute;bottom:14px;left:50%;transform:translate(-50%)}.lit:after{content:"";background:#38e0ff2e;border-radius:14px;animation:1s 1s forwards out;position:absolute;inset:0}.composer{border-top:1px solid var(--line);background:var(--panel);gap:8px;padding:12px 18px 14px;display:grid}.cmp-row,.cmp-acts,.cmp-foot,.cmp-note{align-items:center;gap:8px;display:flex}.cmp-row{align-items:flex-end;gap:10px}.composer textarea{resize:none;border:1px solid var(--line);min-width:0;color:var(--text);font:14px/1.4 var(--sans);background:#070c18;border-radius:12px;flex:1;padding:9px 12px}.composer textarea:focus{border-color:#38e0ff80;outline:none;box-shadow:0 0 0 3px #38e0ff1f}.composer button:disabled{opacity:.45;cursor:default}.cmp-note{flex-wrap:wrap;flex:1;min-height:18px}.cmp-note[data-tone=error],.cmp-alt.cmp-stop{color:#ff8a9c}.cmp-note[data-tone=ok]{color:#3ddc97}.cmp-note[data-tone=ask]{color:var(--gold)}.cmp-link{color:#38e0ff;font:12px var(--sans);cursor:pointer;background:0 0;border:0;padding:0}.cmp-yes{background:var(--gold);color:#06101e;font:600 12px var(--sans);cursor:pointer;border:0;border-radius:8px;padding:3px 10px}.tx{content-visibility:auto;contain-intrinsic-size:auto 90px;min-width:0}.tx time,.tx.note{color:var(--dim);font:11px var(--mono)}.tx.you{justify-items:end;gap:5px;display:grid}.tx.you>header{color:var(--gold);align-items:center;gap:8px;display:flex}.tx.you .ava{color:var(--gold)}.bubble{white-space:pre-wrap;overflow-wrap:anywhere;background:#ffd16614;border:1px solid #ffd16638;border-radius:14px;max-width:80%;padding:9px 13px}.tx.in{grid-template-columns:34px minmax(0,1fr);align-items:start;gap:10px;display:grid}.tx-body{border:1px solid var(--line);background:#0e1628d9;border-radius:14px;gap:8px;padding:10px 14px;display:grid}.tx-body,.tx-body>*{min-width:0}.tx-body>header{color:var(--dim);font:11px var(--mono);align-items:baseline;gap:10px;display:flex}.tx-body>header b{color:#38e0ff;font:600 13px var(--sans)}.stop,.dialog .tag{background:var(--c1);color:var(--c);border-radius:999px;padding:1px 8px;font-size:10px}.fault{color:#ff8a9c;font-size:13px}.thought,.more,.tab-btn{border:1px solid var(--line);color:var(--dim);font:11px var(--sans);cursor:pointer;background:0 0;border-radius:999px;justify-self:start;padding:2px 10px}.thought-text:empty{display:none}.thought-text,.out,.args,.notice pre,.rule pre{white-space:pre-wrap;overflow-wrap:anywhere;color:var(--dim);font:12px/1.4 var(--mono)}.act,.notice{background:#ffffff08;border:1px solid #ffffff12;border-radius:10px}.act>summary,.notice>summary,.rule summary{cursor:pointer;align-items:center;gap:9px;min-width:0;padding:6px 10px;font-size:12.5px;list-style:none;display:flex}summary::-webkit-details-marker{display:none}.act code{color:var(--c);font:600 11px var(--mono);letter-spacing:.06em;text-transform:uppercase}.sum{min-width:0;color:var(--dim)}.act[open] .sum{white-space:normal}.open{flex:none;margin-left:auto}.act>pre,.result{margin:0 10px 8px}.result{gap:6px;display:grid}.tx.sys{padding-left:44px}.notice{background:#966eff12;border-color:#966eff33}.notice .ava{width:22px;height:22px}.notice pre,.rule pre{padding:0 10px 8px}.rule summary{justify-content:center}.rule summary:before,.rule summary:after{content:"";background:var(--line);flex:1;height:1px}.tx.note{text-align:center}.dossier-in{text-align:center;justify-items:center;gap:6px;display:grid}.dossier-in>.tag{text-align:left;justify-self:stretch}.portrait{background:radial-gradient(var(--c1), transparent 70%);border-radius:50%;padding:8px}.portrait .plate{--s:96px}.dossier-in h3{overflow-wrap:anywhere;margin-top:4px;font-size:18px}.d-line,.who p{align-items:baseline;gap:8px;display:flex}.d-note{background:#ffb02e1f;border-radius:10px;padding:8px 10px;font-size:12px}.specs{text-align:left;justify-self:stretch;gap:2px;margin-top:10px;display:grid}.specs div{background:#ffffff09;grid-template-columns:76px minmax(0,1fr);gap:8px;padding:7px 10px;display:grid}.specs dt{font-size:10px}.specs dd{overflow-wrap:anywhere;font-size:12.5px}.d-drones{margin-top:8px}.d-drones .formation{justify-content:center;gap:6px}.md{overflow-wrap:anywhere;line-height:1.5}.md p,.md ul,.md ol,.md pre,.md table,.md blockquote{margin:0 0 10px}.md>:last-child{margin-bottom:0}.md :is(h1,h2,h3,h4,h5,h6){margin:14px 0 6px;font-size:15px}.md>:first-child{margin-top:0}.md h1{font-size:19px}.md ul,.md ol{padding-left:22px}.md li>p{margin:0}.md li.task{margin-left:-18px;list-style:none}.check{vertical-align:-2px;text-align:center;width:14px;height:14px;font:700 10px/12px var(--mono);border:1px solid;border-radius:4px;margin-right:7px;display:inline-block}.check[data-done=true]{color:#06101e;background:#3ddc97}.md code{font:12.5px var(--mono);background:#ffffff14;border-radius:5px;padding:1px 5px}.md pre{border:1px solid var(--line);background:#070c18;border-radius:10px;padding:10px 12px;overflow-x:auto}.md pre code{background:0 0;padding:0}.md blockquote{color:var(--dim);background:#ffffff0a;padding:6px 12px}.md table{border-collapse:collapse;display:block;overflow-x:auto}.md th,.md td{border:1px solid var(--line);padding:4px 10px}.tiles{flex:1 1 0;gap:20px;min-width:0;display:flex}.tile-tabs{display:none}.tile{border:1px solid var(--line);background:var(--panel);border-radius:22px;flex:1 1 0;min-width:0;position:sticky;top:96px}.tile>header svg{width:22px;height:22px;color:var(--gold)}.tile-body{padding:16px 20px;overflow:auto}.tiles.tabbed{flex-direction:column;gap:8px}.tiles.tabbed .tile-tabs{gap:6px;display:flex}.tiles.tabbed .tile:not(.active){display:none}.tab-btn.active,.open{color:var(--gold);border-color:#ffd16666}.dock{z-index:20;pointer-events:none;width:min(300px,100vw - 44px);display:grid;position:fixed;top:108px;right:max(22px,50vw - 718px)}.dialog{pointer-events:auto;border:1px solid var(--c4);background:linear-gradient(var(--c1), #0c1324 70%), #121a30;transform-origin:top;border-radius:18px;grid-area:1/1;padding:14px 16px 16px;transition:transform .3s,opacity .3s;position:relative;box-shadow:0 24px 60px #000c}.dialog:focus{outline:none}.dialog>header{align-items:center;gap:8px;min-width:0;margin-bottom:12px;display:flex}.where{min-width:0}.x{color:var(--dim);cursor:pointer;background:0 0;border:0;margin-left:auto;font-size:20px}.who{align-items:center;gap:14px;display:flex}.who .plate{--s:56px}.who h3{font-size:17px}.intel{background:#060a148c;border-radius:12px;margin-top:12px;padding:10px 12px}.intel h4{margin-bottom:4px}.said{overflow-wrap:anywhere;font-size:13px;line-height:1.45}.pending{color:var(--c);font:12px var(--mono);overflow-wrap:anywhere;margin-top:8px}.dialog footer{flex-wrap:wrap;align-items:center;gap:10px;margin-top:14px;display:flex}.ask{background:#ffb02e0f;border:1px solid #ffb02e59;border-radius:14px;gap:8px;margin:10px 18px 0;padding:12px 14px;display:grid}.dialog .ask{margin:10px 0 0}.ask-one{gap:8px;display:grid}.ask-one+.ask-one{margin-top:8px}.ask-head{color:var(--gold);letter-spacing:.06em;text-transform:uppercase;background:#ffb02e24;border-radius:999px;justify-self:start;padding:1px 9px;font-size:11px}.ask-how{color:var(--dim);font-size:12px}.ask-q{white-space:pre-wrap;overflow-wrap:anywhere;font-weight:600}.ask-ctx,.ask-why{color:var(--dim);white-space:pre-wrap;overflow-wrap:anywhere;max-height:9em;font-size:13px;overflow:auto}.ask-opts{counter-reset:opt;gap:6px;max-height:16em;margin:0;padding:0;list-style:none;display:grid;overflow:auto}.ask-opt{border:1px solid var(--line);overflow-wrap:anywhere;counter-increment:opt;background:#070c18;border-radius:10px;gap:2px;padding:7px 12px;font-size:13px;display:grid}.ask-opt b:before{content:counter(opt) ". ";color:var(--dim)}.ask-opt small{color:var(--dim);font-size:12px}.ask-acts{flex-wrap:wrap;justify-content:space-between;align-items:center;gap:6px 12px;display:flex}.ask-term{color:var(--gold);font-size:12px}.ask button:disabled{opacity:.45;cursor:default}.ask-note:empty{display:none}.ask-note{color:var(--dim);font-size:12px}.ask-note[data-tone=error]{color:#ff8a9c}.go,.later,.chat-pill,.cmp-send,.cmp-alt{font:600 13px var(--sans);cursor:pointer;border-radius:10px;padding:7px 13px;text-decoration:none}.go,.chat-pill{background:var(--c);color:#06101e}.cmp-send{color:#06101e;background:#38e0ff;border:0}.later,.cmp-alt{border:1px solid var(--line);color:var(--text);background:0 0}.queued{color:var(--dim);flex:1 0 100%;font-size:12px}.queued:empty{display:none}html.paused *,html.paused :before,html.paused :after{animation-play-state:paused!important}@media (width<=1100px){.stage{grid-template-columns:1fr}.side{position:static}.stats{display:none}}@media (width<=900px){.work{flex-direction:column;align-items:stretch}.view,.tiles{flex:none}.tile{position:static}.keep{flex-wrap:wrap}}@media (width<=640px){.shell{padding:max(8px, env(safe-area-inset-top)) max(8px, env(safe-area-inset-right)) calc(24px + env(safe-area-inset-bottom)) max(8px, env(safe-area-inset-left))}.hud{flex-wrap:wrap;gap:10px;padding:10px 12px;position:static}.brand p,.link span{display:none}.alerts{flex:100%;order:3;width:auto}.map,.zoom-in{padding:14px}.bases{gap:18px}.keep{gap:12px;padding:6px}.tower.big{width:84px;height:84px}.tally{flex-wrap:wrap}.col{width:100%}.comms-in,.tile{height:calc(var(--vvh,100dvh) - 16px);border-radius:16px;min-height:300px}.chat-scroll{padding:12px}.bubble{max-width:92%}.composer{padding:10px 12px calc(10px + env(safe-area-inset-bottom))}.cmp-row{flex-wrap:wrap}.composer textarea{flex:100%;min-height:64px}.cmp-acts{margin-left:auto}.log{max-height:none}.log li:nth-child(n+3){display:none}.dock{top:auto;right:10px;bottom:calc(10px + env(safe-area-inset-bottom));width:calc(100vw - 20px)}}@media (pointer:coarse){.composer textarea{font-size:16px}.composer button,.go,.later,.x,.chat-pill,.pair-btn,.alerts,.ask button{min-height:40px}}@media (prefers-reduced-motion:reduce){*,:before,:after{transition:none!important;animation:none!important}}
|
|
1
|
+
:root{--bg:#060a14;--panel:#0e1628e0;--line:#7a98e033;--text:#dbe6ff;--dim:#8b99ba;--gold:#ffd166;--grid:linear-gradient(#82a0ff0d 1px, transparent 1px) 0 0 / 44px 44px, linear-gradient(90deg, #82a0ff0d 1px, transparent 1px) 0 0 / 44px 44px;--mono:ui-monospace, "SF Mono", Menlo, Consolas, monospace;--sans:ui-rounded, "Avenir Next", "Trebuchet MS", system-ui, -apple-system, "Segoe UI", sans-serif}*{box-sizing:border-box;margin:0}html{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark}body{min-height:100vh;color:var(--text);font:14px/1.4 var(--sans);background:radial-gradient(1100px 640px at 12% -10%, #38e0ff1c, transparent 62%), radial-gradient(900px 600px at 98% 8%, #966eff1c, transparent 60%), linear-gradient(var(--bg), #0a1020);background-attachment:fixed}svg{display:block}[data-mark=working]{--c:#38e0ff}[data-mark=waiting]{--c:#ffb02e}[data-mark=idle]{--c:#7184ad}[data-mark=done]{--c:#3ddc97}[data-mark=error]{--c:#ff5470}[data-mark=unknown]{--c:#4f5c7c}[data-mark]{--c1:color-mix(in srgb, var(--c) 13%, transparent);--c4:color-mix(in srgb, var(--c) 45%, transparent)}:focus-visible{outline-offset:2px;outline:2px solid #38e0ff}.shell{max-width:1480px;margin:0 auto;padding:18px 22px 40px}.hud{border:1px solid var(--line);background:var(--panel);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);z-index:5;border-radius:18px;align-items:center;gap:24px;padding:12px 18px;display:flex;position:sticky;top:12px}.brand{align-items:center;gap:12px;margin-right:auto;display:flex}.logo{color:#38e0ff;border:1px solid var(--line);background:radial-gradient(circle at 30% 25%,#38e0ff4d,#0a1020e6);border-radius:14px;place-items:center;width:44px;height:44px;display:grid}.logo svg{filter:drop-shadow(0 0 6px #38e0ff);width:28px;height:28px}.brand h1{letter-spacing:.14em;text-transform:uppercase;font-size:20px}.brand p{color:var(--dim);font-size:12px}.stats{gap:10px;display:flex}.stats div,.tally div,.alerts{background:#ffffff0a;border:1px solid #ffffff0f;border-radius:12px;min-width:78px;padding:6px 12px}.stats dt,.tally dt{color:var(--dim);letter-spacing:.08em;text-transform:uppercase;font-size:11px}.stats dd,.tally dd{font:600 20px/1.1 var(--mono)}.stats [data-mark] dd,.tally [data-mark] dd,.count b{color:var(--c)}.pair-btn{border:1px solid var(--line);color:var(--dim);font:600 12px var(--sans);letter-spacing:.08em;text-transform:uppercase;cursor:pointer;background:0 0;border-radius:12px;padding:6px 12px}.pair{text-align:center;color:var(--dim);justify-items:center;gap:12px;font-size:13px;display:grid}.qr{shape-rendering:crispedges;border-radius:12px;width:min(100%,300px)}.link{color:var(--dim);text-transform:uppercase;letter-spacing:.08em;align-items:center;gap:8px;font-size:12px;display:flex}.link i{background:#4f5c7c;border-radius:50%;width:9px;height:9px}.link[data-state=live] i{background:#3ddc97;animation:2.4s ease-in-out infinite blink}.link[data-state=live]{color:#3ddc97}.link[data-state=reconnecting] i,.link[data-state=connecting] i{background:#ffb02e;animation:1s ease-in-out infinite blink}.link[data-state=offline] i{background:#ff5470}.banner{color:#c9d6f5;background:#7184ad29;border-radius:14px;margin:14px 0 0;padding:10px 16px;font-size:13px}.banner[hidden]{display:none}.banner b{font-family:var(--mono);font-weight:600}.stage{grid-template-columns:minmax(0,1fr) 300px;align-items:start;gap:20px;margin-top:18px;transition:opacity .4s;display:grid}.stage[data-stale=true] .map,body[data-stale=true] .stats{opacity:.4}.stage[data-stale=true] *{animation-play-state:paused!important}.map{border:1px solid var(--line);background:var(--grid), #080d1a8c;border-radius:22px;min-height:420px;padding:26px;transition:opacity .4s;position:relative}.links{pointer-events:none;width:100%;height:100%;position:absolute;inset:0}.wire{fill:none;stroke:#38e0ff4d;stroke-width:1.5px;stroke-dasharray:3 7;stroke-linecap:round}.packet{fill:#38e0ff;opacity:.9}.bases{grid-template-columns:repeat(auto-fill,minmax(min(100%,300px),1fr));align-items:start;gap:30px;display:grid;position:relative}.empty{color:var(--dim);text-align:center;padding:120px 0;position:relative}.base{border:1px solid var(--line);background:linear-gradient(#16213c,#0c1324);border-radius:18px;padding:16px;position:relative;box-shadow:0 18px 40px #00000059}.base.head{background:linear-gradient(#ffd1661a,#0000 38%),linear-gradient(#16213c,#0c1324)}.base[data-mark=waiting]{box-shadow:0 18px 40px #00000059,inset 0 0 0 999px #ffb02e0b}.base>header{align-items:center;gap:14px;margin-bottom:14px;display:flex}.title{justify-items:start;min-width:0;margin-right:auto;display:grid}.title h2{white-space:nowrap;text-overflow:ellipsis;max-width:100%;font-size:17px;overflow:hidden}.title p{max-width:100%;color:var(--dim);white-space:nowrap;text-overflow:ellipsis;font-size:12px;overflow:hidden}.crown{letter-spacing:.12em;text-transform:uppercase;color:var(--gold);background:#ffd1661f;border-radius:999px;align-items:center;gap:5px;margin-bottom:3px;padding:2px 9px 2px 6px;font-size:10px;display:inline-flex}.crown svg{width:14px;height:14px}.base:not(.head) .crown{display:none}.tower{width:80px;height:80px;color:var(--c);flex:none;place-items:center;display:grid;position:relative}.tower:before{content:"";background:radial-gradient(circle at 35% 30%, color-mix(in srgb, var(--c) 24%, #101a2e), #0b1222 70%);border:1px solid color-mix(in srgb, var(--c) 45%, transparent);border-radius:50%;position:absolute;inset:0}.tower svg{width:48px;height:48px;filter:drop-shadow(0 0 6px color-mix(in srgb, var(--c) 70%, transparent));position:relative}.tower.ghost{opacity:.45}.tower.ghost:before{border-style:dashed}.sweep,.pulse{opacity:0;pointer-events:none;border-radius:50%;position:absolute;inset:0}.sweep{background:conic-gradient(from 0deg, transparent 0 70%, color-mix(in srgb, var(--c) 55%, transparent) 100%)}.pulse{border:2px solid var(--c)}.tower[data-mark=working] .sweep{opacity:1;animation:3.2s linear infinite spin}.tower[data-mark=waiting] .pulse{animation:1.5s ease-out infinite ping}.tower>.badge{--s:40px;position:absolute;bottom:-2px;right:-2px}.tabs{gap:12px;display:grid}.tab{background:#ffffff06;border:1px solid #ffffff0d;border-radius:14px;padding:10px}.tab h3{color:var(--dim);letter-spacing:.12em;text-transform:uppercase;margin-bottom:8px;font-size:11px;font-weight:600}.units,.subs{gap:8px;display:grid}.outposts{gap:8px;margin-top:12px;display:grid}.outposts:empty{display:none}.outposts:before{content:"Outposts";color:var(--dim);letter-spacing:.12em;text-transform:uppercase;font-size:11px}.card{background:#ffffff09;border:1px solid #ffffff0f;border-radius:12px;align-items:center;gap:10px;padding:8px 10px;transition:background-color .4s;display:flex;position:relative}.unit[data-mark=waiting]>.card{background:#ffb02e1c}.unit[data-mark=error]>.card{background:#ff54701c}.unit[data-mark=working]>.card{background:#38e0ff12}.plate{width:var(--s,40px);height:var(--s,40px);color:var(--c);background:radial-gradient(circle at 35% 30%, color-mix(in srgb, var(--c) 26%, #101a2e), #0b1222 72%);border-radius:50%;flex:none;place-items:center;transition:color .4s;display:grid;position:relative}.plate svg{width:calc(var(--s,40px) * .55);height:calc(var(--s,40px) * .55)}.ring,.plate:after{pointer-events:none;border-radius:50%;position:absolute;inset:-3px}.ring{opacity:0;background:conic-gradient(from 0deg, transparent 0 55%, var(--c));-webkit-mask:radial-gradient(farthest-side,#0000 calc(100% - 3px),#000 calc(100% - 2px));mask:radial-gradient(farthest-side,#0000 calc(100% - 3px),#000 calc(100% - 2px))}.plate[data-mark=working]>.ring{opacity:1;animation:1.1s linear infinite spin}.plate:after{content:"";border:2px solid var(--c);opacity:0}.plate[data-mark=waiting]:after{animation:1.5s ease-out infinite ping}.badge{width:clamp(16px, calc(var(--s,40px) * .3), 24px);height:clamp(16px, calc(var(--s,40px) * .3), 24px);font:700 10px/1 var(--mono);color:#06101e;background:var(--c);border-radius:50%;flex:none;place-items:center;transition:background-color .4s;display:grid}.plate>.badge{position:absolute;bottom:-4px;right:-4px}[data-mark=waiting]>.badge:after{content:"?"}[data-mark=idle]>.badge:after{content:"z"}[data-mark=done]>.badge:after{content:"✓"}[data-mark=error]>.badge:after{content:"!"}[data-mark=unknown]>.badge:after{content:"·"}[data-mark=working]>.badge:after{content:"";border:2px solid #06101e;border-right-color:#0000;border-radius:50%;width:8px;height:8px;animation:.8s linear infinite spin}[data-mark=waiting]>.badge{animation:1.2s ease-in-out infinite hop}.meta{min-width:0;display:grid}.name{white-space:nowrap;text-overflow:ellipsis;font-weight:600;overflow:hidden}.line{color:var(--dim);align-items:baseline;gap:8px;min-width:0;font-size:12px;display:flex}.role{letter-spacing:.1em;text-transform:uppercase;color:color-mix(in srgb, var(--c) 70%, var(--dim));font-size:10px;font-style:normal}.note{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.unit[data-mark=idle]>.card{opacity:.85}.subs{margin:6px 0 0 22px;padding-left:18px;position:relative}.subs:empty{display:none}.subs:before{content:"";background:repeating-linear-gradient(#7a98e080 0 4px,#0000 4px 8px);width:1px;position:absolute;top:-4px;bottom:22px;left:3px}.subs>.unit>.card:before{content:"";background:repeating-linear-gradient(90deg,#7a98e080 0 4px,#0000 4px 8px);width:15px;height:1px;position:absolute;top:50%;left:-15px}.subs>.unit{position:relative}.subs .plate{--s:30px}.subs .name{font-size:13px}.side{gap:16px;display:grid;position:sticky;top:96px}.panel{border:1px solid var(--line);background:var(--panel);border-radius:18px;padding:14px 16px}.panel h2{color:var(--dim);letter-spacing:.14em;text-transform:uppercase;margin-bottom:10px;font-size:11px}.net-log summary{cursor:pointer;justify-content:space-between;align-items:center;list-style:none;display:flex}.net-log summary::-webkit-details-marker{display:none}.net-log summary:after{content:"▾";color:var(--dim);transition:transform .2s}.net-log:not([open]) summary:after{transform:rotate(-90deg)}.net-log:not([open]) h2{margin-bottom:0}.log{gap:7px;max-height:360px;padding:0;list-style:none;display:grid;overflow:hidden}.log:empty:before{content:"Waiting for changes…";color:var(--dim);font-size:12px}.log li{grid-template-columns:auto 1fr;gap:2px 8px;font-size:12px;animation:.4s ease-out both slide;display:grid}.log li:before{content:"";background:var(--c);border-radius:50%;width:8px;height:8px;margin-top:5px}.log time{font:11px var(--mono);color:var(--dim);grid-column:2}.credit{color:var(--dim);padding:0 6px;font-size:11px}.legend{gap:8px;padding:0;font-size:12px;list-style:none;display:grid}.legend li{align-items:center;gap:9px;display:flex}.enter{animation:.5s cubic-bezier(.2,.9,.3,1.15) both pop}.leaving{pointer-events:none;animation:.35s ease-in both out}.flash>.card>.plate,.flash.tower{animation:.6s ease-out flash}@keyframes spin{to{transform:rotate(360deg)}}@keyframes ping{0%{opacity:.6;transform:scale(1)}to{opacity:0;transform:scale(1.7)}}@keyframes hop{50%{transform:translateY(-3px)}}@keyframes blink{50%{opacity:.35}}@keyframes pop{0%{opacity:0;transform:scale(.92)translateY(8px)}}@keyframes out{to{opacity:0;transform:scale(.94)}}@keyframes flash{40%{transform:scale(1.12)}}@keyframes slide{0%{opacity:0;transform:translate(10px)}}@keyframes zoom{0%{opacity:0;transform:scale(.45)}}[hidden]{display:none!important}a{color:inherit}.crumbs,.tally dt,.comms-head small,.tx.you>header,.notice em,.rule summary,.dossier-in>.tag,.d-drones h4,.specs dt,.stop,.dialog .tag,.intel h4,.pending b{color:var(--dim);letter-spacing:.14em;text-transform:uppercase;font-size:11px;font-style:normal}.token .name,.drone .note,.count small,.sum,.where,.tile b{white-space:nowrap;text-overflow:ellipsis;max-width:100%;overflow:hidden}.md a,.bubble a,.notice a,.d-note a,.specs a,.crumbs a{color:#38e0ff}.crumbs{gap:10px;margin:14px 6px 0;display:flex}.crumbs>*+:before{content:"›";opacity:.5;margin-right:10px}.crumbs a,.brand{text-decoration:none}.work{align-items:flex-start;gap:20px;min-width:0;display:flex}.view{flex:1 1 0;min-width:0}body[data-stale=true] .work{opacity:.45}.enter-zoom{transform-origin:var(--ox,50%) var(--oy,0);animation:.5s ease-out both zoom}.enter-slide,.dossier{animation:.4s ease-out both slide}.enter-back{animation:.4s ease-out both pop}.hit,.enter-base:after{z-index:1;border-radius:inherit;position:absolute;inset:0}.enter-base:after{content:"";z-index:0}.hit:hover{box-shadow:inset 0 0 0 1px var(--c)}.base>header{position:relative}.enter-base{text-decoration:none}.base>header:hover h2{color:#38e0ff}.alerts{width:230px;color:inherit;font:inherit;text-align:left;cursor:pointer;align-items:center;gap:10px;display:flex;position:relative}.alerts:disabled{cursor:default;opacity:.6}.alerts:not(:disabled){border-color:var(--c4);background:var(--c1)}.faces{flex:none;padding-left:10px;display:flex}.faces .plate{--s:28px;margin-left:-10px;box-shadow:0 0 0 2px #0e1628}.faces .badge{display:none}.count{min-width:0;display:grid}.count b{font:600 18px/1.1 var(--mono)}.count small,.comms-head p,.cmp-note,.where,.queued,.d-line,.who p{color:var(--dim);font-size:12px}.token{border:1px solid #0000;border-radius:16px;justify-items:center;gap:3px;width:100%;padding:10px 8px 9px;text-decoration:none;display:grid;position:relative}a.token:hover{border-color:var(--c4)}.token[data-mark=waiting]{background:#ffb02e1c}.token[data-mark=error]{background:#ff54701c}.token .plate{--s:64px;margin-bottom:4px}.token .name{font-weight:600}.token .line{justify-items:center;max-width:100%;display:grid}.drone{width:94px;padding:6px;font-size:12px}.drone .plate{--s:44px}.drone .role{display:none}.flash.token>.plate{animation:.6s ease-out flash}.zoom-in,.comms-in{border:1px solid var(--line);background:var(--grid), #080d1a8c;border-radius:22px;position:relative}.zoom-in{min-height:420px;padding:24px}.zoom-in.void>:not(.lost){display:none}.lost,.chat-empty{color:var(--dim);text-align:center;padding:60px 0}.keep{align-items:center;gap:20px;padding:18px 22px;display:flex}.keep h2{font-size:24px}.tower.big{width:120px;height:120px}.tower.big svg{width:72px;height:72px}.tower.big>.badge{--s:96px;bottom:4px;right:4px}a.tower:hover:before{border-color:var(--c)}.tally{gap:10px;display:flex}.squads,.camps{grid-template-columns:repeat(auto-fit,minmax(min(100%,430px),1fr));align-items:start;gap:18px;margin-top:20px;display:grid}.squad{background:#0c1324c7;padding:14px 16px 18px}.squad[data-mark=waiting]{background:#262121d9}.squad h3{align-items:center;gap:10px;margin-bottom:14px;display:flex}.squad h3 b,.crumbs b{color:var(--text)}.squad h3 small{margin-left:auto}.squad h3 svg{width:18px;height:18px}.flag{background:var(--c);width:10px;height:10px;box-shadow:0 0 8px var(--c);border-radius:2px;transform:rotate(45deg)}.formation{flex-wrap:wrap;align-items:flex-start;gap:16px 20px;display:flex}.col{justify-items:center;gap:8px;width:196px;display:grid}.say{width:100%;color:var(--dim);background:#111a2f;border-radius:12px;margin-top:4px;padding:7px 10px;font-size:12px;line-height:1.35}.say p{overflow-wrap:anywhere;max-height:4.05em;overflow:hidden}.drones{flex-wrap:wrap;justify-content:center;gap:8px;width:100%;padding-top:16px;display:flex;position:relative}.drones:empty{display:none}.drones:before{content:"";background:repeating-linear-gradient(#7a98e099 0 4px,#0000 4px 8px);width:1px;height:14px;position:absolute;top:0;left:50%}.camp .token{width:156px}[data-group=outside] .plate{filter:saturate(.3);outline-offset:4px;outline:1px dashed #8b99ba8c}.comms-in,.tile{height:calc(var(--vvh,100vh) - 190px);grid-template-rows:auto minmax(0,1fr) auto;min-height:380px;display:grid;overflow:hidden}.comms-head,.tile>header{background:var(--panel);align-items:center;gap:12px;padding:12px 18px;display:flex}.ava{color:#38e0ff;background:radial-gradient(circle at 35% 30%,#38e0ff47,#0b1222 72%);border-radius:50%;flex:none;place-items:center;width:30px;height:30px;display:grid}.ava svg{width:58%;height:58%}.comms-head h2{font-size:16px}.chan{margin-left:auto}.chat-root{min-height:0;display:grid;position:relative}.comms-in .ask{max-height:calc((var(--vvh,100vh) - 190px) * .55);overscroll-behavior:contain;overflow-y:auto}.chat-scroll{overflow-anchor:none;padding:16px 20px;overflow-y:auto}.chat-list{gap:14px;display:grid}.chat-top{height:1px}.chat-live{color:var(--c);align-items:center;gap:10px;margin-top:14px;padding-left:44px;font-size:12px;display:flex}.chat-pill{--c:#38e0ff;border:0;position:absolute;bottom:14px;left:50%;transform:translate(-50%)}.lit:after{content:"";background:#38e0ff2e;border-radius:14px;animation:1s 1s forwards out;position:absolute;inset:0}.composer{border-top:1px solid var(--line);background:var(--panel);gap:8px;padding:12px 18px 14px;display:grid}.cmp-row,.cmp-acts,.cmp-foot,.cmp-note{align-items:center;gap:8px;display:flex}.cmp-row{align-items:flex-end;gap:10px}.composer textarea{resize:none;border:1px solid var(--line);min-width:0;color:var(--text);font:14px/1.4 var(--sans);background:#070c18;border-radius:12px;flex:1;padding:9px 12px}.composer textarea:focus{border-color:#38e0ff80;outline:none;box-shadow:0 0 0 3px #38e0ff1f}.composer button:disabled{opacity:.45;cursor:default}.cmp-note{flex-wrap:wrap;flex:1;min-height:18px}.cmp-note[data-tone=error],.cmp-alt.cmp-stop{color:#ff8a9c}.cmp-note[data-tone=ok]{color:#3ddc97}.cmp-note[data-tone=ask]{color:var(--gold)}.cmp-link{color:#38e0ff;font:12px var(--sans);cursor:pointer;background:0 0;border:0;padding:0}.cmp-yes{background:var(--gold);color:#06101e;font:600 12px var(--sans);cursor:pointer;border:0;border-radius:8px;padding:3px 10px}.tx{content-visibility:auto;contain-intrinsic-size:auto 90px;min-width:0}.tx time,.tx.note{color:var(--dim);font:11px var(--mono)}.tx.you{justify-items:end;gap:5px;display:grid}.tx.you>header{color:var(--gold);align-items:center;gap:8px;display:flex}.tx.you .ava{color:var(--gold)}.bubble{white-space:pre-wrap;overflow-wrap:anywhere;background:#ffd16614;border:1px solid #ffd16638;border-radius:14px;max-width:80%;padding:9px 13px}.tx.in{grid-template-columns:34px minmax(0,1fr);align-items:start;gap:10px;display:grid}.tx-body{border:1px solid var(--line);background:#0e1628d9;border-radius:14px;gap:8px;padding:10px 14px;display:grid}.tx-body,.tx-body>*{min-width:0}.tx-body>header{color:var(--dim);font:11px var(--mono);align-items:baseline;gap:10px;display:flex}.tx-body>header b{color:#38e0ff;font:600 13px var(--sans)}.stop,.dialog .tag{background:var(--c1);color:var(--c);border-radius:999px;padding:1px 8px;font-size:10px}.fault{color:#ff8a9c;font-size:13px}.thought,.more,.tab-btn{border:1px solid var(--line);color:var(--dim);font:11px var(--sans);cursor:pointer;background:0 0;border-radius:999px;justify-self:start;padding:2px 10px}.thought-text:empty{display:none}.thought-text,.out,.args,.notice pre,.rule pre{white-space:pre-wrap;overflow-wrap:anywhere;color:var(--dim);font:12px/1.4 var(--mono)}.act,.notice{background:#ffffff08;border:1px solid #ffffff12;border-radius:10px}.act>summary,.notice>summary,.rule summary{cursor:pointer;align-items:center;gap:9px;min-width:0;padding:6px 10px;font-size:12.5px;list-style:none;display:flex}summary::-webkit-details-marker{display:none}.act code{color:var(--c);font:600 11px var(--mono);letter-spacing:.06em;text-transform:uppercase}.sum{min-width:0;color:var(--dim)}.act[open] .sum{white-space:normal}.open{flex:none;margin-left:auto}.act>pre,.result{margin:0 10px 8px}.result{gap:6px;display:grid}.tx.sys{padding-left:44px}.notice{background:#966eff12;border-color:#966eff33}.notice .ava{width:22px;height:22px}.notice pre,.rule pre{padding:0 10px 8px}.rule summary{justify-content:center}.rule summary:before,.rule summary:after{content:"";background:var(--line);flex:1;height:1px}.tx.note{text-align:center}.dossier-in{text-align:center;justify-items:center;gap:6px;display:grid}.dossier-in>.tag{text-align:left;justify-self:stretch}.portrait{background:radial-gradient(var(--c1), transparent 70%);border-radius:50%;padding:8px}.portrait .plate{--s:96px}.dossier-in h3{overflow-wrap:anywhere;margin-top:4px;font-size:18px}.d-line,.who p{align-items:baseline;gap:8px;display:flex}.d-note{background:#ffb02e1f;border-radius:10px;padding:8px 10px;font-size:12px}.specs{text-align:left;justify-self:stretch;gap:2px;margin-top:10px;display:grid}.specs div{background:#ffffff09;grid-template-columns:76px minmax(0,1fr);gap:8px;padding:7px 10px;display:grid}.specs dt{font-size:10px}.specs dd{overflow-wrap:anywhere;font-size:12.5px}.d-drones{margin-top:8px}.d-drones .formation{justify-content:center;gap:6px}.md{overflow-wrap:anywhere;line-height:1.5}.md p,.md ul,.md ol,.md pre,.md table,.md blockquote{margin:0 0 10px}.md>:last-child{margin-bottom:0}.md :is(h1,h2,h3,h4,h5,h6){margin:14px 0 6px;font-size:15px}.md>:first-child{margin-top:0}.md h1{font-size:19px}.md ul,.md ol{padding-left:22px}.md li>p{margin:0}.md li.task{margin-left:-18px;list-style:none}.check{vertical-align:-2px;text-align:center;width:14px;height:14px;font:700 10px/12px var(--mono);border:1px solid;border-radius:4px;margin-right:7px;display:inline-block}.check[data-done=true]{color:#06101e;background:#3ddc97}.md code{font:12.5px var(--mono);background:#ffffff14;border-radius:5px;padding:1px 5px}.md pre{border:1px solid var(--line);background:#070c18;border-radius:10px;padding:10px 12px;overflow-x:auto}.md pre code{background:0 0;padding:0}.md blockquote{color:var(--dim);background:#ffffff0a;padding:6px 12px}.md table{border-collapse:collapse;display:block;overflow-x:auto}.md th,.md td{border:1px solid var(--line);padding:4px 10px}.tiles{flex:1 1 0;gap:20px;min-width:0;display:flex}.tile-tabs{display:none}.tile{border:1px solid var(--line);background:var(--panel);border-radius:22px;flex:1 1 0;min-width:0;position:sticky;top:96px}.tile>header svg{width:22px;height:22px;color:var(--gold)}.tile-body{padding:16px 20px;overflow:auto}.tiles.tabbed{flex-direction:column;gap:8px}.tiles.tabbed .tile-tabs{gap:6px;display:flex}.tiles.tabbed .tile:not(.active){display:none}.tab-btn.active,.open{color:var(--gold);border-color:#ffd16666}.dock{z-index:20;pointer-events:none;width:min(300px,100vw - 44px);display:grid;position:fixed;top:108px;right:max(22px,50vw - 718px)}.dialog{pointer-events:auto;border:1px solid var(--c4);background:linear-gradient(var(--c1), #0c1324 70%), #121a30;transform-origin:top;border-radius:18px;grid-area:1/1;padding:14px 16px 16px;transition:transform .3s,opacity .3s;position:relative;box-shadow:0 24px 60px #000c}.dialog:focus{outline:none}.dialog{overscroll-behavior:contain;max-height:calc(100dvh - 128px);overflow-y:auto}.dialog>header{align-items:center;gap:8px;min-width:0;margin-bottom:12px;display:flex}.where{min-width:0}.x{color:var(--dim);cursor:pointer;background:0 0;border:0;margin-left:auto;font-size:20px}.who{align-items:center;gap:14px;display:flex}.who .plate{--s:56px}.who h3{font-size:17px}.intel{background:#060a148c;border-radius:12px;margin-top:12px;padding:10px 12px}.intel h4{margin-bottom:4px}.said{overflow-wrap:anywhere;font-size:13px;line-height:1.45}.pending{color:var(--c);font:12px var(--mono);overflow-wrap:anywhere;margin-top:8px}.dialog footer{flex-wrap:wrap;align-items:center;gap:10px;margin-top:14px;display:flex}.ask{background:#ffb02e0f;border:1px solid #ffb02e59;border-radius:14px;gap:8px;margin:10px 18px 0;padding:12px 14px;display:grid}.dialog .ask{margin:10px 0 0}.ask-one{gap:8px;display:grid}.ask-one+.ask-one{margin-top:8px}.ask-head{color:var(--gold);letter-spacing:.06em;text-transform:uppercase;background:#ffb02e24;border-radius:999px;justify-self:start;padding:1px 9px;font-size:11px}.ask-how{color:var(--dim);font-size:12px}.ask-q{white-space:pre-wrap;overflow-wrap:anywhere;font-weight:600}.ask-ctx,.ask-why{color:var(--dim);white-space:pre-wrap;overflow-wrap:anywhere;max-height:9em;font-size:13px;overflow:auto}.ask-opts{counter-reset:opt;gap:6px;max-height:16em;margin:0;padding:0;list-style:none;display:grid;overflow:auto}.ask-opt{border:1px solid var(--line);overflow-wrap:anywhere;counter-increment:opt;background:#070c18;border-radius:10px;gap:2px;padding:7px 12px;font-size:13px;display:grid}.ask-opt b:before{content:counter(opt) ". ";color:var(--dim)}.ask-opt b[data-n]:before{content:attr(data-n) ". "}.ask-opt small{color:var(--dim);font-size:12px}.ask-acts{flex-wrap:wrap;align-items:center;gap:6px 14px;display:flex}.ask-acts>:last-child{margin-left:auto}.ask-term{color:var(--gold);font-size:12px}.ask button:disabled{opacity:.45;cursor:default}.ask-note:empty{display:none}.ask-note{color:var(--dim);flex-wrap:wrap;align-items:center;gap:4px 10px;font-size:12px;display:flex}.ask-note[data-tone=error]{color:#ff8a9c}.ask-note[data-tone=ok]{color:#3ddc97}.ask-title{font:12.5px/1.45 var(--mono);white-space:pre-wrap;overflow-wrap:anywhere;max-height:12em;margin:0;overflow:auto}div.ask-opts{max-height:none}button.ask-opt{text-align:left;color:var(--text);font:13px var(--sans);cursor:pointer}.ask-opt[aria-checked=true]{background:#ffb02e1f;border-color:#ffb02e}.ask-own{border:1px solid var(--line);min-width:0;color:var(--text);font:13px var(--sans);background:#070c18;border-radius:10px;padding:7px 12px}.ask-memo{font-size:12px}.ask input:disabled{opacity:.45}.ask-send{color:#06101e;font:600 13px var(--sans);cursor:pointer;background:#ffb02e;border:0;border-radius:10px;padding:7px 13px}.go,.later,.chat-pill,.cmp-send,.cmp-alt{font:600 13px var(--sans);cursor:pointer;border-radius:10px;padding:7px 13px;text-decoration:none}.go,.chat-pill{background:var(--c);color:#06101e}.cmp-send{color:#06101e;background:#38e0ff;border:0}.later,.cmp-alt{border:1px solid var(--line);color:var(--text);background:0 0}.queued{color:var(--dim);flex:1 0 100%;font-size:12px}.queued:empty{display:none}html.paused *,html.paused :before,html.paused :after{animation-play-state:paused!important}@media (width<=1100px){.stage{grid-template-columns:1fr}.side{position:static}.stats{display:none}}@media (width<=900px){.work{flex-direction:column;align-items:stretch}.view,.tiles{flex:none}.tile{position:static}.keep{flex-wrap:wrap}}@media (width<=640px){.shell{padding:max(8px, env(safe-area-inset-top)) max(8px, env(safe-area-inset-right)) calc(24px + env(safe-area-inset-bottom)) max(8px, env(safe-area-inset-left))}.hud{flex-wrap:wrap;gap:10px;padding:10px 12px;position:static}.brand p,.link span{display:none}.alerts{flex:100%;order:3;width:auto}.map,.zoom-in{padding:14px}.bases{gap:18px}.keep{gap:12px;padding:6px}.tower.big{width:84px;height:84px}.tally{flex-wrap:wrap}.col{width:100%}.comms-in,.tile{height:calc(var(--vvh,100dvh) - 16px);border-radius:16px;min-height:300px}.chat-scroll{padding:12px}.bubble{max-width:92%}.composer{padding:10px 12px calc(10px + env(safe-area-inset-bottom))}.cmp-row{flex-wrap:wrap}.composer textarea{flex:100%;min-height:64px}.cmp-acts{margin-left:auto}.log{max-height:none}.log li:nth-child(n+3){display:none}.dock{top:auto;right:10px;bottom:calc(10px + env(safe-area-inset-bottom));width:calc(100vw - 20px)}}@media (pointer:coarse){.composer textarea,.ask input{font-size:16px}.composer button,.go,.later,.x,.chat-pill,.pair-btn,.alerts,.ask button{min-height:40px}}@media (prefers-reduced-motion:reduce){*,:before,:after{transition:none!important;animation:none!important}}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e,c as t,d as n,f as r,i,l as a,m as o,o as s,s as c,u as l}from"./index-
|
|
2
|
-
`).filter(Boolean).at(-1))?.slice(0,280),pending:i&&`${i.name} · ${i.summary}`.slice(0,200),at:(r??e.findLast(e=>e.kind!==`result`))?.id}}var v=()=>a(`<section class="dialog" role="dialog" aria-modal="false" tabindex="-1"><header><b class="tag">alert</b><span class="where"></span><button class="x" type="button" aria-label="Close">×</button></header><div class="who">${i}<div><h3></h3><p><em class="role"></em> <span class="state"></span></p></div></div><div class="intel"><h4>Last transmission</h4><p class="said">…</p><p class="pending" hidden><b>waiting on</b> <span></span></p></div><div class="ask-root"></div><footer><a class="go">Open comms</a><button class="later" type="button">Later</button><span class="queued"></span></footer></section>`),y=()=>a(`<section class="tile" tabindex="-1"><header><svg><use href="#i-doc"/></svg><b></b><button class="x" type="button" aria-label="Close document">×</button></header><div class="tile-body"></div></section>`);function b(o){let[f,b,x,S,C]=[s(`dock`,HTMLElement),s(`work`,HTMLElement),s(`tiles`,HTMLElement),s(`tile-tabs`,HTMLElement),s(`alerts`,HTMLButtonElement)],w=new Map,T=(t,n,i=w.get(n.key))=>{let a=t.dataset.gone===`true`;r(t,`.said`,i?.failed?`History unavailable.`:i?.said??`No messages yet.`),t.querySelector(`.pending`).hidden=!i?.pending||a,r(t,`.pending span`,i?.pending??``),e(t.querySelector(`.go`),a?void 0:{view:`session`,ws:n.ws,key:n.key,...i?.at&&{at:i.at}})},E=(e,t={said:`…`})=>{w.set(e.key,t),o.recent(e.key).then(_,()=>({failed:!0})).then(n=>{let r=w.get(e.key)===t&&(w.set(e.key,n),f.querySelector(`.dialog[data-key="${CSS.escape(e.key)}"]`));r&&T(r,e)})},D=(e,n,i,a)=>{l(e,n.mark),e.dataset.gone=String(!!n.gone),e.style.transform=i?`translateY(${-12*i}px) scale(${1-.06*i})`:``,e.style.opacity=String(Math.max(0,1-.3*i)),e.toggleAttribute(`inert`,i>0),e.setAttribute(`aria-label`,`${n.name}: ${c(n.note,n.mark)}`),t(e.querySelector(`.plate`),n.role,n.mark),r(e,`h3`,n.name),r(e,`.role`,n.role===`outside`?`unaligned`:n.role),r(e,`.state`,n.gone?`left the net`:c(n.note,n.mark)),r(e,`.where`,o.label(n.ws)),r(e,`.tag`,n.gone?`gone`:{waiting:`question`,error:`error`,done:`finished`}[n.mark]??`update`),r(e,`.queued`,a.length?`Also queued: ${p(a)}`:``),w.has(n.key)||E(n),T(e,n);let s=O.get(e);s||O.set(e,s=d(e.querySelector(`.ask-root`),o.
|
|
1
|
+
import{a as e,c as t,d as n,f as r,i,l as a,m as o,o as s,s as c,u as l}from"./index-5qCqN1sA.js";import{t as u}from"./post-B39ywXKd.js";import{t as d}from"./ask-Dpo9zn5X.js";var f=(e,t)=>o(e.mark)-o(t.mark)||e.at-t.at,p=e=>{let t=e.filter(e=>o(e.mark)===0).length,n=e.length-t;return[t&&`${t} need${t===1?`s`:``} you`,n&&`${n} finished`].filter(Boolean).join(` · `)};function m(e){let t=[],n=[],r=()=>e.render(t.map(e=>e.alert),n),i=(i,a,o=!0)=>{let s=t.findIndex(e=>e.alert.key===i.key);if(s>=0&&!o)return;let c=s>=0?t.splice(s,1)[0]:{alert:i,back:a,raised:i.mark};!o&&t.length?t.splice(t.length-1,0,c):t.push(c),n=n.filter(e=>e.key!==i.key),r(),o&&e.enter(c.alert)};return{get open(){return t.map(e=>e.alert)},get queue(){return n},arrive(e){let i=t.find(t=>t.alert.key===e.key);if(i)[i.alert,i.raised]=[{...e,at:i.alert.at},e.mark];else{let t=n.find(t=>t.key===e.key);n=[...n.filter(t=>t.key!==e.key),t&&t.mark===e.mark?t:e].sort(f)}r()},prune(e){n=n.filter(t=>e(t.key)?.mark===t.mark);for(let n of t){let t=e(n.alert.key);n.alert=t?{...n.alert,...t,gone:void 0,at:n.alert.at}:{...n.alert,mark:`unknown`,note:void 0,pending:void 0,gone:!0}}r()},redraw:r,show:(t,n=!0)=>i(t,e.focused(),n),raise(n){let r=t.find(e=>e.alert.key===n);r&&r!==t.at(-1)&&i(r.alert,e.focused())},next(){n[0]&&i(n[0],e.focused())},close(a=`close`){let s=t.pop();if(!s)return!1;let c=t.at(-1),l=a===`close`?n.find(e=>o(e.mark)===0):void 0;return a===`later`&&s.alert.mark===s.raised&&(n=[...n,s.alert].sort(f)),!c&&l?(i(l,s.back),!0):(r(),!e.restore(s.back)&&c&&e.enter(c.alert),!0)}}}var h=`a, button, input, textarea, select, summary, label, [role=button]`;function g(e){let t=[],n,r=()=>e.render(t,n);return{get tiles(){return t},get active(){return n},open(i,a=!0){t.some(e=>e.id===i.id)||(t=[...t,i].slice(-4)),(a||!t.some(e=>e.id===n))&&(n=i.id),r(),a&&e.enter(t.find(e=>e.id===i.id))},close(e){let i=t.findIndex(t=>t.id===e);i<0||(t=t.filter(t=>t.id!==e),n===e&&(n=(t[i]??t[i-1])?.id),r())},activate(e){n=e,r()}}}function _(e){let t=new Set(e.flatMap(e=>e.kind===`result`&&e.callId?[e.callId]:[])),n=e.filter(e=>e.kind===`assistant`),r=n.at(-1),i=r?.tools?.find(e=>!t.has(e.id));return{said:(n.findLast(e=>e.text?.trim())?.text?.trim().split(`
|
|
2
|
+
`).filter(Boolean).at(-1))?.slice(0,280),pending:i&&`${i.name} · ${i.summary}`.slice(0,200),at:(r??e.findLast(e=>e.kind!==`result`))?.id}}var v=()=>a(`<section class="dialog" role="dialog" aria-modal="false" tabindex="-1"><header><b class="tag">alert</b><span class="where"></span><button class="x" type="button" aria-label="Close">×</button></header><div class="who">${i}<div><h3></h3><p><em class="role"></em> <span class="state"></span></p></div></div><div class="intel"><h4>Last transmission</h4><p class="said">…</p><p class="pending" hidden><b>waiting on</b> <span></span></p></div><div class="ask-root"></div><footer><a class="go">Open comms</a><button class="later" type="button">Later</button><span class="queued"></span></footer></section>`),y=()=>a(`<section class="tile" tabindex="-1"><header><svg><use href="#i-doc"/></svg><b></b><button class="x" type="button" aria-label="Close document">×</button></header><div class="tile-body"></div></section>`);function b(o){let[f,b,x,S,C]=[s(`dock`,HTMLElement),s(`work`,HTMLElement),s(`tiles`,HTMLElement),s(`tile-tabs`,HTMLElement),s(`alerts`,HTMLButtonElement)],w=new Map,T=(t,n,i=w.get(n.key))=>{let a=t.dataset.gone===`true`;r(t,`.said`,i?.failed?`History unavailable.`:i?.said??`No messages yet.`),t.querySelector(`.pending`).hidden=!i?.pending||a,r(t,`.pending span`,i?.pending??``),e(t.querySelector(`.go`),a?void 0:{view:`session`,ws:n.ws,key:n.key,...i?.at&&{at:i.at}})},E=(e,t={said:`…`})=>{w.set(e.key,t),o.recent(e.key).then(_,()=>({failed:!0})).then(n=>{let r=w.get(e.key)===t&&(w.set(e.key,n),f.querySelector(`.dialog[data-key="${CSS.escape(e.key)}"]`));r&&T(r,e)})},D=(e,n,i,a)=>{l(e,n.mark),e.dataset.gone=String(!!n.gone),e.style.transform=i?`translateY(${-12*i}px) scale(${1-.06*i})`:``,e.style.opacity=String(Math.max(0,1-.3*i)),e.toggleAttribute(`inert`,i>0),e.setAttribute(`aria-label`,`${n.name}: ${c(n.note,n.mark)}`),t(e.querySelector(`.plate`),n.role,n.mark),r(e,`h3`,n.name),r(e,`.role`,n.role===`outside`?`unaligned`:n.role),r(e,`.state`,n.gone?`left the net`:c(n.note,n.mark)),r(e,`.where`,o.label(n.ws)),r(e,`.tag`,n.gone?`gone`:{waiting:`question`,error:`error`,done:`finished`}[n.mark]??`update`),r(e,`.queued`,a.length?`Also queued: ${p(a)}`:``),w.has(n.key)||E(n),T(e,n);let s=O.get(e);s||O.set(e,s=d(e.querySelector(`.ask-root`),o.post?.(n.key)??((e,t)=>u(`sessions/${encodeURIComponent(n.key)}/${e}`,t)))),s.update(n.pending,n.mark===`waiting`&&document.body.dataset.stale!==`true`)},O=new WeakMap,k=m({render(e,o){n(f,e.map(e=>({...e,id:e.key})),v,(t,n)=>D(t,n,e.length-1-e.findIndex(e=>e.key===n.key),o));let s=o[0];C.disabled=!s,C.dataset.mark=s?.mark??`unknown`,r(C,`#alert-count`,String(o.length)),C.title=o.length?`Alerts: ${p(o)}`:``,r(C,`#alert-text`,s?`${s.name} · ${c(s.note,s.mark)}`:`no alerts`),n(C.querySelector(`.faces`),o.slice(0,3).map(e=>({...e,id:e.key})),()=>a(i),(e,n)=>t(e,n.role,n.mark))},enter:e=>f.querySelector(`[data-key="${CSS.escape(e.key)}"] .go`)?.focus(),focused:()=>document.activeElement instanceof HTMLElement&&document.activeElement!==document.body?document.activeElement:void 0,restore:e=>!!(e?.isConnected&&!e.closest(`[inert]`)&&(e.focus(),document.activeElement===e))});C.addEventListener(`click`,()=>k.next()),document.addEventListener(`click`,e=>{let t=t=>{let n=t.getBoundingClientRect();return e.clientX>=n.left&&e.clientX<=n.right&&e.clientY>=n.top&&e.clientY<=n.bottom},n=[...f.querySelectorAll(`.dialog:not(.leaving)`)],r=n.slice(0,-1).reverse().find(t);e.defaultPrevented||!r||!n.length||t(n.at(-1))||e.target?.closest?.(h)||(e.preventDefault(),e.stopPropagation(),k.raise(r.dataset.key))},!0),f.addEventListener(`click`,e=>{let t=e.target;t.closest(`.x`)?k.close():t.closest(`.later`)?k.close(`later`):t.closest(`.go`)&&queueMicrotask(()=>void k.close(`go`))});let A=0,j=()=>x.classList.toggle(`tabbed`,M.tiles.length>1&&b.clientWidth<460+M.tiles.length*400),M=g({render(e,t){x.hidden=!e.length,n(x,e,e=>{let t=y();return t.querySelector(`.tile-body`).append(e.body()),t.querySelector(`.x`).addEventListener(`click`,()=>M.close(e.id)),t},(e,n)=>{r(e,`header b`,n.title),e.classList.toggle(`active`,n.id===t)}),n(S,e,()=>a(`<button type="button" class="tab-btn"></button>`),(e,n)=>{e.textContent=n.title,e.classList.toggle(`active`,n.id===t),e.onclick=()=>M.activate(n.id)}),x.prepend(S),e.length!==A&&(A=e.length,j())},enter:e=>requestAnimationFrame(()=>x.querySelector(`.tile[data-key="${CSS.escape(e.id)}"]`)?.focus())});return new ResizeObserver(j).observe(b),{tiles:M,stack:k,alerts(e,t){for(let t of e)E(t),k.arrive(t);k.prune(e=>t.get(e))}}}export{b as mountPanels};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./index-D8pxo5hc.css"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{a as e,c as t,d as n,f as r,i,l as a,p as o,r as s,s as c,t as l,u}from"./index-5qCqN1sA.js";import{n as d,t as f}from"./post-B39ywXKd.js";import{t as p}from"./ask-Dpo9zn5X.js";var m=16384,h=`Not confirmed. Check the terminal before sending again.`,g=`The original already went to the session; what is here is your edited copy, unsent.`,_=/^\s*\/(quit|exit|new|resume|fork|clone|import|reload)(?=\s|$)/,v=new Map,y=e=>(t,n)=>f(`sessions/${encodeURIComponent(e)}/${t}`,n);function b(e,t,n){if(!e.ok)return[`error`,e.status===504?h:e.body.reason??`Refused (${e.status}).`];if(t&&!t.startsWith(n))return[`ok`,g]}var x=e=>{try{return e?.startsWith(`[`)?JSON.parse(e):e?[`error`,e]:void 0}catch{return[`error`,e]}},S=(e,t)=>e!==``&&!e.startsWith(t)?`Sent as it was; your edits stayed here, unsent.`:`Sent. It shows in the log once pi writes it.`,C=(e,t)=>({hidden:!e.live||!e.control||!!e.asking,disabled:t||!e.online}),w=(e,t)=>e.startsWith(t)?e.slice(t.length).replace(/^\n/,``):e;function T(e){if(!e.online)return`The stream is down; sending waits for it to come back.`;if(!e.live)return`This session is no longer live; its history stays readable.`;if(!e.control)return`No live pi pane backs this unit, so there is nothing to type into.`;if(e.mark===`waiting`)return e.answerable?`It waits on a dialog: answer it above, or in its terminal.`:`It waits on a dialog; answer it in its terminal.`}function E(e,t,n){let r=`sb-draft:${t}`,i=matchMedia(`(pointer: coarse)`).matches,a=d(`textarea`,{rows:`1`,maxlength:String(m),"aria-label":`Message`,enterkeyhint:i?`enter`:`send`}),o=d(`button`,{type:`submit`,class:`cmp-send`},`Send`),s=d(`button`,{type:`button`,class:`cmp-alt`,title:`Alt+Enter`},`Follow-up`),c=d(`button`,{type:`button`,class:`cmp-alt cmp-stop`},`Stop`),l=d(`p`,{class:`cmp-note`,role:`status`,"aria-live":`polite`}),u=d(`button`,{type:`button`,class:`cmp-link`},`Focus terminal`),f=d(`form`,{class:`composer`},d(`div`,{class:`cmp-row`},a,d(`div`,{class:`cmp-acts`},o,s,c)),d(`div`,{class:`cmp-foot`},l,u));e.replaceChildren(f);let p={name:``,control:!1,live:!1,mark:`unknown`,online:!1},g=!1,y=!1,E=e=>{try{e()}catch{}};E(()=>a.value=sessionStorage.getItem(r)??``);let D=()=>E(()=>a.value?sessionStorage.setItem(r,a.value):sessionStorage.removeItem(r)),O=()=>(a.style.height=`auto`,a.style.height=`${Math.min(a.scrollHeight,220)}px`),k=(e,t=``,...n)=>(l.dataset.tone=t,l.replaceChildren(e,...n)),A=(e,t,n)=>{let r=d(`button`,{type:`button`,class:`cmp-yes`},t),i=d(`button`,{type:`button`,class:`cmp-link`},`Cancel`);y=!0,r.onclick=()=>(y=!1,n()),i.onclick=()=>(y=!1,k(``),a.focus()),k(e,`ask`,r,i),r.focus()},[j,M]=[`${r}:note`,()=>{try{return sessionStorage.getItem(r)??``}catch{return}}],N=e=>E(()=>e?sessionStorage.setItem(j,JSON.stringify(e)):sessionStorage.removeItem(j));function P(e,i,a){let o={sent:a,answer:n(e,i)};return a!==void 0&&(N([`error`,h]),v.set(t,o),o.answer.then(e=>{let t=M();e.ok&&t!==void 0&&E(()=>sessionStorage.setItem(r,w(t,a))),N(b(e,t,a))},()=>N([`error`,h]))),F(o)}async function F(e,{sent:n}=e){g=!0,y=!1,L(),k(n===void 0?``:`Sending…`);try{let t=await e.answer;if(!f.isConnected)return;if(!t.ok)return t.status===504||N(),k(t.body.reason??`Refused (${t.status}).`,`error`);if(n===void 0)return k(``);N();let r=S(a.value,n);a.value=w(a.value,n),D(),O(),k(r,`ok`)}catch{k(h,`error`)}finally{v.get(t)===e&&v.delete(t),g=!1,L()}}function I(e,t){let n=a.value,r=T(p),i=t===n;if(g||y||!n.trim())return;if(r)return k(r,`error`);if(new TextEncoder().encode(n).length>16384)return k(`The text is longer than 16 KB; shorten it.`,`error`);let o=!i&&n.match(_)?.[0].trim();if(o)return A(`${o} ends this session or switches its pane to another one.`,`Send ${o}`,()=>I(e,n));P(`input`,{text:n,as:e,confirmed:i},n)}function L(){let e=T(p),t=p.mark===`working`;a.placeholder=e??`Message ${p.name} · ${i?``:`Enter sends, Shift+Enter adds a line · `}lands after any unsent text in its terminal`,o.disabled=g||!!e,s.hidden=c.hidden=!t||!!e,s.disabled=c.disabled=g,Object.assign(u,C(p,g))}f.addEventListener(`submit`,e=>(e.preventDefault(),I(`send`))),s.onclick=()=>I(`followUp`),c.onclick=()=>A(`Stop the current task? Queued messages go back to its terminal editor.`,`Stop`,()=>void(g||P(`keys`,{keys:[`esc`]}))),u.onclick=()=>void(g||P(`focus`,{})),a.addEventListener(`input`,()=>(D(),O())),f.addEventListener(`keydown`,e=>{e.key===`Escape`&&!e.isComposing&&(y||e.target===a&&a.value)&&(e.preventDefault(),y&&(y=!1,k(``),a.focus()))}),a.addEventListener(`keydown`,e=>{e.isComposing||e.keyCode===229||e.key!==`Enter`||e.shiftKey||i&&!e.altKey||(e.preventDefault(),I(e.altKey?`followUp`:`send`))});let R=window.visualViewport,z=()=>document.documentElement.style.setProperty(`--vvh`,`${R.height}px`);return R&&(R.addEventListener(`resize`,z),z()),O(),v.has(t)?F(v.get(t)):E(()=>{let e=x(sessionStorage.getItem(j));sessionStorage.removeItem(j),e&&k(e[1],e[0])}),{box:a,update:e=>(p=e,L()),ready:()=>!T(p)}}var D=200;function O(e,t){for(let n of e?.bases??[]){if(n.tower?.key===t)return{u:{key:t,name:n.tower.name,role:`tower`,mark:n.tower.mark,control:n.tower.control,pending:n.tower.pending,subs:[]},base:n};for(let[e,r]of[...n.tabs.map(e=>[e.label,e.units]),[void 0,n.outside]])for(let i of r){if(i.key===t)return{u:i,base:n,squad:e};let r=i.subs.find(e=>e.key===t);if(r)return{u:r,base:n,squad:e,launcher:i}}}}var k=()=>a(`<a class="token">${i}<span class="name"></span><span class="line"><em class="role"></em><span class="note"></span></span></a>`);function A(n,i,a){e(n,i.key?{view:`session`,ws:a,key:i.key}:void 0),n.toggleAttribute(`hidden`,!1),n.toggleAttribute(`data-alert`,!!i.key&&o(i.mark)),u(n,i.mark),t(n.querySelector(`.plate`),i.role,i.mark),r(n,`.name`,i.name),r(n,`.role`,i.role===`outside`?`unaligned`:i.role),r(n,`.note`,c(i.note,i.mark))}var j=()=>a(`<div class="col"><a class="token">${i}<span class="name"></span><span class="line"><em class="role"></em><span class="note"></span></span></a><div class="say"><p></p></div><div class="drones"></div></div>`),M=`<div class="zoom-in"><header class="base keep"><a class="tower big"><i class="sweep"></i><i class="pulse"></i><svg><use href="#i-tower"/></svg><b class="badge"></b></a><div class="title"><span class="crown"><svg><use href="#i-crown"/></svg>head tower</span><h2></h2><p></p></div><dl class="tally"><div><dt>Squads</dt><dd></dd></div><div><dt>Units</dt><dd></dd></div><div data-mark="working"><dt>Working</dt><dd></dd></div><div data-mark="waiting"><dt>Waiting</dt><dd></dd></div></dl></header><div class="squads"></div><div class="camps"><section class="tab squad camp" data-group="outposts"><h3><svg><use href="#i-outpost"/></svg><b>Outposts</b><small></small></h3><div class="formation"></div></section><section class="tab squad camp" data-group="outside"><h3><svg><use href="#i-outside"/></svg><b>Outside the net</b><small>unaligned pi panes</small></h3><div class="formation"></div></section></div><p class="lost" hidden></p></div>`,N=`<div class="dossier-in"><span class="tag">unit dossier</span><div class="portrait">${i}</div><h3></h3><p class="d-line"><em class="role"></em> <span class="state"></span></p><p class="d-note" hidden></p><dl class="specs"></dl><div class="d-drones" hidden><h4>Dispatched</h4><div class="formation"></div></div></div>`,P=`<div class="comms-in"><header class="comms-head"><span class="logo"><svg><use href="#i-comms"/></svg></span><div><h2><small>comms</small> <span></span></h2><p></p></div><span class="chan link" data-state="live"><i></i><b>channel open</b></span></header><div class="chat-root"></div><div class="ask-root"></div><div class="composer-root"></div></div>`;function F({data:i,restart:d,openTile:f,online:m}){let h=e=>document.getElementById(e),[g,_,v]=[`ws-view`,`session-view`,`dossier`].map(h),b={view:`map`},x,S={},C,w=[],T=!1,F,I,L,R=0,z,B,V=()=>b.view===`map`?``:b.ws,H=(t,n)=>{let r=document.createElement(`a`);return e(r,t),r.textContent=n,r};function U(){let t=(t,n,r)=>{let i=document.createElement(t);return i.textContent=n,r&&e(i,r),i},n=h(`crumbs`),r=b;if(r.view===`map`)return n.replaceChildren(t(`b`,`Straw Net`),t(`span`,`all bases`));let i=x?.bases.find(e=>e.id===r.ws)?.label??r.ws,a=r.view===`session`?O(x,r.key)?.u.name??F?.name??r.key:``;n.replaceChildren(t(`a`,`Straw Net`,{view:`map`}),r.view===`workspace`?t(`b`,i):t(`a`,i,{view:`workspace`,ws:r.ws}),...a?[t(`b`,a)]:[])}function W(e,t,n){let r=e=>[`map`,`workspace`,`session`].indexOf(e.view),i=r(e)<r(t)?`enter-back`:e.view===`workspace`&&n?`enter-zoom`:e.view===`session`&&t.view!==`session`?`enter-slide`:``,a=h({map:`map`,workspace:`ws-view`,session:`session-view`}[e.view]);if(i){if(n){let e=a.getBoundingClientRect();a.style.setProperty(`--ox`,`${Math.round(n.x+n.width/2-e.x)}px`),a.style.setProperty(`--oy`,`${Math.round(n.y+n.height/2-e.y)}px`)}a.classList.remove(`enter-zoom`,`enter-slide`,`enter-back`),a.offsetWidth,a.classList.add(i),setTimeout(()=>a.classList.remove(i),700)}}function G(){g.firstElementChild||g.append(a(M));let t=g.firstElementChild,i=x?.bases.find(e=>e.id===V()),c=t.querySelector(`.lost`);if(c.hidden=!!i,c.textContent=x?`This workspace is not part of the net.`:`Waiting for the net…`,t.classList.toggle(`void`,!i),!i)return;let l=t.querySelector(`.keep`);u(l,i.mark),l.classList.toggle(`head`,i.head);let d=t.querySelector(`.tower`);d.classList.toggle(`ghost`,!i.tower),u(d,i.tower?.mark??`unknown`),e(d,i.tower?{view:`session`,ws:i.id,key:i.tower.key}:void 0),d.toggleAttribute(`hidden`,!1),d.toggleAttribute(`data-alert`,!!(i.tower&&o(i.tower.mark))),r(t,`h2`,i.label),r(t,`.title p`,i.tower?`control tower · ${s[i.tower.mark]}`:`no tower yet`);let f=i.tabs.flatMap(e=>e.units.flatMap(e=>[e,...e.subs]));[i.tabs.length,f.length,f.filter(e=>e.mark===`working`).length,f.filter(e=>e.mark===`waiting`).length].forEach((e,n)=>t.querySelectorAll(`dd`)[n].textContent=String(e));let p=(e,t)=>{u(e,t.mark),A(e.querySelector(`.token`),t,i.id);let a=e.querySelector(`.say`),o=S[t.key]??``;a.hidden=!o,r(a,`p`,o),n(e.querySelector(`.drones`),t.subs,k,(e,t)=>(e.classList.add(`drone`),A(e,t,i.id)))};n(t.querySelector(`.squads`),i.tabs,()=>a(`<section class="tab squad"><h3><i class="flag"></i><b></b><small></small></h3><div class="formation"></div></section>`),(e,t)=>{r(e,`h3 b`,`squad ${t.label}`);let i=t.units.flatMap(e=>[e,...e.subs]);r(e,`h3 small`,`${i.length} unit${i.length===1?``:`s`}`),u(e,[`waiting`,`error`,`working`].find(e=>i.some(t=>t.mark===e))??`idle`),n(e.querySelector(`.formation`),t.units,j,p)});let m=(e,r)=>{let a=t.querySelector(`[data-group="${e}"]`);a.hidden=!r.length,n(a.querySelector(`.formation`),r,k,(e,t)=>A(e,t,i.id))};m(`outposts`,i.outposts.map(e=>({id:e.id,name:e.label,role:`outpost`,mark:e.mark,note:e.mark===`unknown`?`no agent running`:void 0}))),m(`outside`,i.outside)}function K(){if(b.view!==`session`)return;v.firstElementChild||v.append(a(N));let e=v.firstElementChild,i=O(x,b.key),l=i?.u,d=l?.mark??`unknown`;u(e,d),t(e.querySelector(`.plate`),l?.role??F?.role??`member`,d),r(e,`h3`,l?.name??F?.name??b.key),r(e,`.role`,l?.role===`outside`?`unaligned`:l?.role??F?.role??`session`),r(e,`.state`,l?c(l.note,d):`not in the net`);let f=e.querySelector(`.d-note`),p=F?.state;f.hidden=p!==`recent`&&p!==`unknown`,f.replaceChildren(p===`unknown`?`Not in the net (it may have ended more than ten minutes ago).`:`No longer live; its history stays readable for ten minutes.`),F?.successor&&f.append(` Now: `,H({view:`session`,ws:V(),key:F.successor},O(x,F.successor)?.u.name??`the new session`));let h=[[`model`,I],[`context`,L?`${L.toLocaleString()} tokens`:void 0],[`directory`,F?.header?.cwd],[`base`,i&&H({view:`workspace`,ws:i.base.id},i.base.label)],[`squad`,i?.squad],[`launcher`,i?.launcher&&H({view:`session`,ws:i.base.id,key:i.launcher.key},i.launcher.name)],[`unreadable`,F?.unreadable?`${F.unreadable} entr${F.unreadable===1?`y`:`ies`}`:void 0]];e.querySelector(`.specs`).replaceChildren(...h.filter(([,e])=>e).map(([e,t])=>{let n=a(`<div><dt></dt><dd></dd></div>`);return n.firstElementChild.textContent=e,n.lastElementChild.append(t),n}));let g=e.querySelector(`.d-drones`);g.hidden=!l?.subs.length,n(g.querySelector(`.formation`),(l?.subs??[]).map(e=>({...e,id:e.key})),k,(e,t)=>(e.classList.add(`drone`),A(e,t,V())));let y=_.querySelector(`.comms-head`);if(y){r(y,`h2 span`,l?.name??F?.name??``),r(y,`p`,[i?.base.label,i?.squad&&`squad ${i.squad}`].filter(Boolean).join(` · `));let e=y.querySelector(`.chan`),t=p===`live`||!p&&l;e.dataset.state=t?`live`:`closed`,r(e,`b`,t?`channel open`:p===`recent`?`channel closed`:`no channel`)}C?.setLive(d===`working`?`${c(l.note,d)}`:o(d)?s[d]:``,d),z?.update({name:l?.name??F?.name??b.key,control:!!l?.control,live:p?p===`live`:!!l,mark:d,online:m(),asking:!!l?.pending,answerable:!!l?.pending?.answer}),B?.update(l?.pending,d===`waiting`&&!!l?.control&&m())}let q=()=>setTimeout(()=>b.view===`session`&&(document.activeElement??document.body)===document.body&&(matchMedia(`(pointer: fine)`).matches&&z?.ready()?z.box:C?.log)?.focus({preventScroll:!0}));async function J(e){let t=++R,{mountChat:n}=await l(async()=>{let{mountChat:e}=await import(`./chat-BO71QXXf.js`);return{mountChat:e}},__vite__mapDeps([0]),import.meta.url);if(t!==R||b.view!==`session`)return;_.replaceChildren(a(P)),C=n(_.querySelector(`.chat-root`),i(e),{who:()=>O(x,e)?.u??{key:e,name:F?.name??e,role:F?.role??`member`,mark:`unknown`},link:t=>{let n=O(x,e)?.u.subs.find(e=>e.name===t)??x?.bases.flatMap(e=>[...e.tabs.flatMap(e=>e.units),...e.outside]).find(e=>e.name===t);return n&&H({view:`session`,ws:O(x,n.key)?.base.id??V(),key:n.key},t)},openTile:f});let r=i(e).post??y(e);[z,B]=[E(_.querySelector(`.composer-root`),e,r),p(_.querySelector(`.ask-root`),r)],C.reveal(b.at),w.splice(0).forEach(Y),K(),q()}function Y(e){C?.apply(e);for(let t of e.items??[])t.kind===`assistant`&&([I,L]=[t.model??I,t.ctx??L])}let X=()=>(U(),b.view===`workspace`?G():K());return{locate:e=>O(x,e),show(e,t,n){let[r,i]=b.view===`session`?[b.key,b.at]:[];(e.view!==`workspace`||b.view!==`workspace`||e.ws!==b.ws)&&(S={}),b=e,g.hidden=e.view!==`workspace`,_.hidden=v.hidden=e.view!==`session`,e.view===`session`&&e.key!==r?([C,z,B,F,I,L,w,T]=[void 0,void 0,void 0,void 0,void 0,void 0,[],!1],_.replaceChildren(a(`<p class="lost">Opening the channel…</p>`)),J(e.key)):e.view===`session`&&e.at!==i?(C?.reveal(e.at),q()):e.view!==`session`&&(R++,C=z=B=void 0),X(),e!==t&&W(e,t,n)},net(e){x=e,b.view!==`map`&&X()},cards(e){S={...S,...e},b.view===`workspace`&&G()},history(e){if(b.view===`session`&&e.key===b.key){if(F={...F,...e,items:void 0},e.reset&&([I,L]=[void 0,void 0]),document.hidden)return w.length<D?void w.push(e):void(T=!0);C?Y(e):w.push(e),K()}},wake(){if(T)return T=!1,w=[],d();w.splice(0).forEach(e=>C&&Y(e)),X()}}}export{F as mountFocus};
|
package/dist/gui/index.html
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
<meta name="referrer" content="no-referrer">
|
|
7
7
|
<title>Straw Net</title>
|
|
8
8
|
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='8' fill='%230b1220'/%3E%3Cpath d='M16 5l9 7h-4v13h-10V12H7z' fill='%2338e0ff'/%3E%3C/svg%3E">
|
|
9
|
-
<script type="module" crossorigin src="./assets/index-
|
|
10
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
9
|
+
<script type="module" crossorigin src="./assets/index-5qCqN1sA.js"></script>
|
|
10
|
+
<link rel="stylesheet" crossorigin href="./assets/index-D8pxo5hc.css">
|
|
11
11
|
</head>
|
|
12
12
|
<body>
|
|
13
13
|
<!-- Icons: game-icons.net, CC BY 3.0 (Lorc, Delapouite); see gui/ICONS.md -->
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-straw-boss",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Straw Boss coordination for pi in Herdr: sessions join a tab's net by choice, the first joiner is its main agent, a workspace tower opens on demand with a live monitoring dashboard, and boss_broadcast reaches the rest",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/src/ask.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { open, stat } from "node:fs/promises";
|
|
2
2
|
import { type Json, parse } from "./items.ts";
|
|
3
|
-
import type { Net } from "./net.ts";
|
|
3
|
+
import type { Net, Unit } from "./net.ts";
|
|
4
|
+
import type { Answerable, Dialog } from "./owners.ts";
|
|
4
5
|
|
|
5
|
-
// What a waiting session waits on
|
|
6
|
-
// its session file. The snapshot carries it so the alert and the session view can show an ask_user question (its context and options)
|
|
7
|
-
//
|
|
6
|
+
// What a waiting session waits on: the current branch's newest assistant message's tool call with no result yet, read from the end of
|
|
7
|
+
// its session file. The snapshot carries it so the alert and the session view can show an ask_user question (its context and options).
|
|
8
|
+
// A dialog the session's bridge relays (bridge.ts, dialogs.ts) joins it as `answer` when the page may answer it; nothing here sends anything.
|
|
8
9
|
// Two tools are read: pi-ask-user's `ask_user` (one question with a context) and @juicesharp/rpiv-ask-user-question's `ask_user_question` (one to four questions
|
|
9
10
|
// with a header, options with descriptions, and a multi-select flag; no context). Older session files hold the first, new ones the second.
|
|
10
11
|
|
|
@@ -12,8 +13,9 @@ const TAIL = 262_144, LIMIT = 16_777_216, CACHE = new Map<string, { sig: string;
|
|
|
12
13
|
export interface Option { title: string; description?: string }
|
|
13
14
|
/** `multiple`: it takes several choices; `freeform`: it takes the user's own words; `header`: the short tag ask_user_question gives a question. */
|
|
14
15
|
export interface Ask { question: string; header?: string; context?: string; options: Option[]; multiple: boolean; freeform: boolean }
|
|
15
|
-
/** What a waiting session waits on: `ask` for one question, `asks` for two to four (ask_user_question), else `why` there is nothing to show. */
|
|
16
|
-
export interface Pending { callId: string; tool: string; ask?: Ask; asks?: Ask[]; why?: string }
|
|
16
|
+
/** What a waiting session waits on: `ask` for one question, `asks` for two to four (ask_user_question), else `why` there is nothing to show; `answer` when the page may answer it. */
|
|
17
|
+
export interface Pending { callId: string; tool: string; ask?: Ask; asks?: Ask[]; why?: string; answer?: Answerable }
|
|
18
|
+
export const SEVERAL = "It waits on more than one dialog.";
|
|
17
19
|
interface Call { id: string; name: string; args: Json }
|
|
18
20
|
|
|
19
21
|
const clip = (v: unknown, n: number) => String(v ?? "").slice(0, n);
|
|
@@ -93,20 +95,28 @@ export async function pendingOf(file: string): Promise<Pending | undefined> {
|
|
|
93
95
|
if (hit?.sig === sig) return hit.pending;
|
|
94
96
|
const found = s ? await openCalls(file).catch(() => []) : [], calls = found === "cut" ? [] : found, [c] = calls;
|
|
95
97
|
const shape = c?.name === "ask_user" ? askOf(c.args) : c?.name === "ask_user_question" ? questionsOf(c.args) : { why: c?.name === "secret_drop" ? "It waits for a secret." : "It waits on a dialog." };
|
|
96
|
-
const pending = found === "cut" ? { callId: `cut:${sig}`, tool: "dialog", why: "Its call is too long to read here." } : c && { callId: c.id, tool: c.name, ...(calls.length > 1 ? { why:
|
|
98
|
+
const pending = found === "cut" ? { callId: `cut:${sig}`, tool: "dialog", why: "Its call is too long to read here." } : c && { callId: c.id, tool: c.name, ...(calls.length > 1 ? { why: SEVERAL } : shape) };
|
|
97
99
|
CACHE.set(file, { sig, pending });
|
|
98
100
|
if (CACHE.size > 64) CACHE.delete(CACHE.keys().next().value!);
|
|
99
101
|
return pending;
|
|
100
102
|
}
|
|
101
103
|
|
|
102
|
-
/**
|
|
103
|
-
export
|
|
104
|
-
|
|
104
|
+
/** The dialogs bridges relay, by unit key, and how they join what the file says (dialogs.ts). */
|
|
105
|
+
export interface Relayed { dialogsOf(key: string): Dialog[] | undefined; merge(key: string, file: Pending | undefined, dialogs: Dialog[], readable: boolean): Pending }
|
|
106
|
+
|
|
107
|
+
/** Adds what each waiting unit waits on to a snapshot. A unit with a relayed dialog waits even before Herdr reports its pane blocked. */
|
|
108
|
+
export async function withPending(net: Net, fileOf: (key: string) => string | undefined, relayed?: Relayed): Promise<Net> {
|
|
105
109
|
const jobs: Promise<unknown>[] = [];
|
|
106
|
-
for (const
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
+
for (const b of net.bases)
|
|
111
|
+
for (const u of [...(b.tower ? [b.tower] : []), ...[...b.tabs.flatMap((t) => t.units), ...b.outside].flatMap((u) => [u, ...u.subs])]) {
|
|
112
|
+
const dialogs = relayed?.dialogsOf(u.key);
|
|
113
|
+
if (dialogs?.length) [u.mark, b.mark] = ["waiting", "waiting"];
|
|
114
|
+
if (dialogs?.length && u !== b.tower) (u as Unit).note = "waiting on a question";
|
|
115
|
+
const file = u.mark === "waiting" ? fileOf(u.key) : undefined;
|
|
116
|
+
const join = (p?: Pending) => (dialogs?.length ? relayed!.merge(u.key, p, dialogs, Boolean(file)) : p);
|
|
117
|
+
if (file) jobs.push(pendingOf(file).then((p) => (u.pending = join(p))));
|
|
118
|
+
else if (dialogs?.length) u.pending = join();
|
|
119
|
+
}
|
|
110
120
|
await Promise.all(jobs);
|
|
111
121
|
return net;
|
|
112
122
|
}
|