pi-roundtable-web 0.26.0 → 0.26.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. package/CHANGELOG.md +50 -0
  2. package/README.md +32 -12
  3. package/dist/chunk-account-nhpd9j90.js +1 -0
  4. package/dist/chunk-action-menu-ec9jqtxq.js +1 -0
  5. package/dist/chunk-agent-d1xfrawq.js +1 -0
  6. package/dist/chunk-arranged-rooms-bga8yk2v.js +1 -0
  7. package/dist/chunk-character-creator-k67f77w5.js +1 -0
  8. package/dist/chunk-codeeditor-jm2sm333.js +2 -0
  9. package/dist/chunk-confirm-wc5xraev.js +1 -0
  10. package/dist/chunk-connectors-mhnw6d79.js +1 -0
  11. package/dist/chunk-conversations-yjyq4g1y.js +1 -0
  12. package/dist/{chunk-drag-v41gx2mc.js → chunk-drag-nyq52ck7.js} +1 -1
  13. package/dist/chunk-entry-red1597w.js +1 -0
  14. package/dist/chunk-folder-list-x56y26yq.js +1 -0
  15. package/dist/chunk-folds-3p7s2nvx.js +1 -0
  16. package/dist/{chunk-gate-8k61stsc.js → chunk-gate-h41bv4y9.js} +1 -1
  17. package/dist/chunk-group-scene-7eb6jyev.js +1 -0
  18. package/dist/chunk-group-table-rca48kt0.js +1 -0
  19. package/dist/chunk-host-icons-x318gjqp.js +1 -0
  20. package/dist/chunk-host-picture-xswcakgy.js +1 -0
  21. package/dist/chunk-host-state-bpahvk54.js +1 -0
  22. package/dist/chunk-host-ui-tsbwwk38.js +1 -0
  23. package/dist/{chunk-index-hby0ap91.js → chunk-index-029209sy.js} +2 -2
  24. package/dist/chunk-index-066vzexw.js +2 -0
  25. package/dist/chunk-index-0h4h76kw.js +2 -0
  26. package/dist/chunk-index-0n6ja7my.js +1 -0
  27. package/dist/chunk-index-0q15ysrb.js +1 -0
  28. package/dist/chunk-index-0xj30mzw.js +13 -0
  29. package/dist/{chunk-index-rhtvcbsq.js → chunk-index-1f0j335v.js} +2 -2
  30. package/dist/chunk-index-2f5nfekb.js +8 -0
  31. package/dist/chunk-index-31ays46f.js +2 -0
  32. package/dist/chunk-index-43k1rjmx.js +2 -0
  33. package/dist/chunk-index-4gk88a0x.js +4 -0
  34. package/dist/chunk-index-4jf4jvfd.css +1 -0
  35. package/dist/chunk-index-4mf29sbx.js +2 -0
  36. package/dist/chunk-index-51n20yhb.js +2 -0
  37. package/dist/{chunk-index-014rjv9k.js → chunk-index-6tpr6r6d.js} +2 -2
  38. package/dist/{chunk-index-e5sd30xy.js → chunk-index-7bbqtdce.js} +2 -2
  39. package/dist/chunk-index-84v7j6vh.js +50 -0
  40. package/dist/chunk-index-8f9jer8r.js +2 -0
  41. package/dist/chunk-index-91z3g774.js +1 -0
  42. package/dist/{chunk-index-dhpt8qr9.js → chunk-index-934zgd18.js} +2 -2
  43. package/dist/{chunk-index-awx6nnta.js → chunk-index-9nents16.js} +2 -2
  44. package/dist/chunk-index-9w0sar6s.js +2 -0
  45. package/dist/chunk-index-a768zmp6.js +2 -0
  46. package/dist/{chunk-index-nqfkwkfp.js → chunk-index-b7jjca66.js} +2 -2
  47. package/dist/chunk-index-c5x70d9g.js +2 -0
  48. package/dist/chunk-index-cmxs5y22.js +42 -0
  49. package/dist/chunk-index-cwc1vvpw.js +2 -0
  50. package/dist/chunk-index-d85x96q0.js +2 -0
  51. package/dist/chunk-index-datrrs6b.js +2 -0
  52. package/dist/chunk-index-dep2e3f3.js +2 -0
  53. package/dist/chunk-index-dtste2ed.js +2 -0
  54. package/dist/chunk-index-ewj52be9.js +2 -0
  55. package/dist/{chunk-index-pcfhpm8v.js → chunk-index-f3b5nch2.js} +142 -18
  56. package/dist/{chunk-index-km40bhsz.js → chunk-index-frwa2fmc.js} +2 -2
  57. package/dist/chunk-index-grkczq2c.js +2 -0
  58. package/dist/chunk-index-gzvkpe3e.js +2 -0
  59. package/dist/chunk-index-kfv996qe.js +920 -0
  60. package/dist/chunk-index-kw85ajap.js +138 -0
  61. package/dist/chunk-index-satam151.js +2 -0
  62. package/dist/{chunk-index-y8rnq8zf.js → chunk-index-smw1n2pt.js} +5 -5
  63. package/dist/chunk-index-th43f690.js +2 -0
  64. package/dist/chunk-index-ths2hxpe.js +1 -0
  65. package/dist/{chunk-index-wnjp6wv0.js → chunk-index-tmx30r1w.js} +2 -2
  66. package/dist/{chunk-index-hssjbr1k.js → chunk-index-y00wke93.js} +2 -2
  67. package/dist/chunk-index-y4sqmenv.js +2 -0
  68. package/dist/{chunk-index-66nskrdj.js → chunk-index-yrhbhmxz.js} +2 -2
  69. package/dist/chunk-index-zd76pr2k.js +2 -0
  70. package/dist/chunk-lang-css-fa7c0zfj.js +1 -0
  71. package/dist/{chunk-lang-dockerfile-hrav55t7.js → chunk-lang-dockerfile-46rk929v.js} +1 -1
  72. package/dist/{chunk-lang-go-x9ahv6e5.js → chunk-lang-go-qb0qdpg7.js} +3 -3
  73. package/dist/chunk-lang-html-47mf2y0v.js +1 -0
  74. package/dist/chunk-lang-javascript-d32qrvxz.js +1 -0
  75. package/dist/{chunk-lang-json-hsemyd0r.js → chunk-lang-json-1q4fp694.js} +1 -1
  76. package/dist/{chunk-lang-markdown-zkwb4c9n.js → chunk-lang-markdown-5w7t28wa.js} +4 -4
  77. package/dist/{chunk-lang-python-tewx7006.js → chunk-lang-python-3dq0p4rf.js} +2 -2
  78. package/dist/{chunk-lang-rust-0ydx84s1.js → chunk-lang-rust-70pa0agr.js} +1 -1
  79. package/dist/{chunk-lang-shell-gq1tmdz4.js → chunk-lang-shell-4pxt7hf4.js} +1 -1
  80. package/dist/{chunk-lang-sql-xt1qyycg.js → chunk-lang-sql-kgcbh2a9.js} +2 -2
  81. package/dist/{chunk-lang-toml-0hamc5fc.js → chunk-lang-toml-99t95pab.js} +1 -1
  82. package/dist/chunk-lang-typescript-4k1d8z7s.js +1 -0
  83. package/dist/{chunk-lang-xml-wf6h5pt2.js → chunk-lang-xml-mnbv9yfa.js} +1 -1
  84. package/dist/{chunk-lang-yaml-7vk521h1.js → chunk-lang-yaml-2by9g1dy.js} +1 -1
  85. package/dist/chunk-layout-actions-cgghzj1w.js +1 -0
  86. package/dist/chunk-menu-items-24cfwawa.js +2 -0
  87. package/dist/chunk-mode-toggle-v4baz3r1.js +1 -0
  88. package/dist/chunk-note-row-72n6cqyk.js +75 -0
  89. package/dist/chunk-notes-83s3tsey.js +1 -0
  90. package/dist/chunk-notice-bell-a4ty5h1p.js +1 -0
  91. package/dist/chunk-notices-evny44be.js +1 -0
  92. package/dist/chunk-onboarding-q1avjbrx.js +1 -0
  93. package/dist/chunk-overview-42h45ehd.js +1 -0
  94. package/dist/chunk-palette-e44qepmh.js +1 -0
  95. package/dist/chunk-placement-items-v466t0sv.js +1 -0
  96. package/dist/chunk-profile-bqcgkgk4.js +1 -0
  97. package/dist/chunk-prompt-history-hgbtcn4b.js +1 -0
  98. package/dist/chunk-prompts-czs8y6r1.js +1 -0
  99. package/dist/chunk-room-confirms-h8cdj3ng.js +1 -0
  100. package/dist/chunk-room-menu-7s0feajw.js +1 -0
  101. package/dist/chunk-rooms-menu-button-gawqvpsr.js +1 -0
  102. package/dist/{chunk-schedules-2ft6xxyw.js → chunk-schedules-zba7krac.js} +1 -1
  103. package/dist/{chunk-seat-menu-d3npdtx1.js → chunk-seat-menu-ca5p4e9q.js} +1 -1
  104. package/dist/chunk-sheet-hosts-ssbz6hf2.js +1 -0
  105. package/dist/chunk-skill-editor-n0y9pd90.js +8 -0
  106. package/dist/chunk-skills-ea4vb2s4.js +1 -0
  107. package/dist/chunk-switcher-list-pj5csqr9.js +1 -0
  108. package/dist/chunk-tab-dot-4tkpxqeh.js +1 -0
  109. package/dist/chunk-table-j8nmtdnn.js +1 -0
  110. package/dist/chunk-table-seats-qeytqe0m.js +1 -0
  111. package/dist/chunk-table2d-18y029k9.js +1 -0
  112. package/dist/chunk-table3d-q2s31ae0.js +4220 -0
  113. package/dist/chunk-thread-actions-w3eadnh7.js +1 -0
  114. package/dist/chunk-thread-cards-fbpky3c9.js +1 -0
  115. package/dist/chunk-thread-list-pghe84be.js +1 -0
  116. package/dist/chunk-transcript-eqzxgqys.js +1 -0
  117. package/dist/chunk-where-ygyr4jdj.js +1 -0
  118. package/dist/chunk-workspace-h0p32ygy.js +578 -0
  119. package/dist/chunk-zh-tw-k6xx1hp2.js +1 -0
  120. package/dist/index.html +1 -2
  121. package/dist/sw.js +1 -1
  122. package/package.json +2 -2
  123. package/src/api-types.ts +63 -3
  124. package/src/app/api-http.ts +1 -1
  125. package/src/app/app.ts +5 -0
  126. package/src/app/room-log.ts +16 -4
  127. package/src/app/rooms.ts +39 -0
  128. package/src/app/routes.ts +96 -2
  129. package/src/app/socket.ts +45 -9
  130. package/src/app/surface-threads.ts +1 -1
  131. package/src/app/surface.ts +2 -1
  132. package/src/app/threads.ts +51 -2
  133. package/src/auth/authenticator.ts +18 -5
  134. package/src/auth/login-page.ts +4 -2
  135. package/src/auth/oidc-pages.ts +2 -0
  136. package/src/auth/oidc.ts +39 -1
  137. package/src/auth/sessions.ts +10 -3
  138. package/src/authz.ts +2 -1
  139. package/src/console-server.ts +32 -6
  140. package/src/host/cards.ts +18 -5
  141. package/src/host/context.ts +72 -25
  142. package/src/host/forms.ts +3 -0
  143. package/src/host/frames.ts +8 -1
  144. package/src/host/host-app.ts +6 -4
  145. package/src/host/host-routes.ts +36 -3
  146. package/src/host/room-views.ts +6 -6
  147. package/src/host/rooms-service.ts +16 -1
  148. package/src/host/views.ts +3 -0
  149. package/src/i18n/zh-tw.ts +103 -79
  150. package/src/index.ts +15 -1
  151. package/src/options.ts +37 -1
  152. package/src/page-presentation.ts +47 -2
  153. package/src/pwa.ts +32 -4
  154. package/src/web-app.ts +47 -3
  155. package/src/web-plugin.ts +32 -10
  156. package/dist/chunk-account-hw49gd0d.js +0 -1
  157. package/dist/chunk-action-menu-rm5cyqkj.js +0 -1
  158. package/dist/chunk-agent-b017vswv.js +0 -1
  159. package/dist/chunk-arranged-rooms-q5v3dm1r.js +0 -1
  160. package/dist/chunk-character-creator-5dxcvd16.js +0 -1
  161. package/dist/chunk-codeeditor-pyt09fwg.js +0 -2
  162. package/dist/chunk-confirm-521yqmta.js +0 -1
  163. package/dist/chunk-connectors-hrm06nx8.js +0 -1
  164. package/dist/chunk-conversations-e26rrf01.js +0 -1
  165. package/dist/chunk-entry-jxxb3ath.js +0 -1
  166. package/dist/chunk-folder-list-b97xk12b.js +0 -1
  167. package/dist/chunk-folds-b8q7eags.js +0 -1
  168. package/dist/chunk-group-scene-dx6wt19m.js +0 -1
  169. package/dist/chunk-group-table-e4jr8r3a.js +0 -1
  170. package/dist/chunk-host-state-g7e7c0k5.js +0 -1
  171. package/dist/chunk-host-ui-x7k6n07v.js +0 -939
  172. package/dist/chunk-index-2d0kg096.js +0 -2
  173. package/dist/chunk-index-2qd81wbx.js +0 -2
  174. package/dist/chunk-index-2stynxw6.css +0 -1
  175. package/dist/chunk-index-459drsft.js +0 -2
  176. package/dist/chunk-index-4mfj596y.js +0 -2
  177. package/dist/chunk-index-bbsytycb.js +0 -2
  178. package/dist/chunk-index-c07p8k0x.js +0 -4
  179. package/dist/chunk-index-cq1e9xdz.js +0 -2
  180. package/dist/chunk-index-d1prgfbp.js +0 -2
  181. package/dist/chunk-index-g351921r.js +0 -1
  182. package/dist/chunk-index-k2qq1gdj.js +0 -2
  183. package/dist/chunk-index-ke9ynm0n.js +0 -2
  184. package/dist/chunk-index-kpscvg85.js +0 -2
  185. package/dist/chunk-index-m0d100mg.js +0 -2
  186. package/dist/chunk-index-mb72snk9.js +0 -2
  187. package/dist/chunk-index-mjqqver5.js +0 -4
  188. package/dist/chunk-index-nwqk447w.js +0 -2
  189. package/dist/chunk-index-q8h8xzbm.js +0 -2
  190. package/dist/chunk-index-r5vszgfs.js +0 -2
  191. package/dist/chunk-index-rjv7vrwd.js +0 -13
  192. package/dist/chunk-index-v23m38p6.js +0 -50
  193. package/dist/chunk-index-va0g7d88.js +0 -1
  194. package/dist/chunk-index-xgkd15n3.js +0 -2
  195. package/dist/chunk-index-z3k18atc.js +0 -2
  196. package/dist/chunk-lang-css-6bepqpnx.js +0 -1
  197. package/dist/chunk-lang-html-8jc72zt4.js +0 -1
  198. package/dist/chunk-lang-javascript-2p2qtbnf.js +0 -1
  199. package/dist/chunk-lang-typescript-82xf7z2e.js +0 -1
  200. package/dist/chunk-layout-actions-zh7bezk7.js +0 -1
  201. package/dist/chunk-menu-items-1n9qargb.js +0 -2
  202. package/dist/chunk-notes-t15bh04m.js +0 -1
  203. package/dist/chunk-notice-bell-w3y0h0sr.js +0 -1
  204. package/dist/chunk-notices-fa3g7qze.js +0 -1
  205. package/dist/chunk-onboarding-34v3nr17.js +0 -1
  206. package/dist/chunk-overview-km5vq375.js +0 -1
  207. package/dist/chunk-palette-a8txdgd0.js +0 -1
  208. package/dist/chunk-placement-items-wgaxsbvs.js +0 -1
  209. package/dist/chunk-profile-ypxdbsk1.js +0 -1
  210. package/dist/chunk-prompt-history-wm9dsy6s.js +0 -1
  211. package/dist/chunk-prompts-7mhhq7zs.js +0 -1
  212. package/dist/chunk-room-confirms-t11a1gsw.js +0 -1
  213. package/dist/chunk-room-menu-2tm2xtfx.js +0 -1
  214. package/dist/chunk-rooms-menu-button-wxnsxjwc.js +0 -1
  215. package/dist/chunk-sheet-hosts-vngvp7wv.js +0 -1
  216. package/dist/chunk-skill-editor-65n2hsq4.js +0 -8
  217. package/dist/chunk-skills-shkdwes8.js +0 -1
  218. package/dist/chunk-switcher-list-g6hhmr1t.js +0 -1
  219. package/dist/chunk-table-1b6bsq2y.js +0 -1
  220. package/dist/chunk-table-seats-vy1qhdks.js +0 -1
  221. package/dist/chunk-table2d-n26b7gd0.js +0 -1
  222. package/dist/chunk-table3d-8aysyf56.js +0 -4220
  223. package/dist/chunk-transcript-355faceq.js +0 -1
  224. package/dist/chunk-where-j5qdt8a4.js +0 -1
  225. package/dist/chunk-workspace-vrbs6zx1.js +0 -1
  226. package/dist/chunk-zh-tw-zeg600bk.js +0 -1
package/src/i18n/zh-tw.ts CHANGED
@@ -34,7 +34,7 @@ export const ZH_TW: Readonly<Record<string, string>> = {
34
34
  "binary file": "二進位檔",
35
35
  "too large": "檔案太大",
36
36
  "not UTF-8": "不是 UTF-8",
37
- "Agents' workspace": "夥伴工作區",
37
+ "Knights' workspace": "騎士工作區",
38
38
  Scratch: "暫存區",
39
39
  Path: "路徑",
40
40
  "This folder is empty": "這個資料夾是空的",
@@ -59,7 +59,7 @@ export const ZH_TW: Readonly<Record<string, string>> = {
59
59
  "Read only: {reason}": "唯讀:{reason}",
60
60
  "File menu": "檔案選單",
61
61
  "This file is gone": "這個檔案已經不見了",
62
- "A partner is changing this file": "夥伴正在改這個檔案",
62
+ "A knight is changing this file": "騎士正在改這個檔案",
63
63
  "Reload (discard my edits)": "重新載入(放棄我的修改)",
64
64
  "This file is too large to show here.": "這個檔案太大,無法在這裡顯示。",
65
65
  "This file is not text, so it cannot be shown here.":
@@ -82,7 +82,7 @@ export const ZH_TW: Readonly<Record<string, string>> = {
82
82
  "Copy my text": "複製我的內容",
83
83
  "Save mine as a new file": "存成新檔案",
84
84
  "Save mine anyway": "仍用我的版本覆蓋",
85
- "Replace the partner's changes?": "要蓋掉夥伴的修改嗎?",
85
+ "Replace the knight's changes?": "要蓋掉騎士的修改嗎?",
86
86
  "The file has been changed since you opened it. Saving yours writes over those changes.":
87
87
  "你開啟後,這個檔案又被改過。存下你的版本會蓋掉那些修改。",
88
88
  "Unsaved changes, leave?": "還沒存檔,要離開嗎?",
@@ -257,7 +257,6 @@ export const ZH_TW: Readonly<Record<string, string>> = {
257
257
  "Yolo mode on": "Yolo 模式已開啟",
258
258
 
259
259
  // 命令面板
260
- Agent: "夥伴",
261
260
  "Find a room or page": "尋找聊天室或頁面",
262
261
  "Nothing matches.": "沒有符合的項目。",
263
262
  Page: "頁面",
@@ -280,18 +279,19 @@ export const ZH_TW: Readonly<Record<string, string>> = {
280
279
  "讓回合可超過時間上限繼續進行,最多到主機設定的上限。提問仍會等你回應。",
281
280
  "Long-running mode": "長時間執行模式",
282
281
  "Name, prompt, model and picture": "名稱、提示詞、模型與圖像",
283
- "Reply to the agent that started this thread.": "回覆開啟這個討論串的夥伴。",
282
+ "Reply to the knight that started this thread.": "回覆開啟這個討論串的騎士。",
284
283
  "Yolo mode": "Yolo 模式",
285
- "No agents are seated yet.": "圓桌上還沒有夥伴入座。",
284
+ "No knights are seated yet.": "圓桌上還沒有騎士入座。",
286
285
  "Who's at the table": "誰上桌",
287
286
  "Off the table": "離席中",
288
287
  "Leave the table": "離席",
289
288
  "{name} left the table": "{name}已離席",
290
289
  "The table is empty": "圓桌空了",
291
- "Every agent has left the table. Choose who sits down.":
292
- "所有夥伴都離席了。選擇誰要上桌。",
293
- "An agent who leaves the table is muted: its room stops pushing to you. A card that waits for you is always pushed.":
294
- "離席的夥伴會被靜音:它的聊天室不再推播給你。等你回應的卡片仍會推播。",
290
+ "There are no rooms to seat yet.": "還沒有可以入座的聊天室。",
291
+ "Every knight has left the table. Choose who sits down.":
292
+ "所有騎士都離席了。選擇誰要上桌。",
293
+ "A knight who leaves the table is muted: its room stops pushing to you. A card that waits for you is always pushed.":
294
+ "離席的騎士會被靜音:它的聊天室不再推播給你。等你回應的卡片仍會推播。",
295
295
 
296
296
  // 通知
297
297
  "A file is no longer available. Attach it again.":
@@ -327,11 +327,13 @@ export const ZH_TW: Readonly<Record<string, string>> = {
327
327
  Today: "今天",
328
328
  Yesterday: "昨天",
329
329
 
330
- // 夥伴
330
+ // 騎士
331
331
  "Class, colors and parts. The picture here, in the rooms and in Discord all follow it.":
332
332
  "職業、配色與部件。這裡、聊天室與 Discord 的圖像都會跟著改變。",
333
- "Follow the assistant (automatic)": "跟隨夥伴(自動)",
334
- "Follow the assistant": "跟隨夥伴",
333
+ Default: "預設",
334
+ "Default model": "預設模型",
335
+ "Default model ({current})": "預設模型({current})",
336
+ "Default model (server setting)": "預設模型(跟著伺服器設定)",
335
337
  Look: "造型",
336
338
  Name: "名稱",
337
339
  Prompt: "提示詞",
@@ -349,8 +351,8 @@ export const ZH_TW: Readonly<Record<string, string>> = {
349
351
  "Tool list": "工具清單",
350
352
  Unreachable: "無法連線",
351
353
  "Upstream gateways": "上游閘道",
352
- "Upstream MCP gateways and virtual servers used by the assistant.":
353
- "夥伴使用的上游 MCP 閘道與虛擬伺服器。",
354
+ "Upstream MCP gateways and virtual servers used by the knights.":
355
+ "騎士使用的上游 MCP 閘道與虛擬伺服器。",
354
356
  "Used by": "使用者",
355
357
  "Virtual servers": "虛擬伺服器",
356
358
 
@@ -360,15 +362,15 @@ export const ZH_TW: Readonly<Record<string, string>> = {
360
362
  "None stored.": "沒有儲存的內容。",
361
363
  running: "進行中",
362
364
  "Owner channels": "擁有者頻道",
363
- "Direct messages and channels where the owner talks to the assistant.":
364
- "擁有者與夥伴交談的私訊與頻道。",
365
- "Agent channels": "夥伴頻道",
366
- "The agent server's one-to-one channels.": "夥伴伺服器的一對一頻道。",
365
+ "Direct messages and channels where the owner talks to a knight.":
366
+ "擁有者與騎士交談的私訊與頻道。",
367
+ "Bot server channels": "Bot 伺服器頻道",
368
+ "The bot server's one-to-one channels.": "Bot 伺服器的一對一頻道。",
367
369
  "Group channels": "群組頻道",
368
- "The agent server's group channels.": "夥伴伺服器的群組頻道。",
369
- "Outside agents": "外部夥伴",
370
- "Conversations an agent outside Discord holds over MCP.":
371
- "Discord 以外的夥伴透過 MCP 進行的對話。",
370
+ "The bot server's group channels.": "Bot 伺服器的群組頻道。",
371
+ "Outside AI clients": "外部 AI 用戶端",
372
+ "Conversations an outside AI client holds over MCP.":
373
+ "Discord 以外的 AI 用戶端透過 MCP 進行的對話。",
372
374
  "Plugin conversations": "外掛對話",
373
375
  "Conversations a plugin runs, such as a web chat, as the host recorded them.":
374
376
  "外掛(例如網頁聊天)進行的對話,內容為主機所記錄。",
@@ -397,28 +399,28 @@ export const ZH_TW: Readonly<Record<string, string>> = {
397
399
  "Search (words separated by spaces)": "搜尋(以空格分隔關鍵字)",
398
400
  "Search notes": "搜尋記憶",
399
401
  Text: "內容",
400
- "What the assistant remembers. A change applies from the next turn.":
401
- "夥伴記得的內容。變更會從下一個回合起生效。",
402
+ "What a knight remembers. A change applies from the next turn.":
403
+ "騎士記得的內容。變更會從下一個回合起生效。",
402
404
  "Whose notes": "誰的記憶",
403
405
  Core: "核心",
404
406
  "Carried into every turn.": "每個回合都會帶入。",
405
407
  Note: "備忘",
406
- "Searched when the assistant needs them.": "夥伴需要時才會搜尋。",
408
+ "Searched when a knight needs them.": "騎士需要時才會搜尋。",
407
409
  Events: "事件",
408
410
  "Carried into every turn until their date.": "到期日之前每個回合都會帶入。",
409
411
 
410
412
  // 總覽
411
413
  "(No messages)": "(沒有訊息)",
412
414
  "{count} waiting": "{count} 項等待中",
413
- "Agent and group status; starting over archives the conversation and preserves memory.":
414
- "夥伴與群組的狀態;重新開始會封存對話並保留記憶。",
415
- "Agent server": "夥伴伺服器",
415
+ "Knight and group status; starting over archives the conversation and preserves memory.":
416
+ "騎士與群組的狀態;重新開始會封存對話並保留記憶。",
417
+ "Bot server": "Bot 伺服器",
416
418
  Context: "上下文",
417
419
  "Conversation {size} · Archives {count}": "對話 {size} · 封存 {count} 筆",
418
420
  "Conversations opened through remote MCP; after deletion the session ID cannot be resumed.":
419
421
  "透過遠端 MCP 開啟的對話;刪除後無法再用該工作階段 ID 接續。",
420
- "Direct messages and channels where you mention the assistant. Start over archives; delete removes every archive permanently.":
421
- "你在私訊與頻道中提及夥伴的對話。重新開始會封存;刪除會永久移除所有封存。",
422
+ "Direct messages and channels where you mention a knight. Start over archives; delete removes every archive permanently.":
423
+ "你在私訊與頻道中提及騎士的對話。重新開始會封存;刪除會永久移除所有封存。",
422
424
  "Enabled by {name} at {time}": "由{name}於 {time} 啟用",
423
425
  idle: "閒置",
424
426
  "Just compacted (limit {limit})": "剛完成壓縮(上限 {limit})",
@@ -426,13 +428,13 @@ export const ZH_TW: Readonly<Record<string, string>> = {
426
428
  "Members: {members} | Host: {host}": "成員:{members}|主持:{host}",
427
429
  Model: "模型",
428
430
  "My workspaces": "我的工作區",
429
- "No agents.": "沒有夥伴。",
431
+ "No knights.": "沒有騎士。",
430
432
  "No live conversation · Archives {count}":
431
433
  "沒有進行中的對話 · 封存 {count} 筆",
432
- "No outside-agent conversations.": "沒有外部夥伴的對話。",
434
+ "No outside AI client conversations.": "沒有外部 AI 用戶端的對話。",
433
435
  "No party channels.": "沒有派對頻道。",
434
436
  "No workspaces.": "沒有工作區。",
435
- "Outside-agent conversations": "外部夥伴的對話",
437
+ "Outside AI client conversations": "外部 AI 用戶端的對話",
436
438
  "Party channels": "派對頻道",
437
439
  "Replying in {name}'s channel": "正在{name}的頻道中回覆",
438
440
  "Replying in another channel": "正在其他頻道中回覆",
@@ -451,8 +453,8 @@ export const ZH_TW: Readonly<Record<string, string>> = {
451
453
  "Back to rooms": "回到聊天室列表",
452
454
  "Every approval it makes is written into the conversation, and a banner stays up while yolo mode is on.":
453
455
  "它做的每一次核准都會寫進對話,而且 Yolo 模式開啟期間會一直顯示橫幅。",
454
- "In this room, the agent's held actions are approved for you, without a card, as soon as they come up.":
455
- "在這個聊天室中,夥伴保留的操作一出現就會替你核准,不會顯示卡片。",
456
+ "In this room, the knight's held actions are approved for you, without a card, as soon as they come up.":
457
+ "在這個聊天室中,騎士保留的操作一出現就會替你核准,不會顯示卡片。",
456
458
  Latest: "最新",
457
459
  "Load earlier messages": "載入更早的訊息",
458
460
  "Loading…": "載入中…",
@@ -478,7 +480,7 @@ export const ZH_TW: Readonly<Record<string, string>> = {
478
480
  "Working…": "處理中…",
479
481
 
480
482
  // 長按與右鍵選單
481
- "Edit agent": "編輯夥伴",
483
+ "Edit knight": "編輯騎士",
482
484
  "Change look": "換外觀",
483
485
  "Notifications are off": "通知已關閉",
484
486
  "Notifications are on for {name}": "已開啟{name}的通知",
@@ -502,27 +504,27 @@ export const ZH_TW: Readonly<Record<string, string>> = {
502
504
  "Quote reply": "引用回覆",
503
505
  "Select text": "選取文字",
504
506
  Share: "分享",
505
- "Agent profile": "夥伴資料",
507
+ "Knight profile": "騎士資料",
506
508
  "Copy details": "複製細節",
507
509
  Download: "下載",
508
510
  "Could not copy.": "無法複製。",
509
511
  "Could not share.": "無法分享。",
510
512
 
511
513
  // 新增、封存與群組
512
- "New agent": "新增夥伴",
514
+ "New knight": "新增騎士",
513
515
  "New group": "新增群組",
514
516
  Archived: "已封存",
515
517
  Archive: "封存",
516
518
  "Archive {name}": "封存{name}",
517
519
  "Archive {name}?": "要封存{name}嗎?",
518
- "Archive agent": "封存夥伴",
520
+ "Archive knight": "封存騎士",
519
521
  "Archive group": "封存群組",
520
522
  "Archived {name}.": "已封存{name}。",
521
523
  "Restored {name}.": "已還原{name}。",
522
524
  "Deleted {name}.": "已刪除{name}。",
523
525
  "Delete {name}?": "要刪除{name}嗎?",
524
526
  "Made {name}.": "已建立{name}。",
525
- "Make agent": "建立夥伴",
527
+ "Make knight": "建立騎士",
526
528
  "Make group": "建立群組",
527
529
  "Making…": "建立中…",
528
530
  "Permanent name": "固定名稱",
@@ -531,8 +533,8 @@ export const ZH_TW: Readonly<Record<string, string>> = {
531
533
  "Its job, its sources, its limits and how it reports.":
532
534
  "它的工作、資料來源、限制,以及怎麼回報。",
533
535
  "Opening task": "開場任務",
534
- "Optional. The agent starts on it as soon as it is made.":
535
- "可不填。夥伴建立後會立刻開始做。",
536
+ "Optional. The knight starts on it as soon as it is made.":
537
+ "可不填。騎士建立後會立刻開始做。",
536
538
  "Your look": "你選的外觀",
537
539
  "Suggested from its role": "依角色建議的外觀",
538
540
  "Choose a look": "選擇外觀",
@@ -540,31 +542,31 @@ export const ZH_TW: Readonly<Record<string, string>> = {
540
542
  "Edit group": "編輯群組",
541
543
  "Name, members and host": "名稱、成員與主持人",
542
544
  Members: "成員",
543
- "Pick 2 to 6 agents. They take turns in the order picked.":
544
- "選 2 到 6 位夥伴。他們依選取的順序輪流發言。",
545
+ "Pick 2 to 6 knights. They take turns in the order picked.":
546
+ "選 2 到 6 位騎士。他們依選取的順序輪流發言。",
545
547
  Host: "主持人",
546
548
  "It stops answering. The history is kept and it can be restored.":
547
549
  "它會停止回應。歷史會保留,之後可以還原。",
548
- "An archived agent stops answering and its schedules are cancelled. Its history is kept, and you can restore it from Archived.":
549
- "封存後的夥伴不再回應,排程也會取消。歷史會保留,之後可以從「已封存」還原。",
550
+ "An archived knight stops answering and its schedules are cancelled. Its history is kept, and you can restore it from Archived.":
551
+ "封存後的騎士不再回應,排程也會取消。歷史會保留,之後可以從「已封存」還原。",
550
552
  "{name} stops answering and its schedules are cancelled. A group loses it as a member. The history is kept, and Archived in the room list restores it.":
551
553
  "{name}會停止回應,排程也會取消;群組會少掉這位成員。歷史會保留,可以從聊天室列表的「已封存」還原。",
552
- "Archived agents and groups no longer answer. Their history is kept until you delete them.":
553
- "已封存的夥伴與群組不再回應。歷史會保留,直到你刪除它們。",
554
+ "Archived knights and groups no longer answer. Their history is kept until you delete them.":
555
+ "已封存的騎士與群組不再回應。歷史會保留,直到你刪除它們。",
554
556
  "Nothing is archived.": "沒有已封存的項目。",
555
557
  "{name} and its messages in this app are deleted for good, and the name can be used again. This cannot be undone.":
556
558
  "{name}和它在這個應用程式裡的訊息會永久刪除,名稱可以再使用。此動作無法復原。",
557
- "What the agent can load when a task calls for it. It applies from its next turn.":
558
- "夥伴在任務需要時可以載入的技能。下一輪對話起生效。",
559
+ "What the knight can load when a task calls for it. It applies from its next turn.":
560
+ "騎士在任務需要時可以載入的技能。下一輪對話起生效。",
559
561
  "Its file cannot be read.": "讀不到它的檔案。",
560
- "Built in: every agent carries it.": "內建:每位夥伴都有。",
562
+ "Built in: every knight carries it.": "內建:每位騎士都有。",
561
563
  "This host has no skills.": "這個主機沒有技能。",
562
564
  "Give add or remove.": "請給 add 或 remove。",
563
565
  "members must be a list of text.": "members 必須是文字清單。",
564
566
  "Give displayName, members or host.": "請給 displayName、members 或 host。",
565
567
 
566
568
  // 聊天室列表
567
- Agents: "夥伴",
569
+ Knights: "騎士",
568
570
  "Dispatch threads": "派工討論串",
569
571
  "Find a room": "尋找聊天室",
570
572
  "Switch rooms": "切換聊天室",
@@ -573,13 +575,30 @@ export const ZH_TW: Readonly<Record<string, string>> = {
573
575
  Home: "首頁",
574
576
  "Long-running": "長時間執行",
575
577
  "No messages yet": "還沒有訊息",
576
- "No rooms yet. Rooms appear when the team has an agent.":
577
- "還沒有聊天室。團隊有夥伴後,聊天室就會出現。",
578
+ "No rooms yet. Rooms appear when the team has a knight.":
579
+ "還沒有聊天室。團隊有騎士後,聊天室就會出現。",
578
580
  Yolo: "Yolo",
579
581
  "{count} card waiting": "{count} 張卡片等待中",
580
582
  "{count} cards waiting": "{count} 張卡片等待中",
581
583
  "{count} finished thread": "{count} 個已結束的討論串",
582
584
  "{count} finished threads": "{count} 個已結束的討論串",
585
+ Clear: "清除",
586
+ "Clear this thread": "清除這則",
587
+ "Clear all finished": "清除所有已完成",
588
+ "Clear finished": "清除已完成",
589
+ Finished: "已完成",
590
+ "In progress": "進行中",
591
+ "More actions for {name}": "{name} 的更多動作",
592
+ "Cleared “{name}”": "已清除「{name}」",
593
+ "Cleared {count} finished thread": "已清除 {count} 個已完成的討論串",
594
+ "Cleared {count} finished threads": "已清除 {count} 個已完成的討論串",
595
+ "Clear {count} finished thread?": "清除 {count} 個已完成的討論串?",
596
+ "Clear {count} finished threads?": "清除 {count} 個已完成的討論串?",
597
+ "They leave the list for every owner. Each one stays readable by its address, and Undo brings them back.":
598
+ "這些討論串會從所有擁有者的列表中消失,仍可用網址讀取,按「復原」就會回來。",
599
+ "The thread is still open.": "這個討論串還在進行中。",
600
+ "threads must be a list of at most 100 keys.":
601
+ "threads 必須是最多 100 個鍵的清單。",
583
602
 
584
603
  // 排程
585
604
  "{days} at {time}": "每{days} {time}",
@@ -591,8 +610,8 @@ export const ZH_TW: Readonly<Record<string, string>> = {
591
610
  "Every {count} days at {time}": "每 {count} 天 {time}",
592
611
  "Every day at {time}": "每天 {time}",
593
612
  "next {when}": "下次:{when}",
594
- "Nothing is scheduled. Ask an agent to remind you or to run something later.":
595
- "目前沒有排程。你可以請夥伴提醒你,或稍後執行某件事。",
613
+ "Nothing is scheduled. Ask a knight to remind you or to run something later.":
614
+ "目前沒有排程。你可以請騎士提醒你,或稍後執行某件事。",
596
615
  "Once on {date} at {time}": "{date} {time}(僅一次)",
597
616
  "Schedule cancelled.": "排程已取消。",
598
617
  "set by {name}": "由{name}設定",
@@ -610,8 +629,8 @@ export const ZH_TW: Readonly<Record<string, string>> = {
610
629
  Appearance: "外觀",
611
630
  "Color scheme": "色彩配置",
612
631
  Device: "裝置",
613
- "Get a notification on this device when a card waits for you or an agent reports on its own, while the app is not open.":
614
- "應用程式未開啟時,只要有卡片等你處理,或夥伴主動回報,這台裝置就會收到通知。",
632
+ "Get a notification on this device when a card waits for you or a knight reports on its own, while the app is not open.":
633
+ "應用程式未開啟時,只要有卡片等你處理,或騎士主動回報,這台裝置就會收到通知。",
615
634
  "Install it to open from your home screen or dock, in its own window.":
616
635
  "安裝後可從主畫面或 Dock 直接開啟,並使用獨立的視窗。",
617
636
  "Install the app": "安裝應用程式",
@@ -622,8 +641,8 @@ export const ZH_TW: Readonly<Record<string, string>> = {
622
641
  "Notifications were not allowed. Allow them in the browser's site settings.":
623
642
  "通知未獲允許。請在瀏覽器的網站設定中允許通知。",
624
643
  Notifications: "通知",
625
- "Quiet hours, {start} to {end} ({zone}): no notification for an agent's report or a notice. A card waiting for you still notifies. The server sets the hours.":
626
- "勿擾時段 {start} 至 {end}({zone}):這段時間內,夥伴的回報與通知不會推播;等你處理的卡片仍會推播。時段由伺服器設定。",
644
+ "Quiet hours, {start} to {end} ({zone}): no notification for a knight's report or a notice. A card waiting for you still notifies. The server sets the hours.":
645
+ "勿擾時段 {start} 至 {end}({zone}):這段時間內,騎士的回報與通知不會推播;等你處理的卡片仍會推播。時段由伺服器設定。",
627
646
  Remove: "移除",
628
647
  "Signed in as {name}.": "目前登入身分:{name}。",
629
648
  "This browser cannot get push notifications. On iPhone and iPad, install the app from Share, Add to Home Screen, and open it from there.":
@@ -644,15 +663,15 @@ export const ZH_TW: Readonly<Record<string, string>> = {
644
663
  "白天是羊皮紙,夜晚是夜間城堡,搭配金色分隔線、盾形頭像與蠟封印章。",
645
664
 
646
665
  // 技能
647
- "All agents": "所有夥伴",
648
- "Assistant-written": "夥伴撰寫",
666
+ "All knights": "所有騎士",
667
+ "Knight-written": "騎士撰寫",
649
668
  "Built-in": "內建",
650
669
  Carriers: "搭載對象",
651
670
  "File missing": "檔案遺失",
652
671
  "No skills.": "沒有技能。",
653
672
  None: "無",
654
- "Registered skills and their carriers; ask an agent on Discord to edit their contents.":
655
- "已登錄的技能與搭載對象;如要修改內容,請在 Discord 上請夥伴編輯。",
673
+ "Registered skills and their carriers; ask a knight on Discord to edit their contents.":
674
+ "已登錄的技能與搭載對象;如要修改內容,請在 Discord 上請騎士編輯。",
656
675
 
657
676
  // 圓桌
658
677
  "Reset view": "重設視角",
@@ -668,18 +687,19 @@ export const ZH_TW: Readonly<Record<string, string>> = {
668
687
  "Archived {name}": "已封存的{name}",
669
688
  "Current conversation": "目前的對話",
670
689
  "Nothing to show.": "沒有可顯示的內容。",
671
- "Outside agent · {id}": "外部夥伴 · {id}",
690
+ "Outside AI client · {id}": "外部 AI 用戶端 · {id}",
672
691
  Showing: "顯示",
673
692
  "This conversation is longer than the console reads; the oldest entries are not shown.":
674
693
  "這段對話比主控台能讀取的長度還長,最舊的紀錄不會顯示。",
675
694
  "Tool failed": "工具執行失敗",
676
695
  "Tool result": "工具結果",
677
696
  User: "使用者",
678
- Assistant: "夥伴",
697
+ // 命令面板與對話紀錄共用
698
+ Knight: "騎士",
679
699
  "Summary of earlier conversation": "先前對話的摘要",
680
700
 
681
701
  // 伺服器回應
682
- "There is no such room, agent or file.": "找不到這個聊天室、夥伴或檔案。",
702
+ "There is no such room, knight or file.": "找不到這個聊天室、騎士或檔案。",
683
703
  "The body is too large.": "內容太大。",
684
704
  "The body is not JSON.": "內容不是 JSON。",
685
705
  "The body is not an object.": "內容不是物件。",
@@ -843,7 +863,7 @@ export const ZH_TW: Readonly<Record<string, string>> = {
843
863
  "character.class.paladin": "聖騎士",
844
864
  "character.class.archivist": "檔案管理員",
845
865
  // 職業適合的工作
846
- "character.jobs.wizard": "協調者、規劃者、主要夥伴",
866
+ "character.jobs.wizard": "協調者、規劃者、主騎士",
847
867
  "character.jobs.knight": "審查者、品質把關、守護者",
848
868
  "character.jobs.scholar": "研究員、文獻回顧",
849
869
  "character.jobs.smith": "程式開發、建置、重構",
@@ -965,14 +985,14 @@ export const ZH_TW: Readonly<Record<string, string>> = {
965
985
  // 主要提示詞與技能內容的編輯
966
986
  "Main prompts": "主要提示詞",
967
987
  "Edit the main prompts": "編輯主要提示詞",
968
- "The texts the assistant and the agents start from, with a diff to read before you save and a way back to the file's text.":
969
- "夥伴們開始工作時所依據的文字;儲存前可檢視差異,也能回到檔案裡的版本。",
970
- "The texts the assistant and the agents start from. A text you save here replaces the one from the file from the next turn on, until you go back to the file's.":
971
- "夥伴們開始工作時所依據的文字。你在這裡儲存的文字,從下一回合起取代檔案裡的版本,直到你回到檔案版本為止。",
988
+ "The texts the main knight and the other knights start from, with a diff to read before you save and a way back to the file's text.":
989
+ "主騎士與其他騎士開始工作時所依據的文字;儲存前可檢視差異,也能回到檔案裡的版本。",
990
+ "The texts the main knight and the other knights start from. A text you save here replaces the one from the file from the next turn on, until you go back to the file's.":
991
+ "主騎士與其他騎士開始工作時所依據的文字。你在這裡儲存的文字,從下一回合起取代檔案裡的版本,直到你回到檔案版本為止。",
972
992
  "Shared prompt": "共用提示詞",
973
993
  "Guest prompt": "訪客提示詞",
974
- "The base every agent's prompt starts with, the main assistant's included.":
975
- "每位夥伴的提示詞都以它開頭,主要夥伴也不例外。",
994
+ "The base every knight's prompt starts with, the main knight's included.":
995
+ "每位騎士的提示詞都以它開頭,主騎士也不例外。",
976
996
  "Used instead of the shared prompt when the person speaking is not the owner.":
977
997
  "說話的人不是擁有者時,改用它取代共用提示詞。",
978
998
  "No prompts to edit.": "沒有可編輯的提示詞。",
@@ -1003,8 +1023,8 @@ export const ZH_TW: Readonly<Record<string, string>> = {
1003
1023
  "這個技能在你編輯時被更動了。下方的差異是對照目前的版本;再儲存一次會取代它,或回去繼續編輯。",
1004
1024
  "Frontmatter holds the name, which cannot change, and a description that starts with “Use when”. The rest is the skill.":
1005
1025
  "Frontmatter 含有名稱(不能更改)與以「Use when」開頭的描述,其餘就是技能內容。",
1006
- "Registered skills and their carriers. A skill an agent wrote can be edited here; the others are read-only.":
1007
- "已登錄的技能與攜帶者。夥伴撰寫的技能可以在這裡編輯,其他的唯讀。",
1026
+ "Registered skills and their carriers. A skill a knight wrote can be edited here; the others are read-only.":
1027
+ "已登錄的技能與攜帶者。騎士撰寫的技能可以在這裡編輯,其他的唯讀。",
1008
1028
  "Built in with the release; it changes with the release.":
1009
1029
  "隨版本內建;要隨版本更新才會改變。",
1010
1030
  "From the package {package}; it changes when the package is upgraded.":
@@ -1050,8 +1070,12 @@ export const ZH_TW: Readonly<Record<string, string>> = {
1050
1070
  "This page is not available.": "這個頁面無法使用。",
1051
1071
  "You can read this room but not write in it.":
1052
1072
  "你可以閱讀這個聊天室,但不能在其中發言。",
1053
- "Send as": "傳送方式",
1054
- "Ask the agent": "請夥伴處理",
1073
+ "@AI": "@AI",
1074
+ "The message starts with @AI, so the knight answers.":
1075
+ "訊息開頭是 @AI,所以 AI 會回覆。",
1076
+ "Write an internal note…": "寫一則內部備註…",
1077
+ "Ask AI…": "問 AI…",
1078
+ "Internal note": "內部備註",
1055
1079
  "Earlier cards ({count})": "先前的卡片({count})",
1056
1080
  Replaced: "已被取代",
1057
1081
  Image: "圖片",
package/src/index.ts CHANGED
@@ -12,6 +12,7 @@ export type {
12
12
  ConversationView,
13
13
  DashboardView,
14
14
  GroupView,
15
+ HostIconName,
15
16
  NoteInput,
16
17
  NoteKind,
17
18
  NoteView,
@@ -26,7 +27,7 @@ export type {
26
27
  TranscriptRole,
27
28
  TranscriptView,
28
29
  } from "./api-types.ts";
29
- export { PANES } from "./api-types.ts";
30
+ export { HOST_ICONS, PANES } from "./api-types.ts";
30
31
  export type { CloudflareAccessOptions } from "./cloudflare-access.ts";
31
32
  export {
32
33
  cloudflareAccess,
@@ -39,4 +40,17 @@ export type { WebAuthOptions, WebConsoleOptions } from "./options.ts";
39
40
  export { DEFAULT_RELAY_NOTE } from "./options.ts";
40
41
  export type { RequestVerifier, Verdict } from "./verifier.ts";
41
42
  export { admit, admitAs, refuse } from "./verifier.ts";
43
+ export type {
44
+ ActionResult,
45
+ HostCard,
46
+ HostPage,
47
+ HostRoomKind,
48
+ LinkProver,
49
+ Notices,
50
+ OnboardingStep,
51
+ OpenTarget,
52
+ Viewer,
53
+ WebApp,
54
+ } from "./web-app.ts";
55
+ export { WEB_APP } from "./web-app.ts";
42
56
  export { webConsole } from "./web-plugin.ts";
package/src/options.ts CHANGED
@@ -116,6 +116,14 @@ export interface OidcOptions {
116
116
  reauthHours?: number;
117
117
  /** The id_token claims to keep with the session (replaced at each sign-in and re-verify, never logged); default none. */
118
118
  storeClaims?: readonly string[];
119
+ /**
120
+ * Called with the person's principal id when a request or an open socket proves they hold a
121
+ * live session, at most once per session every five minutes. For a host that counts who is
122
+ * present, such as one that keeps a linked chat account only while its web person is active: a
123
+ * person who only has the app open, calling nothing of the host's, still counts. It is not
124
+ * awaited, and an error it throws is logged and never fails the request.
125
+ */
126
+ onSessionVerified?: (principalId: string) => void | Promise<void>;
119
127
  }
120
128
 
121
129
  /** `auth` checked and filled in. */
@@ -145,6 +153,9 @@ export interface ResolvedOidc {
145
153
  endSession: boolean;
146
154
  reauthHours: number | undefined;
147
155
  storeClaims: readonly string[];
156
+ onSessionVerified:
157
+ | ((principalId: string) => void | Promise<void>)
158
+ | undefined;
148
159
  }
149
160
 
150
161
  /** The panes each tier is served, when the list differs by tier. */
@@ -331,6 +342,11 @@ export interface WebConsoleOptions {
331
342
  uploads?: { keepDays?: number };
332
343
  /** The page's title and heading; default `Roundtable`. */
333
344
  title?: string;
345
+ /**
346
+ * The page's description for search results and link previews (`description` and
347
+ * `og:description`); default a line derived from the title.
348
+ */
349
+ description?: string;
334
350
  /** Where the install icons come from; default the ones this package ships. */
335
351
  icons?: { dir: string };
336
352
  /** How the page looks: `modern` (default) or `camelot`. The page's owner can switch it in the app. */
@@ -397,6 +413,7 @@ export interface ResolvedOptions {
397
413
  modes: boolean;
398
414
  uploadKeepDays: number;
399
415
  title: string;
416
+ description: string | undefined;
400
417
  iconsDir: string | undefined;
401
418
  look: "modern" | "camelot";
402
419
  relayNotes: readonly string[];
@@ -546,6 +563,11 @@ function checkPanes(
546
563
  `${label} names the ${pane} pane, which the owners' panes do not have; the pane's API is served for the owners' list`,
547
564
  );
548
565
  }
566
+ // A member's table seats the host rooms they may list, which the rooms pane brings with its socket.
567
+ if (list.includes("table") && !list.includes("rooms"))
568
+ fail(
569
+ `${label} names the table pane without the rooms pane, whose host rooms it seats`,
570
+ );
549
571
  }
550
572
  return { owner, admin, member, given: true };
551
573
  }
@@ -704,6 +726,7 @@ function checkOidc(auth: OidcOptions): ResolvedOidc {
704
726
  "endSession",
705
727
  "reauthHours",
706
728
  "storeClaims",
729
+ "onSessionVerified",
707
730
  ]);
708
731
  for (const key of Object.keys(auth))
709
732
  if (!known.has(key)) fail(`auth.${key} is not an oidc option`);
@@ -778,6 +801,11 @@ function checkOidc(auth: OidcOptions): ResolvedOidc {
778
801
  !storeClaims.every((name) => typeof name === "string" && name.trim())
779
802
  )
780
803
  fail("auth.storeClaims must be a list of claim names");
804
+ if (
805
+ auth.onSessionVerified !== undefined &&
806
+ typeof auth.onSessionVerified !== "function"
807
+ )
808
+ fail("auth.onSessionVerified must be a function");
781
809
  return {
782
810
  mode: "oidc",
783
811
  issuer,
@@ -798,6 +826,7 @@ function checkOidc(auth: OidcOptions): ResolvedOidc {
798
826
  endSession: auth.endSession === true,
799
827
  reauthHours: auth.reauthHours,
800
828
  storeClaims: [...storeClaims],
829
+ onSessionVerified: auth.onSessionVerified,
801
830
  };
802
831
  }
803
832
 
@@ -1028,6 +1057,12 @@ export function resolveOptions(options: WebConsoleOptions): ResolvedOptions {
1028
1057
  fail("appearance.look must be modern or camelot");
1029
1058
  const title = options.title?.trim() ?? "Roundtable";
1030
1059
  if (!title) fail("title is empty");
1060
+ const description = options.description?.trim();
1061
+ if (
1062
+ options.description !== undefined &&
1063
+ (typeof options.description !== "string" || !description)
1064
+ )
1065
+ fail("description is empty. Leave it out for the default");
1031
1066
  return {
1032
1067
  auth,
1033
1068
  origin,
@@ -1050,6 +1085,7 @@ export function resolveOptions(options: WebConsoleOptions): ResolvedOptions {
1050
1085
  modes: options.modes !== false,
1051
1086
  uploadKeepDays: checkUploads(options),
1052
1087
  title,
1088
+ description,
1053
1089
  iconsDir: options.icons?.dir,
1054
1090
  look,
1055
1091
  relayNotes: options.relayNotes ?? [DEFAULT_RELAY_NOTE],
@@ -1069,7 +1105,7 @@ export function workspaceRootsOf(
1069
1105
  if (agents && settings.workspace.agents)
1070
1106
  roots.push({
1071
1107
  id: "agents",
1072
- label: "Agents' workspace",
1108
+ label: "Knights' workspace",
1073
1109
  dir: agents.workDir,
1074
1110
  writable: true,
1075
1111
  });