pi-straw-boss 0.59.0 → 0.59.4

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.
Files changed (44) hide show
  1. package/README.md +3 -2
  2. package/README.zh-TW.md +11 -6
  3. package/dist/gui/assets/allyasks-CcR61QkD.js +2 -0
  4. package/dist/gui/assets/{answer-663FYrp5.js → answer-DfepxpUv.js} +1 -1
  5. package/dist/gui/assets/{ask-GI8fnsYy.js → ask-Cl7AZwX1.js} +1 -1
  6. package/dist/gui/assets/{asks-wFBG7YIZ.js → asks-B2l0K45z.js} +1 -1
  7. package/dist/gui/assets/{chat-D2dRfMsh.js → chat-Djkg_3p0.js} +2 -2
  8. package/dist/gui/assets/{drawer--4vM-3aw.js → drawer-DewQ2WHx.js} +1 -1
  9. package/dist/gui/assets/{index-Brm9t2JN.css → index-CwBU87EN.css} +1 -1
  10. package/dist/gui/assets/{index-A8RfiBLi.js → index-DnIB0kQt.js} +2 -2
  11. package/dist/gui/assets/{layer-N0RYz-Qa.js → layer-p3wa1dOL.js} +1 -1
  12. package/dist/gui/assets/{lightbox-DWkBtVWK.js → lightbox-DkXX9IuA.js} +1 -1
  13. package/dist/gui/assets/{link-CT59UitH.js → link-CZN7PWd8.js} +1 -1
  14. package/dist/gui/assets/{linkdialogs-5vpyLgVB.js → linkdialogs-ZhWsFL3g.js} +1 -1
  15. package/dist/gui/assets/{pair-ByDsS3q1.js → pair-dEZ6XrP-.js} +1 -1
  16. package/dist/gui/assets/{picker-DRWqNSGk.js → picker-ClvBUvXD.js} +1 -1
  17. package/dist/gui/assets/{server-BQehv_I2.js → server-6thw36JH.js} +1 -1
  18. package/dist/gui/assets/{sessionfacts-DLUmSOSc.js → sessionfacts-CZBG2hCP.js} +1 -1
  19. package/dist/gui/assets/{settings-CIFk8BGd.js → settings-BDgBaM9Y.js} +2 -2
  20. package/dist/gui/assets/{spawn-lXu6pRMW.js → spawn-Cowjk_cr.js} +1 -1
  21. package/dist/gui/assets/{termcard-DZ1uMDuP.js → termcard-DxgLuZET.js} +1 -1
  22. package/dist/gui/assets/{trust-Dv6BHnPR.js → trust-CMZhXCND.js} +1 -1
  23. package/dist/gui/assets/{views-DyUJmSGP.js → views-BreX5dze.js} +2 -2
  24. package/dist/gui/assets/{waitpanel-D7O_yFwF.js → waitpanel-DxuevVli.js} +1 -1
  25. package/dist/gui/assets/{zenchunk-k01vug_B.css → zenchunk-ClfLJgV2.css} +1 -1
  26. package/dist/gui/assets/zenchunk-DfwbEkqZ.js +2 -0
  27. package/dist/gui/index.html +2 -2
  28. package/dist/server/main.mjs +157 -24
  29. package/package.json +1 -1
  30. package/prompts/apps-config.md +13 -2
  31. package/prompts/integrator.md +1 -1
  32. package/prompts/main.md +8 -3
  33. package/prompts/planning.md +3 -1
  34. package/prompts/tower-run.md +1 -1
  35. package/prompts/tower.md +5 -0
  36. package/src/briefing.ts +9 -6
  37. package/src/link/dialogs-out.ts +157 -21
  38. package/src/link/holder.ts +5 -2
  39. package/src/runmode.ts +2 -1
  40. package/src/server/dispatcher.ts +17 -1
  41. package/src/server/guihost.ts +1 -1
  42. package/src/server/main.ts +3 -3
  43. package/src/trainswitch.ts +125 -0
  44. package/dist/gui/assets/zenchunk-7ts5CPgH.js +0 -2
package/README.md CHANGED
@@ -56,15 +56,16 @@ Run a few agents on the same project and they start stepping on each other: two
56
56
 
57
57
  - **Everyone joins.** Each pi in Herdr joins its tab's net at start as a member; nothing to ask or remember.
58
58
  - **A main agent per tab, by promotion.** An agent whose work grows calls `boss_promote`, or is promoted when it first dispatches a subagent. A tab has one main, and nobody takes it over except you with `/boss`.
59
- - **A tower per workspace.** It opens in its own tab, pinned first, when agents start to collide: a member dispatches a subagent (it promotes itself first), a workspace has two members while another workspace already has a tower, an agent promotes itself, or you type `/boss tower`. Mains and the tower go together: a tower that opens promotes each tab's earliest member, and a tower that quits turns every main back into a member (its subagents stay). It and coordinates the main agents and the other towers, and opens a tab with a main agent for work no session owns. You don't need to talk to it.
59
+ - **A tower per workspace.** It opens in its own tab, pinned first, when agents start to collide: a member dispatches a subagent (it promotes itself first), a workspace has two members while another workspace already has a tower, an agent promotes itself, or you type `/boss tower`. Mains and the tower go together: a tower that opens promotes each tab's earliest member, and a tower that quits turns every main back into a member (its subagents stay). It coordinates the main agents and the other towers, and opens a tab with a main agent for work no session owns. You don't need to talk to it.
60
60
  - **A live dashboard** in the tower: who joined, and what they and their subagents are doing.
61
61
  - **Towers talk to each other.** A tower lists every workspace's tower (`tower_list`: who a message for it reaches, what its tabs work on) and writes to one or all of them (`tower_send`); a workspace without a tower is reached through its mains, else its members. Every `call_tower`, `boss_broadcast`, and `tower_send` message opens with a header the code writes: who sent it, in what role, to whom, and whether a reply is expected ([how](docs/how-it-works.md#talking-between-towers)).
62
62
  - **A head tower of your own.** One tower that belongs to no project: you talk to it in the GUI (its page, or the line under Zen's circle) or with `/boss head`, it keeps one long conversation with you across runs, and it hands each instruction to the tower of the workspace that owns it (`tower_send`, opening that tower if needed) and tells you in a line when the tower answers. Its tools are the tower's lookup and forwarding tools and nothing else, and it listens only to you and to answers to its own forwards ([how](docs/how-it-works.md#the-head-tower)).
63
63
  - **A work board.** A main's board fills itself from its todo list and its name (`board_set` overrides it); allies see only an auto entry's name and progress (`<name> (3/5)`), never its task text; towers read every main's entry (`board_read`), on this computer and, with Straw Link, on teammates' computers, so a tower routes work knowing where each main stands ([how](docs/how-it-works.md#the-work-board)).
64
64
  - **A tower closes the mains it opened.** A main a tower opened for a request reports to the sender and to the tower, and the tower closes it (`boss_close_main`) when nothing is running in it ([how](docs/how-it-works.md#closing-an-opened-main)).
65
+ - **A merge train per project.** A project that turns it on in `apps.json` has one integrator main take its coordinators' branches as cars. The integrator merges a train of cars together, has the combined result reviewed once, and runs the heavy gates (lint, build, full suites) once per train instead of once per branch. Where the app lists the stages, it goes on to deploy the train (to an `auto` target on the config's standing word, to a `strict` one only on your words for it) and opens one review page per train for your acceptance; a car you comment on goes back to its coordinator. Straw Boss sets the flow and the project's skill holds every concrete check ([how](docs/how-it-works.md#merge-train)). To run without it on a computer, set `STRAW_BOSS_INTEGRATION=off` in the environment of `herdr server` and its sessions, or `"integration": "off"` in `<agentDir>/straw-boss/config.json` (`<agentDir>` is `PI_CODING_AGENT_DIR`, else `~/.pi/agent`; the variable wins; a setting that cannot be read is off, with a notice; under the desk, `STRAW_BOSS_DESK=1`, it is off unless you set it on): no main or tower then takes the integrator role, a merge or a deploy waits for your word, and `integration` in `apps.json` is ignored.
65
66
  - **A digest for the tower**: joins, subagent launches, and renames in its workspace since its last run, read into its next run once and cleared ([how](docs/how-it-works.md#the-towers-digest)).
66
67
  - **A browser view** of the whole net, `/boss gui`: every workspace as a base with its tower, agents, and subagents, animated and read-only. Click a base to zoom in, click a unit to read its chat as a live comms log; units that wait on you queue up as alerts, and Space opens the next one, F enlarges the top dialog, and Escape closes it (none of them while you type); a question is answered from the keyboard too: arrows choose, Tab walks a question's own-words box and note and then on to the next question, and Enter confirms and goes on. A switch in the header's settings (the gear) raises a system notification, and another plays a sound, when a unit waits on you, fails, or finishes; finished units wait in a list of their own, cleared one by one or all at once, and a finished subagent on the map is dismissed one by one or all at once (Dismiss finished, beside the location). A unit's comms show its background monitors, and one that fails or goes quiet raises a notice (a quiet entry under the header's Notices button; only a unit waiting on you raises the prominent alert); a unit that is idle while a subagent of it works, or while a monitor of it runs, shows as commanding with a glow, and one that only waits on a running monitor shows its note in red. On a desktop a unit's terminal takes your keyboard once you click into it. An answer that leaves its next step in a terminal (robot_hand's prompt and pane choices) shows a small card to finish it: the command, a pane's last rows, one line (hidden while a password is asked), and one button, with a link to the full terminal for ssh and vim. It reads in English or Traditional Chinese, following your browser, with a language menu in the header's settings. + New base, the last card on the map, opens a base in a folder you pick with one member and no tower. A base without a tower takes more members (+ Member on the base adds one in a new tab, on a squad beside that squad), and its tower opens by the rules above; a base with a tower takes new mains (+ Main, on the base or in the tower's comms), each in a tab of its own. In a session's composer, a file pasted, dropped, or picked with + (20 MB at most) is stored in a private temp folder and its path goes into the message. × closes a base, a squad, or (in its view) a unit after a confirmation: each agent quits pi as `/quit` would, then its pane, tab, or workspace closes; nothing closes if one of them refuses. Each opening form takes an optional first message; the folder is picked in Finder-style columns (with New folder, and the base named after the folder by default), staying inside your home folder and skipping hidden folders (on Windows also the ones with the Hidden or System attribute, such as AppData and the old profile links), and while the unit opens a deploy panel shows the real steps (create, start, join the net, deliver the first message) with each step's clock, and names the step and the reason when one fails. A pi that must confirm project trust before it starts (a folder with `.pi/` settings, extensions, skills, or MCP servers) asks in the GUI as an alert too, with the folder, what trusting would load, and Trust, Trust this time, or Don't trust (the terminal can answer as well, and the first answer counts; a paired phone may answer; the deploy panel of an opening shows it inline).
67
- - **An unattended device**, a computer nobody sits at (a build box, a server), takes work from teammates' computers over Straw Link: it runs the sb server as the link holder, with no boot pi session, and a controller invites it from the GUI ([setup](docs/unattended-device.md), also [in Traditional Chinese](docs/unattended-device.zh-TW.md)).
68
+ - **An unattended device**, a computer nobody sits at (a build box, a server), takes work from teammates' computers over Straw Link: it runs the sb server as the link holder, with no boot pi session, and a controller invites it from the GUI ([setup](docs/unattended-device.md), also [in Traditional Chinese](docs/unattended-device.zh-TW.md)). On a box several developers share, a unit's questions and notices go only to the controller that dispatched it and to the team's admins, and the work of a device that leaves the team or loses `dispatch` is ended.
68
69
  - **Broadcast** to a tab, a workspace, every tower (a workspace without one, through its mains or members), or every session.
69
70
  - **Tidy tabs.** When a pi starts in a tab or quits out of it, the tab's panes are made equal again, so workers split off one by one don't leave a chain of halves.
70
71
  - **Stranded subagents are asked to report.** A subagent that stays open after finishing, while the pi that launched it was restarted and no longer receives its result, is asked once over intercom to send its final report there ([how it works](docs/how-it-works.md#orphaned-subagents)).
package/README.zh-TW.md CHANGED
@@ -56,15 +56,16 @@
56
56
 
57
57
  - **每個人都會加入。** Herdr 裡的每個 pi 一啟動,就以成員(member)身分加入所在分頁的網,不用問,也不用記。
58
58
  - **每個分頁一個主智慧體,靠升任產生。** 工作變多的智慧體呼叫 `boss_promote`,或在第一次派出子智慧體(subagent)時自動升任。一個分頁只有一個主智慧體,除了你用 `/boss` 接手以外,沒有人能取代它。
59
- - **每個工作區一座塔台。** 工作區出現第一個主智慧體時,塔台就在自己的分頁開起來,固定排在最前面。它負責協調各個主智慧體和其他塔台;沒有 session 負責的工作,它會開一個分頁、啟動新的主智慧體來處理。你不用跟它說話。
59
+ - **每個工作區一座塔台。** 智慧體開始互相干擾時,塔台會在自己的分頁開起來,固定排在最前面:成員派出子智慧體(它會先升任)、另一個工作區已經有塔台而這個工作區有兩位成員、有智慧體升任,或你輸入 `/boss tower`。主智慧體和塔台同進退:塔台開起來時,會把每個分頁最早的成員升為主智慧體;塔台結束時,每個主智慧體都變回成員(它們的子智慧體留著)。塔台負責協調各個主智慧體和其他塔台;沒有 session 負責的工作,它會開一個分頁、啟動新的主智慧體來處理。你不用跟它說話。
60
60
  - **即時儀表板**在塔台裡:誰加入了,他們和他們的子智慧體正在做什麼。
61
61
  - **塔台之間可以直接溝通。** 塔台能列出每個工作區的塔台(`tower_list`:訊息會送到誰、各分頁在做什麼),也能對其中一座或全部發訊息(`tower_send`);沒有塔台的工作區,訊息改送它的主智慧體,沒有主智慧體就送成員。`call_tower`、`boss_broadcast`、`tower_send` 的每則訊息開頭都有一行程式寫的標頭:誰送的、什麼角色、送給誰、要不要回覆([細節](docs/how-it-works.md#talking-between-towers),英文)。
62
62
  - **你自己的主塔台。** 一座不屬於任何專案的塔台:你在 GUI(它自己的一頁,或禪檢視圓圈下方的幾行字)或用 `/boss head` 和它說話,它和你保持一場跨越多次執行的長對話,把每件事轉給該處理的工作區的塔台(用 `tower_send`,必要時先替那個工作區開一座塔台),塔台回覆之後用一行話告訴你。它只有查詢和轉交用的塔台工具,只聽你的話和對它自己轉交的回覆([細節](docs/how-it-works.md#the-head-tower),英文)。
63
63
  - **工作看板。** 主智慧體的看板由它的待辦清單和名稱自動填入(`board_set` 可覆寫);塔台讀每個主智慧體的項目(`board_read`),本機的,加上 Straw Link 團隊中隊友電腦上的,這樣塔台分派工作時知道各主智慧體做到哪([細節](docs/how-it-works.md#the-work-board))。
64
64
  - **塔台會關掉自己開的主智慧體。** 塔台替請求開出的主智慧體做完後,向發話者和那座塔台各回報一次;塔台確認裡面沒有東西在跑,就用 `boss_close_main` 把它關掉([細節](docs/how-it-works.md#closing-an-opened-main),英文)。
65
+ - **每個專案一列合併火車。** 在 `apps.json` 開啟它的專案,由一個整合者(integrator)主智慧體接收各協調者的分支,每條分支是一節車廂。整合者把一列火車的車廂合在一起,請人審查一次合併後的結果,重型的檢查(lint、build、完整測試)每列火車只跑一次,不必每條分支各跑一次。app 有列出後續階段時,整合者接著部署這列火車:`auto` 的目標直接部署,設定檔本身就是你的長期授權;`strict` 的目標,要有你對那個目標的授權才部署。最後為每列火車開一頁審查頁給你驗收,你留言的車廂退回給它的協調者。Straw Boss 只規定流程,所有具體的檢查都寫在專案自己的 skill 裡([細節](docs/how-it-works.md#merge-train),英文)。在某台電腦上不想用合併火車時,在 `herdr server` 與其 session 的環境設 `STRAW_BOSS_INTEGRATION=off`,或在 `<agentDir>/straw-boss/config.json` 設 `"integration": "off"`(`<agentDir>` 是 `PI_CODING_AGENT_DIR`,沒設就是 `~/.pi/agent`;兩者並存時以環境變數為準;讀不懂的設定一律視為關閉並提示一次;桌面版 `STRAW_BOSS_DESK=1` 預設關閉,要明確設為 on 才會開):沒有主智慧體或塔台會擔任整合者,合併與部署都要等你的話,`apps.json` 裡的 `integration` 也會被忽略。
65
66
  - **給塔台的摘要**:自塔台上一輪以來,工作區裡有誰加入、啟動了哪些子智慧體、誰改了名字;塔台下一輪會讀進來一次,讀完就清掉([細節](docs/how-it-works.md#the-towers-digest))。
66
- - **瀏覽器畫面** `/boss gui` 看得到整張網:每個工作區是一座基地,裡面有塔台、智慧體和子智慧體,畫面會動,但只能看。點基地可以放大,點單位可以把它的對話當成即時通訊紀錄來讀;在等你回覆的單位會排成警示,按空白鍵開下一則,按 F 放大最上面的對話框,按 Esc 關掉它(打字時都不會觸發);回答問題也可以只用鍵盤:方向鍵選項目,Tab 依序走過每一題自己的答案框和備註、再換到下一題,Enter 確認並跳到下一題。頂端齒輪「設定」裡有兩個開關:單位在等你、出錯或完成時,一個會跳系統通知,一個會播音效;已完成的單位另外排在自己的清單裡,可以一個一個清,也可以一次全清;地圖上已結束的子智慧體也可以一個一個移除,或用位置列旁的「移除已完成」一次全移除。單位的通訊畫面也會列出它在背景跑的 Monitor,出錯或太久沒輸出的 Monitor 會列進標頭的「通知」(只有在等你回答的單位才會跳出醒目的警示,出錯和完成都只是安靜的通知);自己閒置、但它的子智慧體在工作或等待,或它的 Monitor 還在跑的單位,會顯示成帶光暈的「指揮中」;只在等 Monitor 跑完的單位,備註會用紅字顯示「監看中」。在桌面上點進單位的終端機,就能直接用鍵盤操作它。如果一個答案的下一步要在終端機進行(robot_hand 的「放進提示列」和開新 pane 的選項),畫面會出現一張小卡片讓你完成它:指令、窗格最後幾行、一行輸入(要輸入密碼時會自動遮住)和一個按鈕,另有連到完整終端機的連結,給 ssh 和 vim 這類程式用。畫面有英文和正體中文,預設跟隨瀏覽器語言,也可以從頂端「設定」裡的語言選單切換。地圖最後一張「+新基地」會在選定的資料夾開一座基地,裡面先有一位成員、沒有塔台。沒有塔台的基地只能加成員(基地上的「+成員」開在新分頁,小隊上的開在該小隊旁),等成員自己升格時才會開塔台;有塔台的基地只能加主智慧體(「+主智慧體」,各開在自己的分頁)。在 session 的輸入框貼上、拖進或用「+」選的檔案(最多 20 MB)會存到私有的暫存資料夾,路徑放進訊息。開啟表單都可以先填第一句指令;資料夾選擇只能在家目錄以下,也不會列出點開頭的資料夾。
67
- - **無人值守裝置**是沒有人坐在前面的電腦(建置機、伺服器),透過 Straw Link 接隊友電腦送來的工作:它以 sb server 當連線持有者,沒有開機時啟動的 pi session,由控制端在 GUI 邀請它加入([設定方式](docs/unattended-device.zh-TW.md);[English](docs/unattended-device.md))。
67
+ - **瀏覽器畫面** `/boss gui` 看得到整張網:每個工作區是一座基地,裡面有塔台、智慧體和子智慧體,畫面會動,但只能看。點基地可以放大,點單位可以把它的對話當成即時通訊紀錄來讀;在等你回覆的單位會排成警示,按空白鍵開下一則,按 F 放大最上面的對話框,按 Esc 關掉它(打字時都不會觸發);回答問題也可以只用鍵盤:方向鍵選項目,Tab 依序走過每一題自己的答案框和備註、再換到下一題,Enter 確認並跳到下一題。頂端齒輪「設定」裡有兩個開關:單位在等你、出錯或完成時,一個會跳系統通知,一個會播音效;已完成的單位另外排在自己的清單裡,可以一個一個清,也可以一次全清;地圖上已結束的子智慧體也可以一個一個移除,或用位置列旁的「移除已完成」一次全移除。單位的通訊畫面也會列出它在背景跑的 Monitor,出錯或太久沒輸出的 Monitor 會列進標頭的「通知」(只有在等你回答的單位才會跳出醒目的警示,出錯和完成都只是安靜的通知);自己閒置、但它的子智慧體在工作或等待,或它的 Monitor 還在跑的單位,會顯示成帶光暈的「指揮中」;只在等 Monitor 跑完的單位,備註會用紅字顯示「監看中」。在桌面上點進單位的終端機,就能直接用鍵盤操作它。如果一個答案的下一步要在終端機進行(robot_hand 的「放進提示列」和開新 pane 的選項),畫面會出現一張小卡片讓你完成它:指令、窗格最後幾行、一行輸入(要輸入密碼時會自動遮住)和一個按鈕,另有連到完整終端機的連結,給 ssh 和 vim 這類程式用。畫面有英文和正體中文,預設跟隨瀏覽器語言,也可以從頂端「設定」裡的語言選單切換。地圖最後一張「+新基地」會在選定的資料夾開一座基地,裡面先有一位成員、沒有塔台。沒有塔台的基地只能加成員(基地上的「+成員」開在新分頁,小隊上的開在該小隊旁),等成員自己升格時才會開塔台;有塔台的基地只能加主智慧體(「+主智慧體」,各開在自己的分頁)。在 session 的輸入框貼上、拖進或用「+」選的檔案(最多 20 MB)會存到私有的暫存資料夾,路徑放進訊息。「×」會在確認後關掉一座基地、一個小隊,或(在它自己的畫面裡)一個單位:每個智慧體像 `/quit` 一樣結束 pi,再關掉它的 pane、分頁或工作區;只要其中一個拒絕,就什麼都不關。開啟表單都可以先填第一句指令;資料夾用 Finder 式的欄位挑選(可以「新增資料夾」,基地預設以資料夾命名),只能在家目錄以下,不會列出點開頭的資料夾(Windows 上也不列出帶「隱藏」或「系統」屬性的資料夾,例如 AppData 和舊的設定檔連結)。單位開啟時,部署面板會列出實際的步驟(建立、啟動、加入網、送出第一句話)和每一步的耗時,某一步失敗時會指出是哪一步、為什麼。pi 啟動前要先確認專案信任(資料夾裡有 `.pi/` 設定、擴充、skill 或 MCP 伺服器)時,GUI 也會跳出警示,列出資料夾、信任後會載入什麼,以及「信任」「這次信任」「不信任」(終端機也能回答,先答的算數;配對的手機也能回答;開啟中的部署面板會直接顯示這個問題)。
68
+ - **無人值守裝置**是沒有人坐在前面的電腦(建置機、伺服器),透過 Straw Link 接隊友電腦送來的工作:它以 sb server 當連線持有者,沒有開機時啟動的 pi session,由控制端在 GUI 邀請它加入([設定方式](docs/unattended-device.zh-TW.md);[English](docs/unattended-device.md))。多位開發者共用一台時,單位的問題和通知只送給派出它的控制端和團隊的管理員;離開團隊或失去 `dispatch` 權限的裝置,它在這台機器上的工作會被結束。
68
69
  - **廣播**給一個分頁、一個工作區、所有塔台(沒有塔台的工作區改送主智慧體或成員),或所有 session。
69
70
  - **分頁保持整齊。** pi 在分頁裡啟動或結束時,分頁裡的 pane 會重新平均分配,一個一個切出來的 worker 就不會留下一長串對半切的窄 pane。
70
71
  - **斷線的子智慧體會被提醒回報。** 子智慧體做完後還開著,但開出它的 pi 已經重開、收不到它的結果時,它會收到一則 intercom,請它把最終報告送回去,只會送一次([運作方式](docs/how-it-works.md#orphaned-subagents))。
@@ -105,10 +106,10 @@ pi install npm:pi-straw-boss
105
106
 
106
107
  1. 在 Herdr 分頁裡開一個 pi,交給它工作。它會自己加入網;工作變多時,它會把自己升成這個分頁的主智慧體,同時開出工作區的塔台。你可以用 `/boss` 接手。
107
108
  2. 輸入 `/boss status`,看每個分頁的主智慧體和各座塔台。
108
- 3. 輸入 `/boss tower`,開啟工作區的塔台、看它的儀表板。智慧體呼叫塔台時也會自己把它開起來。
109
+ 3. 輸入 `/boss tower`,開啟工作區的塔台、看它的儀表板。智慧體開始互相干擾時,它也會自己開起來。
109
110
  4. 在任何一個 session 輸入 `/boss gui`,就能在瀏覽器看整張網。
110
111
 
111
- 塔台只負責轉送和協調,所以可以用比較輕的模型:在 `~/.pi/agent/straw-boss/config.json` 設定 `towerModel`([運作方式](docs/how-it-works.md#how-it-works))。
112
+ 塔台只負責轉送和協調,所以可以用比較輕的模型:在 `~/.pi/agent/straw-boss/config.json` 設定 `towerModel`([運作方式](docs/how-it-works.md#how-it-works))。sb 伺服器的塔台服務預設開啟:塔台是一次次的執行,有事件送到才醒來,結束時留下一份交接說明(`/boss tower <提示>` 會寫給它);隊友透過 Straw Link 送來的訊息,則由一次獨立的盟友執行(ally run)處理。每次執行都從頭開始;必須跨越執行留下來的東西(你的長期指示和決定,以及塔台還在等的事),放在一份小小的記憶裡,你用 `/boss memory` 或 GUI 裡塔台的通訊畫面讀取、修改。塔台只能提議長期指示或決定,要你確認才生效([運作方式](docs/how-it-works.md#tower-memory),英文)。在同一個檔案設 `{ "towerRuns": { "enabled": false } }`,就會改回常駐的塔台([運作方式](docs/how-it-works.md#the-tower-service-b4),英文)。
112
113
 
113
114
  ## 工具與指令
114
115
 
@@ -124,10 +125,14 @@ pi install npm:pi-straw-boss
124
125
  | `board_read` | 只有塔台能用:看工作看板,也就是各主智慧體正在做什麼、做到哪;本機的,加上 Straw Link 團隊中隊友電腦上的。 |
125
126
  | `board_set` | 分頁的主智慧體用:覆寫自己的看板項目(一行目前的工作,加最多 8 個清單項),用 `auto: true` 交還給依待辦清單和名稱的自動填入,或用 `clear: true` 在工作做完或擱置時刪掉它。 |
126
127
  | `boss_broadcast` | 傳訊息給一個分頁、一個工作區、所有塔台,或所有 session(訊息開頭有標頭)。 |
128
+ | `boss_server` | 查看 sb 伺服器(伺服器停著時 status 也能用)、讀它的記錄(最多 200 行),或附上理由重新啟動它。你刻意停掉伺服器時會被拒絕,每分鐘最多一次,遠端回合裡也一律拒絕。 |
127
129
  | `boss_rename` | 用一個短語替這個 session 命名,說明它現在在做什麼;net 與 GUI 會顯示它,主智慧體的分頁也會改成這個名稱。主智慧體換工作時會呼叫它。 |
128
130
  | `/boss` | 接手成為這個分頁的主智慧體。 |
129
131
  | `/boss status`、`/boss tower` | 顯示狀態;開啟塔台並切換過去。 |
130
132
  | `/boss memory [-w workspace]`、`/boss memory confirm P1`、`reject P1`、`add standing\|decision <內容>`、`edit S1 <內容>`、`delete D1`、`resolve W1` | 在 pi 裡讀取與修改塔台的記憶(常駐指示、決定、等待),並回應塔台的提議;塔台只能提議,你確認才生效。GUI 的記憶面板是同一個操作。見 [Tower memory](docs/how-it-works.md#tower-memory)。 |
133
+ | `/boss server`、`/boss server stop`、`/boss server restart [理由]` | 顯示 sb 伺服器,停著時順便啟動它;刻意停掉它(先確認;之後只有 `/boss` 指令能再啟動它);在同一個埠重新啟動它(先確認)。GUI 網址不變,開著的頁面會自己重新連上。見 [sb 伺服器](docs/how-it-works.md#the-sb-server)(英文)。 |
134
+ | `/boss server logs [n]` | 顯示 sb 伺服器記錄的最後 `n` 行(預設與上限都是 200),和 `boss_server` 工具的 `logs` 相同。 |
135
+ | `/boss close` | 結束這個 session,並關掉它的 pane。 |
131
136
  | `/boss close all` | 讓這個基地的塔台、主智慧體和成員結束,連同 shell 一起關掉,不存 stash。會先用 stash 的同一套檢查;有會遺失的東西(正在跑的回合、排隊中的訊息、對話框、Monitor、子智慧體、前景有程式的 shell)就什麼都不關,並列出所有原因。其他基地完全不碰。 |
132
137
  | 網頁上的「收起」「已收起」「接回」 | 基地的「收起」以基地名稱收起它;上方的「已收起」列出收起的基地,按「接回」打開。基地的「關掉」會先檢查,和 `/boss close all` 一樣。 |
133
138
  | `/boss stash [名稱]`、`/boss pop [名稱]` | 把整個基地(塔台、主智慧體、成員和閒置的 shell)收起來並關掉;之後再打開,每個 pi 都從自己的 session 檔接回原本的角色。只要有接回後會遺失的東西就拒絕並說明原因:正在跑的回合、排隊中的訊息、開著的對話框、執行中的 Monitor、子智慧體,或前景有程式在跑的 shell。 |
@@ -138,7 +143,7 @@ pi install npm:pi-straw-boss
138
143
  | `/boss link [status]`、`/boss link decide <id> approve\|refuse` | 列出本裝置的團隊與成員,以及等待中的加入要求(附短 id),並做網頁的「核准/拒絕」。核准有人值守的裝置時,pi 會顯示團隊、裝置與各組單字:選新電腦螢幕上顯示的那一組(都不是就是拒絕);核准無人值守的裝置會先確認。id 不存在或不唯一就什麼都不做。已配對的手機能讀、能開單位,但不能決定。 |
139
144
  | `/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 放在沙箱框架裡,表單送出的答案會傳給智慧體;純文字只能讀。 |
140
145
  | `/boss gui devices`、`/boss gui unpair <id\|all>` | 列出已配對的手機(id、標籤、Tailscale 或 Wi-Fi、配對與最後使用時間),並解除配對一支(給 id 或 id 的開頭)或全部(先確認)。網址不會變;要換網址是 `/boss gui rotate`。 |
141
- | `/boss server logs [n]` | 顯示 sb 伺服器記錄的最後 `n` 行(預設與上限都是 200),和 `boss_server` 工具的 `logs` 相同。 |
146
+ | `/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)(英文)。 |
142
147
  | `/boss gui view`、`/boss gui view auto\|standard\|geek\|zen` | 顯示或設定 GUI 的預設檢視。設定頁維持「自動」的裝置會顯示這個預設;自己選了標準或極客的裝置保留自己的選擇;預設為 `auto` 時,裝置依自己螢幕的對比設定。已開啟的頁面立即切換,新開的頁面第一個畫面就是預設檢視(頂端有極客檢視、禪檢視和設定頁的截圖)。只有這個指令能設定:任何頁面(包括已配對的手機)都不行。 |
143
148
  | `/boss gui remote`、`/boss gui remote off` | 透過你的 tailnet 用手機連 GUI(`tailscale serve`,絕不用 Funnel):掃 QR code 配對(已安裝的 app 則輸入 QR 旁邊顯示的短配對碼),手機配對後的紀錄會保留(從最後一次使用起算 90 天,重啟與 `remote off` 都不影響),直到你在設定頁的「手機與裝置」區解除配對;遠端存取在 stop、`/reload`、換新伺服器之後仍會保持開啟,直到 `remote off`;伺服器重啟後 token 不變,已配對的手機照常使用;GUI 換新 token(`/boss gui rotate`、`gui-secrets.json` 遺失,或埠號被占用)時,舊的配對全部清除(cookie 綁在舊 token 的路徑上),手機要重新配對:瀏覽器掃 QR code,已安裝的 app 輸入配對碼(見下);關閉時只移除它自己的 serve 設定。serve 指向 GUI 伺服器的第二個 loopback 監聽埠,請求算不算遠端取決於它進來的監聽埠,不看它帶什麼標頭。頁面可以安裝成 app(加入主畫面,或 Chrome 的「安裝」):app 的起始網址是固定入口 `https://<這台機器>.<tailnet>.ts.net:8443/sb-app/`(沒有 token,只在 tailnet 監聽埠上):已配對時它會帶你到目前的頁面;沒有配對時(換新 token 後,或 iOS 上 app 有自己的 cookie、在 Safari 掃 QR code 永遠到不了 app),它會顯示 8 個輸入格,輸入 `/boss gui remote` 在 QR code 下方印出的**配對碼**(設定頁的「手機與裝置」區也顯示在 QR code 旁),每格一個字元(貼上整組會自動填滿)。配對碼 8 個字元,顯示成兩組各四個(`ABCD EFGH`,不需要輸入連字號),十分鐘內只能用一次,輸錯五次後作廢,要在這台電腦上重新取得新的才能再試。在這個入口出現之前安裝的 app,舊網址現在也會導向入口。 |
144
149
  | `node dist/server/cli.mjs up --dir <資料夾> --label <名稱>`(給外殼程式用,不是 pi 指令) | `up` 的桌面步驟,給自己顯示頁面的外殼程式(straw-boss-desk)使用:在啟動 `herdr server` 與執行這個指令的環境都設了 `STRAW_BOSS_DESK=1` 時,它會在 Herdr 的 pi 整合不是最新時安裝,建立外殼的家基地(在該資料夾開一個工作區,記在 `desk.json`,之後以工作區 id 找回),讓 sb server 代替這個工作區的塔台,等 GUI 起來,最後印出一行 JSON,內有 `url`、`workspace`、`pane`、`tower`、`created`、`integration`。重複執行不會多開東西;沒設這個開關時以代碼 2 結束。詳見[桌面模式](docs/how-it-works.md#desk-mode-up---dir)。 |
@@ -0,0 +1,2 @@
1
+ import{t as e}from"./runtime-ZX6HkxDa.js";import{S as t}from"./towermodel-YlF7HR2k.js";import{J as n,X as r}from"./index-DnIB0kQt.js";import{mountDialogCards as i}from"./linkdialogs-ZhWsFL3g.js";var a=e=>{let n=t(`en`,e?.count,{},!0);return n===`one`?`${e?.count} question waits for you: answer it here`:n===`other`?`${e?.count} questions wait for you: answer them here`:`ally_asks_button`},o=e=>`${e?.count} 個問題等你回答,在這裡回答`,s=((t,n={})=>(n.locale??e())===`zh-TW`?o(t):a(t)),c=e=>e.tower===`blocked`||e.tabs.some(e=>e.state===`blocked`);function l(e){let t=new Map;for(let r of e?.alerts??[]){let i=r.kind===`dialog`?n(r):void 0;if(i!==`open`&&i!==`sent`)continue;let a=(e?.allies??[]).filter(e=>e.device===r.data.device),o=a.filter(e=>e.team===r.team),s=(o.length?o:a).find(c)??(o.length?o:a)[0];s&&t.set(s.id,[...t.get(s.id)??[],r])}return t}var u=`.ally-unit[data-state="blocked"], .ally-tab[data-state="blocked"]`;function d(){let e=new WeakMap,t=t=>{let a=e.get(t);if(a)return a;let o=r(`button`,{type:`button`,class:`ally-asks-btn`,"aria-expanded":`false`}),s=r(`ul`,{class:`ally-asks-list`}),c=r(`div`,{class:`ally-asks`},o,s);return a={box:c,btn:o,list:s,cards:i(),ids:``},e.set(t,a),o.onclick=()=>n(t),t.addEventListener(`click`,e=>{let r=e.target?.closest?.(u);r&&t.contains(r)&&t.dataset.asks&&n(t)}),t.append(c),a};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 a(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=s({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
+ `);o!==i.ids&&(i.list.replaceChildren(...a),i.ids=o)}return{toggle:n,fill:a,show:(e,t,n)=>a(e,l(n).get(t.id)??[])}}export{d as mountAllyAsks};
@@ -1 +1 @@
1
- import{n as e}from"./rolldown-runtime-4tVxZq34.js";import{t}from"./ask-GI8fnsYy.js";import{n}from"./post-CmicYl-f.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
+ import{n as e}from"./rolldown-runtime-4tVxZq34.js";import{t}from"./ask-Cl7AZwX1.js";import{n}from"./post-CmicYl-f.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{Ut as o,X as s,t as c,vt as l}from"./index-A8RfiBLi.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;return e.addEventListener(`keydown`,i=>{let o=a(i.target);if(!o||i.ctrlKey||i.altKey||i.metaKey||i.isComposing)return;let c=i.target;if(o.part!==`opt`&&(i.key===`ArrowUp`?c.selectionStart!==0:i.key===`ArrowDown`&&c.selectionEnd!==c.value.length))return;let l=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(!l||(i.preventDefault(),i.repeat&&[`Enter`,` `].includes(i.key)))return;if(s=i.key===` `,l.pick!==void 0){let e=t[o.q].opts[l.pick];e.getAttribute(`aria-checked`)!==`true`&&e.click()}let u=l.to===`send`?void 0:t[l.to.q],d=l.to===`send`?n():l.to.part===`opt`?u.opts[l.to.o??r(u)]:l.to.part===`own`?u.own:u.note;d&&!d.disabled&&(e.dispatchEvent(new CustomEvent(`ask-reveal`,{detail:d})),d.focus())}),e.addEventListener(`keyup`,e=>s&&e.key===` `&&(s=!1,e.preventDefault())),()=>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:o,by:s}=e.body;return a===`accepted`?[`ok`,i?h():n()]:a===`stale`?[`error`,s===`local`?R():s===`cancel`?I():L()]:a===`rejected`?[`error`,(Object.hasOwn(Q,String(o))?Q[String(o)]:j)()]:a===`busy`?[`error`,t()]:a===`unknown`||e.status===504?[`error`,r(),!0]:[`error`,o??l({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`,l,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 o=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]=o?ne(o,n.cancel===!0):[`error`,r(),!0];[e.done,e.sending,O,e.busy]=[!o||re(o),!1,!1,o?.body.outcome===`busy`],A(e.note,d,p,...m?[u]:[]);let h=o?.body.outcome===`accepted`?o.body.then:void 0,g=h&&c(h,{key:l?.key??``,command:e.copy,answerId:String(n.answerId??``)});g&&A(e.note,d,`${p} ${g}`),j(),e.note.scrollIntoView?.({block:`nearest`}),f&&o?.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 c=e.tool===`secret_drop`;i&&!c&&Z(i,n)&&((a.cancel=s(`button`,{type:`button`,class:`ask-cancel`},o())).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=l&&e.tool!==`secret_drop`&&s(`button`,{type:`button`,class:`cmp-link`},p());m&&(m.onclick=l.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&&!c?i.select?R(a,i):B(a,i):[...t.length?t.map(e=>G(e,r)):[s(`p`,{class:`ask-why`},c?n?M():N():e.why??z())],s(`div`,{class:`ask-acts`},c?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{Ut as o,X as s,t as c,vt as l}from"./index-DnIB0kQt.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;return e.addEventListener(`keydown`,i=>{let o=a(i.target);if(!o||i.ctrlKey||i.altKey||i.metaKey||i.isComposing)return;let c=i.target;if(o.part!==`opt`&&(i.key===`ArrowUp`?c.selectionStart!==0:i.key===`ArrowDown`&&c.selectionEnd!==c.value.length))return;let l=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(!l||(i.preventDefault(),i.repeat&&[`Enter`,` `].includes(i.key)))return;if(s=i.key===` `,l.pick!==void 0){let e=t[o.q].opts[l.pick];e.getAttribute(`aria-checked`)!==`true`&&e.click()}let u=l.to===`send`?void 0:t[l.to.q],d=l.to===`send`?n():l.to.part===`opt`?u.opts[l.to.o??r(u)]:l.to.part===`own`?u.own:u.note;d&&!d.disabled&&(e.dispatchEvent(new CustomEvent(`ask-reveal`,{detail:d})),d.focus())}),e.addEventListener(`keyup`,e=>s&&e.key===` `&&(s=!1,e.preventDefault())),()=>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:o,by:s}=e.body;return a===`accepted`?[`ok`,i?h():n()]:a===`stale`?[`error`,s===`local`?R():s===`cancel`?I():L()]:a===`rejected`?[`error`,(Object.hasOwn(Q,String(o))?Q[String(o)]:j)()]:a===`busy`?[`error`,t()]:a===`unknown`||e.status===504?[`error`,r(),!0]:[`error`,o??l({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`,l,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 o=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]=o?ne(o,n.cancel===!0):[`error`,r(),!0];[e.done,e.sending,O,e.busy]=[!o||re(o),!1,!1,o?.body.outcome===`busy`],A(e.note,d,p,...m?[u]:[]);let h=o?.body.outcome===`accepted`?o.body.then:void 0,g=h&&c(h,{key:l?.key??``,command:e.copy,answerId:String(n.answerId??``)});g&&A(e.note,d,`${p} ${g}`),j(),e.note.scrollIntoView?.({block:`nearest`}),f&&o?.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 c=e.tool===`secret_drop`;i&&!c&&Z(i,n)&&((a.cancel=s(`button`,{type:`button`,class:`ask-cancel`},o())).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=l&&e.tool!==`secret_drop`&&s(`button`,{type:`button`,class:`cmp-link`},p());m&&(m.onclick=l.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&&!c?i.select?R(a,i):B(a,i):[...t.length?t.map(e=>G(e,r)):[s(`p`,{class:`ask-why`},c?n?M():N():e.why??z())],s(`div`,{class:`ask-acts`},c?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 +1 @@
1
- import{n as e}from"./rolldown-runtime-4tVxZq34.js";import{t}from"./runtime-ZX6HkxDa.js";import{m as n}from"./towermodel-YlF7HR2k.js";import{n as r}from"./post-CmicYl-f.js";import{vt as i}from"./index-A8RfiBLi.js";var a=((e={},n={})=>(n.locale??t())===`zh-TW`?`沒有符合這個號碼的請求。`:`No request has that number.`),o=((e={},n={})=>(n.locale??t())===`zh-TW`?`這個請求已經不在了。`:`That request is gone.`),s=((e={},n={})=>(n.locale??t())===`zh-TW`?`連續輸入三次錯誤號碼,所以所有等待中的請求都已拒絕。請按「新的配對碼」重新配對。`:`Three wrong numbers in a row, so every waiting request was denied. Press New code and pair again.`),c=((e={},n={})=>(n.locale??t())===`zh-TW`?`這個請求已經變了,請重新看過。`:`That request changed. Look at it again.`),l=((e={},n={})=>(n.locale??t())===`zh-TW`?`這個請求已經不在了,或已逾時。`:`That request is gone or has timed out.`),u=((e={},n={})=>(n.locale??t())===`zh-TW`?`這個團隊沒有在這台裝置上執行。`:`That team is not running on this device.`),d=((e={},n={})=>(n.locale??t())===`zh-TW`?`已在該裝置上取消。`:`It was cancelled at the device.`),f=((e={},n={})=>(n.locale??t())===`zh-TW`?`你已從這裡回答。`:`You answered it from here.`),p=((e={},n={})=>(n.locale??t())===`zh-TW`?`已在該裝置上回答。`:`Answered at the device itself.`),m=((e={},n={})=>(n.locale??t())===`zh-TW`?`已由團隊的另一個控制端回答。`:`Answered by another controller of this team.`),h=e=>`The answer was not sent: ${e?.reason}`,g=e=>`答案沒有送出:${e?.reason}`,_=((e,n={})=>(n.locale??t())===`zh-TW`?g(e):h(e)),v=((e={},n={})=>(n.locale??t())===`zh-TW`?`問題在有人回答前就結束了。`:`It ended before anyone answered it.`),y=((e={},n={})=>(n.locale??t())===`zh-TW`?`已送出你的答案;對方裝置還沒關閉這個問題。`:`Your answer was sent; the device has not closed the question yet.`),b=((e={},n={})=>(n.locale??t())===`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,t)=>({tell:n=>t(`input`,{text:n,as:`send`,answers:e.id}),dismiss:()=>r(`${n(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(`${n(e.ws)}/memory`,{op:`confirm`,proposal:e.id,rev:e.rev()}),reject:()=>r(`${n(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};
1
+ import{n as e}from"./rolldown-runtime-4tVxZq34.js";import{t}from"./runtime-ZX6HkxDa.js";import{m as n}from"./towermodel-YlF7HR2k.js";import{n as r}from"./post-CmicYl-f.js";import{vt as i}from"./index-DnIB0kQt.js";var a=((e={},n={})=>(n.locale??t())===`zh-TW`?`沒有符合這個號碼的請求。`:`No request has that number.`),o=((e={},n={})=>(n.locale??t())===`zh-TW`?`這個請求已經不在了。`:`That request is gone.`),s=((e={},n={})=>(n.locale??t())===`zh-TW`?`連續輸入三次錯誤號碼,所以所有等待中的請求都已拒絕。請按「新的配對碼」重新配對。`:`Three wrong numbers in a row, so every waiting request was denied. Press New code and pair again.`),c=((e={},n={})=>(n.locale??t())===`zh-TW`?`這個請求已經變了,請重新看過。`:`That request changed. Look at it again.`),l=((e={},n={})=>(n.locale??t())===`zh-TW`?`這個請求已經不在了,或已逾時。`:`That request is gone or has timed out.`),u=((e={},n={})=>(n.locale??t())===`zh-TW`?`這個團隊沒有在這台裝置上執行。`:`That team is not running on this device.`),d=((e={},n={})=>(n.locale??t())===`zh-TW`?`已在該裝置上取消。`:`It was cancelled at the device.`),f=((e={},n={})=>(n.locale??t())===`zh-TW`?`你已從這裡回答。`:`You answered it from here.`),p=((e={},n={})=>(n.locale??t())===`zh-TW`?`已在該裝置上回答。`:`Answered at the device itself.`),m=((e={},n={})=>(n.locale??t())===`zh-TW`?`已由團隊的另一個控制端回答。`:`Answered by another controller of this team.`),h=e=>`The answer was not sent: ${e?.reason}`,g=e=>`答案沒有送出:${e?.reason}`,_=((e,n={})=>(n.locale??t())===`zh-TW`?g(e):h(e)),v=((e={},n={})=>(n.locale??t())===`zh-TW`?`問題在有人回答前就結束了。`:`It ended before anyone answered it.`),y=((e={},n={})=>(n.locale??t())===`zh-TW`?`已送出你的答案;對方裝置還沒關閉這個問題。`:`Your answer was sent; the device has not closed the question yet.`),b=((e={},n={})=>(n.locale??t())===`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,t)=>({tell:n=>t(`input`,{text:n,as:`send`,answers:e.id}),dismiss:()=>r(`${n(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(`${n(e.ws)}/memory`,{op:`confirm`,proposal:e.id,rev:e.rev()}),reject:()=>r(`${n(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};
@@ -1,2 +1,2 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./index-Brm9t2JN.css"])))=>i.map(i=>d[i]);
2
- import{t as e}from"./runtime-ZX6HkxDa.js";import{r as t}from"./towermodel-YlF7HR2k.js";import{i as n,n as r,r as i,t as a}from"./towerturns-sm4atUwy.js";import{n as o,t as s}from"./markdown-DvbY97ID.js";import{F as c,Lt as l,Q as u,X as d,b as f,d as p,w as m}from"./index-A8RfiBLi.js";var ee=((t={},n={})=>(n.locale??e())===`zh-TW`?`可能已被當機的 run 處理過:動手前先確認。`:`A run that crashed may already have handled this: check before acting.`),te=((t={},n={})=>(n.locale??e())===`zh-TW`?`分支摘要`:`branch summary`),ne=((t={},n={})=>(n.locale??e())===`zh-TW`?`通訊紀錄`:`Comms log`),h=e=>`context compacted · ${e?.tokens} tokens summarized`,g=e=>`上下文已壓縮 · 摘要了 ${e?.tokens} tokens`,re=((t,n={})=>(n.locale??e())===`zh-TW`?g(t):h(t)),ie=((t={},n={})=>(n.locale??e())===`zh-TW`?`…(於 1 MB 截斷)`:`… (cut at 1 MB)`),_=e=>`exit ${e?.code}`,v=e=>`結束碼 ${e?.code}`,ae=((t,n={})=>(n.locale??e())===`zh-TW`?v(t):_(t)),y=e=>`New chapter · ${e?.date} · ${e?.why}`,b=e=>`新的一章・${e?.date}・${e?.why}`,oe=((t,n={})=>(n.locale??e())===`zh-TW`?b(t):y(t)),x=((t={},n={})=>(n.locale??e())===`zh-TW`?`第一次對話`:`the first conversation`),S=((t={},n={})=>(n.locale??e())===`zh-TW`?`你要求開新對話`:`you asked for a new conversation`),C=((t={},n={})=>(n.locale??e())===`zh-TW`?`上一章太長了`:`the last one grew too large`),w=((t={},n={})=>(n.locale??e())===`zh-TW`?`上一章無法接續`:`the last one could not be resumed`),T=e=>`Image ${e?.n}`,E=e=>`圖片 ${e?.n}`,se=((t,n={})=>(n.locale??e())===`zh-TW`?E(t):T(t)),ce=((t={},n={})=>(n.locale??e())===`zh-TW`?`圖片無法讀取`:`Image unavailable`),D=e=>`${e?.count} image(s)`,O=e=>`${e?.count} 張圖片`,le=((t,n={})=>(n.locale??e())===`zh-TW`?O(t):D(t)),ue=((t={},n={})=>(n.locale??e())===`zh-TW`?`收到`:`incoming`),k=((t={},n={})=>(n.locale??e())===`zh-TW`?`跳到最新`:`jump to latest`),A=e=>`${e?.count} new`,j=e=>`${e?.count} 則新訊息`,M=((t,n={})=>(n.locale??e())===`zh-TW`?j(t):A(t)),de=((t={},n={})=>(n.locale??e())===`zh-TW`?`還沒有通訊。`:`No transmissions yet.`),fe=((t={},n={})=>(n.locale??e())===`zh-TW`?`通知`:`notice`),pe=((t={},n={})=>(n.locale??e())===`zh-TW`?`細節`:`details`),N=((t={},n={})=>(n.locale??e())===`zh-TW`?`表單回覆`:`form answers`),me=((t={},n={})=>(n.locale??e())===`zh-TW`?`訊息,來自`:`message from`),P=e=>`answer from ${e?.from}`,F=e=>`${e?.from} 的回答`,he=((t,n={})=>(n.locale??e())===`zh-TW`?F(t):P(t)),I=e=>`request from ${e?.from}`,L=e=>`${e?.from} 的請求`,ge=((t,n={})=>(n.locale??e())===`zh-TW`?L(t):I(t)),R=e=>`message from ${e?.from}`,_e=e=>`${e?.from} 的訊息`,ve=((t,n={})=>(n.locale??e())===`zh-TW`?_e(t):R(t)),z=e=>`reply to your ask from ${e?.from}`,B=e=>`${e?.from} 回覆了你的詢問`,ye=((t,n={})=>(n.locale??e())===`zh-TW`?B(t):z(t)),V=((t={},n={})=>(n.locale??e())===`zh-TW`?`記憶`:`memory`),be=((t={},n={})=>(n.locale??e())===`zh-TW`?`監看`:`monitor`),xe=((t={},n={})=>(n.locale??e())===`zh-TW`?`本機`:`this computer`),Se=((t={},n={})=>(n.locale??e())===`zh-TW`?`隊友`:`teammate`),H=((t={},n={})=>(n.locale??e())===`zh-TW`?`提問,來自`:`question from`),U=((t={},n={})=>(n.locale??e())===`zh-TW`?`回報,來自`:`report from`),Ce=((t={},n={})=>(n.locale??e())===`zh-TW`?`sb server 的通知`:`notice from the sb server`),W=((t={},n={})=>(n.locale??e())===`zh-TW`?`狀態:`:`status of`),G=((t={},n={})=>(n.locale??e())===`zh-TW`?`Straw Link 訊息`:`Straw Link message`),we=((t={},n={})=>(n.locale??e())===`zh-TW`?`喚醒鬧鐘`:`wake-up call`),Te=((t={},n={})=>(n.locale??e())===`zh-TW`?`塔台事件`:`tower event`),Ee=((t={},n={})=>(n.locale??e())===`zh-TW`?`在旁開啟`:`open beside`),K=e=>`Open image ${e?.n}`,q=e=>`打開圖片 ${e?.n}`,De=((t,n={})=>(n.locale??e())===`zh-TW`?q(t):K(t)),J=e=>`show all (${e?.size})`,Y=e=>`顯示全部(${e?.size})`,Oe=((t,n={})=>(n.locale??e())===`zh-TW`?Y(t):J(t)),ke=((t={},n={})=>(n.locale??e())===`zh-TW`?`顯示全部參數`:`show all arguments`),X=e=>`◇ thought · ${e?.count} chars`,Z=e=>`◇ 思考 · ${e?.count} 字元`,Ae=((t,n={})=>(n.locale??e())===`zh-TW`?Z(t):X(t)),je=((t={},n={})=>(n.locale??e())===`zh-TW`?`◇ 思考 · 已遮蔽`:`◇ thought · redacted`),Me=((t={},n={})=>(n.locale??e())===`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.`),Ne=((t={},n={})=>(n.locale??e())===`zh-TW`?`無法取得`:`unavailable`),Pe=((t={},n={})=>(n.locale??e())===`zh-TW`?`你`:`you`);function Fe(){let e=!0,t=0;return{get pinned(){return e},scrolled(n){e=n,n&&(t=0)},hold:()=>void(e=!1),arrived(n){return e||(t+=n),e},jump:()=>void(e=!0,t=0),button:n=>e&&!n?void 0:t&&!n?M({count:t}):k()}}async function Ie(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 Le(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 Re=(e,t)=>({first:x,new:S,size:C,unreadable:w})[e??``]?.()??t??``,ze=e=>e.head?l():m(e.role),Be=e=>e?new Date(e).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`,hour12:!1}):``,Ve=e=>e>=1024?`${(e/1024).toFixed(e>=10240?0:1)} KB`:`${e} B`,He={intercom_message:me,subagent_result:U,subagent_ping:H,subagent_status:W,"pi-loop-monitor":be,"memory-context":V,"doc-review":N,"straw-tower":Te,"straw-link":G},Q=e=>{let t=f(`<span class="ava"><svg><use/></svg></span>`);return t.querySelector(`use`).setAttribute(`href`,`#i-${p[e]??e}`),t};function Ue(e){let t=[],n=0;for(let r of e.matchAll(/https?:\/\/[^\s<>)\]]+/g))t.push(e.slice(n,r.index),d(`a`,{href:r[0],rel:`noopener noreferrer`,target:`_blank`},r[0])),n=r.index+r[0].length;return[...t,e.slice(n)]}function We(l,f,{who:p,link:m,docFor:h}){let g=Le(),_=new Map,v=new Set,y=()=>v.forEach(e=>e.button.isConnected?(e.shown=!0,e.button.hidden=!e.paths.some(e=>h?.(e))):e.shown&&v.delete(e)),b=d(`div`,{class:`chat-list`}),x=d(`div`,{class:`chat-top`}),S=d(`div`,{class:`chat-live`}),C=d(`div`,{class:`chat-end`}),w=d(`button`,{class:`chat-pill`,type:`button`,hidden:``}),T=d(`p`,{class:`chat-empty`},de()),E=d(`div`,{class:`chat-scroll`,tabindex:`-1`,"aria-label":ne()},x,b,S,C);l.replaceChildren(E,w);let D=Fe(),O=!1,k=!1,A,j,M=0,N=!1,P,F=()=>N||P!==void 0,I=()=>(clearTimeout(P),P=setTimeout(()=>(P=void 0,D.pinned&&!g.detached&&R()),250)),L=(e=D.button(g.detached))=>(w.hidden=!e,w.textContent=e??``),R=()=>(D.jump(),j=void 0,E.scrollTop=E.scrollHeight,L());async function _e(e){O=!0;let t=await Ie(g,f,e,e=>(q(e),Z(e))).finally(()=>O=!1),n=_.get(e);if(A===e){if(!t||!n)return R();D.hold(),j=n,n.scrollIntoView({block:`center`}),u(n,`lit`),clearTimeout(M),M=window.setTimeout(()=>(j=void 0,n.classList.remove(`lit`)),2e3),L()}}let z=()=>A?void _e(A):R(),B=(e,t,n,r)=>{e.disabled=!0,f.entry(n).then(n=>{let i=n&&r(n);if(i===void 0)return void(e.textContent=Ne());t.textContent=i,e.remove()},()=>e.textContent=Ne())};function V(e,t=0){if(!t||!f.pic)return null;let n=Array.from({length:t},(t,n)=>f.pic(e,n));return d(`div`,{class:`pics`},...n.map((e,t)=>{let r=d(`img`,{src:e,alt:se({n:t+1}),loading:`lazy`,decoding:`async`}),i=d(`button`,{type:`button`,class:`pic`,"aria-label":De({n:t+1})},r);return r.addEventListener(`error`,()=>i.replaceWith(d(`em`,{class:`pic-gone`},ce()))),i.addEventListener(`click`,()=>void c(async()=>{let{lightbox:e}=await import(`./lightbox-DWkBtVWK.js`);return{lightbox:e}},__vite__mapDeps([0]),import.meta.url).then(({lightbox:e})=>e(n,t))),i}))}function be(e,t){let n=g.result(e.id),r=d(`pre`,{class:`out`},n?.text??``),i=d(`pre`,{class:`args`},e.args??``),a=e.cut?d(`button`,{class:`more`,type:`button`},ke()):null;a?.addEventListener(`click`,()=>B(a,i,t,t=>(e=>e&&`${e.args??``}${e.cut?`\n${ie()}`:``}`)(t.tools?.find(t=>t.id===e.id))));let o=n?.more?d(`button`,{class:`more`,type:`button`},Oe({size:Ve(n.bytes??0)})):null;o?.addEventListener(`click`,()=>B(o,r,n.id,e=>e.text));let s=e.name===`show_doc`&&h?d(`button`,{class:`more open`,type:`button`,hidden:``},Ee()):null;s?.addEventListener(`click`,t=>(t.preventDefault(),e.summary.split(`, `).forEach(e=>h?.(e)?.()))),s&&v.add({paths:e.summary.split(`, `),button:s}),s&&queueMicrotask(y);let c=d(`details`,{class:`act`},d(`summary`,{"data-mark":n?n.isError?`error`:`done`:`working`},d(`b`,{class:`badge`}),d(`code`,null,e.name),d(`span`,{class:`sum`},e.summary),s),i,a,n&&d(`div`,{class:`result`},n.images?d(`em`,null,le({count:n.images})):null,r,o)),l=n&&V(n.id,n.images);return l?[c,l]:[c]}let H=e=>d(`time`,null,Be(e.at)),U=(e,t,n,r)=>d(`article`,{class:`tx you`},d(`header`,null,H(e),d(`b`,null,Pe()),Q(`user`)),d(`div`,{class:`bubble`,title:r},n?d(`small`,{class:`boss-flag`},ee()):null,...Ue(t),V(e.id,e.images))),W=(e,t,n,r={})=>d(`article`,{class:`tx sys`},d(`details`,{class:`notice`},d(`summary`,null,Q(`comms`),d(`em`,null,ue()),...t,H(e)),r.crashed?d(`small`,{class:`boss-flag`},ee()):null,d(`pre`,null,n),r.raw?d(`details`,{class:`notice-raw`},d(`summary`,null,pe()),d(`pre`,{class:`raw`},r.raw)):null)),G=e=>{let t=n(e);return[me(),` `,t.name&&m(t.name)||t.name,t.id?` (${t.id})`:``,` · `,xe()]},Te=e=>e.kind===`link`?[{ask:ge,reply:ye,answer:he,message:ve}[e.what]({from:e.from}),` · `,Se()]:e.kind===`intercom`?G(e.from):[e.kind===`server`?Ce():we()];function K(t){switch(t.kind){case`user`:{let e=p().service?i(t.text):void 0;if(e)return W(t,e.kind===`intercom`?G(e.from):[e.kind===`server`?Ce():we()],t.text??``);let n=p().service?a(t.text):void 0;return U(t,n?n.body:t.text??``,n?.crashed,n?t.text??``:``)}case`assistant`:{let e=p(),n=d(`pre`,{class:`thought-text`}),r=t.thought?d(`button`,{class:`thought`,type:`button`},t.thought<0?je():Ae({count:t.thought.toLocaleString()})):null;return t.thought&&t.thought>0&&r?.addEventListener(`click`,()=>B(r,n,t.id,e=>e.thoughtText)),d(`article`,{class:e.head?`tx in head`:`tx in`},Q(e.head?`crown`:e.role),d(`div`,{class:`tx-body`},d(`header`,null,d(`b`,null,ze(e)),t.model?d(`span`,null,t.model):null,H(t),t.stop?d(`span`,{class:`stop`,"data-mark":`error`},t.stop):null),r,n,t.text?d(`div`,{class:`md`},s(o(t.text))):null,t.error?d(`p`,{class:`fault`},t.error):null,...(t.tools??[]).flatMap(e=>be(e,t.id))))}case`bash`:return d(`article`,{class:`tx sys`},d(`details`,{class:`act`},d(`summary`,{"data-mark":t.exit?`error`:`done`},d(`b`,{class:`badge`}),d(`code`,null,`shell`),d(`span`,{class:`sum`},`! ${t.command}`),t.exit?d(`span`,{class:`stop`,"data-mark":`error`},ae({code:t.exit})):null),t.text?d(`pre`,{class:`out`},t.text):null));case`notice`:{let e=r(t);return e?.kind===`boss`&&p().service?U(t,e.body,e.crashed,t.text??``):e&&e.kind!==`boss`?W(t,Te(e),e.body,e.kind===`link`?{raw:e.raw}:{crashed:e.crashed}):W(t,[He[t.type??``]?.()??t.type??fe(),` `,t.from&&m(t.from)||(t.from??``)],t.text??``)}case`divider`:return t.type===`chapter`?d(`article`,{class:`tx rule chapter`},d(`p`,null,oe({date:t.at?new Date(t.at).toLocaleDateString(e(),{year:`numeric`,month:`short`,day:`numeric`}):``,why:Re(t.code,t.text)}))):d(`article`,{class:`tx rule`},d(`details`,null,d(`summary`,null,t.type===`compaction`?re({tokens:(t.tokens??0).toLocaleString()}):te()),d(`pre`,null,t.text??``)));default:return d(`article`,{class:`tx note`},t.text??``,` `,H(t))}}function q(e){e.rebuild&&(_.clear(),b.replaceChildren());for(let t of e.dropped)_.get(t)?.remove(),_.delete(t);let t=e.added.map(e=>(_.set(e.id,K(e)),_.get(e.id)));e.front?b.prepend(...t):b.append(...t),k&&!e.front&&!e.rebuild&&t.forEach(e=>(e.classList.add(`fresh`),e.dataset.born=String(Date.now()))),T.remove();let n=p().service;T.textContent=n?.state===`standing`&&!n.run?Me():de(),g.items.length||b.append(T),x.hidden=!g.before,X()}let J=[],Y=new Map;function X(){let e=new Set;for(let n of J){let r=Date.parse(n.startedAt),i=g.items.findIndex(e=>e.at!==void 0&&Date.parse(e.at)>=r);if(i===0&&g.before)continue;let a=i<0?``:g.items[i].id,o=JSON.stringify([a,t(n)]),s=Y.get(n.id);if(e.add(n.id),s&&s.sig===o&&s.el.isConnected)continue;s?.el.remove();let c=t(n),l=d(`article`,{class:`tx rule conv-rule`},d(`div`,null,d(`b`,null,c.title),c.ended?d(`small`,null,c.ended):null));Y.set(n.id,{el:l,sig:o});let u=a?_.get(a):void 0;u?u.before(l):b.append(l)}for(let[t,n]of Y)e.has(t)||(n.el.remove(),Y.delete(t))}let Z=e=>e.touched.forEach(e=>{let t=_.get(e),n=g.items.find(t=>t.id===e);if(t&&n){let r=K(n);t.classList.contains(`fresh`)&&Date.now()-Number(t.dataset.born??0)<400&&r.classList.add(`fresh`),t.replaceWith(r),_.set(e,r)}}),We=async()=>{if(!O&&g.before&&k){O=!0;try{let e=E.scrollHeight,t=g.prepend(await f.older(g.before));q(t),Z(t),E.scrollTop+=E.scrollHeight-e}finally{O=!1}g.before&&E.clientHeight&&x.getBoundingClientRect().bottom>=E.getBoundingClientRect().top&&We()}};w.addEventListener(`click`,()=>{A=void 0,g.detached?f.latest().then(e=>(q(g.reset(e)),R())):R()});let Ge=[new IntersectionObserver(e=>e.some(e=>e.isIntersecting)&&void We(),{root:E}),new IntersectionObserver(e=>E.clientHeight&&(D.scrolled(e.at(-1).isIntersecting),L()),{root:E,rootMargin:`0px 0px 67px`})],$,Ke=()=>($??(Ge[0].observe(x),Ge[1].observe(C)),clearTimeout($),$=setTimeout(()=>($=void 0,Ge.forEach(e=>e.disconnect())),600));E.addEventListener(`scroll`,()=>(Ke(),!N&&P!==void 0&&I()),{passive:!0}),E.addEventListener(`touchstart`,()=>(N=!0,clearTimeout(P),P=void 0),{passive:!0});for(let e of[`touchend`,`touchcancel`])E.addEventListener(e,()=>(N=!1,I()),{passive:!0});for(let e of[`wheel`,`touchstart`,`pointerdown`,`keydown`])E.addEventListener(e,()=>j=A=void 0,{passive:!0});let qe=new ResizeObserver(()=>F()?void 0:D.pinned&&!g.detached?E.scrollTop=E.scrollHeight:j?.scrollIntoView({block:`center`}));return qe.observe(b),qe.observe(E),{log:E,docs:y,runs(e){JSON.stringify(e)!==JSON.stringify(J)&&(J=e,X())},apply(e){if(e.reset)q(g.reset({items:e.items??[],before:e.before})),k=!0,z();else if(e.items?.length){let t=g.append(e.items);q(t),Z(t),D.arrived(t.added.length)&&!g.detached&&!F()?R():L()}},reveal(e){A=e,k&&z()},setLive(e,t){S.dataset.mark=t,S.lastChild?.textContent!==e&&S.replaceChildren(...e?[d(`b`,{class:`badge`}),d(`span`,null,e)]:[])}}}export{We as mountChat,se as t};
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./index-CwBU87EN.css"])))=>i.map(i=>d[i]);
2
+ import{t as e}from"./runtime-ZX6HkxDa.js";import{r as t}from"./towermodel-YlF7HR2k.js";import{i as n,n as r,r as i,t as a}from"./towerturns-sm4atUwy.js";import{n as o,t as s}from"./markdown-DvbY97ID.js";import{F as c,Lt as l,Q as u,X as d,b as f,d as p,w as m}from"./index-DnIB0kQt.js";var ee=((t={},n={})=>(n.locale??e())===`zh-TW`?`可能已被當機的 run 處理過:動手前先確認。`:`A run that crashed may already have handled this: check before acting.`),te=((t={},n={})=>(n.locale??e())===`zh-TW`?`分支摘要`:`branch summary`),ne=((t={},n={})=>(n.locale??e())===`zh-TW`?`通訊紀錄`:`Comms log`),h=e=>`context compacted · ${e?.tokens} tokens summarized`,g=e=>`上下文已壓縮 · 摘要了 ${e?.tokens} tokens`,re=((t,n={})=>(n.locale??e())===`zh-TW`?g(t):h(t)),ie=((t={},n={})=>(n.locale??e())===`zh-TW`?`…(於 1 MB 截斷)`:`… (cut at 1 MB)`),_=e=>`exit ${e?.code}`,v=e=>`結束碼 ${e?.code}`,ae=((t,n={})=>(n.locale??e())===`zh-TW`?v(t):_(t)),y=e=>`New chapter · ${e?.date} · ${e?.why}`,b=e=>`新的一章・${e?.date}・${e?.why}`,oe=((t,n={})=>(n.locale??e())===`zh-TW`?b(t):y(t)),x=((t={},n={})=>(n.locale??e())===`zh-TW`?`第一次對話`:`the first conversation`),S=((t={},n={})=>(n.locale??e())===`zh-TW`?`你要求開新對話`:`you asked for a new conversation`),C=((t={},n={})=>(n.locale??e())===`zh-TW`?`上一章太長了`:`the last one grew too large`),w=((t={},n={})=>(n.locale??e())===`zh-TW`?`上一章無法接續`:`the last one could not be resumed`),T=e=>`Image ${e?.n}`,E=e=>`圖片 ${e?.n}`,se=((t,n={})=>(n.locale??e())===`zh-TW`?E(t):T(t)),ce=((t={},n={})=>(n.locale??e())===`zh-TW`?`圖片無法讀取`:`Image unavailable`),D=e=>`${e?.count} image(s)`,O=e=>`${e?.count} 張圖片`,le=((t,n={})=>(n.locale??e())===`zh-TW`?O(t):D(t)),ue=((t={},n={})=>(n.locale??e())===`zh-TW`?`收到`:`incoming`),k=((t={},n={})=>(n.locale??e())===`zh-TW`?`跳到最新`:`jump to latest`),A=e=>`${e?.count} new`,j=e=>`${e?.count} 則新訊息`,M=((t,n={})=>(n.locale??e())===`zh-TW`?j(t):A(t)),de=((t={},n={})=>(n.locale??e())===`zh-TW`?`還沒有通訊。`:`No transmissions yet.`),fe=((t={},n={})=>(n.locale??e())===`zh-TW`?`通知`:`notice`),pe=((t={},n={})=>(n.locale??e())===`zh-TW`?`細節`:`details`),N=((t={},n={})=>(n.locale??e())===`zh-TW`?`表單回覆`:`form answers`),me=((t={},n={})=>(n.locale??e())===`zh-TW`?`訊息,來自`:`message from`),P=e=>`answer from ${e?.from}`,F=e=>`${e?.from} 的回答`,he=((t,n={})=>(n.locale??e())===`zh-TW`?F(t):P(t)),I=e=>`request from ${e?.from}`,L=e=>`${e?.from} 的請求`,ge=((t,n={})=>(n.locale??e())===`zh-TW`?L(t):I(t)),R=e=>`message from ${e?.from}`,_e=e=>`${e?.from} 的訊息`,ve=((t,n={})=>(n.locale??e())===`zh-TW`?_e(t):R(t)),z=e=>`reply to your ask from ${e?.from}`,B=e=>`${e?.from} 回覆了你的詢問`,ye=((t,n={})=>(n.locale??e())===`zh-TW`?B(t):z(t)),V=((t={},n={})=>(n.locale??e())===`zh-TW`?`記憶`:`memory`),be=((t={},n={})=>(n.locale??e())===`zh-TW`?`監看`:`monitor`),xe=((t={},n={})=>(n.locale??e())===`zh-TW`?`本機`:`this computer`),Se=((t={},n={})=>(n.locale??e())===`zh-TW`?`隊友`:`teammate`),H=((t={},n={})=>(n.locale??e())===`zh-TW`?`提問,來自`:`question from`),U=((t={},n={})=>(n.locale??e())===`zh-TW`?`回報,來自`:`report from`),Ce=((t={},n={})=>(n.locale??e())===`zh-TW`?`sb server 的通知`:`notice from the sb server`),W=((t={},n={})=>(n.locale??e())===`zh-TW`?`狀態:`:`status of`),G=((t={},n={})=>(n.locale??e())===`zh-TW`?`Straw Link 訊息`:`Straw Link message`),we=((t={},n={})=>(n.locale??e())===`zh-TW`?`喚醒鬧鐘`:`wake-up call`),Te=((t={},n={})=>(n.locale??e())===`zh-TW`?`塔台事件`:`tower event`),Ee=((t={},n={})=>(n.locale??e())===`zh-TW`?`在旁開啟`:`open beside`),K=e=>`Open image ${e?.n}`,q=e=>`打開圖片 ${e?.n}`,De=((t,n={})=>(n.locale??e())===`zh-TW`?q(t):K(t)),J=e=>`show all (${e?.size})`,Y=e=>`顯示全部(${e?.size})`,Oe=((t,n={})=>(n.locale??e())===`zh-TW`?Y(t):J(t)),ke=((t={},n={})=>(n.locale??e())===`zh-TW`?`顯示全部參數`:`show all arguments`),X=e=>`◇ thought · ${e?.count} chars`,Z=e=>`◇ 思考 · ${e?.count} 字元`,Ae=((t,n={})=>(n.locale??e())===`zh-TW`?Z(t):X(t)),je=((t={},n={})=>(n.locale??e())===`zh-TW`?`◇ 思考 · 已遮蔽`:`◇ thought · redacted`),Me=((t={},n={})=>(n.locale??e())===`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.`),Ne=((t={},n={})=>(n.locale??e())===`zh-TW`?`無法取得`:`unavailable`),Pe=((t={},n={})=>(n.locale??e())===`zh-TW`?`你`:`you`);function Fe(){let e=!0,t=0;return{get pinned(){return e},scrolled(n){e=n,n&&(t=0)},hold:()=>void(e=!1),arrived(n){return e||(t+=n),e},jump:()=>void(e=!0,t=0),button:n=>e&&!n?void 0:t&&!n?M({count:t}):k()}}async function Ie(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 Le(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 Re=(e,t)=>({first:x,new:S,size:C,unreadable:w})[e??``]?.()??t??``,ze=e=>e.head?l():m(e.role),Be=e=>e?new Date(e).toLocaleTimeString([],{hour:`2-digit`,minute:`2-digit`,hour12:!1}):``,Ve=e=>e>=1024?`${(e/1024).toFixed(e>=10240?0:1)} KB`:`${e} B`,He={intercom_message:me,subagent_result:U,subagent_ping:H,subagent_status:W,"pi-loop-monitor":be,"memory-context":V,"doc-review":N,"straw-tower":Te,"straw-link":G},Q=e=>{let t=f(`<span class="ava"><svg><use/></svg></span>`);return t.querySelector(`use`).setAttribute(`href`,`#i-${p[e]??e}`),t};function Ue(e){let t=[],n=0;for(let r of e.matchAll(/https?:\/\/[^\s<>)\]]+/g))t.push(e.slice(n,r.index),d(`a`,{href:r[0],rel:`noopener noreferrer`,target:`_blank`},r[0])),n=r.index+r[0].length;return[...t,e.slice(n)]}function We(l,f,{who:p,link:m,docFor:h}){let g=Le(),_=new Map,v=new Set,y=()=>v.forEach(e=>e.button.isConnected?(e.shown=!0,e.button.hidden=!e.paths.some(e=>h?.(e))):e.shown&&v.delete(e)),b=d(`div`,{class:`chat-list`}),x=d(`div`,{class:`chat-top`}),S=d(`div`,{class:`chat-live`}),C=d(`div`,{class:`chat-end`}),w=d(`button`,{class:`chat-pill`,type:`button`,hidden:``}),T=d(`p`,{class:`chat-empty`},de()),E=d(`div`,{class:`chat-scroll`,tabindex:`-1`,"aria-label":ne()},x,b,S,C);l.replaceChildren(E,w);let D=Fe(),O=!1,k=!1,A,j,M=0,N=!1,P,F=()=>N||P!==void 0,I=()=>(clearTimeout(P),P=setTimeout(()=>(P=void 0,D.pinned&&!g.detached&&R()),250)),L=(e=D.button(g.detached))=>(w.hidden=!e,w.textContent=e??``),R=()=>(D.jump(),j=void 0,E.scrollTop=E.scrollHeight,L());async function _e(e){O=!0;let t=await Ie(g,f,e,e=>(q(e),Z(e))).finally(()=>O=!1),n=_.get(e);if(A===e){if(!t||!n)return R();D.hold(),j=n,n.scrollIntoView({block:`center`}),u(n,`lit`),clearTimeout(M),M=window.setTimeout(()=>(j=void 0,n.classList.remove(`lit`)),2e3),L()}}let z=()=>A?void _e(A):R(),B=(e,t,n,r)=>{e.disabled=!0,f.entry(n).then(n=>{let i=n&&r(n);if(i===void 0)return void(e.textContent=Ne());t.textContent=i,e.remove()},()=>e.textContent=Ne())};function V(e,t=0){if(!t||!f.pic)return null;let n=Array.from({length:t},(t,n)=>f.pic(e,n));return d(`div`,{class:`pics`},...n.map((e,t)=>{let r=d(`img`,{src:e,alt:se({n:t+1}),loading:`lazy`,decoding:`async`}),i=d(`button`,{type:`button`,class:`pic`,"aria-label":De({n:t+1})},r);return r.addEventListener(`error`,()=>i.replaceWith(d(`em`,{class:`pic-gone`},ce()))),i.addEventListener(`click`,()=>void c(async()=>{let{lightbox:e}=await import(`./lightbox-DkXX9IuA.js`);return{lightbox:e}},__vite__mapDeps([0]),import.meta.url).then(({lightbox:e})=>e(n,t))),i}))}function be(e,t){let n=g.result(e.id),r=d(`pre`,{class:`out`},n?.text??``),i=d(`pre`,{class:`args`},e.args??``),a=e.cut?d(`button`,{class:`more`,type:`button`},ke()):null;a?.addEventListener(`click`,()=>B(a,i,t,t=>(e=>e&&`${e.args??``}${e.cut?`\n${ie()}`:``}`)(t.tools?.find(t=>t.id===e.id))));let o=n?.more?d(`button`,{class:`more`,type:`button`},Oe({size:Ve(n.bytes??0)})):null;o?.addEventListener(`click`,()=>B(o,r,n.id,e=>e.text));let s=e.name===`show_doc`&&h?d(`button`,{class:`more open`,type:`button`,hidden:``},Ee()):null;s?.addEventListener(`click`,t=>(t.preventDefault(),e.summary.split(`, `).forEach(e=>h?.(e)?.()))),s&&v.add({paths:e.summary.split(`, `),button:s}),s&&queueMicrotask(y);let c=d(`details`,{class:`act`},d(`summary`,{"data-mark":n?n.isError?`error`:`done`:`working`},d(`b`,{class:`badge`}),d(`code`,null,e.name),d(`span`,{class:`sum`},e.summary),s),i,a,n&&d(`div`,{class:`result`},n.images?d(`em`,null,le({count:n.images})):null,r,o)),l=n&&V(n.id,n.images);return l?[c,l]:[c]}let H=e=>d(`time`,null,Be(e.at)),U=(e,t,n,r)=>d(`article`,{class:`tx you`},d(`header`,null,H(e),d(`b`,null,Pe()),Q(`user`)),d(`div`,{class:`bubble`,title:r},n?d(`small`,{class:`boss-flag`},ee()):null,...Ue(t),V(e.id,e.images))),W=(e,t,n,r={})=>d(`article`,{class:`tx sys`},d(`details`,{class:`notice`},d(`summary`,null,Q(`comms`),d(`em`,null,ue()),...t,H(e)),r.crashed?d(`small`,{class:`boss-flag`},ee()):null,d(`pre`,null,n),r.raw?d(`details`,{class:`notice-raw`},d(`summary`,null,pe()),d(`pre`,{class:`raw`},r.raw)):null)),G=e=>{let t=n(e);return[me(),` `,t.name&&m(t.name)||t.name,t.id?` (${t.id})`:``,` · `,xe()]},Te=e=>e.kind===`link`?[{ask:ge,reply:ye,answer:he,message:ve}[e.what]({from:e.from}),` · `,Se()]:e.kind===`intercom`?G(e.from):[e.kind===`server`?Ce():we()];function K(t){switch(t.kind){case`user`:{let e=p().service?i(t.text):void 0;if(e)return W(t,e.kind===`intercom`?G(e.from):[e.kind===`server`?Ce():we()],t.text??``);let n=p().service?a(t.text):void 0;return U(t,n?n.body:t.text??``,n?.crashed,n?t.text??``:``)}case`assistant`:{let e=p(),n=d(`pre`,{class:`thought-text`}),r=t.thought?d(`button`,{class:`thought`,type:`button`},t.thought<0?je():Ae({count:t.thought.toLocaleString()})):null;return t.thought&&t.thought>0&&r?.addEventListener(`click`,()=>B(r,n,t.id,e=>e.thoughtText)),d(`article`,{class:e.head?`tx in head`:`tx in`},Q(e.head?`crown`:e.role),d(`div`,{class:`tx-body`},d(`header`,null,d(`b`,null,ze(e)),t.model?d(`span`,null,t.model):null,H(t),t.stop?d(`span`,{class:`stop`,"data-mark":`error`},t.stop):null),r,n,t.text?d(`div`,{class:`md`},s(o(t.text))):null,t.error?d(`p`,{class:`fault`},t.error):null,...(t.tools??[]).flatMap(e=>be(e,t.id))))}case`bash`:return d(`article`,{class:`tx sys`},d(`details`,{class:`act`},d(`summary`,{"data-mark":t.exit?`error`:`done`},d(`b`,{class:`badge`}),d(`code`,null,`shell`),d(`span`,{class:`sum`},`! ${t.command}`),t.exit?d(`span`,{class:`stop`,"data-mark":`error`},ae({code:t.exit})):null),t.text?d(`pre`,{class:`out`},t.text):null));case`notice`:{let e=r(t);return e?.kind===`boss`&&p().service?U(t,e.body,e.crashed,t.text??``):e&&e.kind!==`boss`?W(t,Te(e),e.body,e.kind===`link`?{raw:e.raw}:{crashed:e.crashed}):W(t,[He[t.type??``]?.()??t.type??fe(),` `,t.from&&m(t.from)||(t.from??``)],t.text??``)}case`divider`:return t.type===`chapter`?d(`article`,{class:`tx rule chapter`},d(`p`,null,oe({date:t.at?new Date(t.at).toLocaleDateString(e(),{year:`numeric`,month:`short`,day:`numeric`}):``,why:Re(t.code,t.text)}))):d(`article`,{class:`tx rule`},d(`details`,null,d(`summary`,null,t.type===`compaction`?re({tokens:(t.tokens??0).toLocaleString()}):te()),d(`pre`,null,t.text??``)));default:return d(`article`,{class:`tx note`},t.text??``,` `,H(t))}}function q(e){e.rebuild&&(_.clear(),b.replaceChildren());for(let t of e.dropped)_.get(t)?.remove(),_.delete(t);let t=e.added.map(e=>(_.set(e.id,K(e)),_.get(e.id)));e.front?b.prepend(...t):b.append(...t),k&&!e.front&&!e.rebuild&&t.forEach(e=>(e.classList.add(`fresh`),e.dataset.born=String(Date.now()))),T.remove();let n=p().service;T.textContent=n?.state===`standing`&&!n.run?Me():de(),g.items.length||b.append(T),x.hidden=!g.before,X()}let J=[],Y=new Map;function X(){let e=new Set;for(let n of J){let r=Date.parse(n.startedAt),i=g.items.findIndex(e=>e.at!==void 0&&Date.parse(e.at)>=r);if(i===0&&g.before)continue;let a=i<0?``:g.items[i].id,o=JSON.stringify([a,t(n)]),s=Y.get(n.id);if(e.add(n.id),s&&s.sig===o&&s.el.isConnected)continue;s?.el.remove();let c=t(n),l=d(`article`,{class:`tx rule conv-rule`},d(`div`,null,d(`b`,null,c.title),c.ended?d(`small`,null,c.ended):null));Y.set(n.id,{el:l,sig:o});let u=a?_.get(a):void 0;u?u.before(l):b.append(l)}for(let[t,n]of Y)e.has(t)||(n.el.remove(),Y.delete(t))}let Z=e=>e.touched.forEach(e=>{let t=_.get(e),n=g.items.find(t=>t.id===e);if(t&&n){let r=K(n);t.classList.contains(`fresh`)&&Date.now()-Number(t.dataset.born??0)<400&&r.classList.add(`fresh`),t.replaceWith(r),_.set(e,r)}}),We=async()=>{if(!O&&g.before&&k){O=!0;try{let e=E.scrollHeight,t=g.prepend(await f.older(g.before));q(t),Z(t),E.scrollTop+=E.scrollHeight-e}finally{O=!1}g.before&&E.clientHeight&&x.getBoundingClientRect().bottom>=E.getBoundingClientRect().top&&We()}};w.addEventListener(`click`,()=>{A=void 0,g.detached?f.latest().then(e=>(q(g.reset(e)),R())):R()});let Ge=[new IntersectionObserver(e=>e.some(e=>e.isIntersecting)&&void We(),{root:E}),new IntersectionObserver(e=>E.clientHeight&&(D.scrolled(e.at(-1).isIntersecting),L()),{root:E,rootMargin:`0px 0px 67px`})],$,Ke=()=>($??(Ge[0].observe(x),Ge[1].observe(C)),clearTimeout($),$=setTimeout(()=>($=void 0,Ge.forEach(e=>e.disconnect())),600));E.addEventListener(`scroll`,()=>(Ke(),!N&&P!==void 0&&I()),{passive:!0}),E.addEventListener(`touchstart`,()=>(N=!0,clearTimeout(P),P=void 0),{passive:!0});for(let e of[`touchend`,`touchcancel`])E.addEventListener(e,()=>(N=!1,I()),{passive:!0});for(let e of[`wheel`,`touchstart`,`pointerdown`,`keydown`])E.addEventListener(e,()=>j=A=void 0,{passive:!0});let qe=new ResizeObserver(()=>F()?void 0:D.pinned&&!g.detached?E.scrollTop=E.scrollHeight:j?.scrollIntoView({block:`center`}));return qe.observe(b),qe.observe(E),{log:E,docs:y,runs(e){JSON.stringify(e)!==JSON.stringify(J)&&(J=e,X())},apply(e){if(e.reset)q(g.reset({items:e.items??[],before:e.before})),k=!0,z();else if(e.items?.length){let t=g.append(e.items);q(t),Z(t),D.arrived(t.added.length)&&!g.detached&&!F()?R():L()}},reveal(e){A=e,k&&z()},setLive(e,t){S.dataset.mark=t,S.lastChild?.textContent!==e&&S.replaceChildren(...e?[d(`b`,{class:`badge`}),d(`span`,null,e)]:[])}}}export{We as mountChat,se as t};
@@ -1 +1 @@
1
- import{t as e}from"./runtime-ZX6HkxDa.js";import"./towermodel-YlF7HR2k.js";import{t}from"./open_main_title-Ccbha5pD.js";import{n,t as r}from"./unit_count-5h7nN0qd.js";import{C as i,D as a,E as o,Lt as s,M as c,N as l,Rt as u,T as ee,X as d,b as f,ct as p,h as m,i as h,j as g,m as _,o as v,p as y,v as b,w as x}from"./index-A8RfiBLi.js";var te=((t={},n={})=>(n.locale??e())===`zh-TW`?`關閉清單`:`Close the list`),S=((t={},n={})=>(n.locale??e())===`zh-TW`?`切換到其他單位`:`Switch to a unit`),C=((t={},n={})=>(n.locale??e())===`zh-TW`?`回到主地圖`:`Back to the map`),w=((t={},n={})=>(n.locale??e())===`zh-TW`?`所有單位`:`All units`),T=((t={},n={})=>(n.locale??e())===`zh-TW`?`指揮中`:`commanding`),E=((t={},n={})=>(n.locale??e())===`zh-TW`?`已結束`:`ended`),D=((t={},n={})=>(n.locale??e())===`zh-TW`?`錯誤`:`error`),O=((t={},n={})=>(n.locale??e())===`zh-TW`?`閒置`:`idle`),k=((t={},n={})=>(n.locale??e())===`zh-TW`?`無狀態`:`unknown`),A=((t={},n={})=>(n.locale??e())===`zh-TW`?`等待`:`waiting`),j=((t={},n={})=>(n.locale??e())===`zh-TW`?`工作中`:`working`),M=.4;function N(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 P=(e,t,n)=>Math.abs(n)>=.45?n>0:e>=t*M,F=(e,t)=>t||e.some(e=>e.editable||e.sink||e.scrollsX||[`input`,`textarea`,`select`].includes(e.tag));function I(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 ne=e=>{let t=[];for(let n=e;n;n=n.parentElement)t.push(I(n));return t},L={working:j,waiting:A,idle:O,done:E,error:D,unknown:k,commanding:T},R=(e,t,n)=>(t?E:L[e])({},n&&{locale:n}),z=(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 B(e){return e.bases.flatMap(e=>{let t=[{id:`tower`,rows:e.tower?z(e.id,[{...e.tower,role:`tower`}]):[]},...e.tabs.map(t=>({id:t.id,label:p({label:t.label}),rows:z(e.id,t.units)})),{id:`outside`,label:n(),rows:z(e.id,e.outside)}].filter(e=>e.rows.length);return t.length?[{id:e.id,label:e.label,mark:e.mark,groups:t}]:[]})}var V=(e,t)=>e?.head?{mark:e.head.mark,word:e.head.state===`absent`?u({},t&&{locale:t}):R(e.head.mark,!1,t)}:void 0,H=e=>e.role===`main`&&e.mark===`idle`,U=e=>e.reduce((e,t)=>(t.sub?e.at(-1)?.subs.push(t):e.push({...t,subs:[]}),e),[]),W=()=>f(`<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>`),G=()=>f(`<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>`),K=()=>f(`<section class="dbase"><h3><a></a><small></small></h3><div class="dgroups"></div></section>`),q=()=>f(`<div class="dgroup"><h4></h4><div class="drows"></div></div>`),J=()=>matchMedia(`(max-width: 640px)`).matches;function Y(e=()=>!1){let n=d(`div`,{class:`drawer-body`}),u=d(`button`,{type:`button`,class:`x`,"aria-label":te()},`×`),p=d(`a`,{class:`drawer-map`},C()),y=d(`button`,{type:`button`,class:`pair-btn`,"data-close":`dismiss-all`,hidden:``}),T=d(`div`,{class:`drawer-sweep`,hidden:``},y);_(p,{view:`map`});let E=f(`<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>`);E.hidden=!0,_(E,{view:`head`});let D=d(`aside`,{class:`drawer`,"aria-label":S()},d(`header`,null,d(`b`,null,w()),u),E,n,d(`footer`,{class:`drawer-foot`},T,p)),O=d(`div`,{class:`drawer-veil`});document.body.append(O,D);let k,A,j=!1,M=!1,I=0,L=0,z,Y=()=>{let e=V(k);E.hidden=!e,e&&(i(E,e.mark),a(E,`.name`,s()),a(E,`.dstate`,e.word),E.classList.toggle(`current`,j),E.toggleAttribute(`data-news`,h(k?.head,v())&&!j)),l(y,k??{bases:[]}),T.hidden=y.hidden;let c=(e,t)=>{_(e.querySelector(`.hit`),{view:`session`,ws:t.ws,key:t.key}),e.querySelector(`.hit`).setAttribute(`aria-label`,`${t.name}: ${R(t.mark,t.ended)}`),e.classList.toggle(`current`,t.key===A),e.toggleAttribute(`data-dismiss`,t.role===`subagent`&&t.ended),e.dataset.key=t.key,i(e,t.mark),b(e.querySelector(`.plate`),t.role,t.mark),a(e,`.name`,t.name),a(e,`.role`,x(t.role)),a(e,`.dstate`,R(t.mark,t.ended)),ee(e,`.note`,t.note,t.mark,t.note?void 0:``);let n=e.querySelector(`:scope > .card > .quit-btn`);H(t)?g(n,t):n.hidden=!0,o(e.querySelector(`.subs`),t.subs??[],W,c)},u=(e,n)=>{let r=e.querySelector(`.tower-go`),s=e.querySelector(`.tower-add`),l=k?.bases.find(e=>e.id===n.ws);_(r,{view:`session`,ws:n.ws,key:n.key}),r.setAttribute(`aria-label`,`${n.name}: ${R(n.mark,n.ended)}`),e.classList.toggle(`current`,n.key===A),e.dataset.key=n.key,i(e,n.mark),b(r.querySelector(`.plate`),`tower`,n.mark),a(r,`.name`,n.name),a(r,`.role`,x(`tower`)),a(r,`.dstate`,R(n.mark,n.ended)),s.hidden=!l,l&&(m(s,l),s.setAttribute(`aria-label`,t({base:l.label}))),o(e.querySelector(`.subs`),n.subs,W,c)};o(n,B(k??{bases:[]}),K,(e,t)=>{i(e,t.mark),a(e,`h3 a`,t.label),_(e.querySelector(`h3 a`),{view:`workspace`,ws:t.id}),a(e,`small`,r({count:t.groups.reduce((e,t)=>e+t.rows.length,0)})),o(e.querySelector(`.dgroups`),t.groups,q,(e,t)=>{a(e,`h4`,t.label??``),e.querySelector(`h4`).toggleAttribute(`hidden`,!t.label),t.id===`tower`?o(e.querySelector(`.drows`),U(t.rows),G,u):o(e.querySelector(`.drows`),U(t.rows),W,c)})})},X=e=>{I=Math.max(0,Math.min(L,e)),D.style.setProperty(`--dx`,`${I}px`),O.style.opacity=String(L?I/L:0),O.style.pointerEvents=I>0?`auto`:`none`},Z=e=>{M=e,D.classList.toggle(`on`,e),D.inert=!e,document.documentElement.classList.remove(`drawer-drag`),X(e?L:0)},Q=()=>{L=D.offsetWidth,Y(),D.classList.add(`on`),document.documentElement.classList.add(`drawer-drag`)};D.inert=!0,document.addEventListener(`touchstart`,t=>{let n=t.target,r=D.contains(n)||n===O;if(z=void 0,!J()||e()||t.touches.length!==1||document.querySelector(`dialog.sheet[open], dialog.lightbox[open], [popover]:popover-open`)||(M?!r:F(ne(n),!!getSelection()?.toString())))return;let i=t.touches[0],a=M?n.closest(`.unit[data-dismiss] > .card`)??void 0:void 0;z={x0:i.clientX,y0:i.clientY,mode:`wait`,was:M,base:I,last:i.clientX,at:performance.now(),v:0,card:a}},{passive:!0}),document.addEventListener(`touchmove`,e=>{if(!z||z.mode===`pass`)return;let t=e.touches[0],n=t.clientX-z.x0,r=t.clientY-z.y0;if(z.mode===`wait`){let e=N(n,r,z.was);if(e===`wait`)return;if(e===`pass`&&z.card&&N(n,r,!1)===`drag`)z.mode=`card`,z.card.classList.add(`swiping`);else if(e===`pass`)return void(z.mode=`pass`);else z.mode=`drag`,Q()}e.preventDefault();let i=performance.now();if(z.v=(t.clientX-z.last)/Math.max(1,i-z.at),[z.last,z.at]=[t.clientX,i],z.mode!==`card`)return X(z.base+n);let a=Math.max(0,n);z.card.style.setProperty(`--sx`,`${a}px`),z.card.style.setProperty(`--so`,String(1-a/z.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`),c({key:e.parentElement.dataset.key}).then(t=>t||e.classList.remove(`gone`)))},$=e=>{let t=z;z=void 0,t?.mode===`drag`&&Z(P(I,L,t.v)),t?.mode===`card`&&re(t.card,e.type===`touchend`&&P(Math.max(0,t.last-t.x0),t.card.offsetWidth,t.v))};return document.addEventListener(`touchend`,$),document.addEventListener(`touchcancel`,$),O.addEventListener(`click`,()=>Z(!1)),D.addEventListener(`click`,e=>e.target.closest(`a[data-route], button[data-open], .x`)&&Z(!1)),document.addEventListener(`keydown`,e=>M&&e.key===`Escape`&&(e.preventDefault(),Z(!1)),!0),document.addEventListener(`sb-drawer`,()=>(M||Q(),Z(!M))),{net(e){k=e,M&&Y()},route(e){A=e.view===`session`?e.key:void 0,j=e.view===`head`||e.view===`session`&&e.ws===`@head`,p.toggleAttribute(`aria-current`,e.view===`map`),M&&Y()}}}export{Y as mountDrawer};
1
+ import{t as e}from"./runtime-ZX6HkxDa.js";import"./towermodel-YlF7HR2k.js";import{t}from"./open_main_title-Ccbha5pD.js";import{n,t as r}from"./unit_count-5h7nN0qd.js";import{C as i,D as a,E as o,Lt as s,M as c,N as l,Rt as u,T as ee,X as d,b as f,ct as p,h as m,i as h,j as g,m as _,o as v,p as y,v as b,w as x}from"./index-DnIB0kQt.js";var te=((t={},n={})=>(n.locale??e())===`zh-TW`?`關閉清單`:`Close the list`),S=((t={},n={})=>(n.locale??e())===`zh-TW`?`切換到其他單位`:`Switch to a unit`),C=((t={},n={})=>(n.locale??e())===`zh-TW`?`回到主地圖`:`Back to the map`),w=((t={},n={})=>(n.locale??e())===`zh-TW`?`所有單位`:`All units`),T=((t={},n={})=>(n.locale??e())===`zh-TW`?`指揮中`:`commanding`),E=((t={},n={})=>(n.locale??e())===`zh-TW`?`已結束`:`ended`),D=((t={},n={})=>(n.locale??e())===`zh-TW`?`錯誤`:`error`),O=((t={},n={})=>(n.locale??e())===`zh-TW`?`閒置`:`idle`),k=((t={},n={})=>(n.locale??e())===`zh-TW`?`無狀態`:`unknown`),A=((t={},n={})=>(n.locale??e())===`zh-TW`?`等待`:`waiting`),j=((t={},n={})=>(n.locale??e())===`zh-TW`?`工作中`:`working`),M=.4;function N(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 P=(e,t,n)=>Math.abs(n)>=.45?n>0:e>=t*M,F=(e,t)=>t||e.some(e=>e.editable||e.sink||e.scrollsX||[`input`,`textarea`,`select`].includes(e.tag));function I(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 ne=e=>{let t=[];for(let n=e;n;n=n.parentElement)t.push(I(n));return t},L={working:j,waiting:A,idle:O,done:E,error:D,unknown:k,commanding:T},R=(e,t,n)=>(t?E:L[e])({},n&&{locale:n}),z=(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 B(e){return e.bases.flatMap(e=>{let t=[{id:`tower`,rows:e.tower?z(e.id,[{...e.tower,role:`tower`}]):[]},...e.tabs.map(t=>({id:t.id,label:p({label:t.label}),rows:z(e.id,t.units)})),{id:`outside`,label:n(),rows:z(e.id,e.outside)}].filter(e=>e.rows.length);return t.length?[{id:e.id,label:e.label,mark:e.mark,groups:t}]:[]})}var V=(e,t)=>e?.head?{mark:e.head.mark,word:e.head.state===`absent`?u({},t&&{locale:t}):R(e.head.mark,!1,t)}:void 0,H=e=>e.role===`main`&&e.mark===`idle`,U=e=>e.reduce((e,t)=>(t.sub?e.at(-1)?.subs.push(t):e.push({...t,subs:[]}),e),[]),W=()=>f(`<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>`),G=()=>f(`<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>`),K=()=>f(`<section class="dbase"><h3><a></a><small></small></h3><div class="dgroups"></div></section>`),q=()=>f(`<div class="dgroup"><h4></h4><div class="drows"></div></div>`),J=()=>matchMedia(`(max-width: 640px)`).matches;function Y(e=()=>!1){let n=d(`div`,{class:`drawer-body`}),u=d(`button`,{type:`button`,class:`x`,"aria-label":te()},`×`),p=d(`a`,{class:`drawer-map`},C()),y=d(`button`,{type:`button`,class:`pair-btn`,"data-close":`dismiss-all`,hidden:``}),T=d(`div`,{class:`drawer-sweep`,hidden:``},y);_(p,{view:`map`});let E=f(`<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>`);E.hidden=!0,_(E,{view:`head`});let D=d(`aside`,{class:`drawer`,"aria-label":S()},d(`header`,null,d(`b`,null,w()),u),E,n,d(`footer`,{class:`drawer-foot`},T,p)),O=d(`div`,{class:`drawer-veil`});document.body.append(O,D);let k,A,j=!1,M=!1,I=0,L=0,z,Y=()=>{let e=V(k);E.hidden=!e,e&&(i(E,e.mark),a(E,`.name`,s()),a(E,`.dstate`,e.word),E.classList.toggle(`current`,j),E.toggleAttribute(`data-news`,h(k?.head,v())&&!j)),l(y,k??{bases:[]}),T.hidden=y.hidden;let c=(e,t)=>{_(e.querySelector(`.hit`),{view:`session`,ws:t.ws,key:t.key}),e.querySelector(`.hit`).setAttribute(`aria-label`,`${t.name}: ${R(t.mark,t.ended)}`),e.classList.toggle(`current`,t.key===A),e.toggleAttribute(`data-dismiss`,t.role===`subagent`&&t.ended),e.dataset.key=t.key,i(e,t.mark),b(e.querySelector(`.plate`),t.role,t.mark),a(e,`.name`,t.name),a(e,`.role`,x(t.role)),a(e,`.dstate`,R(t.mark,t.ended)),ee(e,`.note`,t.note,t.mark,t.note?void 0:``);let n=e.querySelector(`:scope > .card > .quit-btn`);H(t)?g(n,t):n.hidden=!0,o(e.querySelector(`.subs`),t.subs??[],W,c)},u=(e,n)=>{let r=e.querySelector(`.tower-go`),s=e.querySelector(`.tower-add`),l=k?.bases.find(e=>e.id===n.ws);_(r,{view:`session`,ws:n.ws,key:n.key}),r.setAttribute(`aria-label`,`${n.name}: ${R(n.mark,n.ended)}`),e.classList.toggle(`current`,n.key===A),e.dataset.key=n.key,i(e,n.mark),b(r.querySelector(`.plate`),`tower`,n.mark),a(r,`.name`,n.name),a(r,`.role`,x(`tower`)),a(r,`.dstate`,R(n.mark,n.ended)),s.hidden=!l,l&&(m(s,l),s.setAttribute(`aria-label`,t({base:l.label}))),o(e.querySelector(`.subs`),n.subs,W,c)};o(n,B(k??{bases:[]}),K,(e,t)=>{i(e,t.mark),a(e,`h3 a`,t.label),_(e.querySelector(`h3 a`),{view:`workspace`,ws:t.id}),a(e,`small`,r({count:t.groups.reduce((e,t)=>e+t.rows.length,0)})),o(e.querySelector(`.dgroups`),t.groups,q,(e,t)=>{a(e,`h4`,t.label??``),e.querySelector(`h4`).toggleAttribute(`hidden`,!t.label),t.id===`tower`?o(e.querySelector(`.drows`),U(t.rows),G,u):o(e.querySelector(`.drows`),U(t.rows),W,c)})})},X=e=>{I=Math.max(0,Math.min(L,e)),D.style.setProperty(`--dx`,`${I}px`),O.style.opacity=String(L?I/L:0),O.style.pointerEvents=I>0?`auto`:`none`},Z=e=>{M=e,D.classList.toggle(`on`,e),D.inert=!e,document.documentElement.classList.remove(`drawer-drag`),X(e?L:0)},Q=()=>{L=D.offsetWidth,Y(),D.classList.add(`on`),document.documentElement.classList.add(`drawer-drag`)};D.inert=!0,document.addEventListener(`touchstart`,t=>{let n=t.target,r=D.contains(n)||n===O;if(z=void 0,!J()||e()||t.touches.length!==1||document.querySelector(`dialog.sheet[open], dialog.lightbox[open], [popover]:popover-open`)||(M?!r:F(ne(n),!!getSelection()?.toString())))return;let i=t.touches[0],a=M?n.closest(`.unit[data-dismiss] > .card`)??void 0:void 0;z={x0:i.clientX,y0:i.clientY,mode:`wait`,was:M,base:I,last:i.clientX,at:performance.now(),v:0,card:a}},{passive:!0}),document.addEventListener(`touchmove`,e=>{if(!z||z.mode===`pass`)return;let t=e.touches[0],n=t.clientX-z.x0,r=t.clientY-z.y0;if(z.mode===`wait`){let e=N(n,r,z.was);if(e===`wait`)return;if(e===`pass`&&z.card&&N(n,r,!1)===`drag`)z.mode=`card`,z.card.classList.add(`swiping`);else if(e===`pass`)return void(z.mode=`pass`);else z.mode=`drag`,Q()}e.preventDefault();let i=performance.now();if(z.v=(t.clientX-z.last)/Math.max(1,i-z.at),[z.last,z.at]=[t.clientX,i],z.mode!==`card`)return X(z.base+n);let a=Math.max(0,n);z.card.style.setProperty(`--sx`,`${a}px`),z.card.style.setProperty(`--so`,String(1-a/z.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`),c({key:e.parentElement.dataset.key}).then(t=>t||e.classList.remove(`gone`)))},$=e=>{let t=z;z=void 0,t?.mode===`drag`&&Z(P(I,L,t.v)),t?.mode===`card`&&re(t.card,e.type===`touchend`&&P(Math.max(0,t.last-t.x0),t.card.offsetWidth,t.v))};return document.addEventListener(`touchend`,$),document.addEventListener(`touchcancel`,$),O.addEventListener(`click`,()=>Z(!1)),D.addEventListener(`click`,e=>e.target.closest(`a[data-route], button[data-open], .x`)&&Z(!1)),document.addEventListener(`keydown`,e=>M&&e.key===`Escape`&&(e.preventDefault(),Z(!1)),!0),document.addEventListener(`sb-drawer`,()=>(M||Q(),Z(!M))),{net(e){k=e,M&&Y()},route(e){A=e.view===`session`?e.key:void 0,j=e.view===`head`||e.view===`session`&&e.ws===`@head`,p.toggleAttribute(`aria-current`,e.view===`map`),M&&Y()}}}export{Y as mountDrawer};