pi-straw-boss 0.10.1 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/README.zh-TW.md +1 -1
- package/dist/gui/assets/{ask-Bw5jOgnx.js → ask-B8tfeo3k.js} +1 -1
- package/dist/gui/assets/{chat-iv7vekCl.js → chat-f479gS8E.js} +1 -1
- package/dist/gui/assets/index-BkgejQW0.js +1 -0
- package/dist/gui/assets/{layer-DwP_iTgP.js → layer-DIbW2CGy.js} +1 -1
- package/dist/gui/assets/pair-B_oUhsbt.js +1 -0
- package/dist/gui/assets/{post-DQSLbWA2.js → post-C4WkBuZ3.js} +1 -1
- package/dist/gui/assets/{views-DKyvJht_.js → views-Dgtkn3yx.js} +2 -2
- package/dist/gui/index.html +1 -1
- package/package.json +1 -1
- package/src/control.ts +18 -4
- package/src/gui.ts +59 -18
- package/src/index.ts +47 -31
- package/dist/gui/assets/index-CDEHVJil.js +0 -1
- package/dist/gui/assets/pair-Cz99RYOR.js +0 -1
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ The tower only routes and coordinates, so it can run a lighter model: set `tower
|
|
|
52
52
|
| `boss_broadcast` | Message a tab, a workspace, all towers, or every session. |
|
|
53
53
|
| `/boss` | Take over as this tab's main agent. |
|
|
54
54
|
| `/boss status`, `/boss tower` | Show the status; open and focus the tower. |
|
|
55
|
-
| `/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, or work its terminal with the key pad under the terminal tile; 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). Documents a session shows with [pi-herdr-doc-review](https://www.npmjs.com/package/pi-herdr-doc-review) 0.4.0 or newer open beside its comms: HTML in a sandboxed frame whose form answers the agent, text read-only. |
|
|
55
|
+
| `/boss gui`, `/boss gui stop` | Open the net in the browser (any session, joins nothing); stop its server, from any session. The machine runs one server on one URL: it comes back after its session's `/reload`, and a session on a newer pi-straw-boss takes it over, so open pages reload into the new version. Type into a session from its comms view, or work its terminal with the key pad under the terminal tile; 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). Documents a session shows with [pi-herdr-doc-review](https://www.npmjs.com/package/pi-herdr-doc-review) 0.4.0 or newer open beside its comms: HTML in a sandboxed frame whose form answers the agent, text read-only. |
|
|
56
56
|
| `/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. |
|
|
57
57
|
|
|
58
58
|
Subagents and sessions in Herdr worktree workspaces never join: the session that launched them speaks for them. Outside Herdr the extension does nothing.
|
package/README.zh-TW.md
CHANGED
|
@@ -52,7 +52,7 @@ pi 要跑在 Herdr 0.9.4 以上,另外需要 [pi-intercom](https://www.npmjs.c
|
|
|
52
52
|
| `boss_broadcast` | 傳訊息給一個分頁、一個工作區、所有塔台,或所有 session。 |
|
|
53
53
|
| `/boss` | 接手成為這個分頁的主智慧體。 |
|
|
54
54
|
| `/boss status`、`/boss tower` | 顯示狀態;開啟塔台並切換過去。 |
|
|
55
|
-
| `/boss gui`、`/boss gui stop` | 在瀏覽器開啟網(任何 session
|
|
55
|
+
| `/boss gui`、`/boss gui stop` | 在瀏覽器開啟網(任何 session 都能開,不會加入任何東西);停止它的伺服器,在哪個 session 都可以。整台機器只跑一個伺服器、一個網址:開它的 session `/reload` 之後,會在原網址重開;版本較新的 session 會接手,開著的頁面也會自動換成新版。可以在通訊畫面直接打字給某個 session,或用終端機畫面下方的按鍵面板操作它的終端機;在等回覆的 `robot_hand` 選單或 `ask_user_question` 問卷,可以在那裡或它的警示裡作答(其他對話框只能看,要回到終端機回答;`secret_drop` 一律只能在終端機輸入)。session 用 [pi-herdr-doc-review](https://www.npmjs.com/package/pi-herdr-doc-review) 0.4.0 以上顯示的文件,會開在它的通訊畫面旁邊:HTML 放在沙箱框架裡,表單送出的答案會傳給智慧體;純文字只能讀。 |
|
|
56
56
|
| `/boss gui remote`、`/boss gui remote off` | 透過你的 tailnet 用手機連 GUI(`tailscale serve`,絕不用 Funnel):掃 QR code 配對;關閉時只移除它自己的 serve 設定。 |
|
|
57
57
|
|
|
58
58
|
子智慧體,以及在 Herdr worktree 工作區裡的 session,都不會加入網,由開出它們的 session 代表它們。不在 Herdr 裡時,這個擴充套件什麼都不做。
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as e,r as t}from"./post-
|
|
1
|
+
import{n as e,r as t}from"./post-C4WkBuZ3.js";import{E as n}from"./index-BkgejQW0.js";var r=((e={},t={})=>(t.locale??n())===`zh-TW`?`另一個答案正在送出;請查看終端機。`:`Another answer is on its way; check the terminal.`),i=((e={},t={})=>(t.locale??n())===`zh-TW`?`請在終端機中回答。`:`Answer it in the terminal.`),a=((e={},t={})=>(t.locale??n())===`zh-TW`?`請在終端機中回答。`:`Answer them in the terminal.`),o=((e={},t={})=>(t.locale??n())===`zh-TW`?`已回答。`:`Answered.`),s=((e={},t={})=>(t.locale??n())===`zh-TW`?`也可以自己輸入答案。`:`It also takes your own words.`),c=((e={},t={})=>(t.locale??n())===`zh-TW`?`可以複選。`:`It takes several choices.`),l=((e={},t={})=>(t.locale??n())===`zh-TW`?`取消`:`Cancel`),u=((e={},t={})=>(t.locale??n())===`zh-TW`?`再次確認`:`Check again`),d=((e={},t={})=>(t.locale??n())===`zh-TW`?`選擇`:`Choices`),f=((e={},t={})=>(t.locale??n())===`zh-TW`?`瀏覽器拒絕存取剪貼簿。`:`The browser refused the clipboard.`),p=((e={},t={})=>(t.locale??n())===`zh-TW`?`已複製到這台裝置的剪貼簿。`:`Copied to this device's clipboard.`),m=((e={},t={})=>(t.locale??n())===`zh-TW`?`複製指令`:`Copy command`);function h(e,t,n,r){if(typeof t!=`string`||n!==void 0&&!r)return new e(t,n);let i=h;if(n!==void 0){let r=i.prototypeKeys??=new Set([`constructor`,`__defineGetter__`,`__defineSetter__`,`hasOwnProperty`,`__lookupGetter__`,`__lookupSetter__`,`isPrototypeOf`,`propertyIsEnumerable`,`toString`,`valueOf`,`__proto__`,`toLocaleString`]);if(Object.getOwnPropertyNames(Object.prototype).some(e=>!r.has(e)))return new e(t,n)}let a=[];for(let r of Object.keys(n??{}).sort()){let i=n[r];if(i!==void 0){if(i!==null&&![`string`,`number`,`boolean`].includes(typeof i)||typeof i==`number`&&!Number.isFinite(i))return new e(t,n);a.push([r,i])}}let o=JSON.stringify([t,a]),s=i.caches??=new WeakMap,c=s.get(e);if(c||(c=new Map,s.set(e,c)),c.has(o))return c.get(o);let l=new e(t,n);if(c.size>=256){let e=c.keys().next().value;e!==void 0&&c.delete(e)}return c.set(o,l),l}function g(e,t,n,r=!1){return h(Intl.PluralRules,e,n,r).select(Number(t)-Number(n?.offset??0))}var _=((e={},t={})=>(t.locale??n())===`zh-TW`?`切到終端機`:`Focus terminal`),v=((e={},t={})=>(t.locale??n())===`zh-TW`?`這個選項有預覽;請在終端機中查看。`:`It has a preview; see it in the terminal.`),y=((e={},t={})=>(t.locale??n())===`zh-TW`?`連不上 Herdr。`:`Herdr could not be reached.`),b=((e={},t={})=>(t.locale??n())===`zh-TW`?`未確認。請查看終端機。`:`Not confirmed. Check the terminal.`),x=((e={},t={})=>(t.locale??n())===`zh-TW`?`備註`:`Note`),S=((e={},t={})=>(t.locale??n())===`zh-TW`?`備註(選填)`:`Note (optional)`),C=((e={},t={})=>(t.locale??n())===`zh-TW`?`選項`:`Options`),w=((e={},t={})=>(t.locale??n())===`zh-TW`?`另一個答案沒有被採用;這個可以送出。`:`The other answer was not taken; this one can go.`),T=((e={},t={})=>(t.locale??n())===`zh-TW`?`你的答案`:`Your own answer`),E=((e={},t={})=>(t.locale??n())===`zh-TW`?`或自己輸入答案`:`Or type your own answer`),D=((e={},t={})=>(t.locale??n())===`zh-TW`?`問題已變更,請重新閱讀。`:`The question changed; read it again.`),O=((e={},t={})=>(t.locale??n())===`zh-TW`?`session 讀不懂這個答案。`:`The session could not read that answer.`),k=((e={},t={})=>(t.locale??n())===`zh-TW`?`這個答案不符合問題。`:`That answer does not fit the question.`),A=((e={},t={})=>(t.locale??n())===`zh-TW`?`session 拒絕了這個答案。`:`The session refused that answer.`),j=((e={},t={})=>(t.locale??n())===`zh-TW`?`送出答案`:`Send answer`),M=((e={},t={})=>(t.locale??n())===`zh-TW`?`送出中…`:`Sending…`),N=((e={},t={})=>(t.locale??n())===`zh-TW`?`顯示終端機`:`Show terminal`),P=((e={},t={})=>(t.locale??n())===`zh-TW`?`已在終端機中關閉。`:`It was dismissed in the terminal.`),F=((e={},t={})=>(t.locale??n())===`zh-TW`?`它已不再開啟。`:`It is no longer open.`),I=((e={},t={})=>(t.locale??n())===`zh-TW`?`已在終端機中回答。`:`It was already answered in the terminal.`),L=((e={},t={})=>(t.locale??n())===`zh-TW`?`連不上伺服器。`:`The server could not be reached.`),R=((e={},t={})=>(t.locale??n())===`zh-TW`?`它在等待對話框。`:`It waits on a dialog.`),z=e=>e.multiple?c():e.freeform&&e.options.length?s():``,B=(t,n)=>e(`div`,{class:`ask-one`},t.header&&e(`b`,{class:`ask-head`},t.header),e(`p`,{class:`ask-q`},t.question),t.context&&e(`div`,{class:`ask-ctx`},t.context),t.options.length>0&&e(`ol`,{class:`ask-opts`,"aria-label":C()},...t.options.map(t=>e(`li`,{class:`ask-opt`},e(`b`,null,t.title),t.description&&e(`small`,null,t.description)))),n&&z(t)&&e(`small`,{class:`ask-how`},z(t))),V=e=>e.replace(/[\u0000-\u0008\u000b-\u001f\u007f-\u009f]/g,`�`),H=(e,t)=>(e.select?.choices??[]).map((e,t)=>({...e,i:t})).filter(e=>!(t&&e.localOnly)),U=(e,t,n)=>({...e.size?{choices:[...e].sort((e,t)=>e-t)}:{},...t.trim()?{text:t}:{},...n.trim()?{note:n}:{}}),W=(e,t,n)=>({dialog:e.dialog,digest:e.digest,answerId:n,...t}),G={digest:D,"not-allowed":k,malformed:O};function K(e){let{outcome:n,reason:i,by:a}=e.body;return n===`accepted`?[`ok`,o()]:n===`stale`?[`error`,a===`local`?I():a===`cancel`?P():F()]:n===`rejected`?[`error`,(Object.hasOwn(G,String(i))?G[String(i)]:A)()]:n===`busy`?[`error`,r()]:n===`unknown`||e.status===504?[`error`,b(),!0]:[`error`,i??t({status:e.status})]}var q=e=>[`accepted`,`stale`,`busy`,`unknown`].includes(String(e.body.outcome))||e.status===504,J=e=>e.answer?`d\n${e.answer.dialog}\n${e.answer.digest}`:`c\n${e.callId}\n${e.why??``}`;function Y(t,n,r=location.hostname!==`127.0.0.1`,o){let s,c,l,h=!1,g=!1,D;for(let e of[`focusin`,`pointerdown`])document.addEventListener(e,e=>c&&!c.el.contains(e.target)&&(c.lost=void 0));let O=(e,t,n,...r)=>(e.dataset.tone=t,e.replaceChildren(n,...r)),k=()=>{if(!c)return;let e=document.activeElement;e&&e!==document.body&&e!==c.lost&&(c.lost=void 0),c.go.disabled=!h||g,c.controls.forEach(e=>e.disabled=!h||g||c.done),c.send&&(c.send.disabled=!h||g||c.done||!c.pick()),e&&c.el.contains(e)&&e.disabled&&(c.lost=e);let t=c.lost;t&&!t.disabled&&c.el.contains(t)&&(!document.activeElement||document.activeElement===document.body)&&(t.focus(),c.lost=void 0)};async function A(t,r){[t.sending,g,t.spell]=[!0,!0,!1],k(),O(t.note,``,M());let i=await n(`answer`,r).catch(()=>void 0),a=e(`button`,{type:`button`,class:`cmp-link`},u());a.onclick=()=>void A(t,r);let[o,s,c]=i?K(i):[`error`,b(),!0];[t.done,t.sending,g,t.busy]=[!i||q(i),!1,!1,i?.body.outcome===`busy`],O(t.note,o,s,...c?[a]:[]),k(),t.note.scrollIntoView?.({block:`nearest`})}let P=(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 F(t,n){let i,a=H(n,r).map(e=>P(`radio`,e.label,[e.note],()=>(i=e.i,a.forEach((t,i)=>t.setAttribute(`aria-checked`,String(H(n,r)[i].i===e.i))),k()),e.i+1)),o=n.select?.copy!==void 0&&e(`button`,{type:`button`,class:`cmp-link`},m());return o&&(o.disabled=!navigator.clipboard,o.onclick=()=>void navigator.clipboard.writeText(n.select.copy).then(()=>O(t.note,`ok`,p()),()=>O(t.note,`error`,f()))),t.pick=()=>i===void 0?void 0:{choice:i},t.controls=a,[e(`pre`,{class:`ask-title`},V(n.select.title)),e(`div`,{class:`ask-opts`,role:`radiogroup`,"aria-label":d()},...a),e(`div`,{class:`ask-acts`},t.send,o,t.go)]}function I(t,n){let r=n.questions.map(()=>({picks:new Set,text:e(`input`,{type:`text`,maxlength:`8192`,class:`ask-own`,placeholder:E(),"aria-label":T()}),note:e(`input`,{type:`text`,maxlength:`2048`,class:`ask-own ask-memo`,placeholder:S(),"aria-label":x()})})),i=n.questions.map((n,i)=>{let a=r[i],o=n.multiple?`checkbox`:`radio`,s=n.options.map((e,t)=>P(o,e.title,[e.description,e.preview&&v()],()=>{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)))),k()}));return a.text.oninput=()=>(n.multiple||(a.picks.clear(),s.forEach(e=>e.setAttribute(`aria-checked`,`false`))),k()),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":C()},...s),a.text,a.note)});return t.pick=()=>r.every(e=>e.picks.size||e.text.value.trim())?{answers:r.map(e=>U(e.picks,e.text.value,e.note.value))}:void 0,[...i,e(`div`,{class:`ask-acts`},t.send,t.go)]}function L(t){let r=t.asks??(t.ask?[t.ask]:[]),s=r.length>1,c=t.answer,l={key:J(t),el:e(`section`,{class:`ask`}),note:e(`p`,{class:`ask-note`,role:`status`,"aria-live":`polite`}),go:e(`button`,{type:`button`,class:`cmp-link`},_()),controls:[],pick:()=>void 0,done:!1,sending:!1};l.go.onclick=async()=>{g=!0,k();let e=await n(`focus`,{}).catch(()=>void 0);O(l.note,e?.ok?``:`error`,e?.ok?``:e?.body.reason??y()),g=!1,k()},c&&((l.send=e(`button`,{type:`button`,class:`ask-send`},j())).onclick=()=>void(l.pick()&&A(l,W(c,l.pick(),crypto.randomUUID()))));let u=e(`p`,{class:`ask-term`},t.why&&r.length?t.why:`${s?a():i()} ${s||!r[0]?``:z(r[0])}`.trim()),d=o&&t.tool!==`secret_drop`&&e(`button`,{type:`button`,class:`cmp-link`},N());return d&&(d.onclick=o),l.el.append(...c?c.select?F(l,c):I(l,c):[...r.length?r.map(e=>B(e,s)):[e(`p`,{class:`ask-why`},t.why??R())],e(`div`,{class:`ask-acts`},u,d,l.go)],l.note),l}let G=(e,n)=>{let r=document.activeElement;c&&c!==n&&(c.focus=c.el.contains(r)?r:void 0),[s,c,l]=[e,n,n?.send?n:l],t.replaceChildren(...n?[n.el]:[]),k(),n?.focus&&(!document.activeElement||document.activeElement===document.body)&&n.focus.focus()};return{update(e,t){h=t,e&&(D=void clearTimeout(D)),!e&&(c?.done||c?.sending)?D??=setTimeout(()=>(D=void 0,G()),6e3):e?c&&(J(e)===c.key||!e.answer&&(c.done||c.sending)&&e.callId===s?.callId)?((c.busy||c.sending)&&!e.answer?c.spell=!0:c.busy&&c.spell&&e.answer&&([c.done,c.busy]=[!1,!1],O(c.note,``,w())),s=e):G(e,l?.key===J(e)&&!l.done?l:L(e)):G(),k()}}}export{g as a,_ as i,L as n,l as o,M as r,Y as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as e}from"./post-
|
|
1
|
+
import{n as e}from"./post-C4WkBuZ3.js";import{E as t,l as n,n as r}from"./index-BkgejQW0.js";import{n as i,t as a}from"./views-Dgtkn3yx.js";var o=((e={},n={})=>(n.locale??t())===`zh-TW`?`分支摘要`:`branch summary`),s=((e={},n={})=>(n.locale??t())===`zh-TW`?`通訊紀錄`:`Comms log`),c=e=>`context compacted · ${e?.tokens} tokens summarized`,l=e=>`上下文已壓縮 · 摘要了 ${e?.tokens} tokens`,u=((e,n={})=>(n.locale??t())===`zh-TW`?l(e):c(e)),d=((e={},n={})=>(n.locale??t())===`zh-TW`?`…(於 1 MB 截斷)`:`… (cut at 1 MB)`),f=e=>`exit ${e?.code}`,p=e=>`結束碼 ${e?.code}`,m=((e,n={})=>(n.locale??t())===`zh-TW`?p(e):f(e)),h=e=>`${e?.count} image(s)`,g=e=>`${e?.count} 張圖片`,_=((e,n={})=>(n.locale??t())===`zh-TW`?g(e):h(e)),ee=((e={},n={})=>(n.locale??t())===`zh-TW`?`收到`:`incoming`),v=((e={},n={})=>(n.locale??t())===`zh-TW`?`跳到最新`:`jump to latest`),y=e=>`${e?.count} new`,b=e=>`${e?.count} 則新訊息`,x=((e,n={})=>(n.locale??t())===`zh-TW`?b(e):y(e)),S=((e={},n={})=>(n.locale??t())===`zh-TW`?`還沒有通訊。`:`No transmissions yet.`),C=((e={},n={})=>(n.locale??t())===`zh-TW`?`通知`:`notice`),w=((e={},n={})=>(n.locale??t())===`zh-TW`?`表單回覆`:`form answers`),T=((e={},n={})=>(n.locale??t())===`zh-TW`?`訊息,來自`:`message from`),E=((e={},n={})=>(n.locale??t())===`zh-TW`?`記憶`:`memory`),D=((e={},n={})=>(n.locale??t())===`zh-TW`?`監看`:`monitor`),O=((e={},n={})=>(n.locale??t())===`zh-TW`?`提問,來自`:`question from`),k=((e={},n={})=>(n.locale??t())===`zh-TW`?`回報,來自`:`report from`),A=((e={},n={})=>(n.locale??t())===`zh-TW`?`狀態:`:`status of`),j=((e={},n={})=>(n.locale??t())===`zh-TW`?`在旁開啟`:`open beside`),M=e=>`show all (${e?.size})`,N=e=>`顯示全部(${e?.size})`,P=((e,n={})=>(n.locale??t())===`zh-TW`?N(e):M(e)),F=((e={},n={})=>(n.locale??t())===`zh-TW`?`顯示全部參數`:`show all arguments`),I=e=>`◇ thought · ${e?.count} chars`,L=e=>`◇ 思考 · ${e?.count} 字元`,R=((e,n={})=>(n.locale??t())===`zh-TW`?L(e):I(e)),z=((e={},n={})=>(n.locale??t())===`zh-TW`?`◇ 思考 · 已遮蔽`:`◇ thought · redacted`),B=((e={},n={})=>(n.locale??t())===`zh-TW`?`無法取得`:`unavailable`),V=((e={},n={})=>(n.locale??t())===`zh-TW`?`你`:`you`);function H(){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?x({count:t}):v()}}async function U(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)}function W(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 te=e=>e?new Date(e).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`,hour12:!1}):``,ne=e=>e>=1024?`${(e/1024).toFixed(e>=10240?0:1)} KB`:`${e} B`,re={intercom_message:T,subagent_result:k,subagent_ping:O,subagent_status:A,"pi-loop-monitor":D,"memory-context":E,"doc-review":w},G=e=>{let t=n(`<span class="ava"><svg><use/></svg></span>`);return t.querySelector(`use`).setAttribute(`href`,`#i-${r[e]??e}`),t};function ie(t){let n=[],r=0;for(let i of t.matchAll(/https?:\/\/[^\s<>)\]]+/g))n.push(t.slice(r,i.index),e(`a`,{href:i[0],rel:`noopener noreferrer`,target:`_blank`},i[0])),r=i.index+i[0].length;return[...n,t.slice(r)]}function K(t,n,{who:r,link:c,docFor:l}){let f=W(),p=new Map,h=new Set,g=()=>h.forEach(e=>e.button.isConnected?(e.shown=!0,e.button.hidden=!e.paths.some(e=>l?.(e))):e.shown&&h.delete(e)),v=e(`div`,{class:`chat-list`}),y=e(`div`,{class:`chat-top`}),b=e(`div`,{class:`chat-live`}),x=e(`button`,{class:`chat-pill`,type:`button`,hidden:``}),w=e(`p`,{class:`chat-empty`},S()),T=e(`div`,{class:`chat-scroll`,tabindex:`-1`,"aria-label":s()},y,v,b);t.replaceChildren(T,x);let E=H(),D=!1,O=!1,k,A,M=0,N=()=>T.scrollHeight-T.scrollTop-T.clientHeight<80,I=(e=E.button(f.detached))=>(x.hidden=!e,x.textContent=e??``),L=()=>(E.jump(),A=void 0,T.scrollTop=T.scrollHeight,I());async function K(e){D=!0;let t=await U(f,n,e,e=>(X(e),Z(e))).finally(()=>D=!1),r=p.get(e);if(k===e){if(!t||!r)return L();E.hold(),A=r,r.scrollIntoView({block:`center`}),r.classList.remove(`lit`),r.offsetWidth,r.classList.add(`lit`),clearTimeout(M),M=window.setTimeout(()=>(A=void 0,r.classList.remove(`lit`)),2e3),I()}}let q=()=>k?void K(k):L(),J=(e,t,r,i)=>{e.disabled=!0,n.entry(r).then(n=>{let r=n&&i(n);if(r===void 0)return void(e.textContent=B());t.textContent=r,e.remove()},()=>e.textContent=B())};function ae(t,n){let r=f.result(t.id),i=e(`pre`,{class:`out`},r?.text??``),a=e(`pre`,{class:`args`},t.args??``),o=t.cut?e(`button`,{class:`more`,type:`button`},F()):null;o?.addEventListener(`click`,()=>J(o,a,n,e=>(e=>e&&`${e.args??``}${e.cut?`\n${d()}`:``}`)(e.tools?.find(e=>e.id===t.id))));let s=r?.more?e(`button`,{class:`more`,type:`button`},P({size:ne(r.bytes??0)})):null;s?.addEventListener(`click`,()=>J(s,i,r.id,e=>e.text));let c=t.name===`show_doc`&&l?e(`button`,{class:`more open`,type:`button`,hidden:``},j()):null;return c?.addEventListener(`click`,e=>(e.preventDefault(),t.summary.split(`, `).forEach(e=>l?.(e)?.()))),c&&h.add({paths:t.summary.split(`, `),button:c}),c&&queueMicrotask(g),e(`details`,{class:`act`},e(`summary`,{"data-mark":r?r.isError?`error`:`done`:`working`},e(`b`,{class:`badge`}),e(`code`,null,t.name),e(`span`,{class:`sum`},t.summary),c),a,o,r&&e(`div`,{class:`result`},r.images?e(`em`,null,_({count:r.images})):null,i,s))}function Y(t){let n=e(`time`,null,te(t.at));switch(t.kind){case`user`:return e(`article`,{class:`tx you`},e(`header`,null,n,e(`b`,null,V()),G(`user`)),e(`div`,{class:`bubble`},...ie(t.text??``),t.images?e(`em`,null,` · ${_({count:t.images})}`):null));case`assistant`:{let o=r(),s=e(`pre`,{class:`thought-text`}),c=t.thought?e(`button`,{class:`thought`,type:`button`},t.thought<0?z():R({count:t.thought.toLocaleString()})):null;return t.thought&&t.thought>0&&c?.addEventListener(`click`,()=>J(c,s,t.id,e=>e.thoughtText)),e(`article`,{class:`tx in`},G(o.role),e(`div`,{class:`tx-body`},e(`header`,null,e(`b`,null,o.name),t.model?e(`span`,null,t.model):null,n,t.stop?e(`span`,{class:`stop`,"data-mark":`error`},t.stop):null),c,s,t.text?e(`div`,{class:`md`},a(i(t.text))):null,t.error?e(`p`,{class:`fault`},t.error):null,...(t.tools??[]).map(e=>ae(e,t.id))))}case`bash`:return e(`article`,{class:`tx sys`},e(`details`,{class:`act`},e(`summary`,{"data-mark":t.exit?`error`:`done`},e(`b`,{class:`badge`}),e(`code`,null,`shell`),e(`span`,{class:`sum`},`! ${t.command}`),t.exit?e(`span`,{class:`stop`,"data-mark":`error`},m({code:t.exit})):null),t.text?e(`pre`,{class:`out`},t.text):null));case`notice`:return e(`article`,{class:`tx sys`},e(`details`,{class:`notice`},e(`summary`,null,G(`comms`),e(`em`,null,ee()),re[t.type??``]?.()??t.type??C(),` `,t.from&&c(t.from)||(t.from??``),n),e(`pre`,null,t.text??``)));case`divider`:return e(`article`,{class:`tx rule`},e(`details`,null,e(`summary`,null,t.type===`compaction`?u({tokens:(t.tokens??0).toLocaleString()}):o()),e(`pre`,null,t.text??``)));default:return e(`article`,{class:`tx note`},t.text??``,` `,n)}}function X(e){e.rebuild&&(p.clear(),v.replaceChildren());for(let t of e.dropped)p.get(t)?.remove(),p.delete(t);let t=e.added.map(e=>(p.set(e.id,Y(e)),p.get(e.id)));e.front?v.prepend(...t):v.append(...t),w.remove(),f.items.length||v.append(w),y.hidden=!f.before}let Z=e=>e.touched.forEach(e=>{let t=p.get(e),n=f.items.find(t=>t.id===e);if(t&&n){let r=Y(n);t.replaceWith(r),p.set(e,r)}}),Q=async()=>{if(!D&&f.before&&O){D=!0;try{let e=T.scrollHeight,t=f.prepend(await n.older(f.before));X(t),Z(t),T.scrollTop+=T.scrollHeight-e}finally{D=!1}f.before&&T.clientHeight&&y.getBoundingClientRect().bottom>=T.getBoundingClientRect().top&&Q()}};new IntersectionObserver(e=>e.some(e=>e.isIntersecting)&&void Q(),{root:T}).observe(y),x.addEventListener(`click`,()=>{k=void 0,f.detached?n.latest().then(e=>(X(f.reset(e)),L())):L()}),T.addEventListener(`scroll`,()=>(E.scrolled(N()),I()),{passive:!0});for(let e of[`wheel`,`touchstart`,`pointerdown`,`keydown`])T.addEventListener(e,()=>A=k=void 0,{passive:!0});let $=new ResizeObserver(()=>E.pinned&&!f.detached?T.scrollTop=T.scrollHeight:A?.scrollIntoView({block:`center`}));return $.observe(v),$.observe(T),{log:T,docs:g,apply(e){if(e.reset)X(f.reset({items:e.items??[],before:e.before})),O=!0,q();else if(e.items?.length){let t=f.append(e.items);X(t),Z(t),E.arrived(t.added.length)&&!f.detached?L():I()}},reveal(e){k=e,O&&q()},setLive(t,n){b.dataset.mark=n,b.lastChild?.textContent!==t&&b.replaceChildren(...t?[e(`b`,{class:`badge`}),e(`span`,null,t)]:[])}}}export{K as mountChat};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e={},t=[`en`,`zh-TW`],n=`PARAGLIDE_LOCALE`,r=[`baseLocale`],i=[],a=typeof window>`u`;globalThis.__paraglide=globalThis.__paraglide??{},globalThis.__paraglide.ssr=globalThis.__paraglide.ssr??{};var o=!1,s=()=>{let e=r;!a&&typeof window<`u`&&window.location?.href&&(e=g(window.location.href));let t=c(e,typeof window<`u`?window.location?.href:void 0);if(t)return o||(o=!0,d(t,{reload:!1})),t;throw Error(`No locale found. Read the docs https://paraglidejs.com/errors#no-locale-found`)};function c(e,t){let n;for(let t of e){if(t===`baseLocale`)n=`en`;else if(de(t)&&_.has(t)){let e=_.get(t);if(e){let t=e.getLocale();if(t instanceof Promise)continue;if(t!==void 0)return te(t)}}let e=f(n);if(e)return e}}var l=e=>{s=e},u=e=>{e?window.location.href=e:window.location.reload()},d=(e,t)=>{let n={reload:!0,...t},i;try{i=s()}catch{}let o=[],c=r;!a&&typeof window<`u`&&window.location?.href&&(c=g(window.location.href));for(let t of c)if(t===`baseLocale`)continue;else if(de(t)&&_.has(t)){let n=_.get(t);if(n){let r=n.setLocale(e);r instanceof Promise&&(r=r.catch(e=>{throw Error(`Custom strategy "${t}" setLocale failed.`,{cause:e})}),o.push(r))}}let l=()=>{!a&&n.reload&&window.location&&e!==i&&u(void 0)};if(o.length)return Promise.all(o).then(()=>{l()});l()},ee=()=>typeof window<`u`?window.location.origin:`http://fallback.com`;function f(e){if(typeof e!=`string`)return;let n=e.toLowerCase();for(let e of t)if(e.toLowerCase()===n)return e}function te(e){let n=f(e);if(n)return n;throw Error(`Invalid locale: ${e}. Expected one of: ${t.join(`, `)}`)}function p(e){return e}function ne(t,n){return new e(t,n.href)}function re(){return 0}function ie(e){return i}function ae(e,t){return e.exec(t.href)}var oe=n.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`);RegExp(`(?:^|;\\s*)${oe}=([^;]*)`);function se(e){return ce(e)}function ce(e){let t=p(typeof e==`string`?new URL(e,ee()):new URL(e.href)),n=t.pathname.replace(/^\/+/,``).split(`/`);return n.length>0&&f(n[0])&&(t.pathname=`/`+n.slice(1).join(`/`)),p(t)}var le=-1,m,h;function ue(e){if(i.length===0)return;let t=typeof e==`string`?e:e.href,n=re();if(m===t&&le===n)return h;let r=p(new URL(t,`http://example.com`)),a=se(r),o=a.href===r.href?[r]:[r,a],s;for(let e of o){for(let t of ie(e))if(ae(ne(t.match,e),e)){s=t;break}if(s)break}return le=n,m=t,h=s,s}function g(e){let t=ue(e);return t&&t.exclude!==!0&&Array.isArray(t.strategy)?t.strategy:r}var _=new Map;function de(e){return typeof e==`string`&&/^custom-[A-Za-z0-9_-]+$/.test(e)}var fe=((e={},t={})=>(t.locale??s())===`zh-TW`?`警示`:`Alerts`),pe=((e={},t={})=>(t.locale??s())===`zh-TW`?`所有基地`:`all bases`),me=((e={},t={})=>(t.locale??s())===`zh-TW`?``:`.`),he=((e={},t={})=>(t.locale??s())===`zh-TW`?`最後更新:`:`Last update`),ge=e=>`Disconnected. Gave up after ${e?.tries} tries; it reconnects when you return to this tab.`,_e=e=>`連線中斷。重試 ${e?.tries} 次後放棄;回到此分頁時會重新連線。`,ve=((e,t={})=>(t.locale??s())===`zh-TW`?_e(e):ge(e)),ye=e=>`The server is up but cannot read the net: ${e?.problem}`,be=e=>`伺服器正常,但讀不到網:${e?.problem}`,xe=((e,t={})=>(t.locale??s())===`zh-TW`?be(e):ye(e)),Se=((e={},t={})=>(t.locale??s())===`zh-TW`?`與稻草網的連線中斷,正在重新連線…畫面顯示的是最後已知狀態。`:`Disconnected from the straw net. Reconnecting… The view shows the last known state.`),Ce=e=>`Disconnected from the straw net. Reconnecting (try ${e?.attempt})… The view shows the last known state.`,we=e=>`與稻草網的連線中斷,正在重新連線(第 ${e?.attempt} 次)…畫面顯示的是最後已知狀態。`,Te=((e,t={})=>(t.locale??s())===`zh-TW`?we(e):Ce(e)),Ee=((e={},t={})=>(t.locale??s())===`zh-TW`?`Straw Net:所有基地`:`Straw Net: all bases`),De=e=>`control tower · ${e?.state}`,Oe=e=>`塔台 · ${e?.state}`,ke=((e,t={})=>(t.locale??s())===`zh-TW`?Oe(e):De(e)),Ae=((e={},t={})=>(t.locale??s())===`zh-TW`?`圖示來自 game-icons.net(Lorc、Delapouite),CC BY 3.0。`:`Icons from game-icons.net by Lorc and Delapouite, CC BY 3.0.`),je=((e={},t={})=>(t.locale??s())===`zh-TW`?`文件`:`Documents`),Me=((e={},t={})=>(t.locale??s())===`zh-TW`?`還沒有工作區。在 Herdr 開一個 pi session,網就會出現在這裡。`:`No workspaces yet. Open a pi session in Herdr and the net appears here.`),Ne=((e={},t={})=>(t.locale??s())===`zh-TW`?`總塔台`:`head tower`),Pe=((e={},t={})=>(t.locale??s())===`zh-TW`?`語言`:`Language`),v=((e={},t={})=>(t.locale??s())===`zh-TW`?`連線中`:`connecting`),Fe=((e={},t={})=>(t.locale??s())===`zh-TW`?`即時`:`live`),Ie=((e={},t={})=>(t.locale??s())===`zh-TW`?`離線`:`offline`),Le=((e={},t={})=>(t.locale??s())===`zh-TW`?`重新連線中`:`reconnecting`),Re=((e={},t={})=>(t.locale??s())===`zh-TW`?`正體中文`:`English`),ze=((e={},t={})=>(t.locale??s())===`zh-TW`?`位置`:`Location`),Be=e=>`${e?.name} finished`,Ve=e=>`${e?.name} 已完成`,He=((e,t={})=>(t.locale??s())===`zh-TW`?Ve(e):Be(e)),Ue=e=>`${e?.name} hit an error`,We=e=>`${e?.name} 發生錯誤`,Ge=((e,t={})=>(t.locale??s())===`zh-TW`?We(e):Ue(e)),Ke=e=>`${e?.name} went idle`,qe=e=>`${e?.name} 轉為閒置`,Je=((e,t={})=>(t.locale??s())===`zh-TW`?qe(e):Ke(e)),Ye=e=>`${e?.name} joined`,Xe=e=>`${e?.name} 加入`,Ze=((e,t={})=>(t.locale??s())===`zh-TW`?Xe(e):Ye(e)),Qe=e=>`${e?.name} left`,$e=e=>`${e?.name} 離開`,et=((e,t={})=>(t.locale??s())===`zh-TW`?$e(e):Qe(e)),tt=e=>`${e?.name} lost its status`,nt=e=>`${e?.name} 失去狀態`,rt=((e,t={})=>(t.locale??s())===`zh-TW`?nt(e):tt(e)),it=e=>`${e?.name} is waiting on a question`,at=e=>`${e?.name} 正在等待回答`,ot=((e,t={})=>(t.locale??s())===`zh-TW`?at(e):it(e)),st=e=>`${e?.name} started working`,ct=e=>`${e?.name} 開始工作`,lt=((e,t={})=>(t.locale??s())===`zh-TW`?ct(e):st(e)),y=((e={},t={})=>(t.locale??s())===`zh-TW`?`已完成`:`finished`),b=((e={},t={})=>(t.locale??s())===`zh-TW`?`錯誤`:`error`),x=((e={},t={})=>(t.locale??s())===`zh-TW`?`閒置`:`idle`),ut=((e={},t={})=>(t.locale??s())===`zh-TW`?`無狀態`:`no status`),S=((e={},t={})=>(t.locale??s())===`zh-TW`?`等待回答`:`waiting on a question`),dt=((e={},t={})=>(t.locale??s())===`zh-TW`?`工作中`:`working`),ft=((e={},t={})=>(t.locale??s())===`zh-TW`?`網的動態`:`Net log`),pt=((e={},t={})=>(t.locale??s())===`zh-TW`?`從未`:`never`),mt=((e={},t={})=>(t.locale??s())===`zh-TW`?`沒有執行中的智慧體`:`no agent running`),ht=((e={},t={})=>(t.locale??s())===`zh-TW`?`無警示`:`no alerts`),gt=((e={},t={})=>(t.locale??s())===`zh-TW`?`尚無塔台`:`no tower yet`),_t=((e={},t={})=>(t.locale??s())===`zh-TW`?`思考中`:`thinking`),vt=((e={},t={})=>(t.locale??s())===`zh-TW`?`前哨`:`Outposts`),yt=((e={},t={})=>(t.locale??s())===`zh-TW`?`手機`:`Phone`),bt=((e={},t={})=>(t.locale??s())===`zh-TW`?`透過 Tailscale 配對手機`:`Pair a phone over Tailscale`),xt=((e={},t={})=>(t.locale??s())===`zh-TW`?`伺服器送來的快照,頁面無法讀取`:`the server sent a snapshot the page cannot read`),St=((e={},t={})=>(t.locale??s())===`zh-TW`?`伺服器回報了頁面無法讀取的問題`:`the server reported a problem the page cannot read`),Ct=((e={},t={})=>(t.locale??s())===`zh-TW`?`主智慧體`:`main`),wt=((e={},t={})=>(t.locale??s())===`zh-TW`?`成員`:`member`),Tt=((e={},t={})=>(t.locale??s())===`zh-TW`?`前哨`:`outpost`),Et=((e={},t={})=>(t.locale??s())===`zh-TW`?`未編入`:`unaligned`),Dt=((e={},t={})=>(t.locale??s(),`session`)),Ot=((e={},t={})=>(t.locale??s())===`zh-TW`?`子智慧體`:`subagent`),kt=((e={},t={})=>(t.locale??s())===`zh-TW`?`塔台`:`tower`),At=((e={},t={})=>(t.locale??s())===`zh-TW`?`智慧體`:`Agents`),jt=((e={},t={})=>(t.locale??s())===`zh-TW`?`基地`:`Bases`),Mt=((e={},t={})=>(t.locale??s())===`zh-TW`?`等待中`:`Waiting`),Nt=((e={},t={})=>(t.locale??s())===`zh-TW`?`工作中`:`Working`),Pt=((e={},t={})=>(t.locale??s())===`zh-TW`?`狀態`:`States`),Ft=e=>`tab ${e?.label}`,It=e=>`分頁 ${e?.label}`,Lt=((e,t={})=>(t.locale??s())===`zh-TW`?It(e):Ft(e)),Rt=((e={},t={})=>(t.locale??s())===`zh-TW`?`即時網況 · 通訊`:`live net · comms`),zt=((e={},t={})=>(t.locale??s())===`zh-TW`?`網的總計`:`Net totals`),Bt=e=>`${e?.label} tower`,Vt=e=>`${e?.label} 塔台`,Ht=((e,t={})=>(t.locale??s())===`zh-TW`?Vt(e):Bt(e)),Ut=e=>`using ${e?.tool}`,Wt=e=>`使用 ${e?.tool}`,Gt=((e,t={})=>(t.locale??s())===`zh-TW`?Wt(e):Ut(e)),Kt=((e={},t={})=>(t.locale??s())===`zh-TW`?`等待變化…`:`Waiting for changes…`),qt=`sb-locale`;function Jt(e){let t=/^zh\b/i.test(e)&&(/-(hant|tw|hk|mo)\b/i.test(e)?`zh-TW`:/-(hans|cn|sg|my)\b/i.test(e)?`zh-CN`:void 0);return f(e)??(t?f(t):void 0)??f(e.split(`-`)[0])}function Yt(e,t){return f(e)??t.map(Jt).find(Boolean)??`en`}var Xt={brand_label:Ee,tagline:Rt,totals_label:zt,stat_bases:jt,stat_agents:At,stat_working:Nt,stat_waiting:Mt,alerts:fe,no_alerts:ht,pair_button:yt,pair_title:bt,link_connecting:v,location:ze,all_bases:pe,empty_map:Me,documents:je,net_log:ft,states:Pt,mark_working:dt,mark_waiting:S,mark_idle:x,mark_done:y,mark_error:b,credit:Ae,language:Pe,waiting_changes:Kt};Object.keys(Xt);function Zt(){let e=null;try{e=localStorage.getItem(qt)}catch{}let n=Yt(e,navigator.languages??[navigator.language]);l(()=>n),document.documentElement.lang=n;let r={m:(e,t)=>e.textContent=t,mLabel:(e,t)=>e.setAttribute(`aria-label`,t),mTitle:(e,t)=>e.title=t,mEmpty:(e,t)=>e.dataset.empty=t};for(let e of document.querySelectorAll(`[data-m], [data-m-label], [data-m-title], [data-m-empty]`))for(let[t,n]of Object.entries(r))e.dataset[t]&&n(e,Xt[e.dataset[t]]?.()??e.dataset[t]);let i=document.getElementById(`lang`);i.replaceChildren(...t.map(e=>new Option(Re({},{locale:e}),e,!1,e===n))),i.onchange=()=>{try{localStorage.setItem(qt,i.value),location.reload()}catch{i.value=n}}}var Qt={working:lt,waiting:ot,idle:Je,done:He,error:Ge,unknown:rt};function $t(e){let t=new Map;for(let n of e.bases){n.tower&&t.set(`tower:${n.id}`,{name:Ht({label:n.label}),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 en(e,t){if(!e)return[];let[n,r]=[$t(e),$t(t)],i=[];for(let[e,t]of r){let r=n.get(e);r?r.mark!==t.mark&&i.push({text:Qt[t.mark]({name:t.name}),mark:t.mark}):i.push({text:Ze({name:t.name}),mark:t.mark})}for(let[e,t]of n)r.has(e)||i.push({text:et({name:t.name}),mark:`idle`});return i}var tn=e=>e===`waiting`||e===`error`?0:1;function nn(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 rn(e,t){return[...t.values()].filter(t=>e?.get(t.key)?.mark!==t.mark&&(tn(t.mark)===0||e!==void 0&&t.mark===`done`))}var an=e=>{try{return decodeURIComponent(e)}catch{return e}},C=e=>/^\.+$/.test(e)?e.replaceAll(`.`,`%2E`):encodeURIComponent(e);function w(e){let[t,n]=e.split(`#`)[0].split(`?`),[r,i,a,o]=t.replace(/^\/+|\/+$/g,``).split(`/`).map(an);if(r!==`w`||!i)return{view:`map`};if(a!==`s`||!o)return{view:`workspace`,ws:i};let s=new URLSearchParams(n).get(`at`);return s?{view:`session`,ws:i,key:o,at:s}:{view:`session`,ws:i,key:o}}var T=e=>e.view===`map`?``:e.view===`workspace`?`w/${C(e.ws)}`:`w/${C(e.ws)}/s/${C(e.key)}${e.at?`?at=${encodeURIComponent(e.at)}`:``}`,on=e=>e.view===`session`?{view:`workspace`,ws:e.ws}:{view:`map`},E=e=>e.view===`session`?e.key:e.view===`workspace`?`w:${e.ws}`:null;function sn(e,t=new URL(document.baseURI).pathname){let n=()=>w(location.pathname.slice(t.length)+location.search),r={route:n,href:e=>T(e)||`./`,go(n){let r=t+T(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(w(t.getAttribute(`data-route`))))}),r}var cn={main:`main`,member:`member`,subagent:`subagent`,outpost:`outpost`,outside:`outside`,tower:`tower`},D={working:dt,waiting:S,idle:x,done:y,error:b,unknown:ut},ln={main:Ct,member:wt,subagent:Ot,tower:kt,outpost:Tt,outside:Et,session:Dt},un={thinking:_t,idle:x,"waiting on a question":S,finished:y},dn=e=>Object.hasOwn(ln,e)?ln[e]():e,fn=e=>e===`waiting`||e===`error`,O=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)},k=(e,t)=>{let n=document.getElementById(e);if(!(n instanceof t))throw Error(`#${e} is missing from the page`);return n},A=(e,t,n)=>{let r=e.querySelector(t);r.textContent!==n&&(r.textContent=n)},j=(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`))},M=(e,t)=>e?e.startsWith(`tool:`)?Gt({tool:e.slice(5)}):Object.hasOwn(un,e)?un[e]():e:D[t](),N=(e,t)=>{e.toggleAttribute(`hidden`,!t),t&&(e.setAttribute(`href`,T(t)||`./`),e.setAttribute(`data-route`,T(t)))},pn=`<div class="plate"><i class="ring"></i><svg><use href="#i-main"/></svg><b class="badge"></b></div>`;function mn(e,t,n,r){j(e,n);let i=e.querySelector(`use`),a=`#i-${cn[t]??`member`}`,o=r?.filter(e=>e.onScreen).length;i.getAttribute(`href`)!==a&&i.setAttribute(`href`,a),o?e.dataset.docs=String(o):delete e.dataset.docs}function P(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 F=()=>O(`<div class="unit"><div class="card"><a class="hit"></a>${pn}<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 I(e,t){let n=e.closest(`.base`)?.dataset.key,r=e.querySelector(`.hit`);N(r,t.key&&n?{view:`session`,ws:n,key:t.key}:void 0),r.setAttribute(`aria-label`,`${t.name}: ${M(t.note,t.mark)}`),r.toggleAttribute(`data-alert`,fn(t.mark)),j(e,t.mark),mn(e.querySelector(`.plate`),t.role,t.mark,t.docs),A(e,`.name`,t.name),A(e,`.role`,dn(t.role)),A(e,`.note`,M(t.note,t.mark)),P(e.querySelector(`.subs`),t.subs??[],F,I)}var hn=()=>O(`<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>${Ne()}</span><h2><a class="enter-base"></a></h2><p></p></div></header><div class="tabs"></div><div class="outposts" data-label="${vt()}"></div></section>`);function gn(e,t){j(e,t.mark),e.classList.toggle(`head`,t.head);let n=e.querySelector(`.tower`);n.classList.toggle(`ghost`,!t.tower),j(n,t.tower?.mark??`unknown`),A(e,`h2 a`,t.label),N(e.querySelector(`h2 a`),{view:`workspace`,ws:t.id}),A(e,`.title p`,t.tower?ke({state:D[t.tower.mark]()}):gt()),P(e.querySelector(`.tabs`),t.tabs,()=>O(`<div class="tab"><h3></h3><div class="units"></div></div>`),(e,t)=>{A(e,`h3`,Lt({label:t.label})),P(e.querySelector(`.units`),t.units,F,I)}),P(e.querySelector(`.outposts`),t.outposts.map(e=>({id:e.id,name:e.label,role:`outpost`,mark:e.mark,note:e.mark===`unknown`?mt():void 0})),F,I)}function _n(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 vn(){let[e,t,n,r]=[k(`map`,HTMLElement),k(`bases`,HTMLElement),k(`links`,SVGSVGElement),k(`log`,HTMLElement)],i=matchMedia(`(prefers-reduced-motion: reduce)`).matches,a=()=>!e.hidden&&_n(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`)]])k(t,HTMLElement).textContent=r},show(e){P(t,e.bases,hn,gn),k(`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=O(`<li><span></span><time></time></li>`);e.dataset.mark=n.mark,A(e,`span`,n.text),A(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 yn=45e3,bn=1e3,xn=3e4,Sn=(e,t)=>Math.min(xn,bn*2**(e-1))*(.8+.4*t);function Cn(e){try{return JSON.parse(e)}catch{return}}function wn(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(),yn),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,Sn(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=Cn(r);i&&e.onNet(i),o({problem:i?void 0:xt()}),l()}),n.listen(`ping`,()=>t===n&&l()),n.listen(`problem`,e=>{t===n&&(o({problem:Cn(e)??St()}),l())}),r=e.setTimeout(()=>u(),yn)};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 Tn=(function(){let e=typeof document<`u`&&document.createElement(`link`).relList;return e&&e.supports&&e.supports(`modulepreload`)?`modulepreload`:`preload`})(),En=function(e,t){return new URL(e,t).href},Dn={},On=function(e){return e.pathname.endsWith(`.css`)},kn=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},L=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=En(t,n);let r=s(t),i=On(r);return kn(Dn,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`:Tn,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)})};Zt();var R=vn(),z=e=>document.getElementById(e),An=e=>e?new Date(e).toLocaleTimeString([],{hour12:!1}):pt(),jn,Mn,B,V,H={state:`connecting`,attempt:0},U={view:`map`},Nn=!1,W,Pn=``,G,Fn,K=e=>G?e(G):void Fn?.then(e);function In(){Fn??=L(async()=>{let{mountFocus:e}=await import(`./views-Dgtkn3yx.js`);return{mountFocus:e}},[],import.meta.url).then(({mountFocus:e})=>(G=e({data:Gn,restart:()=>$.restart(),openTile:Rn,openTerminal:(e,t)=>J(n=>n.terminal.open(e,t)),online:()=>H.state===`live`}),G.show(U,U),B&&G.net(B),G))}var q,Ln,J=e=>{if(q)return e(q);Ln??=L(async()=>{let{mountPanels:e}=await import(`./layer-DIbW2CGy.js`);return{mountPanels:e}},[],import.meta.url).then(({mountPanels:e})=>q=e({label:e=>B?.bases.find(t=>t.id===e)?.label??e,recent:async e=>(await(Q?Q.data(e).latest():Z(e,`?limit=12`))).items,post:e=>Q&&((t,n)=>Q.data(e).post(t,n)),stream:()=>Pn})),Ln.then(e)},Rn=(e,t)=>J(n=>n.tiles.open(e,t));function Y(e){if(B=V=e,document.hidden)return;R.stats(e);let t=nn(e,Date.now()),n=rn(W,t);(n.length||q)&&J(e=>e.alerts(n,t)),W=t,R.log(en(Mn,e)),Mn=e,K(t=>t.net(e)),U.view===`map`&&(R.show(e),jn=e,V=void 0)}function zn(e){let t=U,n=e.view===`workspace`&&t.view===`map`?document.querySelector(`#bases [data-key="${CSS.escape(e.ws)}"]`)?.getBoundingClientRect():void 0;U=e,e.view!==`map`&&In(),z(`map`).hidden=e.view!==`map`,z(`legend`).hidden=e.view===`session`,R.still(e.view!==`map`),K(r=>r.show(e,t,n)),e.view===`map`&&B&&B!==jn&&(Y(B),requestAnimationFrame(R.layout)),Nn&&E(e)!==E(t)&&$.restart()}function X(e){H=e;let t=e.state===`reconnecting`||e.state===`offline`;document.body.dataset.stale=z(`stage`).dataset.stale=String(t),z(`link`).dataset.state=e.state,z(`link-text`).textContent={connecting:v,live:Fe,reconnecting:Le,offline:Ie}[e.state](),G&&B&&G.net(B),q?.stack.redraw();let n=z(`banner`);n.hidden=!t&&!e.problem;let r=e.state===`offline`?ve({tries:e.attempt-1}):e.state===`reconnecting`?e.attempt?Te({attempt:e.attempt}):Se():xe({problem:e.problem??``}),i=document.createElement(`b`);i.textContent=An(e.lastContact),n.replaceChildren(`${r} ${he()} `,i,me())}function Bn(e,t){try{let n=JSON.parse(t);K(t=>e===`history`?t.history(n):t.cards(n))}catch{}}var Vn=document.querySelector(`meta[name="sb-build"]`)?.content,Hn=e=>!!(Vn&&Vn!==JSON.parse(e).build);function Un(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 Wn=e=>fetch(`api/${e}`,{cache:`no-store`}).then(e=>e.ok?e.json():Promise.reject(Error(String(e.status)))),Z=(e,t=``)=>Wn(`history/${encodeURIComponent(e)}${t}`),Q=void 0,Gn=e=>({older:t=>Z(e,`?before=${encodeURIComponent(t)}`),latest:()=>Z(e),entry:t=>Wn(`entry/${encodeURIComponent(e)}/${encodeURIComponent(t)}`).catch(()=>void 0)}),Kn=()=>{let e=Un(E(U));return e.listen(`history`,e=>Bn(`history`,e)),e.listen(`cards`,e=>Bn(`cards`,e)),e.listen(`hello`,e=>Hn(e)?location.reload():(Pn=e,q?.terminal.hello())),e.listen(`mirror`,e=>q?.terminal.frame(e)),e};document.addEventListener(`click`,e=>{let t=e.target?.closest?.(`a[data-alert]`),n=t&&w(t.getAttribute(`data-route`)??``);if(!n||n.view!==`session`||e.button!==0||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;let r=W?.get(n.key);r&&(e.preventDefault(),J(e=>e.stack.show(r)))},!0);var qn=sn(e=>zn(e)),$=wn({open:Kn,now:Date.now,setTimeout:(e,t)=>window.setTimeout(e,t),clearTimeout:e=>window.clearTimeout(e),random:Math.random,hidden:()=>document.hidden,onNet:Y,onStatus:X}),Jn=()=>$.resume();document.addEventListener(`visibilitychange`,()=>{if(R.pause(document.hidden),document.hidden)return $.hide();V&&Y(V),K(e=>e.wake()),Jn()}),addEventListener(`keydown`,e=>{e.key!==`Escape`||e.defaultPrevented||(e.preventDefault(),!q?.stack.close()&&U.view!==`map`&&qn.go(on(U)))}),z(`pair`).addEventListener(`click`,()=>void L(async()=>{let{pairTile:e}=await import(`./pair-B_oUhsbt.js`);return{pairTile:e}},[],import.meta.url).then(({pairTile:e})=>Rn(e(),!0)));for(let e of[`focus`,`pageshow`,`online`])window.addEventListener(e,()=>!document.hidden&&Jn());X(H),zn(qn.route()),$.start(),Nn=!0;export{je as C,s as E,Ne as S,pe as T,Mt as _,N as a,ht as b,mn as c,dn as d,P as f,Nt as g,tn as h,pn as i,O as l,fn as m,cn as n,k as o,A as p,D as r,M as s,L as t,j as u,vt as v,ke as w,mt as x,gt as y};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as e,n as t,o as n,t as r}from"./ask-Bw5jOgnx.js";import{n as i,r as a,t as o}from"./post-DQSLbWA2.js";import{E as s,a as c,b as l,c as u,d,f,h as p,i as m,l as h,o as g,p as _,s as v,u as ee}from"./index-CDEHVJil.js";var y=e=>`Alerts: ${e?.tally}`,b=e=>`警示:${e?.tally}`,te=((e,t={})=>(t.locale??s())===`zh-TW`?b(e):y(e)),x=e=>`Also queued: ${e?.tally}`,S=e=>`佇列中還有:${e?.tally}`,ne=((e,t={})=>(t.locale??s())===`zh-TW`?S(e):x(e)),C=((e={},t={})=>(t.locale??s())===`zh-TW`?`關閉`:`Close`),w=((e={},t={})=>(t.locale??s())===`zh-TW`?`關閉文件`:`Close document`),T=e=>`Close ${e?.title}`,E=e=>`關閉 ${e?.title}`,re=((e,t={})=>(t.locale??s())===`zh-TW`?E(e):T(e)),D=((e={},t={})=>(t.locale??s())===`zh-TW`?`連線中…`:`Connecting…`),O=((e={},t={})=>(t.locale??s())===`zh-TW`?`警示`:`alert`),ie=((e={},t={})=>(t.locale??s())===`zh-TW`?`符合寬度`:`Fit width`),ae=((e={},t={})=>(t.locale??s())===`zh-TW`?`無法取得紀錄。`:`History unavailable.`),oe=((e={},t={})=>(t.locale??s())===`zh-TW`?`退格鍵`:`Backspace`),k=((e={},t={})=>(t.locale??s())===`zh-TW`?`下`:`Down`),A=((e={},t={})=>(t.locale??s(),`End`)),j=((e={},t={})=>(t.locale??s(),`Enter`)),M=((e={},t={})=>(t.locale??s(),`Escape`)),N=((e={},t={})=>(t.locale??s(),`Home`)),P=((e={},t={})=>(t.locale??s())===`zh-TW`?`左`:`Left`),F=((e={},t={})=>(t.locale??s())===`zh-TW`?`下一頁`:`Page down`),I=((e={},t={})=>(t.locale??s())===`zh-TW`?`上一頁`:`Page up`),L=((e={},t={})=>(t.locale??s())===`zh-TW`?`右`:`Right`),R=((e={},t={})=>(t.locale??s(),`Shift+Tab`)),z=((e={},t={})=>(t.locale??s())===`zh-TW`?`空白鍵`:`Space`),B=((e={},t={})=>(t.locale??s(),`Tab`)),V=((e={},t={})=>(t.locale??s())===`zh-TW`?`上`:`Up`),H=e=>`Keys for ${e?.name}`,U=e=>`${e?.name} 的按鍵`,W=((e,t={})=>(t.locale??s())===`zh-TW`?U(e):H(e)),G=((e={},t={})=>(t.locale??s())===`zh-TW`?`最後一則通訊`:`Last transmission`),K=((e={},t={})=>(t.locale??s())===`zh-TW`?`稍後`:`Later`),q=((e={},t={})=>(t.locale??s())===`zh-TW`?`已離開網`:`left the net`),se=e=>`The mirror ended: ${e?.why}`,ce=e=>`鏡像已結束:${e?.why}`,le=((e,t={})=>(t.locale??s())===`zh-TW`?ce(e):se(e)),ue=((e={},t={})=>(t.locale??s())===`zh-TW`?`等待輸入密碼時隱藏;請在終端機中輸入。`:`Hidden while it waits for a secret; type it in the terminal.`),de=e=>`Live · ${e?.cols}×${e?.rows}`,fe=e=>`即時 · ${e?.cols}×${e?.rows}`,pe=((e,t={})=>(t.locale??s())===`zh-TW`?fe(e):de(e)),me=((e={},t={})=>(t.locale??s())===`zh-TW`?`還沒有訊息。`:`No messages yet.`),he=((e={},t={})=>(t.locale??s())===`zh-TW`?`開啟通訊`:`Open comms`),ge=((e={},t={})=>(t.locale??s())===`zh-TW`?`此分頁隱藏時暫停。`:`Paused while this tab is hidden.`),_e=e=>`${e?.why} Open the terminal again to retry.`,ve=e=>`${e?.why} 重新開啟終端機即可重試。`,ye=((e,t={})=>(t.locale??s())===`zh-TW`?ve(e):_e(e)),be=((e={},t={})=>(t.locale??s())===`zh-TW`?`送出 Enter`:`Send Enter`),xe=((e={},t={})=>(t.locale??s())===`zh-TW`?`送出 Escape`:`Send Escape`),Se=((e={},t={})=>(t.locale??s())===`zh-TW`?`錯誤`:`error`),Ce=((e={},t={})=>(t.locale??s())===`zh-TW`?`已完成`:`finished`),we=((e={},t={})=>(t.locale??s())===`zh-TW`?`已離開`:`gone`),Te=((e={},t={})=>(t.locale??s())===`zh-TW`?`提問`:`question`),J=((e={},t={})=>(t.locale??s())===`zh-TW`?`更新`:`update`),Ee=e=>`${e?.count} finished`,De=e=>`${e?.count} 個已完成`,Oe=((e,t={})=>(t.locale??s())===`zh-TW`?De(e):Ee(e)),ke=t=>{let n=e(`en`,t?.count,{},!0);return n===`one`?`${t?.count} needs you`:n===`other`?`${t?.count} need you`:`tally_need`},Ae=e=>`${e?.count} 個需要你`,je=((e,t={})=>(t.locale??s())===`zh-TW`?Ae(e):ke(e)),Me=e=>`Terminal of ${e?.name}, read only`,Ne=e=>`${e?.name} 的終端機,唯讀`,Pe=((e,t={})=>(t.locale??s())===`zh-TW`?Ne(e):Me(e)),Fe=e=>`Terminal · ${e?.name}`,Ie=e=>`終端機 · ${e?.name}`,Le=((e,t={})=>(t.locale??s())===`zh-TW`?Ie(e):Fe(e)),Re=((e={},t={})=>(t.locale??s())===`zh-TW`?`等待`:`waiting on`),ze=[[[`esc`,`esc`,M],[`tab`,`tab`,B],[`up`,`↑`,V],[`enter`,`enter`,j]],[[`shift+tab`,`⇧tab`,R],[`left`,`←`,P],[`down`,`↓`,k],[`right`,`→`,L]],[[`space`,`space`,z],[`backspace`,`⌫`,oe],[`home`,`home`,N],[`end`,`end`,A],[`pageup`,`pgup`,I],[`pagedown`,`pgdn`,F]]],Be=`123456789`.split(``);function Ve({name:e,state:r,post:o,stream:s}){let c=[],l=i(`p`,{class:`pad-note`,role:`status`}),u=!1,d=([e,t,n])=>{let r=i(`button`,{type:`button`,class:`pad-key`,"data-key":e,"aria-label":n()},t);return r.onclick=t=>t.isTrusted&&!u&&void g(e),c.push(r),r},f=i(`details`,{class:`pad-digits`},i(`summary`,null,`1–9`),i(`div`,{class:`pad-row`},...Be.map(e=>d([e,e,()=>e])))),p=i(`div`,{class:`pad`,role:`group`,"aria-label":W({name:e})},...ze.map(e=>i(`div`,{class:`pad-row`},...e.map(d))),f,l),m=(e,t=``)=>(l.dataset.tone=t,l.replaceChildren(e)),h=(e,t,r)=>{let a=i(`button`,{type:`button`,class:`pad-yes`},e===`enter`?be():xe()),o=i(`button`,{type:`button`,class:`cmp-link`},n());a.onclick=t=>t.isTrusted&&!u&&void g(e,r),o.onclick=()=>m(``),l.dataset.tone=`ask`,l.replaceChildren(i(`span`,null,t),a,o),o.focus()};async function g(e,n){u=!0,_(),m(``);try{let t=await o(`keys`,{key:e,stream:s(),...n?{confirmed:n}:{}});t.status===409&&t.body.error===`confirm`&&typeof t.body.confirm==`string`?h(e,String(t.body.reason??``),t.body.confirm):t.ok||m(t.body.reason??a({status:t.status}),`error`)}catch{m(t(),`error`)}finally{u=!1,_()}}function _(){let e=r();for(let t of c)t.disabled=u||e===`off`||e===`hidden`&&t.dataset.key!==`esc`}return _(),{el:p,update:_}}var Y=[0,95,135,175,215,255],He=120,Ue=5e3,We=3e3,X=e=>Number.isInteger(e)&&e>=0&&e<=255,Ge=e=>X(e)?e<16?e:e<232?`rgb(${Y[Math.floor((e-16)/36)]},${Y[Math.floor((e-16)/6)%6]},${Y[(e-16)%6]})`:`rgb(${8+10*(e-232)},${8+10*(e-232)},${8+10*(e-232)})`:void 0,Ke=([e,t,n])=>[e,t,n].every(e=>X(e))?`rgb(${e},${t},${n})`:void 0;function qe(e,t){let n={...e},r=t.split(`;`);for(let e=0;e<r.length;e++){let t=r[e].split(`:`).map(e=>e===``?0:Number(e)),i=t[0];if(i===38||i===48||i===58){let a=t.length>1?t[1]:Number(r[e+1]),o=t.length>1?t.slice(2):r.slice(e+2,e+(a===5?3:5)).map(Number);t.length===1&&(e+=a===5?2:a===2?4:1);let s=a===5?Ge(o[0]):a===2?Ke(o.slice(-3)):void 0;s!==void 0&&i!==58&&(n[i===38?`fg`:`bg`]=s)}else if(i===0)for(let e of Object.keys(n))delete n[e];else i===1||i===2?n[i===1?`b`:`d`]=!0:i===22?n.b=n.d=!1:i===3||i===23?n.i=i===3:i===4||i===21||i===24?n.u=i!==24&&t[1]!==0:i===7||i===27?n.v=i===7:i===9||i===29?n.s=i===9:i>=30&&i<=37||i>=90&&i<=97?n.fg=i-(i<90?30:82):i>=40&&i<=47||i>=100&&i<=107?n.bg=i-(i<100?40:92):(i===39||i===49)&&delete n[i===39?`fg`:`bg`]}return n}function Je(e){let t=[],n={},r=0,i=e=>{let r=e.replace(/\x1b(\[[0-?]*[ -/]*[@-~]?)?|[\u0000-\u001f\u007f-\u009f]/g,``);if(!r)return;let[i,a]=n.v?[n.bg??`z`,n.fg??`z`]:[n.fg,n.bg],o=[typeof i==`number`||i===`z`?`c${i}`:``,typeof a==`number`||a===`z`?`k${a}`:``,...[`b`,`d`,`i`,`u`,`s`].filter(e=>n[e]).map(e=>`t${e}`)].filter(Boolean).join(` `);t.push({text:r,cls:o,...typeof i==`string`&&i!==`z`&&{fg:i},...typeof a==`string`&&a!==`z`&&{bg:a}})};for(let t of e.matchAll(/\x1b\[([0-9;:]{0,64})m/g))i(e.slice(r,t.index)),n=qe(n,t[1]),r=t.index+t[0].length;return i(e.slice(r)),t}function Z(e,t){let n=Math.min(Math.max(0,Number(t.rows)||0),He);for(;e.children.length<n;)e.append(i(`div`,{class:`tr`}));for(;e.children.length>n;)e.lastElementChild.remove();for(let[r,a]of Array.isArray(t.set)?t.set:[])!Number.isInteger(r)||r<0||r>=n||typeof a!=`string`||e.children[r].replaceChildren(...Je(a).map(e=>{if(!e.cls&&!e.fg&&!e.bg)return e.text;let t=i(`span`,e.cls?{class:e.cls}:null,e.text);return e.fg&&(t.style.color=e.fg),e.bg&&(t.style.backgroundColor=e.bg),t}))}function Ye({tiles:e,post:n,stream:r,pad:o}){let s=new Map,c,l=()=>{try{return String(JSON.parse(r()).stream??``)}catch{return``}},u=(e,t,n=``)=>(e.pad?.update(),(e.state.textContent!==t||e.state.dataset.tone!==n)&&(e.state.dataset.tone=n,e.state.textContent=t)),d=(e,t)=>(e.ended=!0,u(e,ye({why:t}),`error`)),f=(e,n,r=l())=>r&&void(e.queue=e.queue.then(()=>e.post(`mirror`,{stream:r,on:n}).then(t=>n&&!t.ok&&d(e,t.body.reason??a({status:t.status})),()=>n&&d(e,t())))),p=(e,t=Math.max(e.cols,...[...e.box.children].map(e=>e.textContent?.length??0)))=>e.box.style.fontSize=e.fit.getAttribute(`aria-pressed`)===`true`&&t?`${Math.max(6,Math.floor((e.scroll.clientWidth-20)/(t*.6)))}px`:``,m=e=>Date.now()-e.seen>We,h=()=>(clearInterval(c),c=s.size&&!document.hidden?setInterval(()=>s.forEach(e=>(e.box.classList.toggle(`stale`,m(e)),e.pad?.update())),1e3):void 0);document.addEventListener(`visibilitychange`,()=>(h(),s.forEach(e=>{clearTimeout(e.away),document.hidden?e.away=setTimeout(()=>(e.parked=!0,f(e,!1),u(e,ge())),Ue):e.parked&&(e.parked=!1,f(e,!0))})));let g=(e,t)=>{let r={key:e,box:i(`div`,{class:`term`,role:`group`,"aria-label":Pe({name:t})}),scroll:i(`div`,{class:`term-scroll`,tabindex:`0`}),state:i(`p`,{class:`term-state`,role:`status`},D()),fit:i(`button`,{type:`button`,class:`cmp-link`,"aria-pressed":`false`},ie()),post:n(e),cols:0,seen:0,parked:!1,first:!0,ended:!1,queue:Promise.resolve()};return r.fit.onclick=()=>(r.fit.setAttribute(`aria-pressed`,String(r.fit.getAttribute(`aria-pressed`)!==`true`)),p(r)),r.scroll.append(r.box),new ResizeObserver(()=>p(r)).observe(r.scroll),s.set(e,r),f(r,!0),h(),r.pad=o?.({name:t,state:()=>r.parked||r.ended||m(r)?`off`:r.box.classList.contains(`hidden`)?`hidden`:`live`,post:r.post,stream:l}),r.tile={id:`term:${e}`,title:Le({name:t}),icon:`i-comms`,body:()=>i(`div`,{class:`term-tile`},i(`div`,{class:`term-bar`},r.state,r.fit),r.scroll,r.pad?.el),closed:()=>(clearTimeout(r.away),f(r,!1),s.delete(e),h())}};return{open(t,n){let r=s.get(t);r?.ended&&(r.ended=!1,u(r,D()),f(r,!0)),e.open(r?.tile??g(t,n),!0)},hello:()=>s.forEach(e=>!e.parked&&!e.ended&&f(e,!0)),frame(e){let t;try{t=JSON.parse(e)}catch{return}let n=s.get(t.key);if(n){if(n.box.classList.toggle(`hidden`,!!(t.hidden||t.ended)),t.ended)return d(n,le({why:t.ended}));if([n.seen,n.ended]=[Date.now(),!1],n.box.classList.remove(`stale`),t.hidden)return Z(n.box,{key:n.key,rows:0}),u(n,ue());Z(n.box,t),(t.whole||t.cols&&t.cols!==n.cols)&&(n.cols=t.cols||n.cols,p(n)),u(n,pe({cols:n.cols,rows:n.box.children.length}),`ok`),n.first&&t.whole&&(n.first=!1,requestAnimationFrame(()=>n.scroll.scrollTop=n.scroll.scrollHeight))}}}}var Q=(e,t)=>p(e.mark)-p(t.mark)||e.at-t.at,$=e=>{let t=e.filter(e=>p(e.mark)===0).length,n=e.length-t;return[t&&je({count:t}),n&&Oe({count:n})].filter(Boolean).join(` · `)};function Xe(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(Q)}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 o=t.pop();if(!o)return!1;let s=t.at(-1),c=a===`close`?n.find(e=>p(e.mark)===0):void 0;return a===`later`&&o.alert.mark===o.raised&&(n=[...n,o.alert].sort(Q)),!s&&c?(i(c,o.back),!0):(r(),!e.restore(o.back)&&s&&e.enter(s.alert),!0)}}}var Ze=`a, button, input, textarea, select, summary, label, [role=button]`;function Qe(e){let t=[],n,r=()=>e.render(t,n);return{get tiles(){return t},get active(){return n},open(i,a=!0){if(!a&&t.length>=4&&!t.some(e=>e.id===i.id))return void i.closed?.();t.some(e=>e.id===i.id)||(t=[...t,i]).slice(0,-4).forEach(e=>e.closed?.()),t=t.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[i].closed?.(),t=t.filter(t=>t.id!==e),n===e&&(n=(t[i]??t[i-1])?.id),r())},activate(e){n=e,r()}}}function $e(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(`
|
|
1
|
+
import{a as e,n as t,o as n,t as r}from"./ask-B8tfeo3k.js";import{n as i,r as a,t as o}from"./post-C4WkBuZ3.js";import{E as s,a as c,b as l,c as u,d,f,h as p,i as m,l as h,o as g,p as _,s as v,u as ee}from"./index-BkgejQW0.js";var y=e=>`Alerts: ${e?.tally}`,b=e=>`警示:${e?.tally}`,te=((e,t={})=>(t.locale??s())===`zh-TW`?b(e):y(e)),x=e=>`Also queued: ${e?.tally}`,S=e=>`佇列中還有:${e?.tally}`,ne=((e,t={})=>(t.locale??s())===`zh-TW`?S(e):x(e)),C=((e={},t={})=>(t.locale??s())===`zh-TW`?`關閉`:`Close`),w=((e={},t={})=>(t.locale??s())===`zh-TW`?`關閉文件`:`Close document`),T=e=>`Close ${e?.title}`,E=e=>`關閉 ${e?.title}`,re=((e,t={})=>(t.locale??s())===`zh-TW`?E(e):T(e)),D=((e={},t={})=>(t.locale??s())===`zh-TW`?`連線中…`:`Connecting…`),O=((e={},t={})=>(t.locale??s())===`zh-TW`?`警示`:`alert`),ie=((e={},t={})=>(t.locale??s())===`zh-TW`?`符合寬度`:`Fit width`),ae=((e={},t={})=>(t.locale??s())===`zh-TW`?`無法取得紀錄。`:`History unavailable.`),oe=((e={},t={})=>(t.locale??s())===`zh-TW`?`退格鍵`:`Backspace`),k=((e={},t={})=>(t.locale??s())===`zh-TW`?`下`:`Down`),A=((e={},t={})=>(t.locale??s(),`End`)),j=((e={},t={})=>(t.locale??s(),`Enter`)),M=((e={},t={})=>(t.locale??s(),`Escape`)),N=((e={},t={})=>(t.locale??s(),`Home`)),P=((e={},t={})=>(t.locale??s())===`zh-TW`?`左`:`Left`),F=((e={},t={})=>(t.locale??s())===`zh-TW`?`下一頁`:`Page down`),I=((e={},t={})=>(t.locale??s())===`zh-TW`?`上一頁`:`Page up`),L=((e={},t={})=>(t.locale??s())===`zh-TW`?`右`:`Right`),R=((e={},t={})=>(t.locale??s(),`Shift+Tab`)),z=((e={},t={})=>(t.locale??s())===`zh-TW`?`空白鍵`:`Space`),B=((e={},t={})=>(t.locale??s(),`Tab`)),V=((e={},t={})=>(t.locale??s())===`zh-TW`?`上`:`Up`),H=e=>`Keys for ${e?.name}`,U=e=>`${e?.name} 的按鍵`,W=((e,t={})=>(t.locale??s())===`zh-TW`?U(e):H(e)),G=((e={},t={})=>(t.locale??s())===`zh-TW`?`最後一則通訊`:`Last transmission`),K=((e={},t={})=>(t.locale??s())===`zh-TW`?`稍後`:`Later`),q=((e={},t={})=>(t.locale??s())===`zh-TW`?`已離開網`:`left the net`),se=e=>`The mirror ended: ${e?.why}`,ce=e=>`鏡像已結束:${e?.why}`,le=((e,t={})=>(t.locale??s())===`zh-TW`?ce(e):se(e)),ue=((e={},t={})=>(t.locale??s())===`zh-TW`?`等待輸入密碼時隱藏;請在終端機中輸入。`:`Hidden while it waits for a secret; type it in the terminal.`),de=e=>`Live · ${e?.cols}×${e?.rows}`,fe=e=>`即時 · ${e?.cols}×${e?.rows}`,pe=((e,t={})=>(t.locale??s())===`zh-TW`?fe(e):de(e)),me=((e={},t={})=>(t.locale??s())===`zh-TW`?`還沒有訊息。`:`No messages yet.`),he=((e={},t={})=>(t.locale??s())===`zh-TW`?`開啟通訊`:`Open comms`),ge=((e={},t={})=>(t.locale??s())===`zh-TW`?`此分頁隱藏時暫停。`:`Paused while this tab is hidden.`),_e=e=>`${e?.why} Open the terminal again to retry.`,ve=e=>`${e?.why} 重新開啟終端機即可重試。`,ye=((e,t={})=>(t.locale??s())===`zh-TW`?ve(e):_e(e)),be=((e={},t={})=>(t.locale??s())===`zh-TW`?`送出 Enter`:`Send Enter`),xe=((e={},t={})=>(t.locale??s())===`zh-TW`?`送出 Escape`:`Send Escape`),Se=((e={},t={})=>(t.locale??s())===`zh-TW`?`錯誤`:`error`),Ce=((e={},t={})=>(t.locale??s())===`zh-TW`?`已完成`:`finished`),we=((e={},t={})=>(t.locale??s())===`zh-TW`?`已離開`:`gone`),Te=((e={},t={})=>(t.locale??s())===`zh-TW`?`提問`:`question`),J=((e={},t={})=>(t.locale??s())===`zh-TW`?`更新`:`update`),Ee=e=>`${e?.count} finished`,De=e=>`${e?.count} 個已完成`,Oe=((e,t={})=>(t.locale??s())===`zh-TW`?De(e):Ee(e)),ke=t=>{let n=e(`en`,t?.count,{},!0);return n===`one`?`${t?.count} needs you`:n===`other`?`${t?.count} need you`:`tally_need`},Ae=e=>`${e?.count} 個需要你`,je=((e,t={})=>(t.locale??s())===`zh-TW`?Ae(e):ke(e)),Me=e=>`Terminal of ${e?.name}, read only`,Ne=e=>`${e?.name} 的終端機,唯讀`,Pe=((e,t={})=>(t.locale??s())===`zh-TW`?Ne(e):Me(e)),Fe=e=>`Terminal · ${e?.name}`,Ie=e=>`終端機 · ${e?.name}`,Le=((e,t={})=>(t.locale??s())===`zh-TW`?Ie(e):Fe(e)),Re=((e={},t={})=>(t.locale??s())===`zh-TW`?`等待`:`waiting on`),ze=[[[`esc`,`esc`,M],[`tab`,`tab`,B],[`up`,`↑`,V],[`enter`,`enter`,j]],[[`shift+tab`,`⇧tab`,R],[`left`,`←`,P],[`down`,`↓`,k],[`right`,`→`,L]],[[`space`,`space`,z],[`backspace`,`⌫`,oe],[`home`,`home`,N],[`end`,`end`,A],[`pageup`,`pgup`,I],[`pagedown`,`pgdn`,F]]],Be=`123456789`.split(``);function Ve({name:e,state:r,post:o,stream:s}){let c=[],l=i(`p`,{class:`pad-note`,role:`status`}),u=!1,d=([e,t,n])=>{let r=i(`button`,{type:`button`,class:`pad-key`,"data-key":e,"aria-label":n()},t);return r.onclick=t=>t.isTrusted&&!u&&void g(e),c.push(r),r},f=i(`details`,{class:`pad-digits`},i(`summary`,null,`1–9`),i(`div`,{class:`pad-row`},...Be.map(e=>d([e,e,()=>e])))),p=i(`div`,{class:`pad`,role:`group`,"aria-label":W({name:e})},...ze.map(e=>i(`div`,{class:`pad-row`},...e.map(d))),f,l),m=(e,t=``)=>(l.dataset.tone=t,l.replaceChildren(e)),h=(e,t,r)=>{let a=i(`button`,{type:`button`,class:`pad-yes`},e===`enter`?be():xe()),o=i(`button`,{type:`button`,class:`cmp-link`},n());a.onclick=t=>t.isTrusted&&!u&&void g(e,r),o.onclick=()=>m(``),l.dataset.tone=`ask`,l.replaceChildren(i(`span`,null,t),a,o),o.focus()};async function g(e,n){u=!0,_(),m(``);try{let t=await o(`keys`,{key:e,stream:s(),...n?{confirmed:n}:{}});t.status===409&&t.body.error===`confirm`&&typeof t.body.confirm==`string`?h(e,String(t.body.reason??``),t.body.confirm):t.ok||m(t.body.reason??a({status:t.status}),`error`)}catch{m(t(),`error`)}finally{u=!1,_()}}function _(){let e=r();for(let t of c)t.disabled=u||e===`off`||e===`hidden`&&t.dataset.key!==`esc`}return _(),{el:p,update:_}}var Y=[0,95,135,175,215,255],He=120,Ue=5e3,We=3e3,X=e=>Number.isInteger(e)&&e>=0&&e<=255,Ge=e=>X(e)?e<16?e:e<232?`rgb(${Y[Math.floor((e-16)/36)]},${Y[Math.floor((e-16)/6)%6]},${Y[(e-16)%6]})`:`rgb(${8+10*(e-232)},${8+10*(e-232)},${8+10*(e-232)})`:void 0,Ke=([e,t,n])=>[e,t,n].every(e=>X(e))?`rgb(${e},${t},${n})`:void 0;function qe(e,t){let n={...e},r=t.split(`;`);for(let e=0;e<r.length;e++){let t=r[e].split(`:`).map(e=>e===``?0:Number(e)),i=t[0];if(i===38||i===48||i===58){let a=t.length>1?t[1]:Number(r[e+1]),o=t.length>1?t.slice(2):r.slice(e+2,e+(a===5?3:5)).map(Number);t.length===1&&(e+=a===5?2:a===2?4:1);let s=a===5?Ge(o[0]):a===2?Ke(o.slice(-3)):void 0;s!==void 0&&i!==58&&(n[i===38?`fg`:`bg`]=s)}else if(i===0)for(let e of Object.keys(n))delete n[e];else i===1||i===2?n[i===1?`b`:`d`]=!0:i===22?n.b=n.d=!1:i===3||i===23?n.i=i===3:i===4||i===21||i===24?n.u=i!==24&&t[1]!==0:i===7||i===27?n.v=i===7:i===9||i===29?n.s=i===9:i>=30&&i<=37||i>=90&&i<=97?n.fg=i-(i<90?30:82):i>=40&&i<=47||i>=100&&i<=107?n.bg=i-(i<100?40:92):(i===39||i===49)&&delete n[i===39?`fg`:`bg`]}return n}function Je(e){let t=[],n={},r=0,i=e=>{let r=e.replace(/\x1b(\[[0-?]*[ -/]*[@-~]?)?|[\u0000-\u001f\u007f-\u009f]/g,``);if(!r)return;let[i,a]=n.v?[n.bg??`z`,n.fg??`z`]:[n.fg,n.bg],o=[typeof i==`number`||i===`z`?`c${i}`:``,typeof a==`number`||a===`z`?`k${a}`:``,...[`b`,`d`,`i`,`u`,`s`].filter(e=>n[e]).map(e=>`t${e}`)].filter(Boolean).join(` `);t.push({text:r,cls:o,...typeof i==`string`&&i!==`z`&&{fg:i},...typeof a==`string`&&a!==`z`&&{bg:a}})};for(let t of e.matchAll(/\x1b\[([0-9;:]{0,64})m/g))i(e.slice(r,t.index)),n=qe(n,t[1]),r=t.index+t[0].length;return i(e.slice(r)),t}function Z(e,t){let n=Math.min(Math.max(0,Number(t.rows)||0),He);for(;e.children.length<n;)e.append(i(`div`,{class:`tr`}));for(;e.children.length>n;)e.lastElementChild.remove();for(let[r,a]of Array.isArray(t.set)?t.set:[])!Number.isInteger(r)||r<0||r>=n||typeof a!=`string`||e.children[r].replaceChildren(...Je(a).map(e=>{if(!e.cls&&!e.fg&&!e.bg)return e.text;let t=i(`span`,e.cls?{class:e.cls}:null,e.text);return e.fg&&(t.style.color=e.fg),e.bg&&(t.style.backgroundColor=e.bg),t}))}function Ye({tiles:e,post:n,stream:r,pad:o}){let s=new Map,c,l=()=>{try{return String(JSON.parse(r()).stream??``)}catch{return``}},u=(e,t,n=``)=>(e.pad?.update(),(e.state.textContent!==t||e.state.dataset.tone!==n)&&(e.state.dataset.tone=n,e.state.textContent=t)),d=(e,t)=>(e.ended=!0,u(e,ye({why:t}),`error`)),f=(e,n,r=l())=>r&&void(e.queue=e.queue.then(()=>e.post(`mirror`,{stream:r,on:n}).then(t=>n&&!t.ok&&d(e,t.body.reason??a({status:t.status})),()=>n&&d(e,t())))),p=(e,t=Math.max(e.cols,...[...e.box.children].map(e=>e.textContent?.length??0)))=>e.box.style.fontSize=e.fit.getAttribute(`aria-pressed`)===`true`&&t?`${Math.max(6,Math.floor((e.scroll.clientWidth-20)/(t*.6)))}px`:``,m=e=>Date.now()-e.seen>We,h=()=>(clearInterval(c),c=s.size&&!document.hidden?setInterval(()=>s.forEach(e=>(e.box.classList.toggle(`stale`,m(e)),e.pad?.update())),1e3):void 0);document.addEventListener(`visibilitychange`,()=>(h(),s.forEach(e=>{clearTimeout(e.away),document.hidden?e.away=setTimeout(()=>(e.parked=!0,f(e,!1),u(e,ge())),Ue):e.parked&&(e.parked=!1,f(e,!0))})));let g=(e,t)=>{let r={key:e,box:i(`div`,{class:`term`,role:`group`,"aria-label":Pe({name:t})}),scroll:i(`div`,{class:`term-scroll`,tabindex:`0`}),state:i(`p`,{class:`term-state`,role:`status`},D()),fit:i(`button`,{type:`button`,class:`cmp-link`,"aria-pressed":`false`},ie()),post:n(e),cols:0,seen:0,parked:!1,first:!0,ended:!1,queue:Promise.resolve()};return r.fit.onclick=()=>(r.fit.setAttribute(`aria-pressed`,String(r.fit.getAttribute(`aria-pressed`)!==`true`)),p(r)),r.scroll.append(r.box),new ResizeObserver(()=>p(r)).observe(r.scroll),s.set(e,r),f(r,!0),h(),r.pad=o?.({name:t,state:()=>r.parked||r.ended||m(r)?`off`:r.box.classList.contains(`hidden`)?`hidden`:`live`,post:r.post,stream:l}),r.tile={id:`term:${e}`,title:Le({name:t}),icon:`i-comms`,body:()=>i(`div`,{class:`term-tile`},i(`div`,{class:`term-bar`},r.state,r.fit),r.scroll,r.pad?.el),closed:()=>(clearTimeout(r.away),f(r,!1),s.delete(e),h())}};return{open(t,n){let r=s.get(t);r?.ended&&(r.ended=!1,u(r,D()),f(r,!0)),e.open(r?.tile??g(t,n),!0)},hello:()=>s.forEach(e=>!e.parked&&!e.ended&&f(e,!0)),frame(e){let t;try{t=JSON.parse(e)}catch{return}let n=s.get(t.key);if(n){if(n.box.classList.toggle(`hidden`,!!(t.hidden||t.ended)),t.ended)return d(n,le({why:t.ended}));if([n.seen,n.ended]=[Date.now(),!1],n.box.classList.remove(`stale`),t.hidden)return Z(n.box,{key:n.key,rows:0}),u(n,ue());Z(n.box,t),(t.whole||t.cols&&t.cols!==n.cols)&&(n.cols=t.cols||n.cols,p(n)),u(n,pe({cols:n.cols,rows:n.box.children.length}),`ok`),n.first&&t.whole&&(n.first=!1,requestAnimationFrame(()=>n.scroll.scrollTop=n.scroll.scrollHeight))}}}}var Q=(e,t)=>p(e.mark)-p(t.mark)||e.at-t.at,$=e=>{let t=e.filter(e=>p(e.mark)===0).length,n=e.length-t;return[t&&je({count:t}),n&&Oe({count:n})].filter(Boolean).join(` · `)};function Xe(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(Q)}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 o=t.pop();if(!o)return!1;let s=t.at(-1),c=a===`close`?n.find(e=>p(e.mark)===0):void 0;return a===`later`&&o.alert.mark===o.raised&&(n=[...n,o.alert].sort(Q)),!s&&c?(i(c,o.back),!0):(r(),!e.restore(o.back)&&s&&e.enter(s.alert),!0)}}}var Ze=`a, button, input, textarea, select, summary, label, [role=button]`;function Qe(e){let t=[],n,r=()=>e.render(t,n);return{get tiles(){return t},get active(){return n},open(i,a=!0){if(!a&&t.length>=4&&!t.some(e=>e.id===i.id))return void i.closed?.();t.some(e=>e.id===i.id)||(t=[...t,i]).slice(0,-4).forEach(e=>e.closed?.()),t=t.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[i].closed?.(),t=t.filter(t=>t.id!==e),n===e&&(n=(t[i]??t[i-1])?.id),r())},activate(e){n=e,r()}}}function $e(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
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 et=()=>h(`<section class="dialog" role="dialog" aria-modal="false" tabindex="-1"><header><b class="tag">${O()}</b><span class="where"></span><button class="x" type="button" aria-label="${C()}">×</button></header><div class="who">${m}<div><h3></h3><p><em class="role"></em> <span class="state"></span></p></div></div><div class="intel"><h4>${G()}</h4><p class="said">…</p><p class="pending" hidden><b>${Re()}</b> <span></span></p></div><div class="ask-root"></div><footer><a class="go">${he()}</a><button class="later" type="button">${K()}</button><span class="queued"></span></footer></section>`),tt=()=>h(`<section class="tile" tabindex="-1"><header><svg><use href="#i-doc"/></svg><b></b><button class="x" type="button" aria-label="${w()}">×</button></header><div class="tile-body"></div></section>`);function nt(e){let[t,n,i,a,s]=[g(`dock`,HTMLElement),g(`work`,HTMLElement),g(`tiles`,HTMLElement),g(`tile-tabs`,HTMLElement),g(`alerts`,HTMLButtonElement)],p=new Map,y=(e,t,n=p.get(t.key))=>{let r=e.dataset.gone===`true`;_(e,`.said`,n?.failed?ae():n?.said??me()),e.querySelector(`.pending`).hidden=!n?.pending||r,_(e,`.pending span`,n?.pending??``),c(e.querySelector(`.go`),r?void 0:{view:`session`,ws:t.ws,key:t.key,...n?.at&&{at:n.at}})},b=(n,r={said:`…`})=>{p.set(n.key,r),e.recent(n.key).then($e,()=>({failed:!0})).then(e=>{let i=p.get(n.key)===r&&(p.set(n.key,e),t.querySelector(`.dialog[data-key="${CSS.escape(n.key)}"]`));i&&y(i,n)})},x=(t,n,i,a)=>{ee(t,n.mark),t.dataset.gone=String(!!n.gone),t.style.transform=i?`translateY(${-12*i}px) scale(${1-.06*i})`:``,t.style.opacity=String(Math.max(0,1-.3*i)),t.toggleAttribute(`inert`,i>0),t.setAttribute(`aria-label`,`${n.name}: ${v(n.note,n.mark)}`),u(t.querySelector(`.plate`),n.role,n.mark),_(t,`h3`,n.name),_(t,`.role`,d(n.role)),_(t,`.state`,n.gone?q():v(n.note,n.mark)),_(t,`.where`,e.label(n.ws)),_(t,`.tag`,n.gone?we():({waiting:Te,error:Se,done:Ce}[n.mark]??J)()),_(t,`.queued`,a.length?ne({tally:$(a)}):``),p.has(n.key)||b(n),y(t,n);let o=S.get(t);o||S.set(t,o=r(t.querySelector(`.ask-root`),C(n.key),void 0,()=>O.open(n.key,n.name))),o.update(n.pending,n.mark===`waiting`&&document.body.dataset.stale!==`true`)},S=new WeakMap,C=t=>e.post?.(t)??((e,n)=>o(`sessions/${encodeURIComponent(t)}/${e}`,n)),w=Xe({render(e,n){f(t,e.map(e=>({...e,id:e.key})),et,(t,r)=>x(t,r,e.length-1-e.findIndex(e=>e.key===r.key),n));let r=n[0];s.disabled=!r,s.dataset.mark=r?.mark??`unknown`,_(s,`#alert-count`,String(n.length)),s.title=n.length?te({tally:$(n)}):``,_(s,`#alert-text`,r?`${r.name} · ${v(r.note,r.mark)}`:l()),f(s.querySelector(`.faces`),n.slice(0,3).map(e=>({...e,id:e.key})),()=>h(m),(e,t)=>u(e,t.role,t.mark))},enter:e=>t.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))});s.addEventListener(`click`,()=>w.next()),document.addEventListener(`click`,e=>{let n=t=>{let n=t.getBoundingClientRect();return e.clientX>=n.left&&e.clientX<=n.right&&e.clientY>=n.top&&e.clientY<=n.bottom},r=[...t.querySelectorAll(`.dialog:not(.leaving)`)],i=r.slice(0,-1).reverse().find(n);e.defaultPrevented||!i||!r.length||n(r.at(-1))||e.target?.closest?.(Ze)||(e.preventDefault(),e.stopPropagation(),w.raise(i.dataset.key))},!0),t.addEventListener(`click`,e=>{let t=e.target;t.closest(`.x`)?w.close():t.closest(`.later`)?w.close(`later`):t.closest(`.go`)&&queueMicrotask(()=>void w.close(`go`))});let T=0,E=()=>i.classList.toggle(`tabbed`,D.tiles.length>1&&n.clientWidth<460+D.tiles.length*400),D=Qe({render(e,t){i.hidden=!e.length,f(i,e,e=>{let t=tt();return t.querySelector(`use`).setAttribute(`href`,`#${e.icon??`i-doc`}`),t.querySelector(`.x`).setAttribute(`aria-label`,re({title:e.title})),t.querySelector(`.tile-body`).append(e.body()),t.querySelector(`.x`).addEventListener(`click`,()=>D.close(e.id)),t},(e,n)=>{_(e,`header b`,n.title),e.classList.toggle(`active`,n.id===t)}),f(a,e,()=>h(`<button type="button" class="tab-btn"></button>`),(e,n)=>{e.textContent=n.title,e.classList.toggle(`active`,n.id===t),e.onclick=()=>D.activate(n.id)}),i.prepend(a),e.length!==T&&(T=e.length,E())},enter:e=>requestAnimationFrame(()=>i.querySelector(`.tile[data-key="${CSS.escape(e.id)}"]`)?.focus())});new ResizeObserver(E).observe(n);let O=Ye({tiles:D,post:C,stream:e.stream,pad:Ve});return{tiles:D,stack:w,terminal:O,alerts(e,t){for(let t of e)b(t),w.arrive(t);w.prune(e=>t.get(e))}}}export{nt as mountPanels};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{n as e,r as t,t as n}from"./post-C4WkBuZ3.js";import{E as r}from"./index-BkgejQW0.js";var i=((e={},t={})=>(t.locale??r())===`zh-TW`?`正在取得配對碼…`:`Asking for a pairing code…`),a=((e={},t={})=>(t.locale??r())===`zh-TW`?`新的配對碼`:`New code`),o=((e={},t={})=>(t.locale??r())===`zh-TW`?`伺服器沒有回應。`:`The server did not answer.`),s=((e={},t={})=>(t.locale??r())===`zh-TW`?`配對 QR code`:`Pairing QR code`),c=((e={},t={})=>(t.locale??r())===`zh-TW`?`用以本機使用者身分登入 Tailscale 的手機掃描。只能用一次,十分鐘內有效。`:`Scan it with a phone signed in to Tailscale as this machine's user. It works once, within ten minutes.`),l=((e={},t={})=>(t.locale??r())===`zh-TW`?`配對手機`:`Pair a phone`),u=((e={},t={})=>(t.locale??r())===`zh-TW`?`遠端存取還沒開啟。要開啟,讓你 tailnet 上的手機可以開這個頁面嗎?只有用這台電腦的 Tailscale 帳號登入的裝置能配對,絕不使用 Funnel。`:`Remote access is off. Turn it on so a phone on your tailnet can open this page? Only devices signed in to Tailscale as this machine's user can pair; Funnel is never used.`),d=((e={},t={})=>(t.locale??r())===`zh-TW`?`開啟遠端存取`:`Turn on remote access`),f=((e={},t={})=>(t.locale??r())===`zh-TW`?`正在開啟遠端存取…`:`Turning remote access on…`),p=`http://www.w3.org/2000/svg`;function m(e){let t=e.length,n=document.createElementNS(p,`svg`),r=document.createElementNS(p,`rect`),i=document.createElementNS(p,`path`);n.setAttribute(`viewBox`,`-4 -4 ${t+8} ${t+8}`),n.setAttribute(`class`,`qr`),n.setAttribute(`role`,`img`),n.setAttribute(`aria-label`,s());for(let[e,n]of Object.entries({x:`-4`,y:`-4`,width:String(t+8),height:String(t+8),fill:`#fff`}))r.setAttribute(e,n);return i.setAttribute(`d`,e.flatMap((e,t)=>[...e].flatMap((e,n)=>e===`1`?[`M${n} ${t}h1v1h-1z`]:[])).join(``)),i.setAttribute(`fill`,`#06101e`),n.append(r,i),n}function h(){return{id:`pair`,title:l(),body:()=>{let r=e(`div`,{class:`pair`}),s=e(`button`,{type:`button`,class:`later`},a()),l=e(`button`,{type:`button`,class:`pair-btn`},d()),p=(a=`remote/pair`,d=i())=>{r.replaceChildren(e(`p`,{class:`chat-empty`},d)),n(a,{}).then(n=>{let i=n.body.rows,o=String(n.body.url??``);if(n.body.error===`remote_off`)return r.replaceChildren(e(`p`,null,u()),l);if(!n.ok||!Array.isArray(i))return r.replaceChildren(e(`p`,null,n.body.reason??t({status:n.status})),a===`remote/on`?l:s);r.replaceChildren(m(i.map(String)),e(`p`,null,c()),e(`p`,null,e(`code`,null,new URL(o).host)),s)},()=>r.replaceChildren(e(`p`,null,o()),s))};return l.onclick=()=>p(`remote/on`,f()),s.onclick=()=>p(),p(),r}}}export{h as pairTile};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{E as e}from"./index-
|
|
1
|
+
import{E as e}from"./index-BkgejQW0.js";var t=e=>`Refused (${e?.status}).`,n=e=>`已拒絕(${e?.status})。`,r=((r,i={})=>(i.locale??e())===`zh-TW`?n(r):t(r)),i=(...e)=>e.filter(e=>e!==!1&&e!=null);function a(e,t,...n){let r=document.createElement(e);for(let[e,n]of Object.entries(t??{}))r.setAttribute(e,n);return r.append(...i(...n)),r}var o=(e,t)=>fetch(`api/${e}`,{method:`POST`,cache:`no-store`,headers:{"content-type":`application/json`,"x-sb-csrf":document.querySelector(`meta[name="sb-csrf"]`)?.content??``},body:JSON.stringify(t)}).then(async e=>({ok:e.ok,status:e.status,body:await e.json().catch(()=>({}))}));export{a as n,r,o as t};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./index-BHlDoYBI.css"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{a as e,i as t,n,o as r,r as i,t as a}from"./ask-
|
|
2
|
+
import{a as e,i as t,n,o as r,r as i,t as a}from"./ask-B8tfeo3k.js";import{n as o,r as s,t as c}from"./post-C4WkBuZ3.js";import{C as l,E as u,S as d,T as f,_ as p,a as m,c as h,d as g,f as _,g as v,i as y,l as b,m as x,p as S,r as C,s as w,t as T,u as E,v as D,w as O,x as ee,y as k}from"./index-BkgejQW0.js";var A=((e={},t={})=>(t.locale??u())===`zh-TW`?`它在等待對話框:請在上方或它的終端機中回答。`:`It waits on a dialog: answer it above, or in its terminal.`),j=((e={},t={})=>(t.locale??u())===`zh-TW`?`它在等待對話框;請在它的終端機中回答。`:`It waits on a dialog; answer it in its terminal.`),M=((e={},t={})=>(t.locale??u())===`zh-TW`?`這個 session 已不再即時;紀錄仍可閱讀。`:`This session is no longer live; its history stays readable.`),N=((e={},t={})=>(t.locale??u())===`zh-TW`?`這個單位沒有即時的 pi 窗格,無處可輸入。`:`No live pi pane backs this unit, so there is nothing to type into.`),P=((e={},t={})=>(t.locale??u())===`zh-TW`?`串流中斷;要等它恢復才能送出。`:`The stream is down; sending waits for it to come back.`),te=((e={},t={})=>(t.locale??u())===`zh-TW`?`頻道關閉`:`channel closed`),ne=((e={},t={})=>(t.locale??u())===`zh-TW`?`頻道開啟`:`channel open`),F=((e={},t={})=>(t.locale??u())===`zh-TW`?`通訊`:`comms`),I=((e={},t={})=>(t.locale??u())===`zh-TW`?`已派出`:`Dispatched`),L=((e={},t={})=>(t.locale??u())===`zh-TW`?`無法取得:已不在它的 session 中開啟。`:`Unavailable: no longer open in its session.`),R=((e={},t={})=>(t.locale??u())===`zh-TW`?`已不在清單中:已在它的 session 中關閉,或 session 已結束。`:`No longer listed: closed in its session, or the session ended.`),re=((e={},t={})=>(t.locale??u())===`zh-TW`?`已更新:此區塊顯示時會載入新版本。`:`Updated: the new version loads when this tile shows.`),ie=((e={},t={})=>(t.locale??u())===`zh-TW`?`超過轉送上限:請在終端機中閱讀。`:`More than the relay carries: read them in the terminal.`),ae=e=>`${e?.command} ends this session or switches its pane to another one.`,z=e=>`${e?.command} 會結束這個 session,或把它的窗格切換到別的 session。`,oe=((e,t={})=>(t.locale??u())===`zh-TW`?z(e):ae(e)),se=t=>{let n=e(`en`,t?.count,{},!0);return n===`one`?`${t?.count} entry`:n===`other`?`${t?.count} entries`:`entry_count`},B=e=>`${e?.count} 筆`,ce=((e,t={})=>(t.locale??u())===`zh-TW`?B(e):se(e)),V=((e={},t={})=>(t.locale??u())===`zh-TW`?`後續`:`Follow-up`),le=((e={},t={})=>(t.locale??u())===`zh-TW`?`載入中…`:`Loading…`),ue=((e={},t={})=>(t.locale??u())===`zh-TW`?`這個工作區不在網中。`:`This workspace is not part of the net.`),de=((e={},t={})=>(t.locale??u())===`zh-TW`?`訊息`:`Message`),fe=((e={},t={})=>(t.locale??u())===`zh-TW`?`新的 session`:`the new session`),pe=((e={},t={})=>(t.locale??u())===`zh-TW`?`無頻道`:`no channel`),me=((e={},t={})=>(t.locale??u())===`zh-TW`?`不在網中`:`not in the net`),he=((e={},t={})=>(t.locale??u())===`zh-TW`?`已不再即時;紀錄在十分鐘內仍可閱讀。`:`No longer live; its history stays readable for ten minutes.`),ge=((e={},t={})=>(t.locale??u())===`zh-TW`?`不在網中(可能已在十分鐘前結束)。`:`Not in the net (it may have ended more than ten minutes ago).`),_e=((e={},t={})=>(t.locale??u())===`zh-TW`?`不在終端機畫面上`:`off screen in the terminal`),ve=e=>`${e?.reason} · off screen`,ye=e=>`${e?.reason} · 不在畫面上`,be=((e,t={})=>(t.locale??u())===`zh-TW`?ye(e):ve(e)),xe=((e={},t={})=>(t.locale??u())===`zh-TW`?`在新分頁開啟`:`Open in a new tab`),Se=((e={},t={})=>(t.locale??u())===`zh-TW`?`正在開啟頻道…`:`Opening the channel…`),Ce=((e={},t={})=>(t.locale??u())===`zh-TW`?`網外`:`Outside the net`),we=((e={},t={})=>(t.locale??u())===`zh-TW`?`未編入的 pi 窗格`:`unaligned pi panes`),Te=e=>`Message ${e?.name} · Enter sends, Shift+Enter adds a line · lands after any unsent text in its terminal`,Ee=e=>`傳訊息給 ${e?.name} · Enter 送出、Shift+Enter 換行 · 會接在它終端機中未送出的文字之後`,De=((e,t={})=>(t.locale??u())===`zh-TW`?Ee(e):Te(e)),Oe=e=>`Message ${e?.name} · lands after any unsent text in its terminal`,ke=e=>`傳訊息給 ${e?.name} · 會接在它終端機中未送出的文字之後`,Ae=((e,t={})=>(t.locale??u())===`zh-TW`?ke(e):Oe(e)),je=((e={},t={})=>(t.locale??u())===`zh-TW`?`重新載入`:`Reload`),Me=((e={},t={})=>(t.locale??u())===`zh-TW`?`送出`:`Send`),Ne=e=>`Send ${e?.command}`,Pe=e=>`送出 ${e?.command}`,Fe=((e,t={})=>(t.locale??u())===`zh-TW`?Pe(e):Ne(e)),Ie=((e={},t={})=>(t.locale??u())===`zh-TW`?`已送出。pi 寫入後會顯示在紀錄中。`:`Sent. It shows in the log once pi writes it.`),Le=((e={},t={})=>(t.locale??u())===`zh-TW`?`已照原文送出;你的修改留在這裡,尚未送出。`:`Sent as it was; your edits stayed here, unsent.`),Re=e=>`${e?.display}, shown by ${e?.unit}`,ze=e=>`${e?.display},由 ${e?.unit} 顯示`,Be=((e,t={})=>(t.locale??u())===`zh-TW`?ze(e):Re(e)),Ve=((e={},t={})=>(t.locale??u())===`zh-TW`?`基地`:`base`),He=((e={},t={})=>(t.locale??u())===`zh-TW`?`上下文`:`context`),Ue=((e={},t={})=>(t.locale??u())===`zh-TW`?`目錄`:`directory`),We=((e={},t={})=>(t.locale??u())===`zh-TW`?`啟動者`:`launcher`),Ge=((e={},t={})=>(t.locale??u())===`zh-TW`?`模型`:`model`),Ke=((e={},t={})=>(t.locale??u())===`zh-TW`?`小隊`:`squad`),qe=((e={},t={})=>(t.locale??u())===`zh-TW`?`無法讀取`:`unreadable`),Je=e=>`squad ${e?.label}`,Ye=e=>`小隊 ${e?.label}`,Xe=((e,t={})=>(t.locale??u())===`zh-TW`?Ye(e):Je(e)),Ze=((e={},t={})=>(t.locale??u())===`zh-TW`?`小隊`:`Squads`),Qe=((e={},t={})=>(t.locale??u())===`zh-TW`?`停止`:`Stop`),$e=((e={},t={})=>(t.locale??u())===`zh-TW`?`要停止目前的任務嗎?佇列中的訊息會退回它的終端機編輯器。`:`Stop the current task? Queued messages go back to its terminal editor.`),et=((e={},t={})=>(t.locale??u())===`zh-TW`?`現在:`:`Now:`),tt=((e={},t={})=>(t.locale??u())===`zh-TW`?`已完成`:`done`),nt=((e={},t={})=>(t.locale??u())===`zh-TW`?`未完成`:`not done`),rt=((e={},t={})=>(t.locale??u())===`zh-TW`?`終端機`:`Terminal`),it=e=>`${e?.count} tokens`,at=e=>`${e?.count} tokens`,ot=((e,t={})=>(t.locale??u())===`zh-TW`?at(e):it(e)),st=((e={},t={})=>(t.locale??u())===`zh-TW`?`文字超過 16 KB,請縮短。`:`The text is longer than 16 KB; shorten it.`),ct=t=>{let n=e(`en`,t?.count,{},!0);return n===`one`?`${t?.count} unit`:n===`other`?`${t?.count} units`:`unit_count`},lt=e=>`${e?.count} 個單位`,ut=((e,t={})=>(t.locale??u())===`zh-TW`?lt(e):ct(e)),dt=((e={},t={})=>(t.locale??u())===`zh-TW`?`單位檔案`:`unit dossier`),ft=((e={},t={})=>(t.locale??u())===`zh-TW`?`單位`:`Units`),H=((e={},t={})=>(t.locale??u())===`zh-TW`?`未確認。再次送出前請先查看終端機。`:`Not confirmed. Check the terminal before sending again.`),pt=((e={},t={})=>(t.locale??u())===`zh-TW`?`等待網的資料…`:`Waiting for the net…`),mt=((e={},t={})=>(t.locale??u())===`zh-TW`?`原文已送到 session;這裡是你編輯過、尚未送出的副本。`:`The original already went to the session; what is here is your edited copy, unsent.`),U=(e,t,n)=>({tag:e,kids:t,attrs:n}),ht=/^(?:https?:\/\/|mailto:)[^\s\u0000-\u001f]+$/i,gt=(e,t)=>U(`a`,t,{href:e,rel:`noopener noreferrer`,target:`_blank`}),_t=/(`+)([^`]|[^`][^]{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 W(e){let t=[],n=0;for(let r of e.matchAll(_t))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(U(`em`,W(r[5]??r[6]))):r[7]===void 0?t.push(gt(r[9],[r[9]])):t.push(ht.test(r[8])?gt(r[8],W(r[7])):r[0]):t.push(U(`del`,W(r[4]))):t.push(U(`strong`,W(r[3]))):t.push(U(`code`,[r[2]]));return n<e.length&&t.push(e.slice(n)),t}var G=/^(\s*)([-*+]|\d+[.)])\s+(.*)$/,vt=/^\s*([-*_])(\s*\1){2,}\s*$/,yt=/^\s*\|?\s*:?-+:?\s*(\|\s*:?-+:?\s*)*\|?\s*$/,bt=e=>e.trim().replace(/^\|/,``).replace(/\|$/,``).split(`|`).map(e=>e.trim()),xt=(e,t)=>/^\s*(`{3,}|~{3,}|#{1,6}\s|>)/.test(e)||vt.test(e)||G.test(e)||e.includes(`|`)&&t!==void 0&&yt.test(t)&&t.includes(`-`);function K(e,t=0){if(t>=16)return[U(`p`,[e])];let n=e.replace(/\r\n?/g,`
|
|
3
3
|
`).split(`
|
|
4
4
|
`),r=[];for(let e=0;e<n.length;){let i=n[e],a=n[e+1],o=i.match(/^\s*(`{3,}|~{3,})\s*([\w+-]*)/),s=i.match(/^\s*(#{1,6})\s+(.*?)\s*#*\s*$/),c=i.match(G);if(!i.trim())e++;else if(o){let t=[];for(e++;e<n.length&&!n[e].trim().startsWith(o[1]);e++)t.push(n[e]);e++,r.push(U(`pre`,[U(`code`,[t.join(`
|
|
5
5
|
`)],o[2]?{"data-lang":o[2]}:void 0)]))}else if(s)r.push(U(`h${s[1].length}`,W(s[2]))),e++;else if(vt.test(i))r.push(U(`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(U(`blockquote`,K(i.join(`
|
|
6
6
|
`),t+1)))}else if(i.includes(`|`)&&a!==void 0&&yt.test(a)&&a.includes(`-`)){let t=[];for(e+=2;e<n.length&&n[e].trim()&&n[e].includes(`|`);e++)t.push(bt(n[e]));r.push(U(`table`,[U(`thead`,[U(`tr`,bt(i).map(e=>U(`th`,W(e))))]),U(`tbody`,t.map(e=>U(`tr`,e.map(e=>U(`td`,W(e))))))]))}else if(c){let i=c[1].length,a=[];for(;e<n.length;){let r=n[e].match(G);if(!r||r[1].length!==i||/\d/.test(r[2])!==/\d/.test(c[2]))break;let o=[r[3]],s=r[3].match(/^\[([ xX])\]\s+(.*)$/);for(s&&(o[0]=s[2]),e++;e<n.length&&n[e].trim()&&n[e].search(/\S/)>i;e++)o.push(n[e].replace(RegExp(`^ {0,${i+2}}`),``));let l=K(o.join(`
|
|
7
7
|
`),t+1),u=l[0],d=s?.[1]!==` `;s&&(typeof u==`object`&&u.tag===`p`?u.kids:l).unshift(U(`i`,d?[`✓`]:[],{class:`check`,"data-done":String(d),"aria-label":d?tt():nt()})),a.push(U(`li`,l,s?{class:`task`}:void 0)),!n[e]?.trim()&&n[e+1]?.match(G)?.[1]?.length===i&&e++}r.push(U(/\d/.test(c[2])?`ol`:`ul`,a))}else{let t=[i];for(e++;e<n.length&&n[e].trim()&&!xt(n[e],n[e+1]);e++)t.push(n[e]);r.push(U(`p`,W(t.join(`
|
|
8
|
-
`))))}}return r}function St(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}var Ct=16384,wt=/^\s*\/(quit|exit|new|resume|fork|clone|import|reload)(?=\s|$)/,q=new Map,Tt=e=>(t,n)=>c(`sessions/${encodeURIComponent(e)}/${t}`,n);function Et(e,t,n){if(!e.ok)return[`error`,e.status===504?H():e.body.reason??s({status:e.status})];if(t&&!t.startsWith(n))return[`ok`,mt()]}var Dt=e=>{try{return e?.startsWith(`[`)?JSON.parse(e):e?[`error`,e]:void 0}catch{return[`error`,e]}},Ot=(e,t)=>e!==``&&!e.startsWith(t)?Le():Ie(),kt=(e,t)=>({hidden:!e.live||!e.control||!!e.asking,disabled:t||!e.online}),At=(e,t)=>e.startsWith(t)?e.slice(t.length).replace(/^\n/,``):e;function J(e){if(!e.online)return P();if(!e.live)return M();if(!e.control)return N();if(e.mark===`waiting`)return e.answerable?A():j()}function jt(e,n,a){let c=`sb-draft:${n}`,l=matchMedia(`(pointer: coarse)`).matches,u=o(`textarea`,{rows:`1`,maxlength:String(Ct),"aria-label":de(),enterkeyhint:l?`enter`:`send`}),d=o(`button`,{type:`submit`,class:`cmp-send`},Me()),f=o(`button`,{type:`button`,class:`cmp-alt`,title:`Alt+Enter`},V()),p=o(`button`,{type:`button`,class:`cmp-alt cmp-stop`},Qe()),m=o(`p`,{class:`cmp-note`,role:`status`,"aria-live":`polite`}),h=o(`button`,{type:`button`,class:`cmp-link`},t()),g=o(`form`,{class:`composer`},o(`div`,{class:`cmp-row`},u,o(`div`,{class:`cmp-acts`},d,f,p)),o(`div`,{class:`cmp-foot`},m,h));e.replaceChildren(g);let _={name:``,control:!1,live:!1,mark:`unknown`,online:!1},v=!1,y=!1,b=e=>{try{e()}catch{}};b(()=>u.value=sessionStorage.getItem(c)??``);let x=()=>b(()=>u.value?sessionStorage.setItem(c,u.value):sessionStorage.removeItem(c)),S=()=>(u.style.height=`auto`,u.style.height=`${Math.min(u.scrollHeight,220)}px`),C=(e,t=``,...n)=>(m.dataset.tone=t,m.replaceChildren(e,...n)),w=(e,t,n)=>{let i=o(`button`,{type:`button`,class:`cmp-yes`},t),a=o(`button`,{type:`button`,class:`cmp-link`},r());y=!0,i.onclick=()=>(y=!1,n()),a.onclick=()=>(y=!1,C(``),u.focus()),C(e,`ask`,i,a),i.focus()},[T,E]=[`${c}:note`,()=>{try{return sessionStorage.getItem(c)??``}catch{return}}],D=e=>b(()=>e?sessionStorage.setItem(T,JSON.stringify(e)):sessionStorage.removeItem(T));function O(e,t,r){let i={sent:r,answer:a(e,t)};return r!==void 0&&(D([`error`,H()]),q.set(n,i),i.answer.then(e=>{let t=E();e.ok&&t!==void 0&&b(()=>sessionStorage.setItem(c,At(t,r))),D(Et(e,t,r))},()=>D([`error`,H()]))),ee(i)}async function ee(e,{sent:t}=e){v=!0,y=!1,A(),C(t===void 0?``:i());try{let n=await e.answer;if(!g.isConnected)return;if(!n.ok)return n.status===504||D(),C(n.body.reason??s({status:n.status}),`error`);if(t===void 0)return C(``);D();let r=Ot(u.value,t);u.value=At(u.value,t),x(),S(),C(r,`ok`)}catch{C(H(),`error`)}finally{q.get(n)===e&&q.delete(n),v=!1,A()}}function k(e,t){let n=u.value,r=J(_),i=t===n;if(v||y||!n.trim())return;if(r)return C(r,`error`);if(new TextEncoder().encode(n).length>16384)return C(st(),`error`);let a=!i&&n.match(wt)?.[0].trim();if(a)return w(oe({command:a}),Fe({command:a}),()=>k(e,n));O(`input`,{text:n,as:e,confirmed:i},n)}function A(){let e=J(_),t=_.mark===`working`;u.placeholder=e??(l?Ae:De)({name:_.name}),d.disabled=v||!!e,f.hidden=p.hidden=!t||!!e,f.disabled=p.disabled=v,Object.assign(h,kt(_,v))}g.addEventListener(`submit`,e=>(e.preventDefault(),k(`send`))),f.onclick=()=>k(`followUp`),p.onclick=()=>w($e(),Qe(),()=>void(v||O(`keys`,{keys:[`esc`]}))),h.onclick=()=>void(v||O(`focus`,{})),u.addEventListener(`input`,()=>(x(),S())),g.addEventListener(`keydown`,e=>{e.key===`Escape`&&!e.isComposing&&(y||e.target===u&&u.value)&&(e.preventDefault(),y&&(y=!1,C(``),u.focus()))}),u.addEventListener(`keydown`,e=>{e.isComposing||e.keyCode===229||e.key!==`Enter`||e.shiftKey||l&&!e.altKey||(e.preventDefault(),k(e.altKey?`followUp`:`send`))});let j=window.visualViewport,M=()=>document.documentElement.style.setProperty(`--vvh`,`${j.height}px`);return j&&(j.addEventListener(`resize`,M),M()),S(),q.has(n)?ee(q.get(n)):b(()=>{let e=Dt(sessionStorage.getItem(T));sessionStorage.removeItem(T),e&&C(e[1],e[0])}),{box:u,update:e=>(_=e,A()),ready:()=>!J(_)}}var Mt=`allow-forms allow-popups allow-popups-to-escape-sandbox`,Nt={},Y=new Map;function Pt(e,t=``){let n=[];for(let r of(e.startsWith(`/`)?e:`${t}/${e}`).split(`/`))r===`..`?n.pop():r&&r!==`.`&&n.push(r);return`/${n.join(`/`)}`}var Ft=(e,t,n)=>e?.find(e=>Pt(e.display,t)===Pt(n,t));function It(e,t,n=[]){let r=e.get(t);return e.set(t,new Set(n.map(e=>e.display))),r?n.filter(e=>!r.has(e.display)):[]}var X=(e,t,n=``)=>(e.state.dataset.tone=n,e.state.textContent=t),Lt=(e,t)=>(e.failed=!0,X(e,t,`error`)),Rt=e=>Nt.src?.(e)??`doc/${encodeURIComponent(e)}/`;function Z(e){if([e.loaded,e.failed]=[e.card.revision,!1],X(e,``),e.frame)return void(e.frame.src=Rt(e.card.cap));let t=e.card.cap,r=/\.(md|markdown)$/i.test(e.card.display),i=++e.seq;(Nt.load?.(t)??fetch(`api/doc/${encodeURIComponent(t)}`,{cache:`no-store`}).then(e=>e.ok?e.json():void 0)).then(t=>e.seq!==i||(t?e.body.replaceChildren(r?o(`div`,{class:`md`},St(K(t.text))):o(`pre`,{class:`doc-pre`},t.text)):Lt(e,L())),()=>e.seq!==i||Lt(e,n()))}function zt(e,t){let n=Y.get(t.cap);if(n)return n.tile;let r=t.display.split(`/`).pop()||t.display,i=t.kind===`html`?o(`iframe`,{class:`doc-frame`,sandbox:Mt,referrerpolicy:`no-referrer`,title:Be({display:t.display,unit:e})}):void 0,a=o(`button`,{type:`button`,class:`cmp-link`},je()),s=i&&o(`a`,{class:`cmp-link`,href:Rt(t.cap),target:`_blank`,rel:`noopener noreferrer`},xe()),c=i??o(`div`,{class:`doc-text`},o(`p`,{class:`chat-empty`},le())),l=o(`span`,{class:`term-state`,role:`status`}),u=o(`em`,{class:`doc-off`},_e()),d=o(`div`,{class:`doc-tile`},o(`div`,{class:`term-bar doc-bar`},o(`span`,{class:`doc-why`},t.reason),u,l,o(`span`,{class:`doc-acts`},a,s)),c),f=new IntersectionObserver(([e])=>(m.shown=!!e?.isIntersecting,m.shown&&!m.gone&&(m.failed||m.loaded!==m.card.revision)&&Z(m))),p={id:`doc:${t.cap}`,title:`${r} · ${e}`,icon:`i-doc`,body:()=>d,closed:()=>(Y.delete(t.cap),f.disconnect())},m={card:t,tile:p,loaded:0,seq:0,shown:!1,gone:!1,body:c,state:l,off:u,...i&&{frame:i}};return a.onclick=()=>!m.gone&&Z(m),u.hidden=t.onScreen,f.observe(d),Z(m),Y.set(t.cap,m),p}function Bt(e,t,n,r){let i=new Map,a=new Set;for(let o of e.bases)for(let e of[...o.tower?[o.tower]:[],...[...o.tabs.flatMap(e=>e.units),...o.outside].flatMap(e=>[e,...e.subs])]){for(let t of e.docs??[])i.set(t.cap,t);for(let i of It(t,e.key,e.docs))e.key===n&&r(e.name,i);a.add(e.key)}for(let e of t.keys())a.has(e)||t.delete(e);Vt(i)}function Vt(e){for(let t of Y.values()){let n=e.get(t.card.cap);if(!n){t.gone||X(t,R(),`error`),t.gone=!0;continue}let r=t.gone&&(X(t,``),t.failed);[t.card,t.gone,t.off.hidden]=[n,!1,n.onScreen],(n.revision!==t.loaded||r)&&(t.shown?Z(t):n.revision!==t.loaded&&X(t,re()))}}function Ht(e,t,n,r){e.hidden=!t?.length&&!n,e.querySelector(`.d-doc-list`).replaceChildren(...(t??[]).map(e=>{let t=o(`button`,{type:`button`,class:`d-doc`,title:e.reason},o(`b`,null,e.display),o(`small`,null,e.onScreen?e.reason:be({reason:e.reason})));return t.onclick=()=>r(e),t})),e.querySelector(`.d-docs-cut`).hidden=!n}var Ut=200;function Q(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,docs:n.tower.docs,docsCut:n.tower.docsCut,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 Wt=()=>b(`<a class="token">${y}<span class="name"></span><span class="line"><em class="role"></em><span class="note"></span></span></a>`);function $(e,t,n){m(e,t.key?{view:`session`,ws:n,key:t.key}:void 0),e.toggleAttribute(`hidden`,!1),e.toggleAttribute(`data-alert`,!!t.key&&x(t.mark)),E(e,t.mark),h(e.querySelector(`.plate`),t.role,t.mark,t.docs),S(e,`.name`,t.name),S(e,`.role`,g(t.role)),S(e,`.note`,w(t.note,t.mark))}var Gt=()=>b(`<div class="col"><a class="token">${y}<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>`),Kt=()=>`<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>${d()}</span><h2></h2><p></p></div><dl class="tally"><div><dt>${Ze()}</dt><dd></dd></div><div><dt>${ft()}</dt><dd></dd></div><div data-mark="working"><dt>${v()}</dt><dd></dd></div><div data-mark="waiting"><dt>${p()}</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>${D()}</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>${Ce()}</b><small>${we()}</small></h3><div class="formation"></div></section></div><p class="lost" hidden></p></div>`,qt=()=>`<div class="dossier-in"><span class="tag">${dt()}</span><div class="portrait">${y}</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><button class="cmp-link d-term" type="button" hidden>${rt()}</button><div class="d-docs" hidden><h4>${l()}</h4><div class="d-doc-list"></div><p class="d-docs-cut" hidden>${ie()}</p></div><div class="d-drones" hidden><h4>${I()}</h4><div class="formation"></div></div></div>`,Jt=()=>`<div class="comms-in"><header class="comms-head"><span class="logo"><svg><use href="#i-comms"/></svg></span><div><h2><small>${F()}</small> <span></span></h2><p></p></div><span class="chan link" data-state="live"><i></i><b>${ne()}</b></span></header><div class="chat-root"></div><div class="ask-root"></div><div class="composer-root"></div></div>`;function Yt({data:e,restart:t,openTile:n,openTerminal:r,online:i}){let o=e=>document.getElementById(e),[s,c,l]=[`ws-view`,`session-view`,`dossier`].map(o),u={view:`map`},d,p={},v,y=[],D=!1,A=new Map,j,M,N,P=0,F,I,L=()=>u.view===`map`?``:u.ws,R=(e,t)=>{let n=document.createElement(`a`);return m(n,e),n.textContent=t,n};function re(){let e=(e,t,n)=>{let r=document.createElement(e);return r.textContent=t,n&&m(r,n),r},t=o(`crumbs`),n=u;if(n.view===`map`)return t.replaceChildren(e(`b`,`Straw Net`),e(`span`,f()));let r=d?.bases.find(e=>e.id===n.ws)?.label??n.ws,i=n.view===`session`?Q(d,n.key)?.u.name??j?.name??n.key:``;t.replaceChildren(e(`a`,`Straw Net`,{view:`map`}),n.view===`workspace`?e(`b`,r):e(`a`,r,{view:`workspace`,ws:n.ws}),...i?[e(`b`,i)]:[])}function ie(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=o({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 ae(){s.firstElementChild||s.append(b(Kt()));let e=s.firstElementChild,t=d?.bases.find(e=>e.id===L()),n=e.querySelector(`.lost`);if(n.hidden=!!t,n.textContent=d?ue():pt(),e.classList.toggle(`void`,!t),!t)return;let r=e.querySelector(`.keep`);E(r,t.mark),r.classList.toggle(`head`,t.head);let i=e.querySelector(`.tower`);i.classList.toggle(`ghost`,!t.tower),E(i,t.tower?.mark??`unknown`),m(i,t.tower?{view:`session`,ws:t.id,key:t.tower.key}:void 0),i.toggleAttribute(`hidden`,!1),i.toggleAttribute(`data-alert`,!!(t.tower&&x(t.tower.mark))),S(e,`h2`,t.label),S(e,`.title p`,t.tower?O({state:C[t.tower.mark]()}):k());let a=t.tabs.flatMap(e=>e.units.flatMap(e=>[e,...e.subs]));[t.tabs.length,a.length,a.filter(e=>e.mark===`working`).length,a.filter(e=>e.mark===`waiting`).length].forEach((t,n)=>e.querySelectorAll(`dd`)[n].textContent=String(t));let o=(e,n)=>{E(e,n.mark),$(e.querySelector(`.token`),n,t.id);let r=e.querySelector(`.say`),i=p[n.key]??``;r.hidden=!i,S(r,`p`,i),_(e.querySelector(`.drones`),n.subs,Wt,(e,n)=>(e.classList.add(`drone`),$(e,n,t.id)))};_(e.querySelector(`.squads`),t.tabs,()=>b(`<section class="tab squad"><h3><i class="flag"></i><b></b><small></small></h3><div class="formation"></div></section>`),(e,t)=>{S(e,`h3 b`,Xe({label:t.label}));let n=t.units.flatMap(e=>[e,...e.subs]);S(e,`h3 small`,ut({count:n.length})),E(e,[`waiting`,`error`,`working`].find(e=>n.some(t=>t.mark===e))??`idle`),_(e.querySelector(`.formation`),t.units,Gt,o)});let c=(n,r)=>{let i=e.querySelector(`[data-group="${n}"]`);i.hidden=!r.length,_(i.querySelector(`.formation`),r,Wt,(e,n)=>$(e,n,t.id))};c(`outposts`,t.outposts.map(e=>({id:e.id,name:e.label,role:`outpost`,mark:e.mark,note:e.mark===`unknown`?ee():void 0}))),c(`outside`,t.outside)}function z(){if(u.view!==`session`)return;l.firstElementChild||l.append(b(qt()));let e=l.firstElementChild,t=Q(d,u.key),a=t?.u,o=a?.mark??`unknown`;E(e,o),h(e.querySelector(`.plate`),a?.role??j?.role??`member`,o),S(e,`h3`,a?.name??j?.name??u.key),S(e,`.role`,g(a?.role??j?.role??`session`)),S(e,`.state`,a?w(a.note,o):me());let s=e.querySelector(`.d-note`),f=j?.state;s.hidden=f!==`recent`&&f!==`unknown`,s.replaceChildren(f===`unknown`?ge():he()),j?.successor&&s.append(` ${et()} `,R({view:`session`,ws:L(),key:j.successor},Q(d,j.successor)?.u.name??fe()));let p=[[Ge(),M],[He(),N?ot({count:N.toLocaleString()}):void 0],[Ue(),j?.header?.cwd],[Ve(),t&&R({view:`workspace`,ws:t.base.id},t.base.label)],[Ke(),t?.squad],[We(),t?.launcher&&R({view:`session`,ws:t.base.id,key:t.launcher.key},t.launcher.name)],[qe(),j?.unreadable?ce({count:j.unreadable}):void 0]];e.querySelector(`.specs`).replaceChildren(...p.filter(([,e])=>e).map(([e,t])=>{let n=b(`<div><dt></dt><dd></dd></div>`);return n.firstElementChild.textContent=e,n.lastElementChild.append(t),n}));let m=e.querySelector(`.d-term`),y=u.key,T=a?.name??j?.name??y;[m.hidden,m.onclick]=[!a?.control,()=>r(y,T)],Ht(e.querySelector(`.d-docs`),a?.docs,a?.docsCut,e=>n(zt(T,e))),v?.docs();let D=e.querySelector(`.d-drones`);D.hidden=!a?.subs.length,_(D.querySelector(`.formation`),(a?.subs??[]).map(e=>({...e,id:e.key})),Wt,(e,t)=>(e.classList.add(`drone`),$(e,t,L())));let O=c.querySelector(`.comms-head`);if(O){S(O,`h2 span`,a?.name??j?.name??``),S(O,`p`,[t?.base.label,t?.squad&&Xe({label:t.squad})].filter(Boolean).join(` · `));let e=O.querySelector(`.chan`),n=f===`live`||!f&&a;e.dataset.state=n?`live`:`closed`,S(e,`b`,n?ne():f===`recent`?te():pe())}v?.setLive(o===`working`?`${w(a.note,o)}`:x(o)?C[o]():``,o),F?.update({name:a?.name??j?.name??u.key,control:!!a?.control,live:f?f===`live`:!!a,mark:o,online:i(),asking:!!a?.pending,answerable:!!a?.pending?.answer}),I?.update(a?.pending,o===`waiting`&&!!a?.control&&i())}let oe=()=>setTimeout(()=>u.view===`session`&&(document.activeElement??document.body)===document.body&&(matchMedia(`(pointer: fine)`).matches&&F?.ready()?F.box:v?.log)?.focus({preventScroll:!0}));async function se(t){let i=++P,{mountChat:o}=await T(async()=>{let{mountChat:e}=await import(`./chat-iv7vekCl.js`);return{mountChat:e}},__vite__mapDeps([0]),import.meta.url);if(i!==P||u.view!==`session`)return;c.replaceChildren(b(Jt()));let s=()=>Q(d,t)?.u??{key:t,name:j?.name??t,role:j?.role??`member`,mark:`unknown`};v=o(c.querySelector(`.chat-root`),e(t),{who:s,link:e=>{let n=Q(d,t)?.u.subs.find(t=>t.name===e)??d?.bases.flatMap(e=>[...e.tabs.flatMap(e=>e.units),...e.outside]).find(t=>t.name===e);return n&&R({view:`session`,ws:Q(d,n.key)?.base.id??L(),key:n.key},e)},docFor:(e,r=Ft(Q(d,t)?.u.docs,j?.header?.cwd,e))=>r&&(()=>n(zt(s().name,r)))});let l=e(t).post??Tt(t);[F,I]=[jt(c.querySelector(`.composer-root`),t,l),a(c.querySelector(`.ask-root`),l,void 0,()=>r(t,s().name))],v.reveal(u.at),y.splice(0).forEach(B),z(),oe()}function B(e){v?.apply(e);for(let t of e.items??[])t.kind===`assistant`&&([M,N]=[t.model??M,t.ctx??N])}let V=()=>(re(),u.view===`workspace`?ae():z());return{locate:e=>Q(d,e),show(e,t,n){let[r,i]=u.view===`session`?[u.key,u.at]:[];(e.view!==`workspace`||u.view!==`workspace`||e.ws!==u.ws)&&(p={}),u=e,s.hidden=e.view!==`workspace`,c.hidden=l.hidden=e.view!==`session`,e.view===`session`&&e.key!==r?([v,F,I,j,M,N,y,D]=[void 0,void 0,void 0,void 0,void 0,void 0,[],!1],c.replaceChildren(b(`<p class="lost">${Se()}</p>`)),se(e.key)):e.view===`session`&&e.at!==i?(v?.reveal(e.at),oe()):e.view!==`session`&&(P++,v=F=I=void 0),V(),e!==t&&ie(e,t,n)},net(e){d=e,Bt(e,A,u.view===`session`?u.key:void 0,(e,t)=>n(zt(e,t),!1)),u.view!==`map`&&V()},cards(e){p={...p,...e},u.view===`workspace`&&ae()},history(e){if(u.view===`session`&&e.key===u.key){if(j={...j,...e,items:void 0},e.reset&&([M,N]=[void 0,void 0]),document.hidden)return y.length<Ut?void y.push(e):void(D=!0);v?B(e):y.push(e),z()}},wake(){if(D)return D=!1,y=[],t();y.splice(0).forEach(e=>v&&B(e)),V()}}}export{Yt as mountFocus,K as n,St as t};
|
|
8
|
+
`))))}}return r}function St(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}var Ct=16384,wt=/^\s*\/(quit|exit|new|resume|fork|clone|import|reload)(?=\s|$)/,q=new Map,Tt=e=>(t,n)=>c(`sessions/${encodeURIComponent(e)}/${t}`,n);function Et(e,t,n){if(!e.ok)return[`error`,e.status===504?H():e.body.reason??s({status:e.status})];if(t&&!t.startsWith(n))return[`ok`,mt()]}var Dt=e=>{try{return e?.startsWith(`[`)?JSON.parse(e):e?[`error`,e]:void 0}catch{return[`error`,e]}},Ot=(e,t)=>e!==``&&!e.startsWith(t)?Le():Ie(),kt=(e,t)=>({hidden:!e.live||!e.control||!!e.asking,disabled:t||!e.online}),At=(e,t)=>e.startsWith(t)?e.slice(t.length).replace(/^\n/,``):e;function J(e){if(!e.online)return P();if(!e.live)return M();if(!e.control)return N();if(e.mark===`waiting`)return e.answerable?A():j()}function jt(e,n,a){let c=`sb-draft:${n}`,l=matchMedia(`(pointer: coarse)`).matches,u=o(`textarea`,{rows:`1`,maxlength:String(Ct),"aria-label":de(),enterkeyhint:l?`enter`:`send`}),d=o(`button`,{type:`submit`,class:`cmp-send`},Me()),f=o(`button`,{type:`button`,class:`cmp-alt`,title:`Alt+Enter`},V()),p=o(`button`,{type:`button`,class:`cmp-alt cmp-stop`},Qe()),m=o(`p`,{class:`cmp-note`,role:`status`,"aria-live":`polite`}),h=o(`button`,{type:`button`,class:`cmp-link`},t()),g=o(`form`,{class:`composer`},o(`div`,{class:`cmp-row`},u,o(`div`,{class:`cmp-acts`},d,f,p)),o(`div`,{class:`cmp-foot`},m,h));e.replaceChildren(g);let _={name:``,control:!1,live:!1,mark:`unknown`,online:!1},v=!1,y=!1,b=e=>{try{e()}catch{}};b(()=>u.value=sessionStorage.getItem(c)??``);let x=()=>b(()=>u.value?sessionStorage.setItem(c,u.value):sessionStorage.removeItem(c)),S=()=>(u.style.height=`auto`,u.style.height=`${Math.min(u.scrollHeight,220)}px`),C=(e,t=``,...n)=>(m.dataset.tone=t,m.replaceChildren(e,...n)),w=(e,t,n)=>{let i=o(`button`,{type:`button`,class:`cmp-yes`},t),a=o(`button`,{type:`button`,class:`cmp-link`},r());y=!0,i.onclick=()=>(y=!1,n()),a.onclick=()=>(y=!1,C(``),u.focus()),C(e,`ask`,i,a),i.focus()},[T,E]=[`${c}:note`,()=>{try{return sessionStorage.getItem(c)??``}catch{return}}],D=e=>b(()=>e?sessionStorage.setItem(T,JSON.stringify(e)):sessionStorage.removeItem(T));function O(e,t,r){let i={sent:r,answer:a(e,t)};return r!==void 0&&(D([`error`,H()]),q.set(n,i),i.answer.then(e=>{let t=E();e.ok&&t!==void 0&&b(()=>sessionStorage.setItem(c,At(t,r))),D(Et(e,t,r))},()=>D([`error`,H()]))),ee(i)}async function ee(e,{sent:t}=e){v=!0,y=!1,A(),C(t===void 0?``:i());try{let n=await e.answer;if(!g.isConnected)return;if(!n.ok)return n.status===504||D(),C(n.body.reason??s({status:n.status}),`error`);if(t===void 0)return C(``);D();let r=Ot(u.value,t);u.value=At(u.value,t),x(),S(),C(r,`ok`)}catch{C(H(),`error`)}finally{q.get(n)===e&&q.delete(n),v=!1,A()}}function k(e,t){let n=u.value,r=J(_),i=t===n;if(v||y||!n.trim())return;if(r)return C(r,`error`);if(new TextEncoder().encode(n).length>16384)return C(st(),`error`);let a=!i&&n.match(wt)?.[0].trim();if(a)return w(oe({command:a}),Fe({command:a}),()=>k(e,n));O(`input`,{text:n,as:e,confirmed:i},n)}function A(){let e=J(_),t=_.mark===`working`;u.placeholder=e??(l?Ae:De)({name:_.name}),d.disabled=v||!!e,f.hidden=p.hidden=!t||!!e,f.disabled=p.disabled=v,Object.assign(h,kt(_,v))}g.addEventListener(`submit`,e=>(e.preventDefault(),k(`send`))),f.onclick=()=>k(`followUp`),p.onclick=()=>w($e(),Qe(),()=>void(v||O(`keys`,{keys:[`esc`]}))),h.onclick=()=>void(v||O(`focus`,{})),u.addEventListener(`input`,()=>(x(),S())),g.addEventListener(`keydown`,e=>{e.key===`Escape`&&!e.isComposing&&(y||e.target===u&&u.value)&&(e.preventDefault(),y&&(y=!1,C(``),u.focus()))}),u.addEventListener(`keydown`,e=>{e.isComposing||e.keyCode===229||e.key!==`Enter`||e.shiftKey||l&&!e.altKey||(e.preventDefault(),k(e.altKey?`followUp`:`send`))});let j=window.visualViewport,M=()=>document.documentElement.style.setProperty(`--vvh`,`${j.height}px`);return j&&(j.addEventListener(`resize`,M),M()),S(),q.has(n)?ee(q.get(n)):b(()=>{let e=Dt(sessionStorage.getItem(T));sessionStorage.removeItem(T),e&&C(e[1],e[0])}),{box:u,update:e=>(_=e,A()),ready:()=>!J(_)}}var Mt=`allow-forms allow-popups allow-popups-to-escape-sandbox`,Nt={},Y=new Map;function Pt(e,t=``){let n=[];for(let r of(e.startsWith(`/`)?e:`${t}/${e}`).split(`/`))r===`..`?n.pop():r&&r!==`.`&&n.push(r);return`/${n.join(`/`)}`}var Ft=(e,t,n)=>e?.find(e=>Pt(e.display,t)===Pt(n,t));function It(e,t,n=[]){let r=e.get(t);return e.set(t,new Set(n.map(e=>e.display))),r?n.filter(e=>!r.has(e.display)):[]}var X=(e,t,n=``)=>(e.state.dataset.tone=n,e.state.textContent=t),Lt=(e,t)=>(e.failed=!0,X(e,t,`error`)),Rt=e=>Nt.src?.(e)??`doc/${encodeURIComponent(e)}/`;function Z(e){if([e.loaded,e.failed]=[e.card.revision,!1],X(e,``),e.frame)return void(e.frame.src=Rt(e.card.cap));let t=e.card.cap,r=/\.(md|markdown)$/i.test(e.card.display),i=++e.seq;(Nt.load?.(t)??fetch(`api/doc/${encodeURIComponent(t)}`,{cache:`no-store`}).then(e=>e.ok?e.json():void 0)).then(t=>e.seq!==i||(t?e.body.replaceChildren(r?o(`div`,{class:`md`},St(K(t.text))):o(`pre`,{class:`doc-pre`},t.text)):Lt(e,L())),()=>e.seq!==i||Lt(e,n()))}function zt(e,t){let n=Y.get(t.cap);if(n)return n.tile;let r=t.display.split(`/`).pop()||t.display,i=t.kind===`html`?o(`iframe`,{class:`doc-frame`,sandbox:Mt,referrerpolicy:`no-referrer`,title:Be({display:t.display,unit:e})}):void 0,a=o(`button`,{type:`button`,class:`cmp-link`},je()),s=i&&o(`a`,{class:`cmp-link`,href:Rt(t.cap),target:`_blank`,rel:`noopener noreferrer`},xe()),c=i??o(`div`,{class:`doc-text`},o(`p`,{class:`chat-empty`},le())),l=o(`span`,{class:`term-state`,role:`status`}),u=o(`em`,{class:`doc-off`},_e()),d=o(`div`,{class:`doc-tile`},o(`div`,{class:`term-bar doc-bar`},o(`span`,{class:`doc-why`},t.reason),u,l,o(`span`,{class:`doc-acts`},a,s)),c),f=new IntersectionObserver(([e])=>(m.shown=!!e?.isIntersecting,m.shown&&!m.gone&&(m.failed||m.loaded!==m.card.revision)&&Z(m))),p={id:`doc:${t.cap}`,title:`${r} · ${e}`,icon:`i-doc`,body:()=>d,closed:()=>(Y.delete(t.cap),f.disconnect())},m={card:t,tile:p,loaded:0,seq:0,shown:!1,gone:!1,body:c,state:l,off:u,...i&&{frame:i}};return a.onclick=()=>!m.gone&&Z(m),u.hidden=t.onScreen,f.observe(d),Z(m),Y.set(t.cap,m),p}function Bt(e,t,n,r){let i=new Map,a=new Set;for(let o of e.bases)for(let e of[...o.tower?[o.tower]:[],...[...o.tabs.flatMap(e=>e.units),...o.outside].flatMap(e=>[e,...e.subs])]){for(let t of e.docs??[])i.set(t.cap,t);for(let i of It(t,e.key,e.docs))e.key===n&&r(e.name,i);a.add(e.key)}for(let e of t.keys())a.has(e)||t.delete(e);Vt(i)}function Vt(e){for(let t of Y.values()){let n=e.get(t.card.cap);if(!n){t.gone||X(t,R(),`error`),t.gone=!0;continue}let r=t.gone&&(X(t,``),t.failed);[t.card,t.gone,t.off.hidden]=[n,!1,n.onScreen],(n.revision!==t.loaded||r)&&(t.shown?Z(t):n.revision!==t.loaded&&X(t,re()))}}function Ht(e,t,n,r){e.hidden=!t?.length&&!n,e.querySelector(`.d-doc-list`).replaceChildren(...(t??[]).map(e=>{let t=o(`button`,{type:`button`,class:`d-doc`,title:e.reason},o(`b`,null,e.display),o(`small`,null,e.onScreen?e.reason:be({reason:e.reason})));return t.onclick=()=>r(e),t})),e.querySelector(`.d-docs-cut`).hidden=!n}var Ut=200;function Q(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,docs:n.tower.docs,docsCut:n.tower.docsCut,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 Wt=()=>b(`<a class="token">${y}<span class="name"></span><span class="line"><em class="role"></em><span class="note"></span></span></a>`);function $(e,t,n){m(e,t.key?{view:`session`,ws:n,key:t.key}:void 0),e.toggleAttribute(`hidden`,!1),e.toggleAttribute(`data-alert`,!!t.key&&x(t.mark)),E(e,t.mark),h(e.querySelector(`.plate`),t.role,t.mark,t.docs),S(e,`.name`,t.name),S(e,`.role`,g(t.role)),S(e,`.note`,w(t.note,t.mark))}var Gt=()=>b(`<div class="col"><a class="token">${y}<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>`),Kt=()=>`<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>${d()}</span><h2></h2><p></p></div><dl class="tally"><div><dt>${Ze()}</dt><dd></dd></div><div><dt>${ft()}</dt><dd></dd></div><div data-mark="working"><dt>${v()}</dt><dd></dd></div><div data-mark="waiting"><dt>${p()}</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>${D()}</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>${Ce()}</b><small>${we()}</small></h3><div class="formation"></div></section></div><p class="lost" hidden></p></div>`,qt=()=>`<div class="dossier-in"><span class="tag">${dt()}</span><div class="portrait">${y}</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><button class="cmp-link d-term" type="button" hidden>${rt()}</button><div class="d-docs" hidden><h4>${l()}</h4><div class="d-doc-list"></div><p class="d-docs-cut" hidden>${ie()}</p></div><div class="d-drones" hidden><h4>${I()}</h4><div class="formation"></div></div></div>`,Jt=()=>`<div class="comms-in"><header class="comms-head"><span class="logo"><svg><use href="#i-comms"/></svg></span><div><h2><small>${F()}</small> <span></span></h2><p></p></div><span class="chan link" data-state="live"><i></i><b>${ne()}</b></span></header><div class="chat-root"></div><div class="ask-root"></div><div class="composer-root"></div></div>`;function Yt({data:e,restart:t,openTile:n,openTerminal:r,online:i}){let o=e=>document.getElementById(e),[s,c,l]=[`ws-view`,`session-view`,`dossier`].map(o),u={view:`map`},d,p={},v,y=[],D=!1,A=new Map,j,M,N,P=0,F,I,L=()=>u.view===`map`?``:u.ws,R=(e,t)=>{let n=document.createElement(`a`);return m(n,e),n.textContent=t,n};function re(){let e=(e,t,n)=>{let r=document.createElement(e);return r.textContent=t,n&&m(r,n),r},t=o(`crumbs`),n=u;if(n.view===`map`)return t.replaceChildren(e(`b`,`Straw Net`),e(`span`,f()));let r=d?.bases.find(e=>e.id===n.ws)?.label??n.ws,i=n.view===`session`?Q(d,n.key)?.u.name??j?.name??n.key:``;t.replaceChildren(e(`a`,`Straw Net`,{view:`map`}),n.view===`workspace`?e(`b`,r):e(`a`,r,{view:`workspace`,ws:n.ws}),...i?[e(`b`,i)]:[])}function ie(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=o({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 ae(){s.firstElementChild||s.append(b(Kt()));let e=s.firstElementChild,t=d?.bases.find(e=>e.id===L()),n=e.querySelector(`.lost`);if(n.hidden=!!t,n.textContent=d?ue():pt(),e.classList.toggle(`void`,!t),!t)return;let r=e.querySelector(`.keep`);E(r,t.mark),r.classList.toggle(`head`,t.head);let i=e.querySelector(`.tower`);i.classList.toggle(`ghost`,!t.tower),E(i,t.tower?.mark??`unknown`),m(i,t.tower?{view:`session`,ws:t.id,key:t.tower.key}:void 0),i.toggleAttribute(`hidden`,!1),i.toggleAttribute(`data-alert`,!!(t.tower&&x(t.tower.mark))),S(e,`h2`,t.label),S(e,`.title p`,t.tower?O({state:C[t.tower.mark]()}):k());let a=t.tabs.flatMap(e=>e.units.flatMap(e=>[e,...e.subs]));[t.tabs.length,a.length,a.filter(e=>e.mark===`working`).length,a.filter(e=>e.mark===`waiting`).length].forEach((t,n)=>e.querySelectorAll(`dd`)[n].textContent=String(t));let o=(e,n)=>{E(e,n.mark),$(e.querySelector(`.token`),n,t.id);let r=e.querySelector(`.say`),i=p[n.key]??``;r.hidden=!i,S(r,`p`,i),_(e.querySelector(`.drones`),n.subs,Wt,(e,n)=>(e.classList.add(`drone`),$(e,n,t.id)))};_(e.querySelector(`.squads`),t.tabs,()=>b(`<section class="tab squad"><h3><i class="flag"></i><b></b><small></small></h3><div class="formation"></div></section>`),(e,t)=>{S(e,`h3 b`,Xe({label:t.label}));let n=t.units.flatMap(e=>[e,...e.subs]);S(e,`h3 small`,ut({count:n.length})),E(e,[`waiting`,`error`,`working`].find(e=>n.some(t=>t.mark===e))??`idle`),_(e.querySelector(`.formation`),t.units,Gt,o)});let c=(n,r)=>{let i=e.querySelector(`[data-group="${n}"]`);i.hidden=!r.length,_(i.querySelector(`.formation`),r,Wt,(e,n)=>$(e,n,t.id))};c(`outposts`,t.outposts.map(e=>({id:e.id,name:e.label,role:`outpost`,mark:e.mark,note:e.mark===`unknown`?ee():void 0}))),c(`outside`,t.outside)}function z(){if(u.view!==`session`)return;l.firstElementChild||l.append(b(qt()));let e=l.firstElementChild,t=Q(d,u.key),a=t?.u,o=a?.mark??`unknown`;E(e,o),h(e.querySelector(`.plate`),a?.role??j?.role??`member`,o),S(e,`h3`,a?.name??j?.name??u.key),S(e,`.role`,g(a?.role??j?.role??`session`)),S(e,`.state`,a?w(a.note,o):me());let s=e.querySelector(`.d-note`),f=j?.state;s.hidden=f!==`recent`&&f!==`unknown`,s.replaceChildren(f===`unknown`?ge():he()),j?.successor&&s.append(` ${et()} `,R({view:`session`,ws:L(),key:j.successor},Q(d,j.successor)?.u.name??fe()));let p=[[Ge(),M],[He(),N?ot({count:N.toLocaleString()}):void 0],[Ue(),j?.header?.cwd],[Ve(),t&&R({view:`workspace`,ws:t.base.id},t.base.label)],[Ke(),t?.squad],[We(),t?.launcher&&R({view:`session`,ws:t.base.id,key:t.launcher.key},t.launcher.name)],[qe(),j?.unreadable?ce({count:j.unreadable}):void 0]];e.querySelector(`.specs`).replaceChildren(...p.filter(([,e])=>e).map(([e,t])=>{let n=b(`<div><dt></dt><dd></dd></div>`);return n.firstElementChild.textContent=e,n.lastElementChild.append(t),n}));let m=e.querySelector(`.d-term`),y=u.key,T=a?.name??j?.name??y;[m.hidden,m.onclick]=[!a?.control,()=>r(y,T)],Ht(e.querySelector(`.d-docs`),a?.docs,a?.docsCut,e=>n(zt(T,e))),v?.docs();let D=e.querySelector(`.d-drones`);D.hidden=!a?.subs.length,_(D.querySelector(`.formation`),(a?.subs??[]).map(e=>({...e,id:e.key})),Wt,(e,t)=>(e.classList.add(`drone`),$(e,t,L())));let O=c.querySelector(`.comms-head`);if(O){S(O,`h2 span`,a?.name??j?.name??``),S(O,`p`,[t?.base.label,t?.squad&&Xe({label:t.squad})].filter(Boolean).join(` · `));let e=O.querySelector(`.chan`),n=f===`live`||!f&&a;e.dataset.state=n?`live`:`closed`,S(e,`b`,n?ne():f===`recent`?te():pe())}v?.setLive(o===`working`?`${w(a.note,o)}`:x(o)?C[o]():``,o),F?.update({name:a?.name??j?.name??u.key,control:!!a?.control,live:f?f===`live`:!!a,mark:o,online:i(),asking:!!a?.pending,answerable:!!a?.pending?.answer}),I?.update(a?.pending,o===`waiting`&&!!a?.control&&i())}let oe=()=>setTimeout(()=>u.view===`session`&&(document.activeElement??document.body)===document.body&&(matchMedia(`(pointer: fine)`).matches&&F?.ready()?F.box:v?.log)?.focus({preventScroll:!0}));async function se(t){let i=++P,{mountChat:o}=await T(async()=>{let{mountChat:e}=await import(`./chat-f479gS8E.js`);return{mountChat:e}},__vite__mapDeps([0]),import.meta.url);if(i!==P||u.view!==`session`)return;c.replaceChildren(b(Jt()));let s=()=>Q(d,t)?.u??{key:t,name:j?.name??t,role:j?.role??`member`,mark:`unknown`};v=o(c.querySelector(`.chat-root`),e(t),{who:s,link:e=>{let n=Q(d,t)?.u.subs.find(t=>t.name===e)??d?.bases.flatMap(e=>[...e.tabs.flatMap(e=>e.units),...e.outside]).find(t=>t.name===e);return n&&R({view:`session`,ws:Q(d,n.key)?.base.id??L(),key:n.key},e)},docFor:(e,r=Ft(Q(d,t)?.u.docs,j?.header?.cwd,e))=>r&&(()=>n(zt(s().name,r)))});let l=e(t).post??Tt(t);[F,I]=[jt(c.querySelector(`.composer-root`),t,l),a(c.querySelector(`.ask-root`),l,void 0,()=>r(t,s().name))],v.reveal(u.at),y.splice(0).forEach(B),z(),oe()}function B(e){v?.apply(e);for(let t of e.items??[])t.kind===`assistant`&&([M,N]=[t.model??M,t.ctx??N])}let V=()=>(re(),u.view===`workspace`?ae():z());return{locate:e=>Q(d,e),show(e,t,n){let[r,i]=u.view===`session`?[u.key,u.at]:[];(e.view!==`workspace`||u.view!==`workspace`||e.ws!==u.ws)&&(p={}),u=e,s.hidden=e.view!==`workspace`,c.hidden=l.hidden=e.view!==`session`,e.view===`session`&&e.key!==r?([v,F,I,j,M,N,y,D]=[void 0,void 0,void 0,void 0,void 0,void 0,[],!1],c.replaceChildren(b(`<p class="lost">${Se()}</p>`)),se(e.key)):e.view===`session`&&e.at!==i?(v?.reveal(e.at),oe()):e.view!==`session`&&(P++,v=F=I=void 0),V(),e!==t&&ie(e,t,n)},net(e){d=e,Bt(e,A,u.view===`session`?u.key:void 0,(e,t)=>n(zt(e,t),!1)),u.view!==`map`&&V()},cards(e){p={...p,...e},u.view===`workspace`&&ae()},history(e){if(u.view===`session`&&e.key===u.key){if(j={...j,...e,items:void 0},e.reset&&([M,N]=[void 0,void 0]),document.hidden)return y.length<Ut?void y.push(e):void(D=!0);v?B(e):y.push(e),z()}},wake(){if(D)return D=!1,y=[],t();y.splice(0).forEach(e=>v&&B(e)),V()}}}export{Yt as mountFocus,K as n,St as t};
|
package/dist/gui/index.html
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
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-
|
|
9
|
+
<script type="module" crossorigin src="./assets/index-BkgejQW0.js"></script>
|
|
10
10
|
<link rel="stylesheet" crossorigin href="./assets/index-BHlDoYBI.css">
|
|
11
11
|
</head>
|
|
12
12
|
<body>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-straw-boss",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
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/control.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { IncomingMessage } from "node:http";
|
|
|
3
3
|
import { ANSWER_ID, checkAnswer, CONTROL, type Hub, type Sent, type Target } from "./dialogs.ts";
|
|
4
4
|
import { HerdrError, type HerdrCall, type Pane } from "./herdr.ts";
|
|
5
5
|
import { createKeys } from "./keys.ts";
|
|
6
|
+
import type { Asked } from "./gui.ts";
|
|
6
7
|
import type { createMirrors } from "./mirror.ts";
|
|
7
8
|
import type { Found } from "./net.ts";
|
|
8
9
|
import { ENDING } from "./probe.ts";
|
|
@@ -14,6 +15,8 @@ import { ENDING } from "./probe.ts";
|
|
|
14
15
|
// POST /<token>/api/sessions/<key>/answer {dialog, digest, answerId, choice | answers} answers its dialog through its bridge (dialogs.ts); no keys
|
|
15
16
|
// POST /<token>/api/sessions/<key>/mirror {stream, on} shows the pane's screen on that page's stream (mirror.ts), or stops
|
|
16
17
|
// POST /<token>/api/remote/pair a new one-time pairing URL and its QR, while remote access is on
|
|
18
|
+
// POST /<token>/api/remote/on turns remote access on in the server's session, then a pairing URL and its QR (never remote)
|
|
19
|
+
// POST /<token>/api/server/stop {by, take} stops the server: another session's /boss gui stop or takeover (never remote)
|
|
17
20
|
// Every write needs the page's own origin (Origin, Sec-Fetch-Site), a JSON body of at most 64 KB, and the CSRF secret the server wrote into
|
|
18
21
|
// the page; the custom header forces a CORS preflight that is never approved. The key is resolved in the registry (paths and panes never come
|
|
19
22
|
// from the browser), and Herdr is asked right then that the pane still runs pi on that session's file, so a reused pane id is refused.
|
|
@@ -24,7 +27,7 @@ export { ENDING };
|
|
|
24
27
|
|
|
25
28
|
export interface Reply { status: number; body: unknown }
|
|
26
29
|
/** `answers.target` reads the net afresh, so the binding and the dialog are checked again for every answer. */
|
|
27
|
-
export interface ControlDeps { lookup(key: string): Found | undefined; call?: HerdrCall; csrf: string; canonical(file?: string): string | undefined; pair?(): { url: string; rows: string[] } | undefined; mirrors?: Pick<ReturnType<typeof createMirrors>, "toggle" | "fresh">; secret?(file: string): Promise<boolean>; answers?: Pick<Hub, "replay" | "ended" | "send" | "probe"> & { target(key: string): Promise<Target | undefined> } }
|
|
30
|
+
export interface ControlDeps { lookup(key: string): Found | undefined; call?: HerdrCall; csrf: string; canonical(file?: string): string | undefined; pair?(): { url: string; rows: string[] } | undefined; remoteOn?(): Promise<void>; stop?(asked: Asked): void; mirrors?: Pick<ReturnType<typeof createMirrors>, "toggle" | "fresh">; secret?(file: string): Promise<boolean>; answers?: Pick<Hub, "replay" | "ended" | "send" | "probe"> & { target(key: string): Promise<Target | undefined> } }
|
|
28
31
|
|
|
29
32
|
const no = (status: number, error: string, reason: string): Reply => ({ status, body: { error, reason } });
|
|
30
33
|
const same = (a: string, b: string) => a.length === b.length && timingSafeEqual(Buffer.from(a), Buffer.from(b));
|
|
@@ -65,10 +68,10 @@ export function checkText(text: unknown): string | Reply {
|
|
|
65
68
|
return typed;
|
|
66
69
|
}
|
|
67
70
|
|
|
68
|
-
export function createControl({ lookup, call, csrf, canonical, pair, mirrors, secret = async () => true, answers }: ControlDeps) {
|
|
71
|
+
export function createControl({ lookup, call, csrf, canonical, pair, remoteOn, stop, mirrors, secret = async () => true, answers }: ControlDeps) {
|
|
69
72
|
const busy = new Set<string>();
|
|
70
73
|
const pad = createKeys({ fresh: (id, key, pane) => mirrors?.fresh(id, key, pane) ?? false, secret, answerable: async (key) => Boolean(await answers?.target(key)), probe: async (key) => answers?.probe(key) });
|
|
71
|
-
/** The origin checks, then the session checks, then one Herdr call. `parts` is the path after api/: sessions/<key>/<action>, or
|
|
74
|
+
/** The origin checks, then the session checks, then one Herdr call. `parts` is the path after api/: sessions/<key>/<action>, remote/pair, or server/stop. */
|
|
72
75
|
return async function handle(req: IncomingMessage, origin: string, [scope, key = "", action = ""]: string[]): Promise<Reply> {
|
|
73
76
|
if (req.method !== "POST") return no(405, "method", "Use POST.");
|
|
74
77
|
const site = req.headers["sec-fetch-site"], type = String(req.headers["content-type"] ?? "").split(";")[0]!.trim().toLowerCase();
|
|
@@ -77,9 +80,20 @@ export function createControl({ lookup, call, csrf, canonical, pair, mirrors, se
|
|
|
77
80
|
if (!same(String(req.headers["x-sb-csrf"] ?? ""), csrf)) return no(403, "csrf", "The page's token is out of date; reload the page.");
|
|
78
81
|
const read = await body(req);
|
|
79
82
|
if ("status" in read) return read;
|
|
83
|
+
if (scope === "server") {
|
|
84
|
+
const { by, take } = read.json;
|
|
85
|
+
if (key !== "stop" || action || !stop) return no(404, "not_found", "No such action.");
|
|
86
|
+
return typeof by === "string" && by.length <= 200 && typeof take === "boolean" ? (stop({ by, take }), { status: 202, body: { stopping: true } }) : no(400, "bad_request", "A stop names who asks.");
|
|
87
|
+
}
|
|
88
|
+
if (scope === "remote" && key === "on" && !action) {
|
|
89
|
+
if (!remoteOn) return no(503, "unavailable", "This server cannot turn remote access on.");
|
|
90
|
+
const failed = await remoteOn().then(() => undefined, (error: Error) => error.message);
|
|
91
|
+
const paired = !failed && pair?.();
|
|
92
|
+
return paired ? { status: 200, body: paired } : no(502, "remote_failed", failed ?? "Remote access did not turn on.");
|
|
93
|
+
}
|
|
80
94
|
if (scope === "remote") {
|
|
81
95
|
const paired = key === "pair" && !action ? pair?.() : undefined;
|
|
82
|
-
return paired ? { status: 200, body: paired } : key === "pair" && !action ? no(409, "remote_off", "Remote access is off
|
|
96
|
+
return paired ? { status: 200, body: paired } : key === "pair" && !action ? no(409, "remote_off", "Remote access is off.") : no(404, "not_found", "No such action.");
|
|
83
97
|
}
|
|
84
98
|
if (action === "mirror") return mirrors ? mirrors.toggle(key, read.json) : no(503, "unavailable", "This server shows no terminals.");
|
|
85
99
|
if (!["input", "keys", "focus", "answer"].includes(action)) return no(404, "not_found", "No such action.");
|
package/src/gui.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { execFile } from "node:child_process";
|
|
2
|
-
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
3
3
|
import { mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { createServer, type IncomingMessage, request, type ServerResponse } from "node:http";
|
|
5
5
|
import type { AddressInfo } from "node:net";
|
|
@@ -28,6 +28,7 @@ import { api, type Hub as Files, watchSession, type Watch, watchWorkspace } from
|
|
|
28
28
|
// `events?watch=w:<workspace id>` the last line of each session there; /api/history and /api/entry page through a session's file.
|
|
29
29
|
|
|
30
30
|
export const BUNDLE = fileURLToPath(new URL("../dist/gui", import.meta.url));
|
|
31
|
+
export const VERSION: string = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version;
|
|
31
32
|
const TYPES: Record<string, string> = { ".html": "text/html; charset=utf-8", ".js": "text/javascript; charset=utf-8", ".css": "text/css; charset=utf-8", ".svg": "image/svg+xml", ".json": "application/json" };
|
|
32
33
|
const HEADERS = {
|
|
33
34
|
"cache-control": "no-store",
|
|
@@ -40,10 +41,12 @@ const HEADERS = {
|
|
|
40
41
|
export interface Gui { url: string; port: number; token: string; csrf: string; access: Access; stop(): Promise<void> }
|
|
41
42
|
/** `net` is the registry behind the net reading (the allow list of session keys); without it no session can be watched. `call` reaches Herdr for input. */
|
|
42
43
|
/** `hub` carries answers to the dialogs bridges relay (dialogs.ts); it runs exactly as long as the server. */
|
|
43
|
-
|
|
44
|
+
/** `onRemote` turns remote access on from the page, in the session that runs the server. `onStop` takes another session's stop request (requestStop), so the owner also takes its remote entry down; without it the server stops itself. */
|
|
45
|
+
export interface GuiOptions { read(): Promise<Net>; net?: { lookup(key: string): Found | undefined; workspace(id: string): Ref[] }; call?: HerdrCall; hub?: Hub; dir?: string; port?: number; token?: string; csrf?: string; pollMs?: number; pingMs?: number; onStop?(asked: Asked): void; onRemote?(): Promise<void> }
|
|
46
|
+
export interface Asked { by: string; take: boolean }
|
|
44
47
|
|
|
45
48
|
/** Starts the server. A preferred `port` (with its `token` and `csrf`) is reused when free, so a restarted server keeps the URL and the page an open tab already has. */
|
|
46
|
-
export async function startGui({ read, net, call, hub, dir = BUNDLE, port = 0, token = randomBytes(16).toString("hex"), csrf = randomBytes(16).toString("hex"), pollMs = 2000, pingMs = 15_000 }: GuiOptions): Promise<Gui> {
|
|
49
|
+
export async function startGui({ read, net, call, hub, dir = BUNDLE, port = 0, token = randomBytes(16).toString("hex"), csrf = randomBytes(16).toString("hex"), pollMs = 2000, pingMs = 15_000, onStop, onRemote }: GuiOptions): Promise<Gui> {
|
|
47
50
|
try {
|
|
48
51
|
if (!statSync(join(dir, "index.html")).isFile()) throw new Error();
|
|
49
52
|
} catch {
|
|
@@ -51,13 +54,16 @@ export async function startGui({ read, net, call, hub, dir = BUNDLE, port = 0, t
|
|
|
51
54
|
}
|
|
52
55
|
// The whole bundle is read once: a package update replaces dist/gui under a running server, whose page names the old assets.
|
|
53
56
|
const bundle = new Map(readdirSync(dir, { recursive: true, encoding: "utf8" }).filter((f) => statSync(join(dir, f)).isFile()).map((f) => [f.split("\\").join("/"), readFileSync(join(dir, f))]));
|
|
54
|
-
|
|
57
|
+
// `build` names this bundle in the page and in each stream's hello: a page from another build, reconnecting to this server, reloads itself.
|
|
58
|
+
const html = bundle.get("index.html")!, build = createHash("sha256").update(html).digest("hex").slice(0, 16);
|
|
59
|
+
const page = html.toString("utf8").replace("<head>", `<head>\n<base href="/${token}/">\n<meta name="sb-csrf" content="${csrf}">\n<meta name="sb-build" content="${build}">`);
|
|
55
60
|
const files: Files = { lookup: (key) => net?.lookup(key), workspace: (id) => net?.workspace(id) ?? [], readers: readers() };
|
|
56
61
|
// Turning remote access off ends the streams of remote pages; their next request finds the cookie void.
|
|
57
62
|
const clients = new Map<ServerResponse, Watch | undefined>(), remotes = new Set<ServerResponse>(), access = createAccess(token, () => remotes.forEach((c) => c.end()));
|
|
58
63
|
const pair = (code = access.pair(), host = access.remote?.host, url = `https://${host}/${token}/pair/${code}`) => (code && host ? { url, rows: qr(url).map((row) => row.map(Number).join("")) } : undefined);
|
|
59
64
|
const mirrors = createMirrors({ call, lookup: (key) => net?.lookup(key), secret: waitsForSecret, canonical }), docs = hub && createDocs(hub, (key) => net?.lookup(key)?.name ?? key);
|
|
60
|
-
const
|
|
65
|
+
const stop = (asked: Asked) => void setTimeout(() => (onStop ? onStop(asked) : void halt()), 10); // after the reply has gone out
|
|
66
|
+
const control = createControl({ lookup: (key) => net?.lookup(key), call, csrf, canonical, pair, remoteOn: onRemote, mirrors, stop, secret: waitsForSecret, answers: hub && { replay: hub.replay, ended: hub.ended, send: hub.send, probe: hub.probe, target: async (key) => (await tick(), hub.target(key)) } });
|
|
61
67
|
let last: string | undefined, problem: string | undefined, inflight: Promise<void> | undefined;
|
|
62
68
|
let poll: ReturnType<typeof setInterval> | undefined, beat: ReturnType<typeof setInterval> | undefined;
|
|
63
69
|
const send = (to: ServerResponse, data: string, event?: string) => to.writableEnded || to.write(`${event ? `event: ${event}\n` : ""}data: ${data}\n\n`); // a reading in flight at stop ends after the streams
|
|
@@ -84,7 +90,7 @@ export async function startGui({ read, net, call, hub, dir = BUNDLE, port = 0, t
|
|
|
84
90
|
res.writeHead(200, { ...HEADERS, "content-type": "text/event-stream", connection: "keep-alive" });
|
|
85
91
|
if (remote) remotes.add(res);
|
|
86
92
|
// `hello` names this stream for the terminal mirrors it attaches (mirror.ts), which end with it; before the net's first reading, after it.
|
|
87
|
-
const to = (event: string, data: unknown) => send(res, JSON.stringify(data), event), stream = randomBytes(16).toString("hex"), hello = () => to("hello", { stream });
|
|
93
|
+
const to = (event: string, data: unknown) => send(res, JSON.stringify(data), event), stream = randomBytes(16).toString("hex"), hello = () => to("hello", { stream, build });
|
|
88
94
|
mirrors.open(stream, to);
|
|
89
95
|
if (last) hello();
|
|
90
96
|
const watch = target?.startsWith("w:") ? watchWorkspace(files, target.slice(2), to) : target ? watchSession(files, target, to) : undefined;
|
|
@@ -122,7 +128,8 @@ export async function startGui({ read, net, call, hub, dir = BUNDLE, port = 0, t
|
|
|
122
128
|
} catch {
|
|
123
129
|
return void fail(404);
|
|
124
130
|
}
|
|
125
|
-
if (parts[0] === "
|
|
131
|
+
if ((parts[0] === "server" || parts.join("/") === "remote/on") && who.remote) return void fail(403); // only this machine stops the server or opens it to the tailnet
|
|
132
|
+
if (["sessions", "remote", "server"].includes(parts[0]!)) return void control(req, who.origin, parts).then(answer, () => answer({ status: 500, body: { error: "internal", reason: "The request could not be handled." } }));
|
|
126
133
|
if (req.method === "GET") return void (parts[0] === "doc" && docs ? answer(docs.text(parts[1] ?? "")) : api(files, parts, url.searchParams).then(answer, () => fail(404)));
|
|
127
134
|
}
|
|
128
135
|
if (req.method !== "GET") return void fail(403);
|
|
@@ -149,9 +156,8 @@ export async function startGui({ read, net, call, hub, dir = BUNDLE, port = 0, t
|
|
|
149
156
|
}
|
|
150
157
|
const bound = (server.address() as AddressInfo).port;
|
|
151
158
|
hub?.start(() => void (clients.size && tick())); // a relayed dialog shows at once, not at the next poll; the net is read only while a page listens
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
stop: () => new Promise<void>((done) => {
|
|
159
|
+
function halt() {
|
|
160
|
+
return new Promise<void>((done) => {
|
|
155
161
|
hub?.stop();
|
|
156
162
|
mirrors.stop();
|
|
157
163
|
clearInterval(poll);
|
|
@@ -159,16 +165,29 @@ export async function startGui({ read, net, call, hub, dir = BUNDLE, port = 0, t
|
|
|
159
165
|
clients.forEach((_, c) => c.end());
|
|
160
166
|
server.close(() => done());
|
|
161
167
|
server.closeAllConnections();
|
|
162
|
-
})
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
return {
|
|
171
|
+
url: `http://127.0.0.1:${bound}/${token}/`, port: bound, token, csrf, access, stop: halt,
|
|
163
172
|
};
|
|
164
173
|
}
|
|
165
174
|
|
|
166
175
|
// One server per machine. gui.json in the state directory records the running server (pid, port, token, owner session), and
|
|
167
176
|
// gui.lock makes the check-and-start atomic, so a second /boss gui, from this session or another, opens the running server
|
|
168
|
-
// instead of starting one. A dead server's port and token are reused, so a page left open reconnects to its successor.
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
177
|
+
// instead of starting one. A dead server's port and token are reused, so a page left open reconnects to its successor. Any session reaches
|
|
178
|
+
// the running one: it asks it to stop (requestStop), or takes it over, stopping it and starting its own on the same URL. A session whose
|
|
179
|
+
// pi-straw-boss is newer takes it over unasked, so an update reaches every open page once one session has reloaded.
|
|
180
|
+
/** `ownerSession` is the owner's intercom session id: bridges follow it to the server's dialog channel. `reload` marks a server its owner's /reload stopped. */
|
|
181
|
+
export interface GuiRecord { pid: number; port: number; token: string; csrf?: string; owner: string; ownerSession?: string; version?: string; reload?: boolean }
|
|
182
|
+
/** `stale`: the running server is older and could not be taken over. */
|
|
183
|
+
export interface Shared { url: string; owner: string; mine?: Gui; stale?: boolean }
|
|
184
|
+
|
|
185
|
+
/** Whether version `a` is newer than `b`; a server that recorded none predates the handover. */
|
|
186
|
+
export function newer(a: string, b?: string) {
|
|
187
|
+
const [x, y] = [a, b ?? "0"].map((v) => [...v.split(/[.-]/).slice(0, 3).map(Number), 0, 0].slice(0, 3)) as [number[], number[]];
|
|
188
|
+
const i = x.findIndex((n, j) => n !== y[j]);
|
|
189
|
+
return i >= 0 && x[i]! > y[i]!;
|
|
190
|
+
}
|
|
172
191
|
export const urlOf = (r: GuiRecord) => `http://127.0.0.1:${r.port}/${r.token}/`;
|
|
173
192
|
|
|
174
193
|
export function readRecord(dir: string): GuiRecord | undefined {
|
|
@@ -179,6 +198,25 @@ export function readRecord(dir: string): GuiRecord | undefined {
|
|
|
179
198
|
}
|
|
180
199
|
}
|
|
181
200
|
|
|
201
|
+
/** Marks this session's record, so the extension that loads after its /reload starts the server again on the same URL. */
|
|
202
|
+
export function markReload(dir: string, session: string) {
|
|
203
|
+
const record = readRecord(dir);
|
|
204
|
+
if (record?.ownerSession === session) writeFileSync(join(dir, "gui.json"), JSON.stringify({ ...record, reload: true }), { mode: 0o600 });
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** Asks a recorded server to stop, as its own page would, and waits until it is gone; false when it refused (a server from before 0.11.0) or stayed up. */
|
|
208
|
+
export async function requestStop(r: GuiRecord, asked: Asked, sleep: (ms: number) => Promise<void>) {
|
|
209
|
+
const body = JSON.stringify(asked), origin = `http://127.0.0.1:${r.port}`;
|
|
210
|
+
const status = await new Promise<number>((done) => {
|
|
211
|
+
const headers = { host: `127.0.0.1:${r.port}`, origin, "content-type": "application/json", "x-sb-csrf": r.csrf ?? "", "content-length": Buffer.byteLength(body) };
|
|
212
|
+
const req = request({ host: "127.0.0.1", port: r.port, path: `/${r.token}/api/server/stop`, method: "POST", headers, agent: false, timeout: 2000 }, (res) => (res.resume(), done(res.statusCode ?? 0)));
|
|
213
|
+
req.on("error", () => done(0)).on("timeout", () => (req.destroy(), done(0)));
|
|
214
|
+
req.end(body);
|
|
215
|
+
});
|
|
216
|
+
for (const end = Date.now() + 5000; status === 202 && Date.now() < end; await sleep(100)) if (!(await answers(r))) return true;
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
|
|
182
220
|
/** Whether a recorded server answers its own page. */
|
|
183
221
|
export const answers = (r: GuiRecord) =>
|
|
184
222
|
new Promise<boolean>((done) => {
|
|
@@ -190,7 +228,8 @@ export const answers = (r: GuiRecord) =>
|
|
|
190
228
|
req.end();
|
|
191
229
|
});
|
|
192
230
|
|
|
193
|
-
|
|
231
|
+
/** `take` takes the running server over whatever its version; a newer `version` takes it over anyway. */
|
|
232
|
+
export async function sharedGui(dir: string, [owner, ownerSession]: [string, string], start: (prefer: { port?: number; token?: string; csrf?: string }) => Promise<Gui>, sleep: (ms: number) => Promise<void>, { version = VERSION, take = false } = {}): Promise<Shared> {
|
|
194
233
|
mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
195
234
|
const lock = join(dir, "gui.lock");
|
|
196
235
|
for (let tries = 0; ; tries++) {
|
|
@@ -208,9 +247,11 @@ export async function sharedGui(dir: string, [owner, ownerSession]: [string, str
|
|
|
208
247
|
}
|
|
209
248
|
try {
|
|
210
249
|
const record = readRecord(dir);
|
|
211
|
-
|
|
250
|
+
const theirs = record && (await answers(record)) && { url: urlOf(record), owner: record.owner };
|
|
251
|
+
if (theirs && !(take || newer(version, record.version))) return theirs;
|
|
252
|
+
if (theirs && !(await requestStop(record, { by: owner, take: true }, sleep))) return { ...theirs, stale: true };
|
|
212
253
|
const gui = await start(record ? { port: record.port, token: record.token, csrf: record.csrf } : {});
|
|
213
|
-
writeFileSync(join(dir, "gui.json"), JSON.stringify({ pid: process.pid, port: gui.port, token: gui.token, csrf: gui.csrf, owner, ownerSession }), { mode: 0o600 });
|
|
254
|
+
writeFileSync(join(dir, "gui.json"), JSON.stringify({ pid: process.pid, port: gui.port, token: gui.token, csrf: gui.csrf, owner, ownerSession, version }), { mode: 0o600 });
|
|
214
255
|
return { url: gui.url, owner, mine: gui };
|
|
215
256
|
} finally {
|
|
216
257
|
rmSync(lock, { force: true });
|
package/src/index.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { Type, type Static, type TSchema } from "typebox";
|
|
|
8
8
|
import { startBridge } from "./bridge.ts";
|
|
9
9
|
import { collect, startDashboard } from "./dashboard.ts";
|
|
10
10
|
import { createHub, type Hub } from "./dialogs.ts";
|
|
11
|
-
import { answers, type Gui, openBrowser, readRecord, sharedGui, startGui, urlOf } from "./gui.ts";
|
|
11
|
+
import { answers, type Gui, markReload, newer, openBrowser, readRecord, requestStop, type Shared, sharedGui, startGui, urlOf, VERSION } from "./gui.ts";
|
|
12
12
|
import { netSource } from "./net.ts";
|
|
13
13
|
import { clearOrder, markKids, netTokens } from "./order.ts";
|
|
14
14
|
import { opener } from "./opener.ts";
|
|
@@ -46,7 +46,7 @@ interface Saved { tower?: boolean }
|
|
|
46
46
|
type Role = "tower" | "main" | "member";
|
|
47
47
|
type Scope = "tab" | "workspace" | "towers" | "all";
|
|
48
48
|
type Member = ReturnType<typeof netMembers>[number];
|
|
49
|
-
export interface Deps { run?: HerdrRun; api?: HerdrApi; call?: HerdrCall; tailscale?: Run; copy?: (text: string) => Promise<void>; env?: NodeJS.ProcessEnv; sleep?: Sleep; promptDir?: string; bundle?: string; openUrl?: (url: string) => Promise<void>; watch?: HerdrWatch; stateDir?: string; autoTower?: boolean; nudgeMs?: number }
|
|
49
|
+
export interface Deps { run?: HerdrRun; api?: HerdrApi; call?: HerdrCall; tailscale?: Run; copy?: (text: string) => Promise<void>; env?: NodeJS.ProcessEnv; sleep?: Sleep; promptDir?: string; bundle?: string; openUrl?: (url: string) => Promise<void>; watch?: HerdrWatch; stateDir?: string; autoTower?: boolean; nudgeMs?: number; version?: string }
|
|
50
50
|
|
|
51
51
|
/** Live sessions whose pane carries an `sb_role` token: the sessions that joined the net, and towers. */
|
|
52
52
|
function netMembers(sessions: Session[], ps: Pane[]) {
|
|
@@ -58,7 +58,7 @@ function netMembers(sessions: Session[], ps: Pane[]) {
|
|
|
58
58
|
}
|
|
59
59
|
const nameOf = (s?: Session) => (s ? (s.name ?? s.id) : "");
|
|
60
60
|
|
|
61
|
-
export function createStrawBoss({ run = herdrRun, api = herdrApi(), call = herdrCall(), tailscale: ts = tailscale, copy = copyText, env = process.env, sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)), promptDir = fileURLToPath(new URL("../prompts", import.meta.url)), bundle, openUrl = openBrowser, watch = herdrWatch(), stateDir, autoTower = true, nudgeMs = NUDGE_MS }: Deps = {}) {
|
|
61
|
+
export function createStrawBoss({ run = herdrRun, api = herdrApi(), call = herdrCall(), tailscale: ts = tailscale, copy = copyText, env = process.env, sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)), promptDir = fileURLToPath(new URL("../prompts", import.meta.url)), bundle, openUrl = openBrowser, watch = herdrWatch(), stateDir, autoTower = true, nudgeMs = NUDGE_MS, version = VERSION }: Deps = {}) {
|
|
62
62
|
return function strawBoss(pi: ExtensionAPI): void {
|
|
63
63
|
// Outside Herdr there is no tab to coordinate. Every session in Herdr relays its dialogs to the GUI (bridge.ts), subagents too: they ask
|
|
64
64
|
// questions as well. A pi-herdr-agents worker never joins: its parent represents it.
|
|
@@ -77,7 +77,7 @@ export function createStrawBoss({ run = herdrRun, api = herdrApi(), call = herdr
|
|
|
77
77
|
// Why this session cannot join: it sits in a sub workspace, or Herdr could not say whether it does.
|
|
78
78
|
let barred: string | undefined, dashboard: ReturnType<typeof startDashboard> | undefined, hasUI = false;
|
|
79
79
|
let prompts: Record<string, string> = {}, info: Record<string, string> = {}, saved: Saved = {};
|
|
80
|
-
let gui: Gui | undefined, viewer: Channel | undefined, opening: Promise<
|
|
80
|
+
let gui: Gui | undefined, viewer: Channel | undefined, opening: Promise<Shared> | undefined;
|
|
81
81
|
let c!: Channel, at!: Place, ui: ExtensionContext["ui"] | undefined, timer: ReturnType<typeof setInterval> | undefined;
|
|
82
82
|
let queue: Promise<void> = Promise.resolve(), unwatch: (() => void) | undefined;
|
|
83
83
|
// This session's intercom name, which the subagents it launched show as their launcher, and the subagent panes it has marked.
|
|
@@ -400,7 +400,7 @@ export function createStrawBoss({ run = herdrRun, api = herdrApi(), call = herdr
|
|
|
400
400
|
return true;
|
|
401
401
|
};
|
|
402
402
|
|
|
403
|
-
pi.on("session_start", async (
|
|
403
|
+
pi.on("session_start", async (event, ctx) => {
|
|
404
404
|
stopped = false;
|
|
405
405
|
ui = ctx.ui;
|
|
406
406
|
hasUI = ctx.hasUI;
|
|
@@ -433,6 +433,14 @@ export function createStrawBoss({ run = herdrRun, api = herdrApi(), call = herdr
|
|
|
433
433
|
}
|
|
434
434
|
}
|
|
435
435
|
starting?.catch((error: Error) => tell(`Straw Boss: ${error.message}`, "error"));
|
|
436
|
+
// The GUI this process ran before a /reload, /new, or /resume starts again on its URL, and a session newer than the running server
|
|
437
|
+
// takes it over, once pi-intercom has published this session's id: the server's dialogs are routed by it.
|
|
438
|
+
// A /new, /resume, or /fork is another session: it waits for the new id, not the one pi-intercom may still show from before.
|
|
439
|
+
const record = readRecord(guiDir), back = record?.reload && record.pid === process.pid && event.reason !== "startup";
|
|
440
|
+
const ready = () => Boolean(me()) && (!back || event.reason === "reload" || me() !== record!.ownerSession);
|
|
441
|
+
if (back || (record && newer(version, record.version))) void (async () => {
|
|
442
|
+
if ((await waitFor(sleep, ready, CONNECT_MS)) && (back || (await answers(record!)))) await share();
|
|
443
|
+
})().catch(() => {});
|
|
436
444
|
});
|
|
437
445
|
|
|
438
446
|
pi.on("before_agent_start", (event) => {
|
|
@@ -459,6 +467,7 @@ export function createStrawBoss({ run = herdrRun, api = herdrApi(), call = herdr
|
|
|
459
467
|
});
|
|
460
468
|
|
|
461
469
|
pi.on("session_shutdown", async (event) => {
|
|
470
|
+
if (gui && event.reason !== "quit") markReload(guiDir, me()); // a /reload, /new, or /resume starts it again in this process
|
|
462
471
|
if (gui) await switchRemote(gui, false, guiDir, ts).catch(() => {});
|
|
463
472
|
await gui?.stop();
|
|
464
473
|
gui = undefined;
|
|
@@ -497,36 +506,43 @@ export function createStrawBoss({ run = herdrRun, api = herdrApi(), call = herdr
|
|
|
497
506
|
}
|
|
498
507
|
return (c ?? viewer!).listSessions();
|
|
499
508
|
};
|
|
500
|
-
|
|
509
|
+
const label = () => `${me() || "unknown"} (pane ${env.HERDR_PANE_ID})`;
|
|
510
|
+
// This session's server stops, its remote entry first: /boss gui stop here, another session's stop or takeover (`asked`), or the session's end.
|
|
511
|
+
const stopOwn = async (asked?: { by: string; take: boolean }) => {
|
|
512
|
+
const running = gui;
|
|
513
|
+
gui = undefined;
|
|
514
|
+
if (!running) return false;
|
|
515
|
+
const off = await switchRemote(running, false, guiDir, ts).catch((error: Error) => ({ text: error.message, changed: true }));
|
|
516
|
+
if (off.changed) tell(off.text);
|
|
517
|
+
await running.stop();
|
|
518
|
+
tell(!asked ? "Straw net GUI stopped" : asked.take ? `The straw net GUI moved to session ${asked.by}` : `Straw net GUI stopped from session ${asked.by}`);
|
|
519
|
+
return true;
|
|
520
|
+
};
|
|
521
|
+
// One server per machine: a second /boss gui, here or in another session, opens the one that runs, unless `take` (or a newer version) takes it
|
|
522
|
+
// over. Two calls in flight in this session share one start. A server started here has remote off, so a serve entry a crashed one left goes.
|
|
523
|
+
const share = (take = false, remote = false) =>
|
|
524
|
+
(opening ??= (async () => {
|
|
525
|
+
if (gui) return { url: gui.url, owner: label(), mine: gui };
|
|
526
|
+
const start = (prefer: { port?: number; token?: string; csrf?: string }, net = netSource({ run, sessions, hub: (hub = hub?.me === me() ? hub : createHub(pi, me(), bridge)) })) => startGui({ read: net.read, net, call, hub, dir: bundle, ...prefer, onStop: (asked) => void stopOwn(asked), onRemote: async () => tell((await switchRemote(gui!, true, guiDir, ts)).text) });
|
|
527
|
+
const shared = await sharedGui(guiDir, [label(), me()], start, sleep, { version, take });
|
|
528
|
+
if ((gui = shared.mine) && !remote) await switchRemote(gui, false, guiDir, ts).catch(() => {});
|
|
529
|
+
return shared;
|
|
530
|
+
})().finally(() => (opening = undefined)));
|
|
531
|
+
const older = (owner: string) => `The straw net GUI runs in session ${owner} on a pi-straw-boss older than 0.11.0, which cannot hand it over; /reload that session or run the command there`;
|
|
532
|
+
// `mode` is "", "stop", "remote", or "remote off", and works from any session: remote access (remote.ts) goes with the server, so a session takes it over first.
|
|
501
533
|
const guiCommand = async (mode: string) => {
|
|
502
|
-
const elsewhere = async (what: string) => {
|
|
503
|
-
const record = readRecord(guiDir);
|
|
504
|
-
return tell(record && (await answers(record)) ? `The straw net GUI runs in session ${record.owner}; ${what}` : "The straw net GUI is not running");
|
|
505
|
-
};
|
|
506
534
|
if (mode === "stop") {
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
if (running)
|
|
510
|
-
|
|
511
|
-
if (off.changed) tell(off.text);
|
|
512
|
-
return (await running.stop(), tell("Straw net GUI stopped"));
|
|
513
|
-
}
|
|
514
|
-
return elsewhere("stop it there with /boss gui stop");
|
|
535
|
+
if (await stopOwn()) return;
|
|
536
|
+
const record = readRecord(guiDir);
|
|
537
|
+
if (!record || !(await answers(record))) return tell("The straw net GUI is not running");
|
|
538
|
+
return tell((await requestStop(record, { by: label(), take: false }, sleep)) ? `Straw net GUI stopped (it ran in session ${record.owner})` : older(record.owner));
|
|
515
539
|
}
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
if (gui) return gui.url;
|
|
521
|
-
const start = (prefer: { port?: number; token?: string; csrf?: string }, net = netSource({ run, sessions, hub: (hub = hub?.me === me() ? hub : createHub(pi, me(), bridge)) })) => startGui({ read: net.read, net, call, hub, dir: bundle, ...prefer });
|
|
522
|
-
const shared = await sharedGui(guiDir, [`${me() || "unknown"} (pane ${env.HERDR_PANE_ID})`, me()], start, sleep);
|
|
523
|
-
if ((gui = shared.mine) && mode !== "remote") await switchRemote(gui, false, guiDir, ts).catch(() => {});
|
|
524
|
-
return shared.url;
|
|
525
|
-
})().finally(() => (opening = undefined));
|
|
526
|
-
const url = await opening;
|
|
540
|
+
const { url, owner, stale } = await share(mode.startsWith("remote"), mode === "remote");
|
|
541
|
+
if (mode.startsWith("remote") && !gui) return tell(older(owner));
|
|
542
|
+
if (stale) tell(older(owner), "warning");
|
|
543
|
+
if (mode === "remote off") return tell((await switchRemote(gui!, false, guiDir, ts)).text);
|
|
527
544
|
if (mode === "remote") {
|
|
528
|
-
|
|
529
|
-
const { text, lines, link } = await switchRemote(gui, true, guiDir, ts), block = (active: boolean) => pi.events.emit("herdr:blocked", { active, label: "Showing the remote pairing QR code" });
|
|
545
|
+
const { text, lines, link } = await switchRemote(gui!, true, guiDir, ts), block = (active: boolean) => pi.events.emit("herdr:blocked", { active, label: "Showing the remote pairing QR code" });
|
|
530
546
|
tell(text);
|
|
531
547
|
return void (lines && link && ui && (await showLines(ui, lines, { block, keys: pairingKeys(link, copy, openUrl) })));
|
|
532
548
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
var e={},t=[`en`,`zh-TW`],n=`PARAGLIDE_LOCALE`,r=[`baseLocale`],i=[],a=typeof window>`u`;globalThis.__paraglide=globalThis.__paraglide??{},globalThis.__paraglide.ssr=globalThis.__paraglide.ssr??{};var o=!1,s=()=>{let e=r;!a&&typeof window<`u`&&window.location?.href&&(e=g(window.location.href));let t=c(e,typeof window<`u`?window.location?.href:void 0);if(t)return o||(o=!0,d(t,{reload:!1})),t;throw Error(`No locale found. Read the docs https://paraglidejs.com/errors#no-locale-found`)};function c(e,t){let n;for(let t of e){if(t===`baseLocale`)n=`en`;else if(de(t)&&_.has(t)){let e=_.get(t);if(e){let t=e.getLocale();if(t instanceof Promise)continue;if(t!==void 0)return te(t)}}let e=f(n);if(e)return e}}var l=e=>{s=e},u=e=>{e?window.location.href=e:window.location.reload()},d=(e,t)=>{let n={reload:!0,...t},i;try{i=s()}catch{}let o=[],c=r;!a&&typeof window<`u`&&window.location?.href&&(c=g(window.location.href));for(let t of c)if(t===`baseLocale`)continue;else if(de(t)&&_.has(t)){let n=_.get(t);if(n){let r=n.setLocale(e);r instanceof Promise&&(r=r.catch(e=>{throw Error(`Custom strategy "${t}" setLocale failed.`,{cause:e})}),o.push(r))}}let l=()=>{!a&&n.reload&&window.location&&e!==i&&u(void 0)};if(o.length)return Promise.all(o).then(()=>{l()});l()},ee=()=>typeof window<`u`?window.location.origin:`http://fallback.com`;function f(e){if(typeof e!=`string`)return;let n=e.toLowerCase();for(let e of t)if(e.toLowerCase()===n)return e}function te(e){let n=f(e);if(n)return n;throw Error(`Invalid locale: ${e}. Expected one of: ${t.join(`, `)}`)}function p(e){return e}function ne(t,n){return new e(t,n.href)}function re(){return 0}function ie(e){return i}function ae(e,t){return e.exec(t.href)}var oe=n.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`);RegExp(`(?:^|;\\s*)${oe}=([^;]*)`);function se(e){return ce(e)}function ce(e){let t=p(typeof e==`string`?new URL(e,ee()):new URL(e.href)),n=t.pathname.replace(/^\/+/,``).split(`/`);return n.length>0&&f(n[0])&&(t.pathname=`/`+n.slice(1).join(`/`)),p(t)}var le=-1,m,h;function ue(e){if(i.length===0)return;let t=typeof e==`string`?e:e.href,n=re();if(m===t&&le===n)return h;let r=p(new URL(t,`http://example.com`)),a=se(r),o=a.href===r.href?[r]:[r,a],s;for(let e of o){for(let t of ie(e))if(ae(ne(t.match,e),e)){s=t;break}if(s)break}return le=n,m=t,h=s,s}function g(e){let t=ue(e);return t&&t.exclude!==!0&&Array.isArray(t.strategy)?t.strategy:r}var _=new Map;function de(e){return typeof e==`string`&&/^custom-[A-Za-z0-9_-]+$/.test(e)}var fe=((e={},t={})=>(t.locale??s())===`zh-TW`?`警示`:`Alerts`),pe=((e={},t={})=>(t.locale??s())===`zh-TW`?`所有基地`:`all bases`),me=((e={},t={})=>(t.locale??s())===`zh-TW`?``:`.`),he=((e={},t={})=>(t.locale??s())===`zh-TW`?`最後更新:`:`Last update`),ge=e=>`Disconnected. Gave up after ${e?.tries} tries; it reconnects when you return to this tab.`,_e=e=>`連線中斷。重試 ${e?.tries} 次後放棄;回到此分頁時會重新連線。`,ve=((e,t={})=>(t.locale??s())===`zh-TW`?_e(e):ge(e)),ye=e=>`The server is up but cannot read the net: ${e?.problem}`,be=e=>`伺服器正常,但讀不到網:${e?.problem}`,xe=((e,t={})=>(t.locale??s())===`zh-TW`?be(e):ye(e)),Se=((e={},t={})=>(t.locale??s())===`zh-TW`?`與稻草網的連線中斷,正在重新連線…畫面顯示的是最後已知狀態。`:`Disconnected from the straw net. Reconnecting… The view shows the last known state.`),Ce=e=>`Disconnected from the straw net. Reconnecting (try ${e?.attempt})… The view shows the last known state.`,we=e=>`與稻草網的連線中斷,正在重新連線(第 ${e?.attempt} 次)…畫面顯示的是最後已知狀態。`,Te=((e,t={})=>(t.locale??s())===`zh-TW`?we(e):Ce(e)),Ee=((e={},t={})=>(t.locale??s())===`zh-TW`?`Straw Net:所有基地`:`Straw Net: all bases`),De=e=>`control tower · ${e?.state}`,Oe=e=>`塔台 · ${e?.state}`,ke=((e,t={})=>(t.locale??s())===`zh-TW`?Oe(e):De(e)),Ae=((e={},t={})=>(t.locale??s())===`zh-TW`?`圖示來自 game-icons.net(Lorc、Delapouite),CC BY 3.0。`:`Icons from game-icons.net by Lorc and Delapouite, CC BY 3.0.`),je=((e={},t={})=>(t.locale??s())===`zh-TW`?`文件`:`Documents`),Me=((e={},t={})=>(t.locale??s())===`zh-TW`?`還沒有工作區。在 Herdr 開一個 pi session,網就會出現在這裡。`:`No workspaces yet. Open a pi session in Herdr and the net appears here.`),Ne=((e={},t={})=>(t.locale??s())===`zh-TW`?`總塔台`:`head tower`),Pe=((e={},t={})=>(t.locale??s())===`zh-TW`?`語言`:`Language`),v=((e={},t={})=>(t.locale??s())===`zh-TW`?`連線中`:`connecting`),Fe=((e={},t={})=>(t.locale??s())===`zh-TW`?`即時`:`live`),Ie=((e={},t={})=>(t.locale??s())===`zh-TW`?`離線`:`offline`),Le=((e={},t={})=>(t.locale??s())===`zh-TW`?`重新連線中`:`reconnecting`),Re=((e={},t={})=>(t.locale??s())===`zh-TW`?`正體中文`:`English`),ze=((e={},t={})=>(t.locale??s())===`zh-TW`?`位置`:`Location`),Be=e=>`${e?.name} finished`,Ve=e=>`${e?.name} 已完成`,He=((e,t={})=>(t.locale??s())===`zh-TW`?Ve(e):Be(e)),Ue=e=>`${e?.name} hit an error`,We=e=>`${e?.name} 發生錯誤`,Ge=((e,t={})=>(t.locale??s())===`zh-TW`?We(e):Ue(e)),Ke=e=>`${e?.name} went idle`,qe=e=>`${e?.name} 轉為閒置`,Je=((e,t={})=>(t.locale??s())===`zh-TW`?qe(e):Ke(e)),Ye=e=>`${e?.name} joined`,Xe=e=>`${e?.name} 加入`,Ze=((e,t={})=>(t.locale??s())===`zh-TW`?Xe(e):Ye(e)),Qe=e=>`${e?.name} left`,$e=e=>`${e?.name} 離開`,et=((e,t={})=>(t.locale??s())===`zh-TW`?$e(e):Qe(e)),tt=e=>`${e?.name} lost its status`,nt=e=>`${e?.name} 失去狀態`,rt=((e,t={})=>(t.locale??s())===`zh-TW`?nt(e):tt(e)),it=e=>`${e?.name} is waiting on a question`,at=e=>`${e?.name} 正在等待回答`,ot=((e,t={})=>(t.locale??s())===`zh-TW`?at(e):it(e)),st=e=>`${e?.name} started working`,ct=e=>`${e?.name} 開始工作`,lt=((e,t={})=>(t.locale??s())===`zh-TW`?ct(e):st(e)),y=((e={},t={})=>(t.locale??s())===`zh-TW`?`已完成`:`finished`),b=((e={},t={})=>(t.locale??s())===`zh-TW`?`錯誤`:`error`),x=((e={},t={})=>(t.locale??s())===`zh-TW`?`閒置`:`idle`),ut=((e={},t={})=>(t.locale??s())===`zh-TW`?`無狀態`:`no status`),S=((e={},t={})=>(t.locale??s())===`zh-TW`?`等待回答`:`waiting on a question`),dt=((e={},t={})=>(t.locale??s())===`zh-TW`?`工作中`:`working`),ft=((e={},t={})=>(t.locale??s())===`zh-TW`?`網的動態`:`Net log`),pt=((e={},t={})=>(t.locale??s())===`zh-TW`?`從未`:`never`),mt=((e={},t={})=>(t.locale??s())===`zh-TW`?`沒有執行中的智慧體`:`no agent running`),ht=((e={},t={})=>(t.locale??s())===`zh-TW`?`無警示`:`no alerts`),gt=((e={},t={})=>(t.locale??s())===`zh-TW`?`尚無塔台`:`no tower yet`),_t=((e={},t={})=>(t.locale??s())===`zh-TW`?`思考中`:`thinking`),vt=((e={},t={})=>(t.locale??s())===`zh-TW`?`前哨`:`Outposts`),yt=((e={},t={})=>(t.locale??s())===`zh-TW`?`手機`:`Phone`),bt=((e={},t={})=>(t.locale??s())===`zh-TW`?`透過 Tailscale 配對手機(/boss gui remote 會開啟遠端存取)`:`Pair a phone over Tailscale (/boss gui remote turns remote access on)`),xt=((e={},t={})=>(t.locale??s())===`zh-TW`?`伺服器送來的快照,頁面無法讀取`:`the server sent a snapshot the page cannot read`),St=((e={},t={})=>(t.locale??s())===`zh-TW`?`伺服器回報了頁面無法讀取的問題`:`the server reported a problem the page cannot read`),Ct=((e={},t={})=>(t.locale??s())===`zh-TW`?`主智慧體`:`main`),wt=((e={},t={})=>(t.locale??s())===`zh-TW`?`成員`:`member`),Tt=((e={},t={})=>(t.locale??s())===`zh-TW`?`前哨`:`outpost`),Et=((e={},t={})=>(t.locale??s())===`zh-TW`?`未編入`:`unaligned`),Dt=((e={},t={})=>(t.locale??s(),`session`)),Ot=((e={},t={})=>(t.locale??s())===`zh-TW`?`子智慧體`:`subagent`),kt=((e={},t={})=>(t.locale??s())===`zh-TW`?`塔台`:`tower`),At=((e={},t={})=>(t.locale??s())===`zh-TW`?`智慧體`:`Agents`),jt=((e={},t={})=>(t.locale??s())===`zh-TW`?`基地`:`Bases`),Mt=((e={},t={})=>(t.locale??s())===`zh-TW`?`等待中`:`Waiting`),Nt=((e={},t={})=>(t.locale??s())===`zh-TW`?`工作中`:`Working`),Pt=((e={},t={})=>(t.locale??s())===`zh-TW`?`狀態`:`States`),Ft=e=>`tab ${e?.label}`,It=e=>`分頁 ${e?.label}`,Lt=((e,t={})=>(t.locale??s())===`zh-TW`?It(e):Ft(e)),Rt=((e={},t={})=>(t.locale??s())===`zh-TW`?`即時網況 · 通訊`:`live net · comms`),zt=((e={},t={})=>(t.locale??s())===`zh-TW`?`網的總計`:`Net totals`),Bt=e=>`${e?.label} tower`,Vt=e=>`${e?.label} 塔台`,Ht=((e,t={})=>(t.locale??s())===`zh-TW`?Vt(e):Bt(e)),Ut=e=>`using ${e?.tool}`,Wt=e=>`使用 ${e?.tool}`,Gt=((e,t={})=>(t.locale??s())===`zh-TW`?Wt(e):Ut(e)),Kt=((e={},t={})=>(t.locale??s())===`zh-TW`?`等待變化…`:`Waiting for changes…`),qt=`sb-locale`;function Jt(e){let t=/^zh\b/i.test(e)&&(/-(hant|tw|hk|mo)\b/i.test(e)?`zh-TW`:/-(hans|cn|sg|my)\b/i.test(e)?`zh-CN`:void 0);return f(e)??(t?f(t):void 0)??f(e.split(`-`)[0])}function Yt(e,t){return f(e)??t.map(Jt).find(Boolean)??`en`}var Xt={brand_label:Ee,tagline:Rt,totals_label:zt,stat_bases:jt,stat_agents:At,stat_working:Nt,stat_waiting:Mt,alerts:fe,no_alerts:ht,pair_button:yt,pair_title:bt,link_connecting:v,location:ze,all_bases:pe,empty_map:Me,documents:je,net_log:ft,states:Pt,mark_working:dt,mark_waiting:S,mark_idle:x,mark_done:y,mark_error:b,credit:Ae,language:Pe,waiting_changes:Kt};Object.keys(Xt);function Zt(){let e=null;try{e=localStorage.getItem(qt)}catch{}let n=Yt(e,navigator.languages??[navigator.language]);l(()=>n),document.documentElement.lang=n;let r={m:(e,t)=>e.textContent=t,mLabel:(e,t)=>e.setAttribute(`aria-label`,t),mTitle:(e,t)=>e.title=t,mEmpty:(e,t)=>e.dataset.empty=t};for(let e of document.querySelectorAll(`[data-m], [data-m-label], [data-m-title], [data-m-empty]`))for(let[t,n]of Object.entries(r))e.dataset[t]&&n(e,Xt[e.dataset[t]]?.()??e.dataset[t]);let i=document.getElementById(`lang`);i.replaceChildren(...t.map(e=>new Option(Re({},{locale:e}),e,!1,e===n))),i.onchange=()=>{try{localStorage.setItem(qt,i.value),location.reload()}catch{i.value=n}}}var Qt={working:lt,waiting:ot,idle:Je,done:He,error:Ge,unknown:rt};function $t(e){let t=new Map;for(let n of e.bases){n.tower&&t.set(`tower:${n.id}`,{name:Ht({label:n.label}),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 en(e,t){if(!e)return[];let[n,r]=[$t(e),$t(t)],i=[];for(let[e,t]of r){let r=n.get(e);r?r.mark!==t.mark&&i.push({text:Qt[t.mark]({name:t.name}),mark:t.mark}):i.push({text:Ze({name:t.name}),mark:t.mark})}for(let[e,t]of n)r.has(e)||i.push({text:et({name:t.name}),mark:`idle`});return i}var tn=e=>e===`waiting`||e===`error`?0:1;function nn(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 rn(e,t){return[...t.values()].filter(t=>e?.get(t.key)?.mark!==t.mark&&(tn(t.mark)===0||e!==void 0&&t.mark===`done`))}var an=e=>{try{return decodeURIComponent(e)}catch{return e}},C=e=>/^\.+$/.test(e)?e.replaceAll(`.`,`%2E`):encodeURIComponent(e);function w(e){let[t,n]=e.split(`#`)[0].split(`?`),[r,i,a,o]=t.replace(/^\/+|\/+$/g,``).split(`/`).map(an);if(r!==`w`||!i)return{view:`map`};if(a!==`s`||!o)return{view:`workspace`,ws:i};let s=new URLSearchParams(n).get(`at`);return s?{view:`session`,ws:i,key:o,at:s}:{view:`session`,ws:i,key:o}}var T=e=>e.view===`map`?``:e.view===`workspace`?`w/${C(e.ws)}`:`w/${C(e.ws)}/s/${C(e.key)}${e.at?`?at=${encodeURIComponent(e.at)}`:``}`,on=e=>e.view===`session`?{view:`workspace`,ws:e.ws}:{view:`map`},E=e=>e.view===`session`?e.key:e.view===`workspace`?`w:${e.ws}`:null;function sn(e,t=new URL(document.baseURI).pathname){let n=()=>w(location.pathname.slice(t.length)+location.search),r={route:n,href:e=>T(e)||`./`,go(n){let r=t+T(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(w(t.getAttribute(`data-route`))))}),r}var cn={main:`main`,member:`member`,subagent:`subagent`,outpost:`outpost`,outside:`outside`,tower:`tower`},D={working:dt,waiting:S,idle:x,done:y,error:b,unknown:ut},ln={main:Ct,member:wt,subagent:Ot,tower:kt,outpost:Tt,outside:Et,session:Dt},un={thinking:_t,idle:x,"waiting on a question":S,finished:y},dn=e=>Object.hasOwn(ln,e)?ln[e]():e,fn=e=>e===`waiting`||e===`error`,O=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)},k=(e,t)=>{let n=document.getElementById(e);if(!(n instanceof t))throw Error(`#${e} is missing from the page`);return n},A=(e,t,n)=>{let r=e.querySelector(t);r.textContent!==n&&(r.textContent=n)},j=(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`))},M=(e,t)=>e?e.startsWith(`tool:`)?Gt({tool:e.slice(5)}):Object.hasOwn(un,e)?un[e]():e:D[t](),N=(e,t)=>{e.toggleAttribute(`hidden`,!t),t&&(e.setAttribute(`href`,T(t)||`./`),e.setAttribute(`data-route`,T(t)))},pn=`<div class="plate"><i class="ring"></i><svg><use href="#i-main"/></svg><b class="badge"></b></div>`;function mn(e,t,n,r){j(e,n);let i=e.querySelector(`use`),a=`#i-${cn[t]??`member`}`,o=r?.filter(e=>e.onScreen).length;i.getAttribute(`href`)!==a&&i.setAttribute(`href`,a),o?e.dataset.docs=String(o):delete e.dataset.docs}function P(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 F=()=>O(`<div class="unit"><div class="card"><a class="hit"></a>${pn}<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 I(e,t){let n=e.closest(`.base`)?.dataset.key,r=e.querySelector(`.hit`);N(r,t.key&&n?{view:`session`,ws:n,key:t.key}:void 0),r.setAttribute(`aria-label`,`${t.name}: ${M(t.note,t.mark)}`),r.toggleAttribute(`data-alert`,fn(t.mark)),j(e,t.mark),mn(e.querySelector(`.plate`),t.role,t.mark,t.docs),A(e,`.name`,t.name),A(e,`.role`,dn(t.role)),A(e,`.note`,M(t.note,t.mark)),P(e.querySelector(`.subs`),t.subs??[],F,I)}var hn=()=>O(`<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>${Ne()}</span><h2><a class="enter-base"></a></h2><p></p></div></header><div class="tabs"></div><div class="outposts" data-label="${vt()}"></div></section>`);function gn(e,t){j(e,t.mark),e.classList.toggle(`head`,t.head);let n=e.querySelector(`.tower`);n.classList.toggle(`ghost`,!t.tower),j(n,t.tower?.mark??`unknown`),A(e,`h2 a`,t.label),N(e.querySelector(`h2 a`),{view:`workspace`,ws:t.id}),A(e,`.title p`,t.tower?ke({state:D[t.tower.mark]()}):gt()),P(e.querySelector(`.tabs`),t.tabs,()=>O(`<div class="tab"><h3></h3><div class="units"></div></div>`),(e,t)=>{A(e,`h3`,Lt({label:t.label})),P(e.querySelector(`.units`),t.units,F,I)}),P(e.querySelector(`.outposts`),t.outposts.map(e=>({id:e.id,name:e.label,role:`outpost`,mark:e.mark,note:e.mark===`unknown`?mt():void 0})),F,I)}function _n(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 vn(){let[e,t,n,r]=[k(`map`,HTMLElement),k(`bases`,HTMLElement),k(`links`,SVGSVGElement),k(`log`,HTMLElement)],i=matchMedia(`(prefers-reduced-motion: reduce)`).matches,a=()=>!e.hidden&&_n(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`)]])k(t,HTMLElement).textContent=r},show(e){P(t,e.bases,hn,gn),k(`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=O(`<li><span></span><time></time></li>`);e.dataset.mark=n.mark,A(e,`span`,n.text),A(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 yn=45e3,bn=1e3,xn=3e4,Sn=(e,t)=>Math.min(xn,bn*2**(e-1))*(.8+.4*t);function Cn(e){try{return JSON.parse(e)}catch{return}}function wn(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(),yn),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,Sn(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=Cn(r);i&&e.onNet(i),o({problem:i?void 0:xt()}),l()}),n.listen(`ping`,()=>t===n&&l()),n.listen(`problem`,e=>{t===n&&(o({problem:Cn(e)??St()}),l())}),r=e.setTimeout(()=>u(),yn)};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 Tn=(function(){let e=typeof document<`u`&&document.createElement(`link`).relList;return e&&e.supports&&e.supports(`modulepreload`)?`modulepreload`:`preload`})(),En=function(e,t){return new URL(e,t).href},Dn={},On=function(e){return e.pathname.endsWith(`.css`)},kn=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},L=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=En(t,n);let r=s(t),i=On(r);return kn(Dn,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`:Tn,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)})};Zt();var R=vn(),z=e=>document.getElementById(e),An=e=>e?new Date(e).toLocaleTimeString([],{hour12:!1}):pt(),jn,Mn,B,V,H={state:`connecting`,attempt:0},U={view:`map`},Nn=!1,W,Pn=``,G,Fn,K=e=>G?e(G):void Fn?.then(e);function In(){Fn??=L(async()=>{let{mountFocus:e}=await import(`./views-DKyvJht_.js`);return{mountFocus:e}},[],import.meta.url).then(({mountFocus:e})=>(G=e({data:Un,restart:()=>$.restart(),openTile:Rn,openTerminal:(e,t)=>J(n=>n.terminal.open(e,t)),online:()=>H.state===`live`}),G.show(U,U),B&&G.net(B),G))}var q,Ln,J=e=>{if(q)return e(q);Ln??=L(async()=>{let{mountPanels:e}=await import(`./layer-DwP_iTgP.js`);return{mountPanels:e}},[],import.meta.url).then(({mountPanels:e})=>q=e({label:e=>B?.bases.find(t=>t.id===e)?.label??e,recent:async e=>(await(Q?Q.data(e).latest():Z(e,`?limit=12`))).items,post:e=>Q&&((t,n)=>Q.data(e).post(t,n)),stream:()=>Pn})),Ln.then(e)},Rn=(e,t)=>J(n=>n.tiles.open(e,t));function Y(e){if(B=V=e,document.hidden)return;R.stats(e);let t=nn(e,Date.now()),n=rn(W,t);(n.length||q)&&J(e=>e.alerts(n,t)),W=t,R.log(en(Mn,e)),Mn=e,K(t=>t.net(e)),U.view===`map`&&(R.show(e),jn=e,V=void 0)}function zn(e){let t=U,n=e.view===`workspace`&&t.view===`map`?document.querySelector(`#bases [data-key="${CSS.escape(e.ws)}"]`)?.getBoundingClientRect():void 0;U=e,e.view!==`map`&&In(),z(`map`).hidden=e.view!==`map`,z(`legend`).hidden=e.view===`session`,R.still(e.view!==`map`),K(r=>r.show(e,t,n)),e.view===`map`&&B&&B!==jn&&(Y(B),requestAnimationFrame(R.layout)),Nn&&E(e)!==E(t)&&$.restart()}function X(e){H=e;let t=e.state===`reconnecting`||e.state===`offline`;document.body.dataset.stale=z(`stage`).dataset.stale=String(t),z(`link`).dataset.state=e.state,z(`link-text`).textContent={connecting:v,live:Fe,reconnecting:Le,offline:Ie}[e.state](),G&&B&&G.net(B),q?.stack.redraw();let n=z(`banner`);n.hidden=!t&&!e.problem;let r=e.state===`offline`?ve({tries:e.attempt-1}):e.state===`reconnecting`?e.attempt?Te({attempt:e.attempt}):Se():xe({problem:e.problem??``}),i=document.createElement(`b`);i.textContent=An(e.lastContact),n.replaceChildren(`${r} ${he()} `,i,me())}function Bn(e,t){try{let n=JSON.parse(t);K(t=>e===`history`?t.history(n):t.cards(n))}catch{}}function Vn(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 Hn=e=>fetch(`api/${e}`,{cache:`no-store`}).then(e=>e.ok?e.json():Promise.reject(Error(String(e.status)))),Z=(e,t=``)=>Hn(`history/${encodeURIComponent(e)}${t}`),Q=void 0,Un=e=>({older:t=>Z(e,`?before=${encodeURIComponent(t)}`),latest:()=>Z(e),entry:t=>Hn(`entry/${encodeURIComponent(e)}/${encodeURIComponent(t)}`).catch(()=>void 0)}),Wn=()=>{let e=Vn(E(U));return e.listen(`history`,e=>Bn(`history`,e)),e.listen(`cards`,e=>Bn(`cards`,e)),e.listen(`hello`,e=>(Pn=e,q?.terminal.hello())),e.listen(`mirror`,e=>q?.terminal.frame(e)),e};document.addEventListener(`click`,e=>{let t=e.target?.closest?.(`a[data-alert]`),n=t&&w(t.getAttribute(`data-route`)??``);if(!n||n.view!==`session`||e.button!==0||e.metaKey||e.ctrlKey||e.shiftKey||e.altKey)return;let r=W?.get(n.key);r&&(e.preventDefault(),J(e=>e.stack.show(r)))},!0);var Gn=sn(e=>zn(e)),$=wn({open:Wn,now:Date.now,setTimeout:(e,t)=>window.setTimeout(e,t),clearTimeout:e=>window.clearTimeout(e),random:Math.random,hidden:()=>document.hidden,onNet:Y,onStatus:X}),Kn=()=>$.resume();document.addEventListener(`visibilitychange`,()=>{if(R.pause(document.hidden),document.hidden)return $.hide();V&&Y(V),K(e=>e.wake()),Kn()}),addEventListener(`keydown`,e=>{e.key!==`Escape`||e.defaultPrevented||(e.preventDefault(),!q?.stack.close()&&U.view!==`map`&&Gn.go(on(U)))}),z(`pair`).addEventListener(`click`,()=>void L(async()=>{let{pairTile:e}=await import(`./pair-Cz99RYOR.js`);return{pairTile:e}},[],import.meta.url).then(({pairTile:e})=>Rn(e(),!0)));for(let e of[`focus`,`pageshow`,`online`])window.addEventListener(e,()=>!document.hidden&&Kn());X(H),zn(Gn.route()),$.start(),Nn=!0;export{je as C,s as E,Ne as S,pe as T,Mt as _,N as a,ht as b,mn as c,dn as d,P as f,Nt as g,tn as h,pn as i,O as l,fn as m,cn as n,k as o,A as p,D as r,M as s,L as t,j as u,vt as v,ke as w,mt as x,gt as y};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{n as e,r as t,t as n}from"./post-DQSLbWA2.js";import{E as r}from"./index-CDEHVJil.js";var i=((e={},t={})=>(t.locale??r())===`zh-TW`?`正在取得配對碼…`:`Asking for a pairing code…`),a=((e={},t={})=>(t.locale??r())===`zh-TW`?`新的配對碼`:`New code`),o=((e={},t={})=>(t.locale??r())===`zh-TW`?`伺服器沒有回應。`:`The server did not answer.`),s=((e={},t={})=>(t.locale??r())===`zh-TW`?`配對 QR code`:`Pairing QR code`),c=((e={},t={})=>(t.locale??r())===`zh-TW`?`用以本機使用者身分登入 Tailscale 的手機掃描。只能用一次,十分鐘內有效。`:`Scan it with a phone signed in to Tailscale as this machine's user. It works once, within ten minutes.`),l=((e={},t={})=>(t.locale??r())===`zh-TW`?`配對手機`:`Pair a phone`),u=`http://www.w3.org/2000/svg`;function d(e){let t=e.length,n=document.createElementNS(u,`svg`),r=document.createElementNS(u,`rect`),i=document.createElementNS(u,`path`);n.setAttribute(`viewBox`,`-4 -4 ${t+8} ${t+8}`),n.setAttribute(`class`,`qr`),n.setAttribute(`role`,`img`),n.setAttribute(`aria-label`,s());for(let[e,n]of Object.entries({x:`-4`,y:`-4`,width:String(t+8),height:String(t+8),fill:`#fff`}))r.setAttribute(e,n);return i.setAttribute(`d`,e.flatMap((e,t)=>[...e].flatMap((e,n)=>e===`1`?[`M${n} ${t}h1v1h-1z`]:[])).join(``)),i.setAttribute(`fill`,`#06101e`),n.append(r,i),n}function f(){return{id:`pair`,title:l(),body:()=>{let r=e(`div`,{class:`pair`}),s=e(`button`,{type:`button`,class:`later`},a()),l=()=>{r.replaceChildren(e(`p`,{class:`chat-empty`},i())),n(`remote/pair`,{}).then(n=>{let i=n.body.rows,a=String(n.body.url??``);if(!n.ok||!Array.isArray(i))return r.replaceChildren(e(`p`,null,n.body.reason??t({status:n.status})),s);r.replaceChildren(d(i.map(String)),e(`p`,null,c()),e(`p`,null,e(`code`,null,new URL(a).host)),s)},()=>r.replaceChildren(e(`p`,null,o()),s))};return s.onclick=l,l(),r}}}export{f as pairTile};
|