pi-straw-boss 0.60.4 → 0.61.2
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 +8 -1
- package/README.zh-TW.md +8 -1
- package/dist/gui/assets/{allyasks-CJxdPdzh.js → allyasks-DI3EYpVp.js} +1 -1
- package/dist/gui/assets/allyunits-BSgXjQtA.js +2 -0
- package/dist/gui/assets/{answer-OS32mOu4.js → answer-BL7apmgb.js} +1 -1
- package/dist/gui/assets/{ask-YZFjNZjB.js → ask-CoIm0jPX.js} +1 -1
- package/dist/gui/assets/{asks-CMp6NkUO.js → asks-BnnooiNx.js} +1 -1
- package/dist/gui/assets/chat-D_0h7YQb.js +2 -0
- package/dist/gui/assets/drawer-CKn_xzVL.js +1 -0
- package/dist/gui/assets/index-DGft1IHG.js +4 -0
- package/dist/gui/assets/index-DvbZ79bq.css +1 -0
- package/dist/gui/assets/{layer-BA0eMfcJ.js → layer-C51gEY-z.js} +1 -1
- package/dist/gui/assets/{lightbox-C51XgY6l.js → lightbox-Db_eNcwV.js} +1 -1
- package/dist/gui/assets/link-Ccmv-Guu.js +1 -0
- package/dist/gui/assets/linkdialogs-Dt1edAFc.js +1 -0
- package/dist/gui/assets/{pair-Dn7hwN0V.js → pair-Dfz2AqHg.js} +3 -3
- package/dist/gui/assets/{picker-C_7d5eHv.js → picker-B5tXMVe5.js} +1 -1
- package/dist/gui/assets/{server-CQHWTBIA.js → server-C3XiRAMg.js} +1 -1
- package/dist/gui/assets/{sessionfacts-Hd2shmTO.js → sessionfacts-4aDFyhS2.js} +1 -1
- package/dist/gui/assets/{settings-D2sV4lze.js → settings-CgtiQKfq.js} +2 -2
- package/dist/gui/assets/{spawn-BGo74s7g.js → spawn-DZBpICnV.js} +1 -1
- package/dist/gui/assets/{termcard-CaVpNZ5h.js → termcard-BqdHNLk8.js} +5 -5
- package/dist/gui/assets/{trust-CiT_NDdI.js → trust-2hmISung.js} +1 -1
- package/dist/gui/assets/views-DsIdYMD3.js +2 -0
- package/dist/gui/assets/{waitpanel-BfHK_ZC-.js → waitpanel-R1MWgBZ0.js} +1 -1
- package/dist/gui/assets/zenchunk-BsqxzIto.js +2 -0
- package/dist/gui/index.html +2 -2
- package/dist/server/main.mjs +1130 -413
- package/package.json +1 -1
- package/prompts/head-run.md +1 -1
- package/prompts/tower-run.md +1 -1
- package/src/boss.ts +44 -16
- package/src/bosslink.ts +491 -0
- package/src/bossopen.ts +132 -9
- package/src/bosspaths.ts +76 -3
- package/src/bosssend.ts +21 -0
- package/src/bridge.ts +9 -3
- package/src/closemain.ts +27 -15
- package/src/control.ts +20 -13
- package/src/headcmd.ts +34 -10
- package/src/heremark.ts +56 -0
- package/src/host.ts +6 -2
- package/src/index.ts +2 -2
- package/src/lanface.ts +17 -4
- package/src/link/crypto.ts +46 -0
- package/src/link/holder.ts +377 -39
- package/src/link/kinds.ts +134 -18
- package/src/link/operate.ts +407 -0
- package/src/link/policy.ts +130 -5
- package/src/link/relay.ts +14 -0
- package/src/link/routing.ts +5 -2
- package/src/link/service.ts +10 -3
- package/src/link/sse.ts +28 -1
- package/src/link/unitstatus.ts +11 -4
- package/src/memorycmd.ts +3 -1
- package/src/nethead.ts +4 -2
- package/src/runhead.ts +5 -1
- package/src/runmode.ts +1 -1
- package/src/safetext.ts +8 -0
- package/src/secretscreen.ts +54 -0
- package/src/server/allyport.ts +9 -0
- package/src/server/allyroute.ts +20 -2
- package/src/server/headasks.ts +83 -6
- package/src/server/headbrief.ts +1 -1
- package/src/server/headcmds.ts +14 -3
- package/src/server/headnet.ts +23 -2
- package/src/server/headtools.ts +9 -3
- package/src/server/main.ts +26 -13
- package/src/server/opentower.ts +39 -9
- package/src/server/operateguard.ts +110 -0
- package/src/server/operatescope.ts +159 -0
- package/src/server/revoke.ts +58 -17
- package/src/server/runs.ts +14 -2
- package/src/server/runtools.ts +21 -1
- package/src/server/towers.ts +43 -6
- package/src/server/unitstop.ts +94 -0
- package/src/server-look.ts +3 -2
- package/src/towercmd.ts +99 -9
- package/dist/gui/assets/allyunits-ChyQh77X.js +0 -2
- package/dist/gui/assets/chat-IH62WkJv.js +0 -2
- package/dist/gui/assets/drawer-C3BmsXB9.js +0 -1
- package/dist/gui/assets/index-D-RXzgke.css +0 -1
- package/dist/gui/assets/index-uxjnEvw4.js +0 -3
- package/dist/gui/assets/link-CK5OjaQE.js +0 -1
- package/dist/gui/assets/linkdialogs-CoddZULy.js +0 -1
- package/dist/gui/assets/views-C8d493C2.js +0 -2
- package/dist/gui/assets/zenchunk-DyqlVkbq.js +0 -2
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ English | [繁體中文](https://github.com/wayne930242/pi-straw-boss/blob/main/
|
|
|
18
18
|
|
|
19
19
|
<p align="center"><sub>A unit's comms, a question you can answer from the browser, the Geek view, the settings page where each device picks its view, and the same page on a phone. A tower's wait for you is answered in place: **Handle** in its dialog (or on the tower's card) unfolds a box, and Enter tells the tower.</sub></p>
|
|
20
20
|
|
|
21
|
-
**Zen** is the third view, for the hours when you are answering the net rather than steering it. When something waits for you, the page shows that one thing alone: no map. A card never takes the screen by itself, whatever you are doing: one quiet line (above the input on the circle, under the name beside a session) says how many wait ("1 card waits for Enter. No rush, when you're ready."), and **Enter**, or a tap on the line, takes the next, blocking questions first. Enter then presses the card's main button (Allow, Trust, Handle, the first choice, Run), but never inside a text field. A card you are on is never replaced or pulled away: if its question is answered elsewhere it stays, says so (answered elsewhere, or that its unit left), and waits for you to close it. Nothing else takes the screen from you either: a terminal opened from a card stays until you go back, a session that ended or lost control stays with a quiet note (its box read-only, Send off), a changed server default view applies at the next load, and a new version of the page loads when you are back at the breath, not under you (one quiet line says it is ready). When you answer
|
|
21
|
+
**Zen** is the third view, for the hours when you are answering the net rather than steering it. When something waits for you, the page shows that one thing alone: no map. A card never takes the screen by itself, whatever you are doing: one quiet line (above the input on the circle, under the name beside a session) says how many wait ("1 card waits for Enter. No rush, when you're ready."), and **Enter**, or a tap on the line, takes the next, blocking questions first. Enter then presses the card's main button (Allow, Trust, Handle, the first choice, Run), but never inside a text field. A card you are on is never replaced or pulled away: if its question is answered elsewhere it stays, says so (answered elsewhere, or that its unit left), and waits for you to close it. Nothing else takes the screen from you either: a terminal opened from a card stays until you go back, a session that ended or lost control stays with a quiet note (its box read-only, Send off), a changed server default view applies at the next load, and a new version of the page loads when you are back at the breath, not under you (one quiet line says it is ready). When you answer or cancel a card you took, the next one that was already waiting when you answered is drawn right after, with no breath between (a card that arrives after your answer, a page without the focus, or a visit to Zen that begins after you left it waits for Enter; for its first 400 ms it ignores a held or doubled Enter, a tap, and Esc, so the key that answered cannot press it); the pause comes after the last card, after you skip one (Maybe later), or after you close one whose question ended elsewhere, and Zen breathes again with the others waiting for Enter. A wait a tower recorded on you (a question only you can settle) is a card of its own: **Handle** unfolds an answer box right on it, Enter or **Send** tells the tower in your words, and the card leaves with the knock; **Dismiss** drops the wait, and **Esc** folds the box with your draft kept. Four things Standard shows in the Link button, the Wi-Fi notice, and a tower's notices are cards of their own too: a **confirm** a teammate's tower asks of this computer (Allow or Deny, with the tool's full arguments), a **dialog a Straw Link box forwarded**, a **pair request** (type the number the phone shows, then Allow or Deny), and a **memory proposal** from a tower (Confirm or Reject). They answer through the same functions as Standard's rows, the server decides when one is over, and a paired phone keeps only the authority it has in Standard (no pair-request card: that is this computer's to decide). A join request stays in Standard. A dialog with several questions shows one at a time: the one you are on is open and clear, the others fold to one faded line (the question, and your answer once it has one), and a scroll or swipe, picking an answer, Tab, or a tap on a line moves on to the next. When nothing waits, a breathing circle and a short line on mindfulness or stillness, with whom it comes from (a Japanese source also has its original, small, below): every visit starts there. `[` or `]` steps to a session to keep you company, its live log and its composer, and the circle sits where the list wraps round; ⌘K's *Back to the breath* returns to it. No session, a tower included, is put there for you. One Esc cancels the question on the page, or skips the card when it cannot be cancelled; Esc twice (or the corner menu's last row) goes back to Standard. The corner menu also holds the language, the view, and the sound and volume, and the button beside it takes the page to full screen. An answer that leaves a terminal step (robot_hand's *Put it in my prompt* or a new Herdr pane) shows a small card in ink to finish it, which stays until you go back to Zen, with a quiet line when its step is done; *Full terminal* on the card opens the whole terminal inside Zen, with *Back to Zen* in the top right corner. **Keys.** Enter or Space ends the breathing pause early (so does a tap); Esc answers or skips the card on the page, and a second Esc within 600 ms goes back to Standard (with the corner menu open, Esc only closes it; with text in a box, it only lets the box go). Inside a terminal the page does not take Esc: Shift+Esc lets the keyboard out of the terminal. **H** opens *Context* on a card, the unit's session log inside the card, read-only, and you can still answer while it is open; H or Esc closes it. `[` and `]` step the session beside you (the companion) through the sessions you can talk to. **⌘K** (Ctrl+K off a Mac) opens a command palette for the page's actions and the corner menu's choices. While nothing waits, a quiet line at the top says how many units work and how many are idle; it never counts what waits. Moving the pointer leaves faint ripples. **Sound** follows the settings page's Sound switch (off by default) and Volume: a soft singing-bowl tone when an item takes the screen, a wooden-fish knock when one is done, a lower bowl on an error; the corner menu's *Try the sounds* plays them. Set it as the default with `/boss gui view zen`, or pick it on a device's settings page. Music is yours: put audio files (mp3, m4a, ogg, wav, flac, and the like) in `~/.pi/agent/straw-boss-music/` and Zen shows a ♪ in the corner that plays them on a loop, with a ⌄ to choose the track (shown when there are two or more); with no files there is no ♪. The folder is read each time Zen shows, and tracks cross-fade into themselves so the loop has no gap. On a phone nothing plays before your first tap (♪ says *tap to play* until then, and again after the phone locks), the music pauses while the page is hidden, and the ringer switch mutes it. Motion stops under *reduce motion*, and the page follows the system's forced colours.
|
|
22
22
|
|
|
23
23
|
<p align="center"><img src="docs/gui-zen-item.png" width="49%" alt="The Zen view with one item: a robot_hand question from ops-main on an ink-dark page, its choices as lines of text, each with a dot, and Maybe later below"> <img src="docs/gui-zen-idle.png" width="49%" alt="The Zen view when nothing waits: a session stepped to with ], its live log and its composer"></p>
|
|
24
24
|
|
|
@@ -130,6 +130,9 @@ The tower only routes and coordinates, so it can run a lighter model: set `tower
|
|
|
130
130
|
| `boss_rename` | Name this session with a short phrase for its current work; the net and the GUI show it, and a main agent's tab takes it as its label. Main agents call it when their work changes. |
|
|
131
131
|
| `/boss` | Take over as this tab's main agent. |
|
|
132
132
|
| `/boss status`, `/boss tower` | Show the status; open and focus the tower. |
|
|
133
|
+
| `/boss tower [-w <workspace id\|label\|head>] [--answers W3] <status\|parked\|retry\|deliver <id>\|drop <id>\|leave\|new\|message>` | Act on another workspace's tower from any pi with a screen, as the tower's card and composer do (`-w head` is the head tower, and so is the head's own Herdr workspace named by id or label; a label two workspaces share is refused with their ids). A write at another tower asks you first and names it, the head included (`-w head` does confirm; `/boss head …` does not); a message goes as the boss's words with no opening and no focus change. `--answers W3` marks a wait for you answered once the tower took the message (the rest is then always the message). See [`/boss tower`](docs/how-it-works.md#the-boss-conversation). |
|
|
134
|
+
| `/boss head retry`, `parked`, `deliver <id>`, `drop <id>`, `--answers W3 <message>` | The head tower's notices and parked events, and a message that answers a wait: the pi twins of the head page's buttons and composer (the same as `/boss tower -w head …`). |
|
|
135
|
+
| `/boss send <name\|key> [--after] <text>`, `/boss stop <name\|key>` | Write to any session on the net as the boss, as the page's composer does (`--after` queues it for when the session is idle), or press Esc in it as Stop does (asked in pi first, as the page asks). Quote a name that has spaces: `/boss send "fix login" hi`. The post says it came through a `/boss send`, so the server holds it to the guards a paired device's own write meets, whatever its address: a command that is local-only, the `/boss gui lan` screen's mark, an open `link_request`; and to the usual ones: a blocked dialog, a command that ends the session (asked in pi first), the 16 KB limit. A paired device's composer cannot hide a local-only command in a `/boss send`. |
|
|
133
136
|
| `/boss memory [-w workspace]`, `/boss memory confirm P1`, `reject P1`, `add standing\|decision <text>`, `edit S1 <text>`, `delete D1`, `resolve W1` | Read and change the tower's memory from pi: its standing instructions, decisions, and waits, and the proposals the tower made that wait for you. The GUI's Memory panel is the same operation. See [Tower memory](docs/how-it-works.md#tower-memory). |
|
|
134
137
|
| `/boss server`, `/boss server stop`, `/boss server restart [reason]` | Show the sb server and start it when it is down; stop it on purpose (after a confirm; nothing but a boss command starts it again); restart it (after a confirm) on the same port; the GUI keeps its address, so open pages reconnect by themselves. See [The sb server](docs/how-it-works.md#the-sb-server). |
|
|
135
138
|
| `/boss server logs [n]` | Show the last `n` lines of the sb server's log (default and most 200), as the `boss_server` tool's `logs` does. |
|
|
@@ -142,6 +145,10 @@ The tower only routes and coordinates, so it can run a lighter model: set `tower
|
|
|
142
145
|
| `/boss dismiss [all\|<name>]` | Hide finished subagents from the net, all of them or one by name, as the page's Dismiss does. |
|
|
143
146
|
| `/boss open base <dir> [label]`, `/boss open member [dir]`, `/boss open main <dir> [prompt]` | The page's + Base, + Member, and + Main, typed. `<dir>` is relative to this session's folder (`~` is home; quote a path with spaces); the server still only takes folders under home. A base opens with one member; a member opens beside this session (or in a tab of its own in `<dir>`); a main opens in a new tab of this base and takes the prompt. A project trust question the new pi waits on is asked in pi. |
|
|
144
147
|
| `/boss link [status]`, `/boss link decide <id> approve\|refuse` | This device's teams and members and the join requests waiting (with a short id), and the page's Approve / Refuse. Approving an attended device shows the team, the device, and the sets of words in pi: pick the set the new computer's screen shows (none of them refuses); approving an unattended device asks first. An unknown or ambiguous id does nothing. A paired phone can read and open but not decide. |
|
|
148
|
+
| `/boss link confirms`, `link confirm <id> allow\|deny`, `link asks`, `link answer <id> <number \| text>` | The confirms teammates' towers wait on (who, tool, age, the call's arguments in full) and the questions unattended devices forwarded, listed; Allow / Deny and the answer go to the page's routes. Every allow and every answer asks first, on this computer only: while that screen waits, a paired device's key pad can send Escape only. |
|
|
149
|
+
| `/boss link invite show\|cancel <hash>`, `link join cancel`, `link leave <team> [--force]` | Show an open invite's text on a screen of its own (never in the chat), cancel an invite (asks first), cancel the join in progress, leave a team (asks first). |
|
|
150
|
+
| `/boss link create <relay> <dir> [--share status\|presence] [--label x]`, `link join <invite \| @file> [--project <dir>] [--share …] [--label x]` | Create or join a team in pi. Both ask first, naming the relay and the folder. `create` asks for the relay's token on a masked screen that returns it only to the request; `join` prints the four words for the inviter to pick (the folder is this session's unless `--project` says otherwise). Use `@file` for an invite rather than typing it into the command line. |
|
|
151
|
+
| `/boss link units [box]`, `link stop <box> <main \| handle start> [--interrupt] [reason]` | List the units an unattended box reported and the mains this computer may stop; ask the box to stop one (the page's Stop). Stop confirms first, naming the box, the main, who dispatched it and the mode (`--interrupt` also aborts the turn in progress); the box decides and tells you what happened. A reason may be up to 200 bytes. |
|
|
145
152
|
| `/boss gui`, `/boss gui stop`, `/boss gui rotate` | Open the net in the browser (any session, joins nothing); stop its GUI, from any session. The GUI is served by the sb server, one per machine, so it does not depend on which pi session runs: `/boss gui` starts the server when none runs and prints the URL, and a server that went down comes back when any pi session starts or looks (or from `cli.mjs up`). The URL carries a random token that is kept across a restart, an upgrade, a crash, a reboot, and a `/boss gui stop` followed by `/boss gui` (on the same port, in `gui-secrets.json`), so a page left open reconnects by itself and a phone stays paired. A new token comes only from `/boss gui rotate` (after a confirm; it unpairs every phone and opens the new address), a missing or corrupt `gui-secrets.json`, or a port that was taken at the next start: the old address then answers 403 and a phone scans the QR code again. Keeping the token has a cost you chose: another account on this machine that binds the port during a crash or restart gap sees what an open page sends; rotate after a gap you do not trust. With `STRAW_BOSS_DESK=1` (a desk shell shows the page itself) it opens no browser and the page leaves out Phone & devices and Stash. Only `/boss gui stop` keeps the GUI stopped, until the next `/boss gui` or `cli.mjs up`; `/boss stash` and `/boss close all` do not start a stopped GUI. The settings page's Server section (this computer's page only) shows the server's state, restarts it, and shows its log. Type into a session from its comms view, or work its terminal with the key pad under the terminal tile, or on a desktop by clicking into it and typing; answer a waiting `robot_hand` selector, `ask_user_question` questionnaire, or pi-code hook confirmation there or in its alert (so can any extension's `select` and `confirm`, also from a paired device; other dialogs show read-only, to answer in the terminal; `secret_drop` always takes its secret in the terminal, never on a page, local or over the tailnet, because pi-intercom identities are self-reported). 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. |
|
|
146
153
|
| `/boss gui devices`, `/boss gui unpair <id\|all>` | List the paired phones (id, label, Tailscale or Wi-Fi, when paired and last seen) and unpair one (an id or the start of one) or all of them (after a confirm). The address does not change; `/boss gui rotate` is the one that gives a new address. |
|
|
147
154
|
| `/boss gui lan`, `/boss gui lan off`, `/boss gui lan reset` | Reach the GUI from a phone on the same Wi-Fi, without Tailscale. It is off until you turn it on. This computer makes its own certificate, after showing you the risk: anyone who copies its key from this computer could pose to your phones as private-network sites (your router's page, a NAS) until you remove it from each phone. So use it on your phone's hotspot, or on a Wi-Fi that connects the phone directly to this computer. Each phone installs the certificate once (AirDrop or Quick Share it from the computer, and check it as the screen says), then pairs by QR code or typed code, and you allow each new phone on the computer by typing the number it shows. [How it works](docs/how-it-works.md#browser-view). |
|
package/README.zh-TW.md
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
<p align="center"><sub>單位的通訊畫面、可以直接在瀏覽器回答的問題、極客檢視、每個裝置自選檢視的設定頁,以及同一個頁面在手機上的樣子。塔台記在你身上的等待事項就在原處回覆:在它的對話框(或塔台卡片上)按「去處理」展開輸入框,按 Enter 就送給塔台。</sub></p>
|
|
20
20
|
|
|
21
|
-
**禪(Zen)** 是第三種檢視,給你在回應這張網、而不是指揮它的時候用。有東西在等你時,整個畫面只放那一件事:沒有地圖。不管你正在做什麼,卡片都不會自己搶走畫面:有一行安靜的字說有幾張在等(在圓圈上是輸入框上方,陪著某個 session 時在名字下面,「1 張卡等 Enter。不急,等你準備好。」),按 **Enter** 或點那一行才接下一張,會阻擋智慧體的問題先來。接下來 Enter 會按下卡片的主要按鈕(允許、信任、去處理、第一個選項、執行),但在文字輸入框裡不會。你正在看的卡片也不會被換掉或抽走:它的問題如果在別處被回答了(或它的單位離開了),卡片會留著、說明原因,等你自己關掉。其他東西也不會把畫面從你手上拿走:從卡片開的終端機會待到你自己回去,陪伴的 session 結束或失去控制時畫面會留著並安靜地註明(輸入框唯讀、送出關閉),伺服器預設檢視改了,也要等下次載入才套用,頁面有新版本也一樣:卡片、終端機、陪伴的 session
|
|
21
|
+
**禪(Zen)** 是第三種檢視,給你在回應這張網、而不是指揮它的時候用。有東西在等你時,整個畫面只放那一件事:沒有地圖。不管你正在做什麼,卡片都不會自己搶走畫面:有一行安靜的字說有幾張在等(在圓圈上是輸入框上方,陪著某個 session 時在名字下面,「1 張卡等 Enter。不急,等你準備好。」),按 **Enter** 或點那一行才接下一張,會阻擋智慧體的問題先來。接下來 Enter 會按下卡片的主要按鈕(允許、信任、去處理、第一個選項、執行),但在文字輸入框裡不會。你正在看的卡片也不會被換掉或抽走:它的問題如果在別處被回答了(或它的單位離開了),卡片會留著、說明原因,等你自己關掉。其他東西也不會把畫面從你手上拿走:從卡片開的終端機會待到你自己回去,陪伴的 session 結束或失去控制時畫面會留著並安靜地註明(輸入框唯讀、送出關閉),伺服器預設檢視改了,也要等下次載入才套用,頁面有新版本也一樣:卡片、終端機、陪伴的 session、主塔台的對話、指令面板或選單開著時不會重新載入,只有一行安靜的字說「有新版本,回到呼吸時會更新」,回到呼吸圓圈、什麼都沒開時才載入。你回答或取消一張自己接下的卡片之後,你送出答案的當下已經在排的下一張卡片會直接接上,中間不再回到呼吸(答案送出之後才來的卡片、沒有焦點的頁面、離開禪之後才開始的新一次造訪,都改等你按 Enter;接上的前 400 毫秒內,按住或連按的 Enter、點擊和 Esc 都不會按到它,所以剛才答題的那一下不會誤按下一張);最後一張答完、跳過(「晚點再說」),或關掉一張問題已在別處結束的卡片之後,才會有一次呼吸般的停頓,回到呼吸,其餘的仍等你按 Enter。塔台記在你身上的等待事項(只有你能決定的事)自己是一張卡片:按「去處理」會在卡片上直接展開輸入框,按 Enter 或「送出」把你的話交給塔台,卡片隨一聲木魚離開;「略過」把這則等待丟掉,Esc 把輸入框收起並保留草稿。標準檢視裡放在 Link 按鈕、Wi-Fi 通知和塔台通知的四件事,在禪裡也各是一張卡片:隊友的塔台向這台電腦要的**確認**(允許或拒絕,附上工具的完整參數)、Straw Link 盒子**轉過來的對話框**、**配對請求**(輸入手機上顯示的號碼,再按允許或拒絕),以及塔台提出的**記憶提案**(確認或駁回)。它們呼叫的是和標準檢視同一組函式,什麼時候算結束由伺服器決定,已配對的手機只有它在標準檢視裡原本就有的權限(沒有配對請求卡片:那是這台電腦自己決定的事)。加入團隊的請求仍留在標準檢視。一個對話框有好幾個問題時,一次只清楚地顯示一題:你正在回答的那題展開、清晰,其餘收成一行淡淡的字(題目,答了就接著你的答案),捲動或滑動、選好答案、按 Tab 或點一下那一行就移到下一題。沒有東西在等時,畫面是一個呼吸的圓圈和一句正念的話,每次進入禪都從這裡開始。用 `[` 或 `]` 可以挑一個 session 來陪,畫面會換成它的即時紀錄和輸入框;清單繞完一圈會回到呼吸圓圈,⌘K 裡的「回到呼吸」也能隨時回去。不會自動放一個 session(包括塔台)在那裡。按一次 Esc 會取消畫面上的問題,不能取消的卡片則是跳過;連按兩次 Esc(或選單最後一列)回到標準檢視。右上角的選單還有語言、檢視、音效與音量,旁邊的按鈕可以讓頁面全螢幕。回答之後留下終端機步驟的選項(robot_hand 的「放進我的 prompt」或新的 Herdr 窗格)會在禪裡面出現一張墨色的小卡片讓你完成它,它會待到你自己回到禪,步驟完成時在上方安靜地註明;卡片上的「完整終端機」會在禪裡打開整個終端機,右上角有「回到禪」。**按鍵。** Enter 或空白鍵可以提早結束呼吸停頓(點一下畫面也行);Esc 回答或跳過畫面上的卡片,600 毫秒內再按一次 Esc 回到標準檢視(選單開著時 Esc 只關選單;輸入框裡有字時只是離開輸入框)。終端機在使用中時頁面不攔 Esc,Shift+Esc 可以讓鍵盤離開終端機。**H** 在卡片上展開「前情」,也就是這個 unit 的 session 紀錄,唯讀地顯示在卡片裡,展開時仍然可以回答;再按 H 或 Esc 收起。`[` 與 `]` 在你能對話的 session 之間切換身邊陪著的那一個。**⌘K**(不在 Mac 上是 Ctrl+K)打開指令面板,列出頁面的動作和右上角選單的選項。沒有東西在等時,頂端有一行淡淡的字說明幾個 unit 在工作、幾個閒著,不會數還在等的。滑鼠移動時會留下淡淡的漣漪。**音效**跟隨設定頁的「音效」開關(預設關)與音量:待辦出現時是一聲柔和的頌缽,完成時是一聲木魚,出錯時是低一點的缽聲;選單裡的「試聽音效」可以先聽。用 `/boss gui view zen` 把它設成預設,或在裝置的設定頁自己選。音樂由你自己放:把音檔(mp3、m4a、ogg、wav、flac 等)放進 `~/.pi/agent/straw-boss-music/`,禪的右上角就會出現 ♪,循環播放,旁邊的 ⌄ 可以選曲(有兩首以上才出現);資料夾裡沒有檔案就不會出現 ♪。每次顯示禪時都會重讀資料夾,曲子播完前會與自己交叉淡入淡出,所以循環沒有空檔。手機上要先點一下才會出聲(在那之前 ♪ 寫「點一下播放」,手機鎖屏之後也會再次這樣寫),頁面被藏起來時音樂暫停,靜音開關也會讓它靜音。「減少動態效果」開啟時畫面不動,系統的強制色彩模式也會被遵守。
|
|
22
22
|
|
|
23
23
|
<p align="center"><img src="docs/gui-zen-item.png" width="49%" alt="禪檢視裡的一件待辦:墨色畫面上是 ops-main 的 robot_hand 問題,選項是一行行前面有小圓點的字,下方有「晚點再說」"> <img src="docs/gui-zen-idle.png" width="49%" alt="沒有東西在等時的禪檢視:用 ] 挑來陪的 session,有它的即時紀錄和輸入框"></p>
|
|
24
24
|
|
|
@@ -140,8 +140,15 @@ pi install npm:pi-straw-boss
|
|
|
140
140
|
| `/boss close <名稱\|key>`、`/boss close all <工作區>` | 結束另一個單位、小隊(分頁)或整個基地,結束前在 pi 裡確認(確認畫面會列出誰要結束)。名稱對到不只一個時會列出候選並什麼都不做,名稱前加 `unit:`、`squad:` 或 `base:` 可指定種類。它送到網頁「關掉」用的同一個伺服器路由,所以檢查規則不變。單獨的 `/boss close` 仍是結束這個 session;只有老闆打的指令才有效,塔台執行與盟友執行都碰不到。 |
|
|
141
141
|
| `/boss stash [名稱] --workspace <標籤\|id>` | 把另一個基地收起來(先確認),名稱預設為它的標籤。 |
|
|
142
142
|
| `/boss dismiss [all\|<名稱>]` | 把已結束的子智慧體從網路上隱藏,全部或依名稱一個,和網頁的「移除」相同。 |
|
|
143
|
+
| `/boss tower [-w <工作區 id\|標籤\|head>] [--answers W3] <status\|parked\|retry\|deliver <id>\|drop <id>\|leave\|new\|訊息>` | 在任何有畫面的 pi 裡,對另一個工作區的塔台動作,和塔台的卡片與輸入框一樣(`-w head` 是主塔台;主塔台自己的 Herdr 工作區用 id 或標籤指名,也是主塔台;兩個工作區共用的標籤會被拒絕並列出它們的 id)。對另一座塔台的寫入會先問你並指名,主塔台也一樣;訊息以老闆的話送出,不會開啟也不會切換焦點。`--answers W3` 在塔台收下訊息之後,才把一個等你回覆的等待標為已回覆(此後其餘內容一律是訊息;單獨的 `/quit` 或 `/new` 會被拒絕,和網頁一樣)。見 [`/boss tower`](docs/how-it-works.md#the-boss-conversation)。 |
|
|
144
|
+
| `/boss head retry`、`parked`、`deliver <id>`、`drop <id>`、`--answers W3 <訊息>` | 主塔台的通知與擱置事件,以及回覆等待的訊息:主塔台頁面按鈕與輸入框的 pi 版(不先確認,和 `/boss tower -w head …` 的差別在這裡)。 |
|
|
145
|
+
| `/boss send <名稱\|key> [--after] <內容>`、`/boss stop <名稱\|key>` | 以老闆的身分寫給網路上任何一個 session,和網頁輸入框相同(`--after` 排在它閒下來之後);或對它按 Esc,和「停止」相同(會先在 pi 裡確認)。名稱含空白時加引號:`/boss send "fix login" hi`。這個請求會標明它來自 `/boss send`,所以伺服器用已配對裝置自己寫入時的檢查擋它,不論位址:只限本機的指令、`/boss gui lan` 畫面的標記、等待中的 `link_request`;一般的檢查也照舊:被擋住的對話框、會結束 session 的指令(先在 pi 裡確認)、16 KB 上限。已配對的手機不能把只限本機的指令藏在 `/boss send` 裡。 |
|
|
143
146
|
| `/boss open base <資料夾> [名稱]`、`/boss open member [資料夾]`、`/boss open main <資料夾> [提示]` | 網頁的「+基地」「+成員」「+主智慧體」,用打字完成。`<資料夾>` 相對於本工作階段的資料夾(`~` 是家目錄;路徑有空格要加引號);伺服器仍只接受家目錄底下的資料夾。基地會附一位成員;成員開在本工作階段旁邊(給資料夾則開在它的新分頁);主智慧體開在本基地的新分頁,可帶提示。新的 pi 若在等專案信任問題,會在 pi 裡問你。 |
|
|
144
147
|
| `/boss link [status]`、`/boss link decide <id> approve\|refuse` | 列出本裝置的團隊與成員,以及等待中的加入要求(附短 id),並做網頁的「核准/拒絕」。核准有人值守的裝置時,pi 會顯示團隊、裝置與各組單字:選新電腦螢幕上顯示的那一組(都不是就是拒絕);核准無人值守的裝置會先確認。id 不存在或不唯一就什麼都不做。已配對的手機能讀、能開單位,但不能決定。 |
|
|
148
|
+
| `/boss link confirms`、`link confirm <id> allow\|deny`、`link asks`、`link answer <id> <編號 \| 文字>` | 列出隊友塔台在等的確認(誰、工具、多久前、呼叫的完整參數),和無人值守裝置轉送來的問題;允許/拒絕與答案送到網頁用的路由。每次允許、每次回答都會先問,且只在這台電腦上問:問的畫面開著時,已配對裝置的按鍵板只能送 Escape。 |
|
|
149
|
+
| `/boss link invite show\|cancel <hash>`、`link join cancel`、`link leave <團隊> [--force]` | 在專屬畫面顯示未用邀請的文字(不會出現在聊天裡)、取消邀請(會先問)、取消進行中的加入、離開團隊(會先問)。 |
|
|
150
|
+
| `/boss link create <中繼站> <資料夾> [--share status\|presence] [--label x]`、`link join <邀請 \| @檔案> [--project <資料夾>] [--share …] [--label x]` | 在 pi 裡建立或加入團隊。兩者都會先問,並列出中繼站與資料夾。`create` 會在遮蔽畫面請你輸入中繼站的 token,只交給那個請求;`join` 會印出四個單字,讓邀請人去選(資料夾預設是本工作階段的,用 `--project` 改)。邀請請用 `@檔案`,不要直接打在指令列。 |
|
|
151
|
+
| `/boss link units [無人機]`、`link stop <無人機> <主智慧體名稱 \| 代號開頭> [--interrupt] [原因]` | 列出無人值守機器回報的單位,以及這台電腦可以停止的主智慧體;請那台機器停止其中一個(網頁的「停止」)。停止前會先確認,列出機器、主智慧體、派工者與模式(`--interrupt` 會連進行中的回合一起中斷);由那台機器決定,結果會通知你。原因最多 200 位元組。 |
|
|
145
152
|
| `/boss gui`、`/boss gui stop`、`/boss gui rotate` | 在瀏覽器開啟網(任何 session 都能開,不會加入任何東西);停止它的伺服器,在哪個 session 都可以。整台機器只跑一個伺服器,網址會保留(見下):開它的 session `/reload` 之後會重開(網址不變);跑它的 session 結束時(關掉 pane、離開 pi、當機),另一個還開著的 session 會在幾秒內重開它(網址不變)(塔台優先;pi-straw-boss 版本比伺服器舊的 session 要等約六秒才接手,直到下一個較新的 session 再接回去);之後才啟動的 session 也會把停著的伺服器重開,即使所有 session 都離開過或機器重開機;版本較新的 session 會接手,但開著的頁面不會自動換成新版:它會顯示「這個網址已失效」,要用 `/boss gui` 重開。網址裡的 token 會跨過重啟保留:伺服器重啟、升級、當機、重開機,或 `/boss gui stop` 之後再 `/boss gui`,都沿用同一個 token(存在 `gui-secrets.json`,連同埠號),開著的分頁會自行重新連線,手機仍維持配對。只有 `/boss gui rotate`(會先確認;換新 token 與 CSRF 密鑰、解除所有手機的配對並開啟新網址)、`gui-secrets.json` 遺失或損毀,或下次啟動時埠號被占用,才會換新 token:舊網址回 403,手機要重新掃 QR code。保留 token 的代價是你選擇接受的:當機或重啟的空檔裡,這台機器上其他帳號若搶先佔用該埠,會看到開著的頁面送出的內容;對空檔不放心時請 rotate。設了 `STRAW_BOSS_DESK=1`(桌面殼自己顯示頁面)時,它不會開瀏覽器,頁面也不顯示設定頁的「手機與裝置」與 Stash。只有 `/boss gui stop` 會讓它維持停止,直到下一次 `/boss gui`;`/boss stash` 和 `/boss close all` 不會把停著的伺服器重開。可以在通訊畫面直接打字給某個 session,或用終端機畫面下方的按鍵面板操作它的終端機,在桌面上也可以點進終端機直接打字;在等回覆的 `robot_hand` 選單、`ask_user_question` 問卷或 pi-code 的 hook 確認,可以在那裡或它的警示裡作答(任何 extension 的 `select` 和 `confirm` 也可以,`confirm` 也可以從配對的裝置作答;其他對話框只能看,要回到終端機回答;`secret_drop` 的機密一律在終端機輸入,任何頁面(本機或 tailnet)都不接受,因為 pi-intercom 的身分是自己申報的,無法驗證)。session 用 [pi-herdr-doc-review](https://www.npmjs.com/package/pi-herdr-doc-review) 0.4.0 以上顯示的文件,會開在它的通訊畫面旁邊:HTML 放在沙箱框架裡,表單送出的答案會傳給智慧體;純文字只能讀。 |
|
|
146
153
|
| `/boss gui devices`、`/boss gui unpair <id\|all>` | 列出已配對的手機(id、標籤、Tailscale 或 Wi-Fi、配對與最後使用時間),並解除配對一支(給 id 或 id 的開頭)或全部(先確認)。網址不會變;要換網址是 `/boss gui rotate`。 |
|
|
147
154
|
| `/boss gui lan`、`/boss gui lan off`、`/boss gui lan reset` | 不用 Tailscale,讓同一個 Wi-Fi 上的手機連 GUI。預設關閉,要你自己打開。這台電腦會先說明風險,再自己產生憑證:任何人只要從這台電腦複製走它的金鑰,就能對你的手機冒充私有網路上的網站(路由器的設定頁、NAS),直到你從每支手機移除這張憑證為止。所以請在手機的個人熱點上用,或用能讓手機直接連到這台電腦的 Wi-Fi。每支手機安裝一次憑證(從電腦用 AirDrop 或 Quick Share 傳過去,照螢幕說明核對),再掃 QR code 或輸入代碼配對;每支新手機都要你在電腦上輸入它顯示的數字才放行。[運作方式](docs/how-it-works.md#browser-view)(英文)。 |
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{w as e}from"./towermodel-DJLQh2fz.js";import{t}from"./runtime-ZX6HkxDa.js";import{
|
|
1
|
+
import{w as e}from"./towermodel-DJLQh2fz.js";import{t}from"./runtime-ZX6HkxDa.js";import{$ as n,Z as r,tt as i}from"./index-DGft1IHG.js";import{mountDialogCards as a}from"./linkdialogs-Dt1edAFc.js";var o=t=>{let n=e(`en`,t?.count,{},!0);return n===`one`?`${t?.count} question waits for you: answer it here`:n===`other`?`${t?.count} questions wait for you: answer them here`:`ally_asks_button`},s=e=>`${e?.count} 個問題等你回答,在這裡回答`,c=((e,n={})=>(n.locale??t())===`zh-TW`?s(e):o(e)),l=e=>e.tower===`blocked`||e.tabs.some(e=>e.state===`blocked`);function u(e){let t=new Map,i=n(e?.allies??[]);for(let n of e?.alerts??[]){let e=n.kind===`dialog`?r(n):void 0;if(e!==`open`&&e!==`sent`)continue;let a=i.filter(e=>e.device===n.data.device),o=a.filter(e=>e.teams.some(e=>e.team===n.team)),s=o.length?o:a,c=s.find(l)??s[0];c&&t.set(c.id,[...t.get(c.id)??[],n])}return t}var d=`.ally-unit[data-state="blocked"], .ally-tab[data-state="blocked"]`;function f(){let e=new WeakMap,t=t=>{let r=e.get(t);if(r)return r;let o=i(`button`,{type:`button`,class:`ally-asks-btn`,"aria-expanded":`false`}),s=i(`ul`,{class:`ally-asks-list`}),c=i(`div`,{class:`ally-asks`},o,s);return r={box:c,btn:o,list:s,cards:a(),ids:``},e.set(t,r),o.onclick=()=>n(t),t.addEventListener(`click`,e=>{let r=e.target?.closest?.(d);r&&t.contains(r)&&t.dataset.asks&&!e.target.closest(`details`)&&n(t)}),t.append(c),r};function n(t){let n=e.get(t);if(!n||!t.dataset.asks)return;let r=t.dataset.asking===void 0;r?t.dataset.asking=``:delete t.dataset.asking,n.list.hidden=!r,n.btn.setAttribute(`aria-expanded`,String(r))}function r(n,r){if(!r.length&&!e.has(n))return;let i=t(n);if(i.box.hidden=!r.length,!r.length){delete n.dataset.asks,delete n.dataset.asking,i.btn.setAttribute(`aria-expanded`,`false`),i.cards.keep(new Set),i.list.replaceChildren(),i.ids=``;return}n.dataset.asks=String(r.length),i.btn.textContent=c({count:r.length}),i.list.hidden=n.dataset.asking===void 0,i.cards.keep(new Set(r.map(e=>e.id)));let a=r.map(e=>i.cards.row(e)),o=r.map(e=>e.id).join(`
|
|
2
2
|
`);o!==i.ids&&(i.list.replaceChildren(...a),i.ids=o)}return{toggle:n,fill:r,show:(e,t,n)=>r(e,u(n).get(t.id)??[])}}export{f as mountAllyAsks};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{w as e}from"./towermodel-DJLQh2fz.js";import{t}from"./runtime-ZX6HkxDa.js";import{n}from"./post-DDdE-PdN.js";import{Ct as r,Et as i,Ft as a,O as o,P as s,R as c,S as l,et as u,h as d,k as f}from"./index-DGft1IHG.js";var p=e=>`by ${e?.who}`,m=e=>`派工者 ${e?.who}`,h=((e,n={})=>(n.locale??t())===`zh-TW`?m(e):p(e)),g=((e={},n={})=>(n.locale??t())===`zh-TW`?`中斷並停止`:`Interrupt and stop`),_=e=>`${e?.box} was not asked: ${e?.reason}`,v=e=>`沒有請 ${e?.box} 停止:${e?.reason}`,y=((e,n={})=>(n.locale??t())===`zh-TW`?v(e):_(e)),b=((e={},n={})=>(n.locale??t())===`zh-TW`?`停止`:`Stop`),x=e=>`Stop the main ${e?.name}`,S=e=>`停止主智慧體 ${e?.name}`,C=((e,n={})=>(n.locale??t())===`zh-TW`?S(e):x(e)),w=e=>`Ask ${e?.box} to stop the main ${e?.name}? Stop lets it quit when it is idle; Interrupt and stop aborts the turn it is in first. The box decides and tells you what happened.`,T=e=>`要請 ${e?.box} 停止主智慧體 ${e?.name} 嗎?「停止」等它閒下來才結束;「中斷並停止」會先中止它進行中的回合。由那台機器決定,結果會通知你。`,E=((e,n={})=>(n.locale??t())===`zh-TW`?T(e):w(e)),D=e=>`Mains (${e?.count})`,O=e=>`主智慧體(${e?.count})`,k=((e,n={})=>(n.locale??t())===`zh-TW`?O(e):D(e)),A=((e={},n={})=>(n.locale??t())===`zh-TW`?`前`:` ago`),j=((e={},n={})=>(n.locale??t())===`zh-TW`?`發生了什麼事`:`What happened`),M=((e={},n={})=>(n.locale??t())===`zh-TW`?`這個單位最後一次回報的時間`:`When this unit last reported`),N=t=>{let n=e(`en`,t?.count,{},!0);return n===`one`?`${t?.count} monitor`:n===`other`?`${t?.count} monitors`:`link_unit_monitors`},P=e=>`${e?.count} 個監看程序`,F=((e,n={})=>(n.locale??t())===`zh-TW`?P(e):N(e)),ee=((e={},n={})=>(n.locale??t())===`zh-TW`?`最後回報`:`Last report`),I=((e={},n={})=>(n.locale??t())===`zh-TW`?`最近沒有狀態`:`no status lately`),L=((e={},n={})=>(n.locale??t())===`zh-TW`?`盒子已超過 3 分鐘沒送狀態,這是它最後一次的內容`:`The box has sent no status for 3 minutes; this is its last one`),R=((e={},n={})=>(n.locale??t())===`zh-TW`?`請在盒子的 trust.json 加入這個專案`:`Add the project to the box's trust.json`),z=((e={},n={})=>(n.locale??t())===`zh-TW`?`為什麼停了`:`Why it stopped`),B=((e={},n={})=>(n.locale??t())===`zh-TW`?`前更新`:` ago`),V=((e={},n={})=>(n.locale??t())===`zh-TW`?``:`updated `),H={choose:s,post:(e,t)=>n(e,t)},U=12e4,W=new Map,G=(e,t)=>`${e.device}/${t.handle}`,K=(e,t,n=Date.now())=>n-(W.get(G(e,t))??-1/0)<U;async function q(e,t,n){let a=await H.choose(E({box:n,name:t.name}),[{label:b(),value:`quit`},{label:g(),value:`interrupt`,tone:`danger`}]);if(!a)return!1;let o=await H.post(`link/unit-stop`,{team:e.team,device:e.device,handle:t.handle,mode:a,reason:``}).catch(()=>({ok:!1,status:0,body:{}}));return o.ok?(W.set(G(e,t),Date.now()),!0):(await H.choose(y({box:n,reason:o.body.reason??(o.status?r({status:o.status}):i())}),[]),!1)}var J=()=>l(`<li class="ally-unit"><div class="au-head"><i class="au-dot"></i><b class="au-word"></b><span class="au-name"></span><span class="au-time" hidden><span class="au-pre"></span><span class="age"></span><span class="au-ago"></span></span><em class="au-stale" hidden></em></div><p class="au-mons" hidden><b></b><span></span></p><details class="au-mains" hidden><summary><b class="au-mains-label"></b></summary><ul class="au-main-list"></ul></details><details class="au-crash" hidden><summary><b></b><span class="au-time"><span class="age"></span><span class="au-ago"></span></span></summary><pre></pre><p class="au-hint" hidden></p></details><details class="au-report" hidden><summary><b class="au-label"></b><span class="au-peek"></span></summary><div class="md au-md"></div></details></li>`),Y,X=new WeakMap;function Z(e){let t=e.querySelector(`.au-md`),n=X.get(e)??``;e.open&&t.dataset.report!==n&&(Y?Promise.resolve(Y):c(()=>import(`./markdown-Bk5NWfKQ.js`).then(e=>e.t).then(e=>Y=e),[],import.meta.url)).then(({mount:r,parse:i})=>{e.open&&X.get(e)===n&&(t.dataset.report=n,t.replaceChildren(r(i(n))))})}function Q(e,t,n=``,r=A()){let i=e.querySelector(`.age`);i.dataset.since=String(t),i.textContent=d(t),e.querySelector(`.au-pre`)?.replaceChildren(n),e.querySelector(`.au-ago`).textContent=r}var $=()=>l(`<li class="au-main"><span class="au-mdot"></span><b class="au-mname"></b><span class="au-mstate"></span><span class="au-mby" hidden></span><button type="button" class="au-stop" hidden></button></li>`);function te(e,t,n){let r=e.querySelector(`.au-mains`);r.hidden=!t.mains.length,t.mains.length&&(f(r,`.au-mains-label`,k({count:t.mains.length})),o(r.querySelector(`.au-main-list`),t.mains.map(e=>({...e,id:e.handle})),$,(e,r)=>{let i=r.stopping||K(t,r),o=i?a():r.word;e.dataset.tone=i?`other`:r.tone,f(e,`.au-mname`,r.name),f(e,`.au-mstate`,o);let s=e.querySelector(`.au-mby`);s.hidden=r.byLabel===void 0,s.textContent=r.byLabel===void 0?``:h({who:r.byLabel});let c=e.querySelector(`.au-stop`);c.hidden=!r.canStop||i,c.textContent=b(),c.setAttribute(`aria-label`,C({name:r.name})),c.onclick=()=>{c.disabled=!0,q(t,r,n).then(t=>{c.disabled=!1,t&&(e.dataset.tone=`other`,f(e,`.au-mstate`,a()),c.hidden=!0)})}}))}function ne(e,t,n,r=``){o(e,t.map(e=>({...e,id:e.unit,named:n})),J,(e,t)=>{e.dataset.state=t.state,e.dataset.tone=t.tone,e.classList.toggle(`stale`,t.stale),f(e,`.au-word`,t.word),f(e,`.au-name`,t.named?t.unit:``);let n=e.querySelector(`.au-head > .au-time`);n.hidden=!1,n.title=M(),Q(n,t.at,V(),B());let i=e.querySelector(`.au-stale`);i.hidden=!t.stale,i.textContent=t.stale?I():``,i.title=t.stale?L():``;let a=e.querySelector(`.au-mons`);a.hidden=!t.monitors.length,t.monitors.length&&(f(a,`b`,F({count:t.monitors.length})),f(a,`span`,t.monitors.join(` · `)),a.title=t.monitors.join(`
|
|
2
|
+
`)),te(e,t,r);let o=e.querySelector(`.au-crash`);if(o.hidden=!t.crash,o.toggleAttribute(`data-trust`,t.crash?.trust===!0),t.crash){f(o,`summary > b`,t.crash.trust?z():j()),Q(o.querySelector(`summary > .au-time`),t.crash.at),f(o,`pre`,t.crash.text);let e=o.querySelector(`.au-hint`);e.hidden=!t.crash.trust,e.textContent=t.crash.trust?R():``}let s=e.querySelector(`.au-report`);s.hidden=!t.report,t.report&&(f(s,`.au-label`,ee()),f(s,`.au-peek`,u(t.report)),X.set(s,t.report),s.ontoggle=()=>Z(s),Z(s))})}export{ne as fillAllyUnits};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./rolldown-runtime-DK3Fl9T5.js";import{t}from"./ask-
|
|
1
|
+
import{t as e}from"./rolldown-runtime-DK3Fl9T5.js";import{t}from"./ask-CoIm0jPX.js";import{n}from"./post-DDdE-PdN.js";var r=e({answerPost:()=>i,canAnswer:()=>o,mountAnswer:()=>s,trustPost:()=>a}),i=(e,t)=>t?.(e)??((t,r)=>n(e.startsWith(`grant:`)?`panes/${encodeURIComponent(e.slice(6))}/${t}`:`sessions/${encodeURIComponent(e)}/${t}`,r)),a=e=>e??(e=>n(`trust/answer`,e)),o=(e,...t)=>e===`waiting`&&t.every(Boolean),s=(e,{key:n,show:r,post:i,remote:a,accepted:o,label:s})=>t(e,i,a,{key:n,show:r},o,s);export{a,s as i,r as n,o as r,i as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./runtime-ZX6HkxDa.js";import{a as t,i as n,n as r,r as i,t as a}from"./sending-aEpvzoz2.js";import{St as o,et as s,qt as c,t as l}from"./index-uxjnEvw4.js";var u=((t={},n={})=>(n.locale??e())===`zh-TW`?`請在終端機中回答。`:`Answer it in the terminal.`),d=((t={},n={})=>(n.locale??e())===`zh-TW`?`請在終端機中回答。`:`Answer them in the terminal.`),f=((t={},n={})=>(n.locale??e())===`zh-TW`?`下方還有 ▾`:`More below ▾`),p=((t={},n={})=>(n.locale??e())===`zh-TW`?`也可以自己輸入答案。`:`It also takes your own words.`),m=((t={},n={})=>(n.locale??e())===`zh-TW`?`可以複選。`:`It takes several choices.`),h=((t={},n={})=>(n.locale??e())===`zh-TW`?`已取消。`:`Cancelled.`),g=((t={},n={})=>(n.locale??e())===`zh-TW`?`選擇`:`Choices`),_=((t={},n={})=>(n.locale??e())===`zh-TW`?`瀏覽器拒絕存取剪貼簿。`:`The browser refused the clipboard.`),v=((t={},n={})=>(n.locale??e())===`zh-TW`?`已複製到這台裝置的剪貼簿。`:`Copied to this device's clipboard.`),y=((t={},n={})=>(n.locale??e())===`zh-TW`?`複製指令`:`Copy command`),ee=((t={},n={})=>(n.locale??e())===`zh-TW`?`這個選項有預覽;請在終端機中查看。`:`It has a preview; see it in the terminal.`),b=((t={},n={})=>(n.locale??e())===`zh-TW`?`備註`:`Note`),x=((t={},n={})=>(n.locale??e())===`zh-TW`?`備註(選填)`:`Note (optional)`),S=e=>`Opened while ${e?.tool} was running; it may not be about that call.`,C=e=>`在 ${e?.tool} 執行時開啟,不一定與該呼叫有關。`,te=((t,n={})=>(n.locale??e())===`zh-TW`?C(t):S(t)),w=((t={},n={})=>(n.locale??e())===`zh-TW`?`選項`:`Options`),T=((t={},n={})=>(n.locale??e())===`zh-TW`?`另一個答案沒有被採用;這個可以送出。`:`The other answer was not taken; this one can go.`),E=((t={},n={})=>(n.locale??e())===`zh-TW`?`你的答案`:`Your own answer`),D=((t={},n={})=>(n.locale??e())===`zh-TW`?`或自己輸入答案`:`Or type your own answer`),O=((t={},n={})=>(n.locale??e())===`zh-TW`?`問題已變更,請重新閱讀。`:`The question changed; read it again.`),k=((t={},n={})=>(n.locale??e())===`zh-TW`?`session 讀不懂這個答案。`:`The session could not read that answer.`),A=((t={},n={})=>(n.locale??e())===`zh-TW`?`這個答案不符合問題。`:`That answer does not fit the question.`),j=((t={},n={})=>(n.locale??e())===`zh-TW`?`session 拒絕了這個答案。`:`The session refused that answer.`),M=((t={},n={})=>(n.locale??e())===`zh-TW`?`安全考量,遠端不支援輸入機密。請到執行 GUI 的那台電腦的終端機中回答。`:`For security, entering a secret is not supported remotely. Answer it in the terminal on the computer the GUI runs on.`),N=((t={},n={})=>(n.locale??e())===`zh-TW`?`機密內容只能在終端機輸入,這裡不接受。請到執行 GUI 的那台電腦的終端機中回答。`:`A secret is entered in the terminal only, not here. Answer it in the terminal on the computer the GUI runs on.`),P=((t={},n={})=>(n.locale??e())===`zh-TW`?`送出答案`:`Send answer`),F=((t={},n={})=>(n.locale??e())===`zh-TW`?`顯示終端機`:`Show terminal`),I=((t={},n={})=>(n.locale??e())===`zh-TW`?`已在終端機中關閉。`:`It was dismissed in the terminal.`),L=((t={},n={})=>(n.locale??e())===`zh-TW`?`它已不再開啟。`:`It is no longer open.`),R=((t={},n={})=>(n.locale??e())===`zh-TW`?`已在終端機中回答。`:`It was already answered in the terminal.`),z=((t={},n={})=>(n.locale??e())===`zh-TW`?`它在等待對話框。`:`It waits on a dialog.`),B={ArrowDown:1,ArrowRight:1,ArrowUp:-1,ArrowLeft:-1};function V(e,t,n,r,i){let{q:a}=n,o=r[a],s=B[e]??0,c=e===`ArrowUp`,l=c||e===`ArrowDown`,u=()=>({to:r.map((e,t)=>({q:(a+1+t)%r.length,part:`opt`})).find(e=>e.q!==a&&!i[e.q])??`send`});if(e===`Tab`){let e=r[a-1],i=n.part===`opt`?o.own||o.note:n.part===`own`&&o.note;return t?n.part===`opt`&&e?{to:{q:a-1,part:e.note?`note`:e.own?`own`:`opt`}}:void 0:i||a===r.length-1?void 0:{to:{q:a+1,part:`opt`}}}if(!t){if(n.part===`opt`){let t=n.o+s;if(s)return t>=0&&t<o.options?{to:{q:a,part:`opt`,o:t},...o.multiple?{}:{pick:t}}:{to:s>0&&o.own?{q:a,part:`own`}:n};if(e===`Enter`||e===` `&&!o.multiple)return{...u(),...o.multiple?{}:{pick:n.o}}}else if(n.part===`own`){if(e===`Enter`)return u();if(l)return{to:c?{q:a,part:`opt`,o:o.options-1}:{q:a,part:`note`}}}else if(c)return{to:{q:a,part:`own`}}}}function H(e,t,n){let r=e=>Math.max(0,e.opts.findIndex(e=>e.getAttribute(`aria-checked`)===`true`)),i=(e,t)=>e.opts.forEach((e,n)=>e.setAttribute(`tabindex`,n===t?`0`:`-1`)),a=e=>{for(let[n,r]of t.entries()){let t=r.opts.indexOf(e);if(t>=0)return{q:n,part:`opt`,o:t};if(e===r.own||e===r.note)return{q:n,part:e===r.own?`own`:`note`}}};t.forEach(e=>i(e,r(e)));let o=e=>{let n=a(e.target);n?.part===`opt`&&i(t[n.q],n.o)};e.addEventListener(`focusin`,o),e.addEventListener(`click`,o);let s=!1,c=!1;return e.addEventListener(`keydown`,i=>{i.key===` `&&(c=!0);let o=a(i.target);if(!o||i.ctrlKey||i.altKey||i.metaKey||i.isComposing)return;let l=i.target;if(o.part!==`opt`&&(i.key===`ArrowUp`?l.selectionStart!==0:i.key===`ArrowDown`&&l.selectionEnd!==l.value.length))return;let u=V(i.key,i.shiftKey,o,t.map(e=>({options:e.opts.length,multiple:e.multiple,own:!!e.own,note:!!e.note})),t.map(e=>e.answered()));if(!u||(i.preventDefault(),i.repeat&&[`Enter`,` `].includes(i.key)))return;if(s=i.key===` `,u.pick!==void 0){let e=t[o.q].opts[u.pick];e.getAttribute(`aria-checked`)!==`true`&&e.click()}let d=u.to===`send`?void 0:t[u.to.q],f=u.to===`send`?n():u.to.part===`opt`?d.opts[u.to.o??r(d)]:u.to.part===`own`?d.own:d.note;f&&!f.disabled&&(e.dispatchEvent(new CustomEvent(`ask-reveal`,{detail:f})),f.focus())}),e.addEventListener(`keyup`,e=>{e.key===` `&&((s||!c)&&e.preventDefault(),s=c=!1)}),()=>t[0]?.opts[r(t[0])]}var U=e=>e.multiple?m():e.freeform&&e.options.length?p():``,W=90,G=(e,t)=>s(`div`,{class:`ask-one`},e.header&&s(`b`,{class:`ask-head`},e.header),s(`p`,{class:`ask-q`,...e.question.length>W?{"data-long":``}:{}},e.question),e.context&&s(`div`,{class:`ask-ctx`},e.context),e.options.length>0&&s(`ol`,{class:`ask-opts`,"aria-label":w()},...e.options.map(e=>s(`li`,{class:`ask-opt`},s(`b`,null,e.title),e.description&&s(`small`,null,e.description)))),t&&U(e)&&s(`small`,{class:`ask-how`},U(e))),K=e=>e.replace(/[\u0000-\u0008\u000b-\u001f\u007f-\u009f\p{Cf}]/gu,`�`),q=e=>(e.select?.choices??[]).map((e,t)=>({...e,i:t})),J=(e,t,n)=>({...e.size?{choices:[...e].sort((e,t)=>e-t)}:{},...t.trim()?{text:t}:{},...n.trim()?{note:n}:{}}),Y=(e,t,n)=>({dialog:e.dialog,digest:e.digest,answerId:n,...t}),X=(e,t)=>({dialog:e.dialog,digest:e.digest,answerId:t,cancel:!0}),Z=(e,t)=>e.cancel===!0&&!(t&&e.select?.choices.every(e=>e.hereOnly)),Q={digest:O,"not-allowed":A,malformed:k};function ne(e,i=!1){let{outcome:a,reason:s,by:c}=e.body;return a===`accepted`?[`ok`,i?h():n()]:a===`stale`?[`error`,c===`local`?R():c===`cancel`?I():L()]:a===`rejected`?[`error`,(Object.hasOwn(Q,String(s))?Q[String(s)]:j)()]:a===`busy`?[`error`,t()]:a===`unknown`||e.status===504?[`error`,r(),!0]:[`error`,s??o({status:e.status})]}var re=e=>[`accepted`,`stale`,`busy`,`unknown`].includes(String(e.body.outcome))||e.status===504,$=e=>e.answer?`d\n${e.answer.dialog}\n${e.answer.digest}`:`c\n${e.callId}\n${e.why??``}`;function ie(e){if(e.dataset.cued)return;e.dataset.cued=`1`;let t=()=>{e.toggleAttribute(`data-more`,e.scrollHeight-e.scrollTop-e.clientHeight>4);for(let t of e.querySelectorAll(`.ask-acts`))t.dataset.cue=f()};for(let n of[`scroll`,`input`])e.addEventListener(n,t,{passive:!0});typeof ResizeObserver<`u`&&new ResizeObserver(t).observe(e),typeof MutationObserver<`u`&&new MutationObserver(t).observe(e,{childList:!0,subtree:!0,characterData:!0}),typeof requestAnimationFrame<`u`&&requestAnimationFrame(t)}function ae(e,t,n=location.hostname!==`127.0.0.1`,o,f,p=F){let m,h,S,C=!1,O=!1,k;for(let e of[`focusin`,`pointerdown`])document.addEventListener(e,e=>h&&!h.el.contains(e.target)&&(h.lost=void 0));let A=(e,t,n,...r)=>(e.dataset.tone=t,e.replaceChildren(n,...r)),j=()=>{if(!h)return;let e=document.activeElement;e&&e!==document.body&&e!==h.lost&&(h.lost=void 0),h.controls.forEach(e=>e.disabled=!C||O||h.done),h.send&&(h.send.disabled=!C||O||h.done||!h.pick()),e&&h.el.contains(e)&&e.disabled&&(h.lost=e);let t=h.lost;t&&!t.disabled&&h.el.contains(t)&&(!document.activeElement||document.activeElement===document.body)&&(t.focus(),h.lost=void 0)};async function I(e,n){[e.sending,O,e.spell]=[!0,!0,!1],j(),A(e.note,``,a());let c=await t(`answer`,n).catch(()=>void 0),u=s(`button`,{type:`button`,class:`cmp-link`},i());u.onclick=()=>void I(e,n);let[d,p,m]=c?ne(c,n.cancel===!0):[`error`,r(),!0];[e.done,e.sending,O,e.busy]=[!c||re(c),!1,!1,c?.body.outcome===`busy`],A(e.note,d,p,...m?[u]:[]);let h=c?.body.outcome===`accepted`?c.body.then:void 0,g=h&&l(h,{key:o?.key??``,command:e.copy,answerId:String(n.answerId??``)});g&&A(e.note,d,`${p} ${g}`),j(),e.note.scrollIntoView?.({block:`nearest`}),f&&c?.body.outcome===`accepted`&&setTimeout(()=>f(!!h&&!g),h&&!g?0:1200)}let L=(e,t,n,r,i)=>{let a=s(`button`,{type:`button`,class:`ask-opt`,role:e,"aria-checked":`false`},s(`b`,i?{"data-n":String(i)}:null,t),...n.filter(Boolean).map(e=>s(`small`,null,e)));return a.onclick=r,a};function R(e,t){let r,i=q(t).map(e=>L(`radio`,K(e.label),[e.note&&K(e.note)],()=>(r=e.i,i.forEach((n,r)=>n.setAttribute(`aria-checked`,String(q(t)[r].i===e.i))),j()),e.i+1)),a=t.select?.copy!==void 0&&s(`button`,{type:`button`,class:`cmp-link`},y());a&&(a.disabled=!navigator.clipboard,a.onclick=()=>void navigator.clipboard.writeText(t.select.copy).then(()=>A(e.note,`ok`,v()),()=>A(e.note,`error`,_())));let o=i.filter((e,r)=>!(n&&q(t)[r].hereOnly));return i.forEach(e=>!o.includes(e)&&(e.disabled=!0)),e.pick=()=>r===void 0?void 0:{choice:r},e.first=H(e.el,[{opts:i,multiple:!1,answered:()=>r!==void 0}],()=>e.send),e.controls=o,[s(`pre`,{class:`ask-title`},K(t.select.title)),s(`div`,{class:`ask-opts`,role:`radiogroup`,"aria-label":g()},...i),s(`div`,{class:`ask-acts`},e.send,e.cancel,a)]}function B(e,t){let n=t.questions.map(()=>({picks:new Set,text:s(`textarea`,{rows:`1`,maxlength:`8192`,class:`ask-own`,placeholder:D(),"aria-label":E()}),note:s(`input`,{type:`text`,maxlength:`2048`,class:`ask-own ask-memo`,placeholder:x(),"aria-label":b()})})),r=[],i=t.questions.map((t,i)=>{let a=n[i],o=t.multiple?`checkbox`:`radio`,c=t.options.map((e,n)=>L(o,e.title,[e.description,e.preview&&ee()],()=>{t.multiple||(a.picks.clear(),a.text.value=``),a.picks.has(n)?a.picks.delete(n):a.picks.add(n),c.forEach((e,t)=>e.setAttribute(`aria-checked`,String(a.picks.has(t)))),j()}));return a.text.oninput=()=>(t.multiple||(a.picks.clear(),c.forEach(e=>e.setAttribute(`aria-checked`,`false`))),j()),e.controls.push(...c,a.text,a.note),r.push({opts:c,multiple:!!t.multiple,own:a.text,note:a.note,answered:()=>a.picks.size>0||a.text.value.trim()!==``}),s(`div`,{class:`ask-one`},t.header&&s(`b`,{class:`ask-head`},t.header),s(`p`,{class:`ask-q`,...t.question.length>W?{"data-long":``}:{}},t.question),s(`div`,{class:`ask-opts`,role:t.multiple?`group`:`radiogroup`,"aria-label":w()},...c),a.text,a.note)});return e.pick=()=>n.every(e=>e.picks.size||e.text.value.trim())?{answers:n.map(e=>J(e.picks,e.text.value,e.note.value))}:void 0,e.first=H(e.el,r,()=>e.send),[...i,s(`div`,{class:`ask-acts`},e.send,e.cancel)]}function V(e){let t=e.asks??(e.ask?[e.ask]:[]),r=t.length>1,i=e.answer,a={copy:i?.select?.copy,key:$(e),el:s(`section`,{class:`ask`}),note:s(`p`,{class:`ask-note`,role:`status`,"aria-live":`polite`}),controls:[],pick:()=>void 0,done:!1,sending:!1};i&&((a.send=s(`button`,{type:`button`,class:`ask-send`},P())).onclick=()=>void(a.pick()&&I(a,Y(i,a.pick(),crypto.randomUUID()))));let l=e.tool===`secret_drop`;i&&!l&&Z(i,n)&&((a.cancel=s(`button`,{type:`button`,class:`ask-cancel`},c())).onclick=()=>void I(a,X(i,crypto.randomUUID())));let f=s(`p`,{class:`ask-term`},e.why&&t.length?e.why:`${r?d():u()} ${r||!t[0]?``:U(t[0])}`.trim()),m=o&&e.tool!==`secret_drop`&&s(`button`,{type:`button`,class:`cmp-link`},p());m&&(m.onclick=o.show);let h=e.answer?.twin&&e.tool&&e.tool!==`dialog`?[s(`p`,{class:`ask-why`},te({tool:e.tool}))]:[];return a.el.append(...h,...i&&!l?i.select?R(a,i):B(a,i):[...t.length?t.map(e=>G(e,r)):[s(`p`,{class:`ask-why`},l?n?M():N():e.why??z())],s(`div`,{class:`ask-acts`},l?s(`p`,{class:`ask-term`},u()):f,m)],a.note),a.cancel&&a.controls.push(a.cancel),a}let Q=(t,n)=>{let r=document.activeElement;h&&h!==n&&(h.focus=h.el.contains(r)?r:void 0),[m,h,S]=[t,n,n?.send?n:S],e.replaceChildren(...n?[n.el]:[]),n&&ie(n.el),j(),n?.focus&&(!document.activeElement||document.activeElement===document.body)&&n.focus.focus()};return{enter(){let e=h&&!h.done?h.first?.():void 0;return!!(e&&!e.disabled&&(e.focus(),1))},cancel(){let e=h&&!h.done?h.cancel:void 0;return!!(e&&!e.disabled&&(e.click(),1))},sending:()=>O,update(e,t){C=t,e&&(k=void clearTimeout(k)),!e&&(h?.done||h?.sending)?k??=setTimeout(()=>(k=void 0,Q()),6e3):e?h&&($(e)===h.key||!e.answer&&(h.done||h.sending)&&e.callId===m?.callId)?((h.busy||h.sending)&&!e.answer?h.spell=!0:h.busy&&h.spell&&e.answer&&([h.done,h.busy]=[!1,!1],A(h.note,``,T())),m=e):Q(e,S?.key===$(e)&&!S.done?S:V(e)):Q(),j()}}}export{ae as t};
|
|
1
|
+
import{t as e}from"./runtime-ZX6HkxDa.js";import{a as t,i as n,n as r,r as i,t as a}from"./sending-aEpvzoz2.js";import{Ct as o,Yt as s,t as c,tt as l}from"./index-DGft1IHG.js";var u=((t={},n={})=>(n.locale??e())===`zh-TW`?`請在終端機中回答。`:`Answer it in the terminal.`),d=((t={},n={})=>(n.locale??e())===`zh-TW`?`請在終端機中回答。`:`Answer them in the terminal.`),f=((t={},n={})=>(n.locale??e())===`zh-TW`?`下方還有 ▾`:`More below ▾`),p=((t={},n={})=>(n.locale??e())===`zh-TW`?`也可以自己輸入答案。`:`It also takes your own words.`),m=((t={},n={})=>(n.locale??e())===`zh-TW`?`可以複選。`:`It takes several choices.`),h=((t={},n={})=>(n.locale??e())===`zh-TW`?`已取消。`:`Cancelled.`),g=((t={},n={})=>(n.locale??e())===`zh-TW`?`選擇`:`Choices`),_=((t={},n={})=>(n.locale??e())===`zh-TW`?`瀏覽器拒絕存取剪貼簿。`:`The browser refused the clipboard.`),v=((t={},n={})=>(n.locale??e())===`zh-TW`?`已複製到這台裝置的剪貼簿。`:`Copied to this device's clipboard.`),y=((t={},n={})=>(n.locale??e())===`zh-TW`?`複製指令`:`Copy command`),ee=((t={},n={})=>(n.locale??e())===`zh-TW`?`這個選項有預覽;請在終端機中查看。`:`It has a preview; see it in the terminal.`),b=((t={},n={})=>(n.locale??e())===`zh-TW`?`備註`:`Note`),x=((t={},n={})=>(n.locale??e())===`zh-TW`?`備註(選填)`:`Note (optional)`),S=e=>`Opened while ${e?.tool} was running; it may not be about that call.`,C=e=>`在 ${e?.tool} 執行時開啟,不一定與該呼叫有關。`,te=((t,n={})=>(n.locale??e())===`zh-TW`?C(t):S(t)),w=((t={},n={})=>(n.locale??e())===`zh-TW`?`選項`:`Options`),T=((t={},n={})=>(n.locale??e())===`zh-TW`?`另一個答案沒有被採用;這個可以送出。`:`The other answer was not taken; this one can go.`),E=((t={},n={})=>(n.locale??e())===`zh-TW`?`你的答案`:`Your own answer`),D=((t={},n={})=>(n.locale??e())===`zh-TW`?`或自己輸入答案`:`Or type your own answer`),O=((t={},n={})=>(n.locale??e())===`zh-TW`?`問題已變更,請重新閱讀。`:`The question changed; read it again.`),k=((t={},n={})=>(n.locale??e())===`zh-TW`?`session 讀不懂這個答案。`:`The session could not read that answer.`),A=((t={},n={})=>(n.locale??e())===`zh-TW`?`這個答案不符合問題。`:`That answer does not fit the question.`),j=((t={},n={})=>(n.locale??e())===`zh-TW`?`session 拒絕了這個答案。`:`The session refused that answer.`),M=((t={},n={})=>(n.locale??e())===`zh-TW`?`安全考量,遠端不支援輸入機密。請到執行 GUI 的那台電腦的終端機中回答。`:`For security, entering a secret is not supported remotely. Answer it in the terminal on the computer the GUI runs on.`),N=((t={},n={})=>(n.locale??e())===`zh-TW`?`機密內容只能在終端機輸入,這裡不接受。請到執行 GUI 的那台電腦的終端機中回答。`:`A secret is entered in the terminal only, not here. Answer it in the terminal on the computer the GUI runs on.`),P=((t={},n={})=>(n.locale??e())===`zh-TW`?`送出答案`:`Send answer`),F=((t={},n={})=>(n.locale??e())===`zh-TW`?`顯示終端機`:`Show terminal`),I=((t={},n={})=>(n.locale??e())===`zh-TW`?`已在終端機中關閉。`:`It was dismissed in the terminal.`),L=((t={},n={})=>(n.locale??e())===`zh-TW`?`它已不再開啟。`:`It is no longer open.`),R=((t={},n={})=>(n.locale??e())===`zh-TW`?`已在終端機中回答。`:`It was already answered in the terminal.`),z=((t={},n={})=>(n.locale??e())===`zh-TW`?`它在等待對話框。`:`It waits on a dialog.`),B={ArrowDown:1,ArrowRight:1,ArrowUp:-1,ArrowLeft:-1};function V(e,t,n,r,i){let{q:a}=n,o=r[a],s=B[e]??0,c=e===`ArrowUp`,l=c||e===`ArrowDown`,u=()=>({to:r.map((e,t)=>({q:(a+1+t)%r.length,part:`opt`})).find(e=>e.q!==a&&!i[e.q])??`send`});if(e===`Tab`){let e=r[a-1],i=n.part===`opt`?o.own||o.note:n.part===`own`&&o.note;return t?n.part===`opt`&&e?{to:{q:a-1,part:e.note?`note`:e.own?`own`:`opt`}}:void 0:i||a===r.length-1?void 0:{to:{q:a+1,part:`opt`}}}if(!t){if(n.part===`opt`){let t=n.o+s;if(s)return t>=0&&t<o.options?{to:{q:a,part:`opt`,o:t},...o.multiple?{}:{pick:t}}:{to:s>0&&o.own?{q:a,part:`own`}:n};if(e===`Enter`||e===` `&&!o.multiple)return{...u(),...o.multiple?{}:{pick:n.o}}}else if(n.part===`own`){if(e===`Enter`)return u();if(l)return{to:c?{q:a,part:`opt`,o:o.options-1}:{q:a,part:`note`}}}else if(c)return{to:{q:a,part:`own`}}}}function H(e,t,n){let r=e=>Math.max(0,e.opts.findIndex(e=>e.getAttribute(`aria-checked`)===`true`)),i=(e,t)=>e.opts.forEach((e,n)=>e.setAttribute(`tabindex`,n===t?`0`:`-1`)),a=e=>{for(let[n,r]of t.entries()){let t=r.opts.indexOf(e);if(t>=0)return{q:n,part:`opt`,o:t};if(e===r.own||e===r.note)return{q:n,part:e===r.own?`own`:`note`}}};t.forEach(e=>i(e,r(e)));let o=e=>{let n=a(e.target);n?.part===`opt`&&i(t[n.q],n.o)};e.addEventListener(`focusin`,o),e.addEventListener(`click`,o);let s=!1,c=!1;return e.addEventListener(`keydown`,i=>{i.key===` `&&(c=!0);let o=a(i.target);if(!o||i.ctrlKey||i.altKey||i.metaKey||i.isComposing)return;let l=i.target;if(o.part!==`opt`&&(i.key===`ArrowUp`?l.selectionStart!==0:i.key===`ArrowDown`&&l.selectionEnd!==l.value.length))return;let u=V(i.key,i.shiftKey,o,t.map(e=>({options:e.opts.length,multiple:e.multiple,own:!!e.own,note:!!e.note})),t.map(e=>e.answered()));if(!u||(i.preventDefault(),i.repeat&&[`Enter`,` `].includes(i.key)))return;if(s=i.key===` `,u.pick!==void 0){let e=t[o.q].opts[u.pick];e.getAttribute(`aria-checked`)!==`true`&&e.click()}let d=u.to===`send`?void 0:t[u.to.q],f=u.to===`send`?n():u.to.part===`opt`?d.opts[u.to.o??r(d)]:u.to.part===`own`?d.own:d.note;f&&!f.disabled&&(e.dispatchEvent(new CustomEvent(`ask-reveal`,{detail:f})),f.focus())}),e.addEventListener(`keyup`,e=>{e.key===` `&&((s||!c)&&e.preventDefault(),s=c=!1)}),()=>t[0]?.opts[r(t[0])]}var U=e=>e.multiple?m():e.freeform&&e.options.length?p():``,W=90,G=(e,t)=>l(`div`,{class:`ask-one`},e.header&&l(`b`,{class:`ask-head`},e.header),l(`p`,{class:`ask-q`,...e.question.length>W?{"data-long":``}:{}},e.question),e.context&&l(`div`,{class:`ask-ctx`},e.context),e.options.length>0&&l(`ol`,{class:`ask-opts`,"aria-label":w()},...e.options.map(e=>l(`li`,{class:`ask-opt`},l(`b`,null,e.title),e.description&&l(`small`,null,e.description)))),t&&U(e)&&l(`small`,{class:`ask-how`},U(e))),K=e=>e.replace(/[\u0000-\u0008\u000b-\u001f\u007f-\u009f\p{Cf}]/gu,`�`),q=e=>(e.select?.choices??[]).map((e,t)=>({...e,i:t})),J=(e,t,n)=>({...e.size?{choices:[...e].sort((e,t)=>e-t)}:{},...t.trim()?{text:t}:{},...n.trim()?{note:n}:{}}),Y=(e,t,n)=>({dialog:e.dialog,digest:e.digest,answerId:n,...t}),X=(e,t)=>({dialog:e.dialog,digest:e.digest,answerId:t,cancel:!0}),Z=(e,t)=>e.cancel===!0&&!(t&&e.select?.choices.every(e=>e.hereOnly)),Q={digest:O,"not-allowed":A,malformed:k};function ne(e,i=!1){let{outcome:a,reason:s,by:c}=e.body;return a===`accepted`?[`ok`,i?h():n()]:a===`stale`?[`error`,c===`local`?R():c===`cancel`?I():L()]:a===`rejected`?[`error`,(Object.hasOwn(Q,String(s))?Q[String(s)]:j)()]:a===`busy`?[`error`,t()]:a===`unknown`||e.status===504?[`error`,r(),!0]:[`error`,s??o({status:e.status})]}var re=e=>[`accepted`,`stale`,`busy`,`unknown`].includes(String(e.body.outcome))||e.status===504,$=e=>e.answer?`d\n${e.answer.dialog}\n${e.answer.digest}`:`c\n${e.callId}\n${e.why??``}`;function ie(e){if(e.dataset.cued)return;e.dataset.cued=`1`;let t=()=>{e.toggleAttribute(`data-more`,e.scrollHeight-e.scrollTop-e.clientHeight>4);for(let t of e.querySelectorAll(`.ask-acts`))t.dataset.cue=f()};for(let n of[`scroll`,`input`])e.addEventListener(n,t,{passive:!0});typeof ResizeObserver<`u`&&new ResizeObserver(t).observe(e),typeof MutationObserver<`u`&&new MutationObserver(t).observe(e,{childList:!0,subtree:!0,characterData:!0}),typeof requestAnimationFrame<`u`&&requestAnimationFrame(t)}function ae(e,t,n=location.hostname!==`127.0.0.1`,o,f,p=F){let m,h,S,C=!1,O=!1,k;for(let e of[`focusin`,`pointerdown`])document.addEventListener(e,e=>h&&!h.el.contains(e.target)&&(h.lost=void 0));let A=(e,t,n,...r)=>(e.dataset.tone=t,e.replaceChildren(n,...r)),j=()=>{if(!h)return;let e=document.activeElement;e&&e!==document.body&&e!==h.lost&&(h.lost=void 0),h.controls.forEach(e=>e.disabled=!C||O||h.done),h.send&&(h.send.disabled=!C||O||h.done||!h.pick()),e&&h.el.contains(e)&&e.disabled&&(h.lost=e);let t=h.lost;t&&!t.disabled&&h.el.contains(t)&&(!document.activeElement||document.activeElement===document.body)&&(t.focus(),h.lost=void 0)};async function I(e,n){[e.sending,O,e.spell]=[!0,!0,!1],j(),A(e.note,``,a());let s=await t(`answer`,n).catch(()=>void 0),u=l(`button`,{type:`button`,class:`cmp-link`},i());u.onclick=()=>void I(e,n);let[d,p,m]=s?ne(s,n.cancel===!0):[`error`,r(),!0];[e.done,e.sending,O,e.busy]=[!s||re(s),!1,!1,s?.body.outcome===`busy`],A(e.note,d,p,...m?[u]:[]);let h=s?.body.outcome===`accepted`?s.body.then:void 0,g=h&&c(h,{key:o?.key??``,command:e.copy,answerId:String(n.answerId??``)});g&&A(e.note,d,`${p} ${g}`),j(),e.note.scrollIntoView?.({block:`nearest`}),f&&s?.body.outcome===`accepted`&&setTimeout(()=>f(!!h&&!g),h&&!g?0:1200)}let L=(e,t,n,r,i)=>{let a=l(`button`,{type:`button`,class:`ask-opt`,role:e,"aria-checked":`false`},l(`b`,i?{"data-n":String(i)}:null,t),...n.filter(Boolean).map(e=>l(`small`,null,e)));return a.onclick=r,a};function R(e,t){let r,i=q(t).map(e=>L(`radio`,K(e.label),[e.note&&K(e.note)],()=>(r=e.i,i.forEach((n,r)=>n.setAttribute(`aria-checked`,String(q(t)[r].i===e.i))),j()),e.i+1)),a=t.select?.copy!==void 0&&l(`button`,{type:`button`,class:`cmp-link`},y());a&&(a.disabled=!navigator.clipboard,a.onclick=()=>void navigator.clipboard.writeText(t.select.copy).then(()=>A(e.note,`ok`,v()),()=>A(e.note,`error`,_())));let o=i.filter((e,r)=>!(n&&q(t)[r].hereOnly));return i.forEach(e=>!o.includes(e)&&(e.disabled=!0)),e.pick=()=>r===void 0?void 0:{choice:r},e.first=H(e.el,[{opts:i,multiple:!1,answered:()=>r!==void 0}],()=>e.send),e.controls=o,[l(`pre`,{class:`ask-title`},K(t.select.title)),l(`div`,{class:`ask-opts`,role:`radiogroup`,"aria-label":g()},...i),l(`div`,{class:`ask-acts`},e.send,e.cancel,a)]}function B(e,t){let n=t.questions.map(()=>({picks:new Set,text:l(`textarea`,{rows:`1`,maxlength:`8192`,class:`ask-own`,placeholder:D(),"aria-label":E()}),note:l(`input`,{type:`text`,maxlength:`2048`,class:`ask-own ask-memo`,placeholder:x(),"aria-label":b()})})),r=[],i=t.questions.map((t,i)=>{let a=n[i],o=t.multiple?`checkbox`:`radio`,s=t.options.map((e,n)=>L(o,e.title,[e.description,e.preview&&ee()],()=>{t.multiple||(a.picks.clear(),a.text.value=``),a.picks.has(n)?a.picks.delete(n):a.picks.add(n),s.forEach((e,t)=>e.setAttribute(`aria-checked`,String(a.picks.has(t)))),j()}));return a.text.oninput=()=>(t.multiple||(a.picks.clear(),s.forEach(e=>e.setAttribute(`aria-checked`,`false`))),j()),e.controls.push(...s,a.text,a.note),r.push({opts:s,multiple:!!t.multiple,own:a.text,note:a.note,answered:()=>a.picks.size>0||a.text.value.trim()!==``}),l(`div`,{class:`ask-one`},t.header&&l(`b`,{class:`ask-head`},t.header),l(`p`,{class:`ask-q`,...t.question.length>W?{"data-long":``}:{}},t.question),l(`div`,{class:`ask-opts`,role:t.multiple?`group`:`radiogroup`,"aria-label":w()},...s),a.text,a.note)});return e.pick=()=>n.every(e=>e.picks.size||e.text.value.trim())?{answers:n.map(e=>J(e.picks,e.text.value,e.note.value))}:void 0,e.first=H(e.el,r,()=>e.send),[...i,l(`div`,{class:`ask-acts`},e.send,e.cancel)]}function V(e){let t=e.asks??(e.ask?[e.ask]:[]),r=t.length>1,i=e.answer,a={copy:i?.select?.copy,key:$(e),el:l(`section`,{class:`ask`}),note:l(`p`,{class:`ask-note`,role:`status`,"aria-live":`polite`}),controls:[],pick:()=>void 0,done:!1,sending:!1};i&&((a.send=l(`button`,{type:`button`,class:`ask-send`},P())).onclick=()=>void(a.pick()&&I(a,Y(i,a.pick(),crypto.randomUUID()))));let c=e.tool===`secret_drop`;i&&!c&&Z(i,n)&&((a.cancel=l(`button`,{type:`button`,class:`ask-cancel`},s())).onclick=()=>void I(a,X(i,crypto.randomUUID())));let f=l(`p`,{class:`ask-term`},e.why&&t.length?e.why:`${r?d():u()} ${r||!t[0]?``:U(t[0])}`.trim()),m=o&&e.tool!==`secret_drop`&&l(`button`,{type:`button`,class:`cmp-link`},p());m&&(m.onclick=o.show);let h=e.answer?.twin&&e.tool&&e.tool!==`dialog`?[l(`p`,{class:`ask-why`},te({tool:e.tool}))]:[];return a.el.append(...h,...i&&!c?i.select?R(a,i):B(a,i):[...t.length?t.map(e=>G(e,r)):[l(`p`,{class:`ask-why`},c?n?M():N():e.why??z())],l(`div`,{class:`ask-acts`},c?l(`p`,{class:`ask-term`},u()):f,m)],a.note),a.cancel&&a.controls.push(a.cancel),a}let Q=(t,n)=>{let r=document.activeElement;h&&h!==n&&(h.focus=h.el.contains(r)?r:void 0),[m,h,S]=[t,n,n?.send?n:S],e.replaceChildren(...n?[n.el]:[]),n&&ie(n.el),j(),n?.focus&&(!document.activeElement||document.activeElement===document.body)&&n.focus.focus()};return{enter(){let e=h&&!h.done?h.first?.():void 0;return!!(e&&!e.disabled&&(e.focus(),1))},cancel(){let e=h&&!h.done?h.cancel:void 0;return!!(e&&!e.disabled&&(e.click(),1))},sending:()=>O,update(e,t){C=t,e&&(k=void clearTimeout(k)),!e&&(h?.done||h?.sending)?k??=setTimeout(()=>(k=void 0,Q()),6e3):e?h&&($(e)===h.key||!e.answer&&(h.done||h.sending)&&e.callId===m?.callId)?((h.busy||h.sending)&&!e.answer?h.spell=!0:h.busy&&h.spell&&e.answer&&([h.done,h.busy]=[!1,!1],A(h.note,``,T())),m=e):Q(e,S?.key===$(e)&&!S.done?S:V(e)):Q(),j()}}}export{ae as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{t as e}from"./rolldown-runtime-DK3Fl9T5.js";import{m as t}from"./towermodel-DJLQh2fz.js";import{t as n}from"./runtime-ZX6HkxDa.js";import{n as r}from"./post-DDdE-PdN.js";import{
|
|
1
|
+
import{t as e}from"./rolldown-runtime-DK3Fl9T5.js";import{m as t}from"./towermodel-DJLQh2fz.js";import{t as n}from"./runtime-ZX6HkxDa.js";import{n as r}from"./post-DDdE-PdN.js";import{Ct as i}from"./index-DGft1IHG.js";var a=((e={},t={})=>(t.locale??n())===`zh-TW`?`沒有符合這個號碼的請求。`:`No request has that number.`),o=((e={},t={})=>(t.locale??n())===`zh-TW`?`這個請求已經不在了。`:`That request is gone.`),s=((e={},t={})=>(t.locale??n())===`zh-TW`?`連續輸入三次錯誤號碼,所以所有等待中的請求都已拒絕。請按「新的配對碼」重新配對。`:`Three wrong numbers in a row, so every waiting request was denied. Press New code and pair again.`),c=((e={},t={})=>(t.locale??n())===`zh-TW`?`這個請求已經變了,請重新看過。`:`That request changed. Look at it again.`),l=((e={},t={})=>(t.locale??n())===`zh-TW`?`這個請求已經不在了,或已逾時。`:`That request is gone or has timed out.`),u=((e={},t={})=>(t.locale??n())===`zh-TW`?`這個團隊沒有在這台裝置上執行。`:`That team is not running on this device.`),d=((e={},t={})=>(t.locale??n())===`zh-TW`?`已在該裝置上取消。`:`It was cancelled at the device.`),f=((e={},t={})=>(t.locale??n())===`zh-TW`?`你已從這裡回答。`:`You answered it from here.`),p=((e={},t={})=>(t.locale??n())===`zh-TW`?`已在該裝置上回答。`:`Answered at the device itself.`),m=((e={},t={})=>(t.locale??n())===`zh-TW`?`已由團隊的另一個控制端回答。`:`Answered by another controller of this team.`),h=e=>`The answer was not sent: ${e?.reason}`,g=e=>`答案沒有送出:${e?.reason}`,_=((e,t={})=>(t.locale??n())===`zh-TW`?g(e):h(e)),v=((e={},t={})=>(t.locale??n())===`zh-TW`?`問題在有人回答前就結束了。`:`It ended before anyone answered it.`),y=((e={},t={})=>(t.locale??n())===`zh-TW`?`已送出你的答案;對方裝置還沒關閉這個問題。`:`Your answer was sent; the device has not closed the question yet.`),b=((e={},t={})=>(t.locale??n())===`zh-TW`?`你已不再負責回答這台裝置的問題;問題在那邊仍未結束。`:`You no longer answer this device's questions; it is still open there.`);function x(e){switch(e){case`sent`:return y();case`done-here`:return f();case`done-other`:return m();case`done-local`:return p();case`cancelled`:return d();case`expired`:return v();case`withdrawn`:return b()}}var S=e=>typeof e==`object`&&!!e&&!Array.isArray(e),C=e=>typeof e==`string`,w=e=>Array.isArray(e)&&e.every(e=>S(e)&&C(e.title));function T(e){let{dialog:t,dialogId:n,digest:r}=e.data;if(!C(t)||!C(n)||!C(r))return;let i;try{i=JSON.parse(t)}catch{return}if(!S(i))return;let{select:a,questions:o,cancel:s}=i,c={dialog:n,digest:r,...s===!0?{cancel:!0}:{}};if(S(a)&&C(a.title)&&Array.isArray(a.choices)&&a.choices.every(e=>S(e)&&C(e.label)))return{callId:n,tool:`dialog`,answer:{...c,select:a}};if(Array.isArray(o)&&o.length>0&&o.every(e=>S(e)&&C(e.question)&&w(e.options)))return{callId:n,tool:`dialog`,answer:{...c,questions:o}}}var E=e=>e.cancel===!0?{cancel:!0}:e.choice===void 0?{answers:e.answers}:{choice:e.choice},D=e({confirmActions:()=>M,confirmWhy:()=>N,forwardedAnswer:()=>P,joined:()=>k,lanActions:()=>I,lanReading:()=>L,outcome:()=>O,proposalActions:()=>F,taken:()=>j,waitActions:()=>A}),O=e=>{let t=e.body.outcome;return t===void 0?e.status===504?`unknown`:e.ok&&(e.body.accepted===!0||Array.isArray(e.body.entries))?`accepted`:`refused`:t===`accepted`?`accepted`:t===`unknown`?`unknown`:`refused`},k=e=>e.replace(/^([A-Z])(?=[a-z])/,e=>e.toLowerCase()),A=(e,n)=>({tell:t=>n(`input`,{text:t,as:`send`,answers:e.id}),dismiss:()=>r(`${t(e.ws)}/memory`,{op:`drop`,id:e.id}),goto:{view:`session`,ws:e.ws,key:e.tower}}),j=e=>e.ok&&e.body.outcome===void 0?{...e,body:{...e.body,outcome:`accepted`}}:e,M=e=>{let t=t=>r(`link/confirm-answer`,{dialogId:e.dialogId,digest:e.digest,allow:t}).then(j);return{allow:()=>t(!0),deny:()=>t(!1)}},N=e=>{let t=String(e.body.reason??e.body.error??``);return[[/^That request is gone/,l],[/^That team is not running/,u],[/^That request changed/,c]].find(([e])=>e.test(t))?.[1]()??(t||i({status:e.status}))},P=e=>async(t,n)=>{let a=await r(`link/dialog-answer`,{device:e.device,dialogId:e.dialogId,digest:e.digest,answer:E(n)});return a.ok?j(a):{ok:!1,status:a.status,body:{reason:_({reason:a.body.reason??i({status:a.status})})}}},F=e=>({confirm:()=>r(`${t(e.ws)}/memory`,{op:`confirm`,proposal:e.id,rev:e.rev()}),reject:()=>r(`${t(e.ws)}/memory`,{op:`reject`,proposal:e.id})}),I=e=>({approve:t=>e(`lan/approve`,{number:t}).then(j),deny:t=>e(`lan/approve`,{deny:t}).then(e=>e.ok&&e.body.denied===0?{...e,ok:!1,body:{error:`gone`,reason:o()}}:j(e)),denyAll:()=>e(`lan/approve`,{deny:`all`}).then(j)});function L(e){let t=!e.ok&&e.body.error===`no_match`&&Number(e.body.denied)>0;return{answer:e.ok||t?``:e.body.error===`no_match`?a():String(e.body.reason??i({status:e.status})),verdict:t?s():``}}export{k as a,O as c,x as d,T as f,P as i,F as l,M as n,I as o,N as r,L as s,D as t,A as u};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./index-DvbZ79bq.css"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{r as e}from"./towermodel-DJLQh2fz.js";import{t}from"./runtime-ZX6HkxDa.js";import{i as n,n as r,r as i,t as a}from"./towerturns-CYO3ciQ8.js";import{n as o,r as s}from"./markdown-Bk5NWfKQ.js";import{E as c,R as l,S as u,Ut as d,f,rt as ee,tt as p}from"./index-DGft1IHG.js";var te=((e={},n={})=>(n.locale??t())===`zh-TW`?`可能已被當機的 run 處理過:動手前先確認。`:`A run that crashed may already have handled this: check before acting.`),ne=((e={},n={})=>(n.locale??t())===`zh-TW`?`分支摘要`:`branch summary`),re=((e={},n={})=>(n.locale??t())===`zh-TW`?`通訊紀錄`:`Comms log`),m=e=>`context compacted · ${e?.tokens} tokens summarized`,ie=e=>`上下文已壓縮 · 摘要了 ${e?.tokens} tokens`,ae=((e,n={})=>(n.locale??t())===`zh-TW`?ie(e):m(e)),oe=((e={},n={})=>(n.locale??t())===`zh-TW`?`…(於 1 MB 截斷)`:`… (cut at 1 MB)`),h=e=>`exit ${e?.code}`,g=e=>`結束碼 ${e?.code}`,se=((e,n={})=>(n.locale??t())===`zh-TW`?g(e):h(e)),_=e=>`New chapter · ${e?.date} · ${e?.why}`,ce=e=>`新的一章・${e?.date}・${e?.why}`,le=((e,n={})=>(n.locale??t())===`zh-TW`?ce(e):_(e)),v=((e={},n={})=>(n.locale??t())===`zh-TW`?`第一次對話`:`the first conversation`),y=((e={},n={})=>(n.locale??t())===`zh-TW`?`你要求開新對話`:`you asked for a new conversation`),b=((e={},n={})=>(n.locale??t())===`zh-TW`?`上一章太長了`:`the last one grew too large`),x=((e={},n={})=>(n.locale??t())===`zh-TW`?`上一章無法接續`:`the last one could not be resumed`),S=e=>`Image ${e?.n}`,C=e=>`圖片 ${e?.n}`,ue=((e,n={})=>(n.locale??t())===`zh-TW`?C(e):S(e)),de=((e={},n={})=>(n.locale??t())===`zh-TW`?`圖片無法讀取`:`Image unavailable`),w=e=>`${e?.count} image(s)`,T=e=>`${e?.count} 張圖片`,fe=((e,n={})=>(n.locale??t())===`zh-TW`?T(e):w(e)),pe=((e={},n={})=>(n.locale??t())===`zh-TW`?`收到`:`incoming`),E=((e={},n={})=>(n.locale??t())===`zh-TW`?`跳到最新`:`jump to latest`),D=e=>`${e?.count} new`,O=e=>`${e?.count} 則新訊息`,k=((e,n={})=>(n.locale??t())===`zh-TW`?O(e):D(e)),me=((e={},n={})=>(n.locale??t())===`zh-TW`?`還沒有通訊。`:`No transmissions yet.`),he=((e={},n={})=>(n.locale??t())===`zh-TW`?`通知`:`notice`),ge=((e={},n={})=>(n.locale??t())===`zh-TW`?`細節`:`details`),A=((e={},n={})=>(n.locale??t())===`zh-TW`?`表單回覆`:`form answers`),_e=((e={},n={})=>(n.locale??t())===`zh-TW`?`訊息,來自`:`message from`),j=e=>`answer from ${e?.from}`,M=e=>`${e?.from} 的回答`,ve=((e,n={})=>(n.locale??t())===`zh-TW`?M(e):j(e)),N=e=>`request from ${e?.from}`,P=e=>`${e?.from} 的請求`,ye=((e,n={})=>(n.locale??t())===`zh-TW`?P(e):N(e)),F=e=>`message from ${e?.from}`,I=e=>`${e?.from} 的訊息`,be=((e,n={})=>(n.locale??t())===`zh-TW`?I(e):F(e)),L=e=>`reply to your ask from ${e?.from}`,xe=e=>`${e?.from} 回覆了你的詢問`,Se=((e,n={})=>(n.locale??t())===`zh-TW`?xe(e):L(e)),R=((e={},n={})=>(n.locale??t())===`zh-TW`?`記憶`:`memory`),z=((e={},n={})=>(n.locale??t())===`zh-TW`?`監看`:`monitor`),Ce=((e={},n={})=>(n.locale??t())===`zh-TW`?`本機`:`this computer`),we=((e={},n={})=>(n.locale??t())===`zh-TW`?`隊友`:`teammate`),B=((e={},n={})=>(n.locale??t())===`zh-TW`?`提問,來自`:`question from`),Te=((e={},n={})=>(n.locale??t())===`zh-TW`?`回報,來自`:`report from`),Ee=((e={},n={})=>(n.locale??t())===`zh-TW`?`sb server 的通知`:`notice from the sb server`),V=((e={},n={})=>(n.locale??t())===`zh-TW`?`狀態:`:`status of`),H=((e={},n={})=>(n.locale??t())===`zh-TW`?`Straw Link 訊息`:`Straw Link message`),De=((e={},n={})=>(n.locale??t())===`zh-TW`?`喚醒鬧鐘`:`wake-up call`),U=((e={},n={})=>(n.locale??t())===`zh-TW`?`塔台事件`:`tower event`),Oe=((e={},n={})=>(n.locale??t())===`zh-TW`?`在旁開啟`:`open beside`),W=e=>`Open image ${e?.n}`,ke=e=>`打開圖片 ${e?.n}`,Ae=((e,n={})=>(n.locale??t())===`zh-TW`?ke(e):W(e)),G=e=>`show all (${e?.size})`,K=e=>`顯示全部(${e?.size})`,je=((e,n={})=>(n.locale??t())===`zh-TW`?K(e):G(e)),Me=((e={},n={})=>(n.locale??t())===`zh-TW`?`顯示全部參數`:`show all arguments`),q=e=>`◇ thought · ${e?.count} chars`,J=e=>`◇ 思考 · ${e?.count} 字元`,Ne=((e,n={})=>(n.locale??t())===`zh-TW`?J(e):q(e)),Pe=((e={},n={})=>(n.locale??t())===`zh-TW`?`◇ 思考 · 已遮蔽`:`◇ thought · redacted`),Fe=((e={},n={})=>(n.locale??t())===`zh-TW`?`這座塔台正在待命。有訊息進來時,sb server 會喚醒它跑一個 run;你在這裡送出的第一則訊息就會啟動它。`:`This tower stands by. The sb server wakes it for a run when a message arrives; your first message here starts that run.`),Ie=((e={},n={})=>(n.locale??t())===`zh-TW`?`無法取得`:`unavailable`),Le=((e={},n={})=>(n.locale??t())===`zh-TW`?`你`:`you`);function Re(){let e=!0,t=0,n=!0,r=0;return{get pinned(){return e},scrolled(r){r!==n&&(n=e=r,r&&(t=0))},parked:e=>void(r=e),moved(i,a){let o=i-r;return r=i,o<-.5&&e&&a()-i>1?!(e=!1):o!==0&&!e&&n&&a()-i<=1&&(e=!0,t=0,!0)},hold:()=>void(n=e=!1),arrived(n){return e||(t+=n),e},jump:()=>void(n=e=!0,t=0),button:n=>e&&!n?void 0:t&&!n?k({count:t}):E()}}async function ze(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 Be(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 Ve=(e,t)=>({first:v,new:y,size:b,unreadable:x})[e??``]?.()??t??``,He=e=>e.head?d():c(e.role),Ue=e=>e?new Date(e).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`,hour12:!1}):``,We=e=>e>=1024?`${(e/1024).toFixed(e>=10240?0:1)} KB`:`${e} B`,Ge={intercom_message:_e,subagent_result:Te,subagent_ping:B,subagent_status:V,"pi-loop-monitor":z,"memory-context":R,"doc-review":A,"straw-tower":U,"straw-link":H},Y=e=>{let t=u(`<span class="ava"><svg><use/></svg></span>`);return t.querySelector(`use`).setAttribute(`href`,`#i-${f[e]??e}`),t};function Ke(e){let t=[],n=0;for(let r of e.matchAll(/https?:\/\/[^\s<>)\]]+/g))t.push(e.slice(n,r.index),p(`a`,{href:r[0],rel:`noopener noreferrer`,target:`_blank`},r[0])),n=r.index+r[0].length;return[...t,e.slice(n)]}function X(c,u,{who:d,link:f,docFor:m,page:ie}){let h=Be(),g=new Map,_=new Set,ce=()=>_.forEach(e=>e.button.isConnected?(e.shown=!0,e.button.hidden=!e.paths.some(e=>m?.(e))):e.shown&&_.delete(e)),v=p(`div`,{class:`chat-list`}),y=p(`div`,{class:`chat-top`}),b=p(`div`,{class:`chat-live`}),x=p(`div`,{class:`chat-end`}),S=p(`button`,{class:`chat-pill`,type:`button`,hidden:``}),C=p(`p`,{class:`chat-empty`},me()),w=p(`div`,{class:`chat-scroll`,tabindex:`-1`,"aria-label":re()},y,v,b,x);c.replaceChildren(w,S);let T=Re(),E=!1,D=!1,O,k,A=0,j=!1,M,N=()=>j||M!==void 0,P=()=>(clearTimeout(M),M=setTimeout(()=>(M=void 0,T.pinned&&!h.detached&&L()),250)),F=(e=T.button(h.detached))=>(S.hidden=!e,S.textContent=e??``),I=()=>(w.scrollTop=w.scrollHeight,T.parked(w.scrollTop)),L=()=>(T.jump(),k=void 0,I(),F());async function xe(e){E=!0;let t=await ze(h,u,e,e=>(J(e),Q(e))).finally(()=>E=!1),n=g.get(e);if(O===e){if(!t||!n)return L();T.hold(),k=n,n.scrollIntoView({block:`center`}),ee(n,`lit`),clearTimeout(A),A=window.setTimeout(()=>(k=void 0,n.classList.remove(`lit`)),2e3),F()}}let R=()=>O?void xe(O):L(),z=(e,t,n,r)=>{e.disabled=!0,u.entry(n).then(n=>{let i=n&&r(n);if(i===void 0)return void(e.textContent=Ie());t.textContent=i,e.remove()},()=>e.textContent=Ie())};function B(e,t=0){if(!t||!u.pic)return null;let n=Array.from({length:t},(t,n)=>u.pic(e,n));return p(`div`,{class:`pics`},...n.map((e,t)=>{let r=p(`img`,{src:e,alt:ue({n:t+1}),loading:`lazy`,decoding:`async`}),i=p(`button`,{type:`button`,class:`pic`,"aria-label":Ae({n:t+1})},r);return r.addEventListener(`error`,()=>i.replaceWith(p(`em`,{class:`pic-gone`},de()))),i.addEventListener(`click`,()=>void l(async()=>{let{lightbox:e}=await import(`./lightbox-Db_eNcwV.js`);return{lightbox:e}},__vite__mapDeps([0]),import.meta.url).then(({lightbox:e})=>e(n,t))),i}))}function Te(e,t){let n=h.result(e.id),r=p(`pre`,{class:`out`},n?.text??``),i=p(`pre`,{class:`args`},e.args??``),a=e.cut?p(`button`,{class:`more`,type:`button`},Me()):null;a?.addEventListener(`click`,()=>z(a,i,t,t=>(e=>e&&`${e.args??``}${e.cut?`\n${oe()}`:``}`)(t.tools?.find(t=>t.id===e.id))));let o=n?.more?p(`button`,{class:`more`,type:`button`},je({size:We(n.bytes??0)})):null;o?.addEventListener(`click`,()=>z(o,r,n.id,e=>e.text));let s=e.name===`show_doc`&&m?p(`button`,{class:`more open`,type:`button`,hidden:``},Oe()):null;s?.addEventListener(`click`,t=>(t.preventDefault(),e.summary.split(`, `).forEach(e=>m?.(e)?.()))),s&&_.add({paths:e.summary.split(`, `),button:s}),s&&queueMicrotask(ce);let c=p(`details`,{class:`act`},p(`summary`,{"data-mark":n?n.isError?`error`:`done`:`working`},p(`b`,{class:`badge`}),p(`code`,null,e.name),p(`span`,{class:`sum`},e.summary),s),i,a,n&&p(`div`,{class:`result`},n.images?p(`em`,null,fe({count:n.images})):null,r,o)),l=n&&B(n.id,n.images);return l?[c,l]:[c]}let V=e=>p(`time`,null,Ue(e.at)),H=(e,t,n,r)=>p(`article`,{class:`tx you`},p(`header`,null,V(e),p(`b`,null,Le()),Y(`user`)),p(`div`,{class:`bubble`,title:r},n?p(`small`,{class:`boss-flag`},te()):null,...Ke(t),B(e.id,e.images))),U=(e,t,n,r={})=>p(`article`,{class:`tx sys`},p(`details`,{class:`notice`},p(`summary`,null,Y(`comms`),p(`em`,null,pe()),...t,V(e)),r.crashed?p(`small`,{class:`boss-flag`},te()):null,p(`pre`,null,n),r.raw?p(`details`,{class:`notice-raw`},p(`summary`,null,ge()),p(`pre`,{class:`raw`},r.raw)):null)),W=e=>{let t=n(e);return[_e(),` `,t.name&&f(t.name)||t.name,t.id?` (${t.id})`:``,` · `,Ce()]},ke=e=>e.kind===`link`?[{ask:ye,reply:Se,answer:ve,message:be}[e.what]({from:e.from}),` · `,we()]:e.kind===`intercom`?W(e.from):[e.kind===`server`?Ee():De()],G=()=>ie===!0&&d().head===!0,K=()=>p(`article`,{class:`tx skip`,hidden:``});function q(e){switch(e.kind){case`user`:{let t=d().service?i(e.text):void 0;if(t)return U(e,t.kind===`intercom`?W(t.from):[t.kind===`server`?Ee():De()],e.text??``);let n=d().service?a(e.text):void 0;return H(e,n?n.body:e.text??``,n?.crashed,n?e.text??``:``)}case`assistant`:{let t=d();if(G()&&!e.text&&!e.thought&&!e.error&&!e.stop)return K();let n=p(`pre`,{class:`thought-text`}),r=e.thought?p(`button`,{class:`thought`,type:`button`},e.thought<0?Pe():Ne({count:e.thought.toLocaleString()})):null;return e.thought&&e.thought>0&&r?.addEventListener(`click`,()=>z(r,n,e.id,e=>e.thoughtText)),p(`article`,{class:t.head?`tx in head`:`tx in`},Y(t.head?`crown`:t.role),p(`div`,{class:`tx-body`},p(`header`,null,p(`b`,null,He(t)),e.model?p(`span`,null,e.model):null,V(e),e.stop?p(`span`,{class:`stop`,"data-mark":`error`},e.stop):null),r,n,e.text?p(`div`,{class:`md`},o(s(e.text))):null,e.error?p(`p`,{class:`fault`},e.error):null,...(G()?[]:e.tools??[]).flatMap(t=>Te(t,e.id))))}case`bash`:return G()?K():p(`article`,{class:`tx sys`},p(`details`,{class:`act`},p(`summary`,{"data-mark":e.exit?`error`:`done`},p(`b`,{class:`badge`}),p(`code`,null,`shell`),p(`span`,{class:`sum`},`! ${e.command}`),e.exit?p(`span`,{class:`stop`,"data-mark":`error`},se({code:e.exit})):null),e.text?p(`pre`,{class:`out`},e.text):null));case`notice`:{let t=r(e);return t?.kind===`boss`&&d().service?H(e,t.body,t.crashed,e.text??``):G()&&(t?.kind===`server`||t?.kind===`timer`)?K():t&&t.kind!==`boss`?U(e,ke(t),t.body,t.kind===`link`?{raw:t.raw}:{crashed:t.crashed}):U(e,[Ge[e.type??``]?.()??e.type??he(),` `,e.from&&f(e.from)||(e.from??``)],e.text??``)}case`divider`:return e.type===`chapter`?p(`article`,{class:`tx rule chapter`},p(`p`,null,le({date:e.at?new Date(e.at).toLocaleDateString(t(),{year:`numeric`,month:`short`,day:`numeric`}):``,why:Ve(e.code,e.text)}))):p(`article`,{class:`tx rule`},p(`details`,null,p(`summary`,null,e.type===`compaction`?ae({tokens:(e.tokens??0).toLocaleString()}):ne()),p(`pre`,null,e.text??``)));default:return p(`article`,{class:`tx note`},e.text??``,` `,V(e))}}function J(e){e.rebuild&&(g.clear(),v.replaceChildren());for(let t of e.dropped)g.get(t)?.remove(),g.delete(t);let t=e.added.map(e=>(g.set(e.id,q(e)),g.get(e.id)));e.front?v.prepend(...t):v.append(...t),D&&!e.front&&!e.rebuild&&t.forEach(e=>(e.classList.add(`fresh`),e.dataset.born=String(Date.now()))),C.remove();let n=d().service;C.textContent=n?.state===`standing`&&!n.run?Fe():me(),h.items.length||v.append(C),y.hidden=!h.before,qe()}let X=[],Z=new Map;function qe(){let t=new Set;for(let n of X){let r=Date.parse(n.startedAt),i=h.items.findIndex(e=>e.at!==void 0&&Date.parse(e.at)>=r);if(i===0&&h.before)continue;let a=i<0?``:h.items[i].id,o=JSON.stringify([a,e(n)]),s=Z.get(n.id);if(t.add(n.id),s&&s.sig===o&&s.el.isConnected)continue;s?.el.remove();let c=e(n),l=p(`article`,{class:`tx rule conv-rule`},p(`div`,null,p(`b`,null,c.title),c.ended?p(`small`,null,c.ended):null));Z.set(n.id,{el:l,sig:o});let u=a?g.get(a):void 0;u?u.before(l):v.append(l)}for(let[e,n]of Z)t.has(e)||(n.el.remove(),Z.delete(e))}let Q=e=>e.touched.forEach(e=>{let t=g.get(e),n=h.items.find(t=>t.id===e);if(t&&n){let r=q(n);t.classList.contains(`fresh`)&&Date.now()-Number(t.dataset.born??0)<400&&r.classList.add(`fresh`),t.replaceWith(r),g.set(e,r)}}),Je=async()=>{if(!E&&h.before&&D){E=!0;try{let e=w.scrollHeight,t=h.prepend(await u.older(h.before));J(t),Q(t),w.scrollTop+=w.scrollHeight-e}finally{E=!1}h.before&&w.clientHeight&&y.getBoundingClientRect().bottom>=w.getBoundingClientRect().top&&Je()}};S.addEventListener(`click`,()=>{O=void 0,h.detached?u.latest().then(e=>(J(h.reset(e)),L())):L()});let Ye=[new IntersectionObserver(e=>e.some(e=>e.isIntersecting)&&void Je(),{root:w}),new IntersectionObserver(e=>w.clientHeight&&(T.scrolled(e.at(-1).isIntersecting),F()),{root:w,rootMargin:`0px 0px 67px`})],$,Xe=()=>($??(Ye[0].observe(y),Ye[1].observe(x)),clearTimeout($),$=setTimeout(()=>($=void 0,Ye.forEach(e=>e.disconnect())),600));w.addEventListener(`scroll`,()=>(Xe(),T.moved(w.scrollTop,()=>w.scrollHeight-w.clientHeight)&&F(),!j&&M!==void 0&&P()),{passive:!0}),w.addEventListener(`wheel`,e=>e.deltaY<0&&P(),{passive:!0}),w.addEventListener(`keydown`,e=>([`ArrowUp`,`PageUp`,`Home`].includes(e.key)||e.key===` `&&e.shiftKey)&&P(),{passive:!0}),w.addEventListener(`touchstart`,()=>(j=!0,clearTimeout(M),M=void 0),{passive:!0});for(let e of[`touchend`,`touchcancel`])w.addEventListener(e,()=>(j=!1,P()),{passive:!0});for(let e of[`wheel`,`touchstart`,`pointerdown`,`keydown`])w.addEventListener(e,()=>k=O=void 0,{passive:!0});let Ze=new ResizeObserver(()=>N()?T.parked(w.scrollTop):T.pinned&&!h.detached?I():k?.scrollIntoView({block:`center`}));return Ze.observe(v),Ze.observe(w),{log:w,docs:ce,runs(e){JSON.stringify(e)!==JSON.stringify(X)&&(X=e,qe())},apply(e){if(e.reset)J(h.reset({items:e.items??[],before:e.before})),D=!0,R();else if(e.items?.length){let t=h.append(e.items);J(t),Q(t),T.arrived(t.added.length)&&!h.detached&&!N()?L():F()}},reveal(e){O=e,D&&R()},setLive(e,t){b.dataset.mark=t,b.lastChild?.textContent!==e&&b.replaceChildren(...e?[p(`b`,{class:`badge`}),p(`span`,null,e)]:[])}}}export{X as mountChat,ue as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./towermodel-DJLQh2fz.js";import{t as e}from"./runtime-ZX6HkxDa.js";import{t}from"./open_main_title-Ccbha5pD.js";import{n,t as r}from"./unit_count-CJMBHDBg.js";import{D as i,E as a,F as o,I as s,N as c,O as l,S as u,T as d,Ut as f,Wt as p,_ as m,b as h,g,i as _,k as v,m as y,pt as b,s as x,tt as S}from"./index-DGft1IHG.js";var ee=((t={},n={})=>(n.locale??e())===`zh-TW`?`關閉清單`:`Close the list`),C=((t={},n={})=>(n.locale??e())===`zh-TW`?`切換到其他單位`:`Switch to a unit`),w=((t={},n={})=>(n.locale??e())===`zh-TW`?`回到主地圖`:`Back to the map`),T=((t={},n={})=>(n.locale??e())===`zh-TW`?`所有單位`:`All units`),E=((t={},n={})=>(n.locale??e())===`zh-TW`?`指揮中`:`commanding`),D=((t={},n={})=>(n.locale??e())===`zh-TW`?`已結束`:`ended`),O=((t={},n={})=>(n.locale??e())===`zh-TW`?`錯誤`:`error`),k=((t={},n={})=>(n.locale??e())===`zh-TW`?`閒置`:`idle`),A=((t={},n={})=>(n.locale??e())===`zh-TW`?`無狀態`:`unknown`),j=((t={},n={})=>(n.locale??e())===`zh-TW`?`等待`:`waiting`),M=((t={},n={})=>(n.locale??e())===`zh-TW`?`工作中`:`working`),N=.4;function P(e,t,n){let[r,i]=[Math.abs(e),Math.abs(t)];return Math.max(r,i)<10?`wait`:r>=1.7*i&&(n?e<0:e>0)?`drag`:`pass`}var F=(e,t,n)=>Math.abs(n)>=.45?n>0:e>=t*N,I=(e,t)=>t||e.some(e=>e.editable||e.sink||e.scrollsX||[`input`,`textarea`,`select`].includes(e.tag));function L(e){let t=e,n=getComputedStyle(e).overflowX;return{tag:e.tagName.toLowerCase(),editable:t.isContentEditable,sink:e.matches(`.composer, .term-sink`),scrollsX:(n===`auto`||n===`scroll`)&&e.scrollWidth>e.clientWidth+1}}var R=e=>{let t=[];for(let n=e;n;n=n.parentElement)t.push(L(n));return t},z={working:M,waiting:j,idle:k,done:D,error:O,unknown:A,commanding:E},B=(e,t,n)=>(t?D:z[e])({},n&&{locale:n}),V=(e,t)=>t.flatMap(t=>[t,...t.subs.map(e=>({...e,sub:!0}))].map(t=>({id:t.key,key:t.key,ws:e,name:t.name,role:t.role,mark:t.mark,note:t.note,ended:!!t.ended,sub:`sub`in t,control:!!t.control})));function H(e){return e.bases.flatMap(e=>{let t=[{id:`tower`,rows:e.tower?V(e.id,[{...e.tower,role:`tower`}]):[]},...e.tabs.map(t=>({id:t.id,label:b({label:t.label}),rows:V(e.id,t.units)})),{id:`outside`,label:n(),rows:V(e.id,e.outside)}].filter(e=>e.rows.length);return t.length?[{id:e.id,label:e.label,mark:e.mark,groups:t}]:[]})}var U=(e,t)=>e?.head?{mark:e.head.mark,word:e.head.state===`absent`?p({},t&&{locale:t}):B(e.head.mark,!1,t)}:void 0,W=e=>e.role===`main`&&e.mark===`idle`,G=e=>e.reduce((e,t)=>(t.sub?e.at(-1)?.subs.push(t):e.push({...t,subs:[]}),e),[]),K=()=>u(`<div class="unit"><div class="card"><a class="hit"></a>${y}<div class="meta"><span class="name"></span><span class="line"><em class="role"></em><b class="dstate"></b><span class="note"></span></span></div><button type="button" class="quit-btn" data-close="unit" hidden></button></div><div class="subs"></div></div>`),q=()=>u(`<div class="unit tower-row"><div class="trow"><a class="tower-go">${y}<span class="meta"><span class="name"></span><span class="line"><em class="role"></em><b class="dstate"></b></span></span></a><button type="button" class="pair-btn tower-add"></button></div><div class="subs"></div></div>`),J=()=>u(`<section class="dbase"><h3><a></a><small></small></h3><div class="dgroups"></div></section>`),te=()=>u(`<div class="dgroup"><h4></h4><div class="drows"></div></div>`),ne=()=>matchMedia(`(max-width: 640px)`).matches;function Y(e=()=>!1){let n=S(`div`,{class:`drawer-body`}),p=S(`button`,{type:`button`,class:`x`,"aria-label":ee()},`×`),y=S(`a`,{class:`drawer-map`},w()),b=S(`button`,{type:`button`,class:`pair-btn`,"data-close":`dismiss-all`,hidden:``}),E=S(`div`,{class:`drawer-sweep`,hidden:``},b);g(y,{view:`map`});let D=u(`<a class="drawer-head"><svg viewBox="0 0 512 512" aria-hidden="true"><use href="#i-crown"/></svg><span class="name"></span><b class="dstate"></b></a>`);D.hidden=!0,g(D,{view:`head`});let O=S(`aside`,{class:`drawer`,"aria-label":C()},S(`header`,null,S(`b`,null,T()),p),D,n,S(`footer`,{class:`drawer-foot`},E,y)),k=S(`div`,{class:`drawer-veil`});document.body.append(k,O);let A,j,M=!1,N=!1,L=0,z=0,V,Y=()=>{let e=U(A);D.hidden=!e,e&&(d(D,e.mark),v(D,`.name`,f()),v(D,`.dstate`,e.word),D.classList.toggle(`current`,M),D.toggleAttribute(`data-news`,_(A?.head,x())&&!M)),s(b,A??{bases:[]}),E.hidden=b.hidden;let o=(e,t)=>{g(e.querySelector(`.hit`),{view:`session`,ws:t.ws,key:t.key}),e.querySelector(`.hit`).setAttribute(`aria-label`,`${t.name}: ${B(t.mark,t.ended)}`),e.classList.toggle(`current`,t.key===j),e.toggleAttribute(`data-dismiss`,t.role===`subagent`&&t.ended),e.dataset.key=t.key,d(e,t.mark),h(e.querySelector(`.plate`),t.role,t.mark),v(e,`.name`,t.name),v(e,`.role`,a(t.role)),v(e,`.dstate`,B(t.mark,t.ended)),i(e,`.note`,t.note,t.mark,t.note?void 0:``);let n=e.querySelector(`:scope > .card > .quit-btn`);W(t)?c(n,t):n.hidden=!0,l(e.querySelector(`.subs`),t.subs??[],K,o)},u=(e,n)=>{let r=e.querySelector(`.tower-go`),i=e.querySelector(`.tower-add`),s=A?.bases.find(e=>e.id===n.ws);g(r,{view:`session`,ws:n.ws,key:n.key}),r.setAttribute(`aria-label`,`${n.name}: ${B(n.mark,n.ended)}`),e.classList.toggle(`current`,n.key===j),e.dataset.key=n.key,d(e,n.mark),h(r.querySelector(`.plate`),`tower`,n.mark),v(r,`.name`,n.name),v(r,`.role`,a(`tower`)),v(r,`.dstate`,B(n.mark,n.ended)),i.hidden=!s,s&&(m(i,s),i.setAttribute(`aria-label`,t({base:s.label}))),l(e.querySelector(`.subs`),n.subs,K,o)};l(n,H(A??{bases:[]}),J,(e,t)=>{d(e,t.mark),v(e,`h3 a`,t.label),g(e.querySelector(`h3 a`),{view:`workspace`,ws:t.id}),v(e,`small`,r({count:t.groups.reduce((e,t)=>e+t.rows.length,0)})),l(e.querySelector(`.dgroups`),t.groups,te,(e,t)=>{v(e,`h4`,t.label??``),e.querySelector(`h4`).toggleAttribute(`hidden`,!t.label),t.id===`tower`?l(e.querySelector(`.drows`),G(t.rows),q,u):l(e.querySelector(`.drows`),G(t.rows),K,o)})})},X=e=>{L=Math.max(0,Math.min(z,e)),O.style.setProperty(`--dx`,`${L}px`),k.style.opacity=String(z?L/z:0),k.style.pointerEvents=L>0?`auto`:`none`},Z=e=>{N=e,O.classList.toggle(`on`,e),O.inert=!e,document.documentElement.classList.remove(`drawer-drag`),X(e?z:0)},Q=()=>{z=O.offsetWidth,Y(),O.classList.add(`on`),document.documentElement.classList.add(`drawer-drag`)};O.inert=!0,document.addEventListener(`touchstart`,t=>{let n=t.target,r=O.contains(n)||n===k;if(V=void 0,!ne()||e()||t.touches.length!==1||document.querySelector(`dialog.sheet[open], dialog.lightbox[open], [popover]:popover-open`)||(N?!r:I(R(n),!!getSelection()?.toString())))return;let i=t.touches[0],a=N?n.closest(`.unit[data-dismiss] > .card`)??void 0:void 0;V={x0:i.clientX,y0:i.clientY,mode:`wait`,was:N,base:L,last:i.clientX,at:performance.now(),v:0,card:a}},{passive:!0}),document.addEventListener(`touchmove`,e=>{if(!V||V.mode===`pass`)return;let t=e.touches[0],n=t.clientX-V.x0,r=t.clientY-V.y0;if(V.mode===`wait`){let e=P(n,r,V.was);if(e===`wait`)return;if(e===`pass`&&V.card&&P(n,r,!1)===`drag`)V.mode=`card`,V.card.classList.add(`swiping`);else if(e===`pass`)return void(V.mode=`pass`);else V.mode=`drag`,Q()}e.preventDefault();let i=performance.now();if(V.v=(t.clientX-V.last)/Math.max(1,i-V.at),[V.last,V.at]=[t.clientX,i],V.mode!==`card`)return X(V.base+n);let a=Math.max(0,n);V.card.style.setProperty(`--sx`,`${a}px`),V.card.style.setProperty(`--so`,String(1-a/V.card.offsetWidth))},{passive:!1});let re=(e,t)=>{e.classList.remove(`swiping`),e.style.removeProperty(`--sx`),e.style.removeProperty(`--so`),t&&(e.classList.add(`gone`),o({key:e.parentElement.dataset.key}).then(t=>t||e.classList.remove(`gone`)))},$=e=>{let t=V;V=void 0,t?.mode===`drag`&&Z(F(L,z,t.v)),t?.mode===`card`&&re(t.card,e.type===`touchend`&&F(Math.max(0,t.last-t.x0),t.card.offsetWidth,t.v))};return document.addEventListener(`touchend`,$),document.addEventListener(`touchcancel`,$),k.addEventListener(`click`,()=>Z(!1)),O.addEventListener(`click`,e=>e.target.closest(`a[data-route], button[data-open], .x`)&&Z(!1)),document.addEventListener(`keydown`,e=>N&&e.key===`Escape`&&(e.preventDefault(),Z(!1)),!0),document.addEventListener(`sb-drawer`,()=>(N||Q(),Z(!N))),{net(e){A=e,N&&Y()},route(e){j=e.view===`session`?e.key:void 0,M=e.view===`head`||e.view===`session`&&e.ws===`@head`,y.toggleAttribute(`aria-current`,e.view===`map`),N&&Y()}}}export{Y as mountDrawer};
|