bazilion 0.13.0 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/cli.js.map +1 -1
  3. package/dist/daemon.js +25 -5
  4. package/dist/daemon.js.map +1 -1
  5. package/dist/web/client/assets/AgentTabs-BcmmwYJc.js +1 -0
  6. package/dist/web/client/assets/ConfigPage-BCLp-FUC.js +1 -0
  7. package/dist/web/client/assets/ConfirmDialog-CyL9A20V.js +1 -0
  8. package/dist/web/client/assets/FieldRow-D6REbYUa.js +1 -0
  9. package/dist/web/client/assets/Page-NV96O47A.js +1 -0
  10. package/dist/web/client/assets/ProductionTeamPolicyEditor-DBKnOezm.js +7 -0
  11. package/dist/web/client/assets/{ProfileCommunicationEditor-BcSf2Hao.js → ProfileCommunicationEditor-4RK2laqO.js} +1 -1
  12. package/dist/web/client/assets/SectionTabs-4kCQXuFY.js +1 -0
  13. package/dist/web/client/assets/TeamTabs-CdtNEqt4.js +1 -0
  14. package/dist/web/client/assets/{TemplatesTabs-CyDVzrOl.js → TemplatesTabs-CZyss2Y0.js} +1 -1
  15. package/dist/web/client/assets/UnsavedChangesGuard-CEoK-ZcN.js +1 -0
  16. package/dist/web/client/assets/_id-4ZS-w_Aj.js +1 -0
  17. package/dist/web/client/assets/{_id-DWTMH7Eb.js → _id-DIqtdQij.js} +1 -1
  18. package/dist/web/client/assets/_id-DbcC2E7F.js +1 -0
  19. package/dist/web/client/assets/_id-f_r5M0p3.js +1 -0
  20. package/dist/web/client/assets/activity-CB9Ufth-.js +1 -0
  21. package/dist/web/client/assets/agents-D-JGXVg9.js +1 -0
  22. package/dist/web/client/assets/agents-DS2XafoA.js +1 -0
  23. package/dist/web/client/assets/approvals-Cke_mrJv.js +1 -0
  24. package/dist/web/client/assets/attention-PYwRM2wC.js +1 -0
  25. package/dist/web/client/assets/chevron-right-BG4OeFRQ.js +1 -0
  26. package/dist/web/client/assets/config-DF9Gqmfa.js +3 -0
  27. package/dist/web/client/assets/{inbox-D2NypLee.js → inbox-DC_HdOfI.js} +1 -1
  28. package/dist/web/client/assets/index-Cp6UHWr2.js +52 -0
  29. package/dist/web/client/assets/learning-BfrQ4YZY.js +1 -0
  30. package/dist/web/client/assets/login-D4n3AcBR.js +1 -0
  31. package/dist/web/client/assets/mcp-CnjQc_JJ.js +1 -0
  32. package/dist/web/client/assets/members-wxsVTJdW.js +1 -0
  33. package/dist/web/client/assets/memory-Du60O3pE.js +1 -0
  34. package/dist/web/client/assets/{policy-CHM95pMU.js → policy-BOfnkJsL.js} +1 -1
  35. package/dist/web/client/assets/{preload-helper-mNuBjNXU.js → preload-helper-bztXdkDj.js} +1 -1
  36. package/dist/web/client/assets/routes-B9CuhzUW.js +1 -0
  37. package/dist/web/client/assets/services-DyvqJqM2.js +1 -0
  38. package/dist/web/client/assets/skills-DQo7ioW7.js +1 -0
  39. package/dist/web/client/assets/styles-B5vcgXln.css +2 -0
  40. package/dist/web/client/assets/{teams-Dm_huGxn.js → teams-DPggy97H.js} +1 -1
  41. package/dist/web/client/assets/teams-DdawcfNR.js +1 -0
  42. package/dist/web/client/assets/telegram-DcTeDpP5.js +1 -0
  43. package/dist/web/client/assets/tokens-CIEKwZXc.js +1 -0
  44. package/dist/web/client/assets/triggers-Bc2RrUPm.js +1 -0
  45. package/dist/web/client/assets/utils-B6KiDbIe.js +1 -0
  46. package/dist/web/client/assets/welcome-DlhNXUIa.js +1 -0
  47. package/dist/web/client/assets/wire-constants-BzdHSc6A.js +74 -0
  48. package/dist/web/client/assets/x-DAXGIe_Q.js +1 -0
  49. package/dist/web/server/assets/{AgentTabs-aXdsiiMp.js → AgentTabs-Dq8hDM2Q.js} +9 -2
  50. package/dist/web/server/assets/{ChatPane-Ba5wTsVk.js → ChatPane-CgSe7tsy.js} +81 -43
  51. package/dist/web/server/assets/{ConfigPage-BKlh5vOU.js → ConfigPage-CiQ-gxmJ.js} +3 -2
  52. package/dist/web/server/assets/ConfirmDialog-C-MPYYSU.js +99 -0
  53. package/dist/web/server/assets/FieldRow-DCOF07kl.js +160 -0
  54. package/dist/web/server/assets/{Page-LENulSXY.js → Page-Bz-ydB8j.js} +4 -10
  55. package/dist/web/server/assets/{ProductionTeamPolicyEditor-Y4mzFFvR.js → ProductionTeamPolicyEditor-DQSdP7Yx.js} +140 -123
  56. package/dist/web/server/assets/{SectionTabs-BJTPr5nU.js → SectionTabs-B2Yw81XN.js} +2 -2
  57. package/dist/web/server/assets/{Sidebar-DsRVCszF.js → Sidebar-DKyk7oIo.js} +563 -283
  58. package/dist/web/server/assets/{TeamTabs-zZzbP1t_.js → TeamTabs-Co3n2exj.js} +2 -6
  59. package/dist/web/server/assets/{TemplatesTabs-CcRxZhJe.js → TemplatesTabs-B0fA361R.js} +1 -1
  60. package/dist/web/server/assets/UnsavedChangesGuard-CiStXyBI.js +40 -0
  61. package/dist/web/server/assets/{_id-xTD_6ApX.js → _id-BAA9KJBU.js} +1 -1
  62. package/dist/web/server/assets/{_id-BQ2zoMiR.js → _id-BM5m2FLT.js} +4 -4
  63. package/dist/web/server/assets/{_id-BENqNBfK.js → _id-BYKpT2Tu.js} +1 -2
  64. package/dist/web/server/assets/{_id-BreRHYV2.js → _id-BeKhPKw3.js} +350 -185
  65. package/dist/web/server/assets/{_id-CPIXIqyO.js → _id-BqWTB8Wl.js} +188 -86
  66. package/dist/web/server/assets/{_id-DkrNqqTw.js → _id-BwvCtzlD.js} +1 -1
  67. package/dist/web/server/assets/{_id-BZWunvy7.js → _id-DYU6uIBx.js} +0 -1
  68. package/dist/web/server/assets/{_id-BFELaMIN.js → _id-ndxFHx0t.js} +75 -71
  69. package/dist/web/server/assets/{_id-CvYqVJPU.js → _id-sNu5aXZt.js} +2 -1
  70. package/dist/web/server/assets/{_tanstack-start-manifest_v-COkJjXt_.js → _tanstack-start-manifest_v-C-OiOZeM.js} +110 -87
  71. package/dist/web/server/assets/{activity-B6N1T_5N.js → activity-BWv1goK6.js} +3 -3
  72. package/dist/web/server/assets/{activity-BazZNfvf.js → activity-LjpblbDL.js} +1 -1
  73. package/dist/web/server/assets/{agents-BpSeOA30.js → agents-BDFGrU3o.js} +1 -1
  74. package/dist/web/server/assets/{agents-DY630p6x.js → agents-CJk4pxKu.js} +1 -1
  75. package/dist/web/server/assets/{agents-wSYNPuyK.js → agents-CYw1xHoY.js} +138 -16
  76. package/dist/web/server/assets/{agents-DfoLnTyD.js → agents-DfNKc_Q7.js} +52 -8
  77. package/dist/web/server/assets/{approvals-BkUGmYU9.js → approvals-7JOoBchn.js} +1 -1
  78. package/dist/web/server/assets/{approvals-BYajNOdE.js → approvals-Bz123liE.js} +59 -21
  79. package/dist/web/server/assets/{attention-Bw_wiiqI.js → attention-B35JvhOL.js} +1 -1
  80. package/dist/web/server/assets/{attention-Z3bGuxOD.js → attention-C1pPWSXw.js} +3 -3
  81. package/dist/web/server/assets/{config-wYtIhkRm.js → config-BlMkHStx.js} +1 -1
  82. package/dist/web/server/assets/config-ExacOzHX.js +958 -0
  83. package/dist/web/server/assets/{inbox-DTTfSuGU.js → inbox-RweGCV3D.js} +3 -3
  84. package/dist/web/server/assets/{inbox-0iiSg-Y1.js → inbox-cu3jLzNP.js} +1 -1
  85. package/dist/web/server/assets/{learning-DpyLNVe8.js → learning-BaKM6qaw.js} +1 -1
  86. package/dist/web/server/assets/{learning-fG8316uc.js → learning-CbtNlqYo.js} +76 -23
  87. package/dist/web/server/assets/{login-D_GDeTrB.js → login-BNj3U6ok.js} +21 -11
  88. package/dist/web/server/assets/{login-CrFVVUaE.js → login-Be8eP4Jp.js} +2 -2
  89. package/dist/web/server/assets/{mcp-BQtp2T87.js → mcp-B0goWO8Q.js} +1 -1
  90. package/dist/web/server/assets/mcp-CiBs8unU.js +332 -0
  91. package/dist/web/server/assets/members-DHYTVgwb.js +100 -0
  92. package/dist/web/server/assets/{members-DXu2oAS_.js → members-DiYtr-zm.js} +1 -1
  93. package/dist/web/server/assets/{memory-C6fX_FKI.js → memory-CkXUgf5s.js} +150 -48
  94. package/dist/web/server/assets/{memory-Iq2M0-Yc.js → memory-DTFEmfF3.js} +1 -1
  95. package/dist/web/server/assets/{policy-D7kj3Cy7.js → policy-BddK4xom.js} +1 -1
  96. package/dist/web/server/assets/{policy-Bg6u-rTq.js → policy-Bvvav8fh.js} +4 -4
  97. package/dist/web/server/assets/{router-D-6TzLRZ.js → router-pjH2t8Rl.js} +345 -172
  98. package/dist/web/server/assets/{routes-CiPfEldd.js → routes-BgHisAxH.js} +22 -5
  99. package/dist/web/server/assets/{routes-CNRzy79H.js → routes-COtkyZG1.js} +1 -1
  100. package/dist/web/server/assets/{routes-D933ngZS.js → routes-DAU2g7Uz.js} +1 -1
  101. package/dist/web/server/assets/services-ClyGBU7W.js +83 -0
  102. package/dist/web/server/assets/{services-OB4LAr2A.js → services-DgoU1udp.js} +1 -1
  103. package/dist/web/server/assets/{skills-Babb9jsQ.js → skills-CYih9TJw.js} +47 -6
  104. package/dist/web/server/assets/{skills-D5DQL8bM.js → skills-Dw3cI3si.js} +1 -1
  105. package/dist/web/server/assets/{start-uKQNK6if.js → start-D4Wq9iTa.js} +1 -1
  106. package/dist/web/server/assets/{teams-Dz6ZEMRo.js → teams-BJuoNOTB.js} +1 -1
  107. package/dist/web/server/assets/{teams-Bk6ZT0MD.js → teams-DF3RViAg.js} +3 -3
  108. package/dist/web/server/assets/{teams-DqC4wZxu.js → teams-DFnuc660.js} +1 -1
  109. package/dist/web/server/assets/{teams-Cc2Czynq.js → teams-TV6nbEN_.js} +101 -10
  110. package/dist/web/server/assets/{telegram-J4T0XhwQ.js → telegram-DbOFpTFm.js} +1 -1
  111. package/dist/web/server/assets/{telegram-DUbDIVGX.js → telegram-Dj4Wwhd6.js} +147 -47
  112. package/dist/web/server/assets/{tokens-CJM_0NDa.js → tokens-DDwtO15P.js} +88 -19
  113. package/dist/web/server/assets/{tokens-DO5BzNOn.js → tokens-_2hptHP6.js} +1 -1
  114. package/dist/web/server/assets/{triggers-BdBx-HwR.js → triggers-BvjYNmmY.js} +1 -1
  115. package/dist/web/server/assets/triggers-CHk9O3rU.js +367 -0
  116. package/dist/web/server/assets/utils-C_uf36nf.js +8 -0
  117. package/dist/web/server/assets/{welcome-DDB11L5j.js → welcome-B8nchXdF.js} +9 -8
  118. package/dist/web/server/server.js +5 -9
  119. package/package.json +3 -3
  120. package/dist/web/client/assets/AgentTabs-R6gSjIj3.js +0 -1
  121. package/dist/web/client/assets/ConfigPage-BCwfgyjD.js +0 -1
  122. package/dist/web/client/assets/FieldRow-avAFLgYW.js +0 -1
  123. package/dist/web/client/assets/Page-CwNuDhWz.js +0 -1
  124. package/dist/web/client/assets/ProductionTeamPolicyEditor-DdpYInwV.js +0 -7
  125. package/dist/web/client/assets/SectionTabs-DZzy01az.js +0 -1
  126. package/dist/web/client/assets/TeamTabs-Bk89JfN7.js +0 -1
  127. package/dist/web/client/assets/_id-CAJTTnee.js +0 -1
  128. package/dist/web/client/assets/_id-CN6jPaBu.js +0 -1
  129. package/dist/web/client/assets/_id-DGwJqqDc.js +0 -1
  130. package/dist/web/client/assets/activity-DK_M0-bn.js +0 -1
  131. package/dist/web/client/assets/agents-B-i5pASm.js +0 -1
  132. package/dist/web/client/assets/agents-n8U7qNxw.js +0 -1
  133. package/dist/web/client/assets/approvals-CmVxCy0Z.js +0 -1
  134. package/dist/web/client/assets/attention-F0lUQCWE.js +0 -1
  135. package/dist/web/client/assets/chevron-down-OndG7r1U.js +0 -1
  136. package/dist/web/client/assets/config-DuApZ9xS.js +0 -3
  137. package/dist/web/client/assets/context-C1sMnW6K.js +0 -1
  138. package/dist/web/client/assets/index-B3vdrEEg.js +0 -12
  139. package/dist/web/client/assets/learning-zYDCfVxT.js +0 -1
  140. package/dist/web/client/assets/login-B1Un51Zx.js +0 -1
  141. package/dist/web/client/assets/mcp-DSVmJBdv.js +0 -1
  142. package/dist/web/client/assets/members-Pl7hXJcN.js +0 -1
  143. package/dist/web/client/assets/memory-Co3BEaAq.js +0 -1
  144. package/dist/web/client/assets/plus-Dor-_wmL.js +0 -1
  145. package/dist/web/client/assets/routes-D29qjwG0.js +0 -1
  146. package/dist/web/client/assets/services-CCQ_6YWQ.js +0 -1
  147. package/dist/web/client/assets/skills-3xAIvzvP.js +0 -1
  148. package/dist/web/client/assets/styles-D6RPN7RK.css +0 -2
  149. package/dist/web/client/assets/teams-UGLyjHYj.js +0 -1
  150. package/dist/web/client/assets/telegram-3KvrJVO6.js +0 -1
  151. package/dist/web/client/assets/tokens-DUSFmV5_.js +0 -1
  152. package/dist/web/client/assets/triggers-DlQ2KF1h.js +0 -1
  153. package/dist/web/client/assets/welcome-DkP8qzK1.js +0 -1
  154. package/dist/web/client/assets/wire-constants-BhVKOCQa.js +0 -74
  155. package/dist/web/server/assets/FieldRow-B4eTegH9.js +0 -94
  156. package/dist/web/server/assets/config-DGzM28F_.js +0 -554
  157. package/dist/web/server/assets/context-BkDDwbby.js +0 -12
  158. package/dist/web/server/assets/context-DMc0KyHh.js +0 -12
  159. package/dist/web/server/assets/context-poimKI7w.js +0 -47
  160. package/dist/web/server/assets/mcp-DlgXUcAS.js +0 -261
  161. package/dist/web/server/assets/members-CteHKPSF.js +0 -46
  162. package/dist/web/server/assets/services-DJRA1A0-.js +0 -79
  163. package/dist/web/server/assets/triggers-B87fycBl.js +0 -216
@@ -1,6 +1,7 @@
1
- import { t as Route } from "./telegram-J4T0XhwQ.js";
1
+ import { t as Route } from "./telegram-DbOFpTFm.js";
2
2
  import { t as Button } from "./Button-Dsnw22OF.js";
3
- import { t as ConfigPage } from "./ConfigPage-BKlh5vOU.js";
3
+ import { t as ConfirmDialog } from "./ConfirmDialog-C-MPYYSU.js";
4
+ import { t as ConfigPage } from "./ConfigPage-CiQ-gxmJ.js";
4
5
  import { useEffect, useState } from "react";
5
6
  import { useRouter } from "@tanstack/react-router";
6
7
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -13,10 +14,16 @@ function TelegramIntegrationPage() {
13
14
  const [saving, setSaving] = useState(false);
14
15
  const [saveError, setSaveError] = useState(null);
15
16
  const [saveOk, setSaveOk] = useState(false);
17
+ const [confirmDisconnect, setConfirmDisconnect] = useState(false);
16
18
  const [health, setHealth] = useState(null);
17
19
  const [checking, setChecking] = useState(false);
18
20
  async function save(e) {
19
21
  e.preventDefault();
22
+ if (initial.configured && token.trim().length === 0) {
23
+ setSaveOk(false);
24
+ setSaveError(chatId.trim() === initial.chatId ? "Nothing changed. Paste a replacement token to update credentials." : "Paste the bot token again when changing the supergroup, so the existing secret is never cleared or reused silently.");
25
+ return;
26
+ }
20
27
  setSaving(true);
21
28
  setSaveError(null);
22
29
  setSaveOk(false);
@@ -43,18 +50,17 @@ function TelegramIntegrationPage() {
43
50
  }
44
51
  }
45
52
  async function disconnect() {
46
- if (!confirm("Clear the saved Telegram credentials?")) return;
47
- try {
48
- await fetch("/api/config/telegram", { method: "DELETE" });
49
- setToken("");
50
- setChatId("");
51
- setHealth(null);
52
- setSaveOk(false);
53
- setSaveError(null);
54
- await router.invalidate();
55
- } catch (e) {
56
- setSaveError(e.message);
53
+ const response = await fetch("/api/config/telegram", { method: "DELETE" });
54
+ if (!response.ok && response.status !== 204) {
55
+ const body = await response.json().catch(() => null);
56
+ throw new Error(body?.error ?? `Could not clear Telegram credentials (${response.status})`);
57
57
  }
58
+ setToken("");
59
+ setChatId("");
60
+ setHealth(null);
61
+ setSaveOk(false);
62
+ setSaveError(null);
63
+ await router.invalidate();
58
64
  }
59
65
  async function runHealth() {
60
66
  setChecking(true);
@@ -119,7 +125,10 @@ function TelegramIntegrationPage() {
119
125
  type: "password",
120
126
  autoComplete: "off",
121
127
  value: token,
122
- onChange: (e) => setToken(e.target.value),
128
+ onChange: (e) => {
129
+ setToken(e.target.value);
130
+ setSaveError(null);
131
+ },
123
132
  placeholder: initial.configured ? "(leave blank to keep stored value)" : "1234567890:ABC...",
124
133
  className: "w-full rounded-md border bg-background px-2 py-1.5 font-mono text-sm outline-none focus:ring-2 focus:ring-ring/30",
125
134
  required: !initial.configured
@@ -131,6 +140,10 @@ function TelegramIntegrationPage() {
131
140
  /* @__PURE__ */ jsx("em", { children: "Bot Settings → Team Privacy → Turn off" }),
132
141
  "."
133
142
  ]
143
+ }),
144
+ initial.configured && /* @__PURE__ */ jsx("p", {
145
+ className: "mt-1 text-xs text-muted-foreground",
146
+ children: "Blank preserves the stored token. To remove it, use clear credentials and confirm the integration shutdown."
134
147
  })
135
148
  ]
136
149
  }),
@@ -144,7 +157,10 @@ function TelegramIntegrationPage() {
144
157
  /* @__PURE__ */ jsx("input", {
145
158
  type: "text",
146
159
  value: chatId,
147
- onChange: (e) => setChatId(e.target.value),
160
+ onChange: (e) => {
161
+ setChatId(e.target.value);
162
+ setSaveError(null);
163
+ },
148
164
  placeholder: "-1001234567890",
149
165
  className: "w-full rounded-md border bg-background px-2 py-1.5 font-mono text-sm outline-none focus:ring-2 focus:ring-ring/30",
150
166
  required: true
@@ -174,7 +190,7 @@ function TelegramIntegrationPage() {
174
190
  }),
175
191
  initial.configured && /* @__PURE__ */ jsx(Button, {
176
192
  variant: "danger",
177
- onClick: disconnect,
193
+ onClick: () => setConfirmDisconnect(true),
178
194
  children: "clear credentials"
179
195
  }),
180
196
  saveOk && /* @__PURE__ */ jsx("span", {
@@ -182,6 +198,7 @@ function TelegramIntegrationPage() {
182
198
  children: "saved ✓"
183
199
  }),
184
200
  saveError && /* @__PURE__ */ jsxs("span", {
201
+ role: "alert",
185
202
  className: "text-xs text-danger",
186
203
  children: ["error: ", saveError]
187
204
  })
@@ -223,7 +240,22 @@ function TelegramIntegrationPage() {
223
240
  ]
224
241
  }),
225
242
  initial.configured && /* @__PURE__ */ jsx(OwnerPairingCard, {}),
226
- initial.configured && /* @__PURE__ */ jsx(AccessControlCard, {})
243
+ initial.configured && /* @__PURE__ */ jsx(AccessControlCard, {}),
244
+ /* @__PURE__ */ jsx(ConfirmDialog, {
245
+ open: confirmDisconnect,
246
+ title: "Disconnect Telegram?",
247
+ description: /* @__PURE__ */ jsx("p", { children: "This permanently removes the saved bot token and supergroup ID. Telegram polling, ingress, and outbound delivery stop until new credentials are saved and pairing is completed again." }),
248
+ confirmLabel: "clear credentials and disconnect",
249
+ onConfirm: async () => {
250
+ try {
251
+ await disconnect();
252
+ } catch (error) {
253
+ setSaveError(error instanceof Error ? error.message : String(error));
254
+ throw error;
255
+ }
256
+ },
257
+ onOpenChange: setConfirmDisconnect
258
+ })
227
259
  ]
228
260
  });
229
261
  }
@@ -231,6 +263,7 @@ function OwnerPairingCard() {
231
263
  const [status, setStatus] = useState(null);
232
264
  const [code, setCode] = useState(null);
233
265
  const [err, setErr] = useState(null);
266
+ const [confirmReset, setConfirmReset] = useState(false);
234
267
  const load = async () => {
235
268
  const res = await fetch("/api/config/telegram/pairing");
236
269
  if (!res.ok) throw new Error(res.statusText);
@@ -248,17 +281,24 @@ function OwnerPairingCard() {
248
281
  setStatus(body);
249
282
  }
250
283
  async function cancelChallenge() {
251
- await fetch("/api/config/telegram/pairing/challenge", { method: "DELETE" });
284
+ const res = await fetch("/api/config/telegram/pairing/challenge", { method: "DELETE" });
285
+ if (!res.ok && res.status !== 204) {
286
+ const body = await res.json().catch(() => null);
287
+ throw new Error(body?.error ?? "Could not cancel the pairing code");
288
+ }
252
289
  setCode(null);
253
290
  await load();
254
291
  }
255
292
  async function resetOwner() {
256
- if (!confirm("Revoke the Telegram owner now? Ingress will close until a new owner pairs.")) return;
257
- if (!(await fetch("/api/config/telegram/pairing/reset", {
293
+ const res = await fetch("/api/config/telegram/pairing/reset", {
258
294
  method: "POST",
259
295
  headers: { "content-type": "application/json" },
260
296
  body: JSON.stringify({ confirm: true })
261
- })).ok) return setErr("Could not reset Telegram owner");
297
+ });
298
+ if (!res.ok) {
299
+ const body = await res.json().catch(() => null);
300
+ throw new Error(body?.error ?? "Could not reset Telegram owner");
301
+ }
262
302
  setCode(null);
263
303
  await load();
264
304
  }
@@ -288,7 +328,7 @@ function OwnerPairingCard() {
288
328
  children: "✓ owner paired"
289
329
  }), /* @__PURE__ */ jsx(Button, {
290
330
  variant: "danger",
291
- onClick: resetOwner,
331
+ onClick: () => setConfirmReset(true),
292
332
  children: "reset owner"
293
333
  })]
294
334
  }) : /* @__PURE__ */ jsxs("div", {
@@ -317,15 +357,31 @@ function OwnerPairingCard() {
317
357
  children: "generate pairing code"
318
358
  }), status?.challengeActive && /* @__PURE__ */ jsx(Button, {
319
359
  variant: "ghost",
320
- onClick: cancelChallenge,
360
+ onClick: () => void cancelChallenge().catch((error) => setErr(error instanceof Error ? error.message : String(error))),
321
361
  children: "cancel code"
322
362
  })]
323
363
  })
324
364
  ]
325
365
  }),
326
366
  err && /* @__PURE__ */ jsx("p", {
367
+ role: "alert",
327
368
  className: "mt-2 text-xs text-danger",
328
369
  children: err
370
+ }),
371
+ /* @__PURE__ */ jsx(ConfirmDialog, {
372
+ open: confirmReset,
373
+ title: "Revoke the paired Telegram owner?",
374
+ description: /* @__PURE__ */ jsx("p", { children: "This immediately revokes the current owner and closes all Telegram ingress. No one can use the bot until a new one-time pairing code is generated and consumed." }),
375
+ confirmLabel: "revoke owner and close ingress",
376
+ onConfirm: async () => {
377
+ try {
378
+ await resetOwner();
379
+ } catch (error) {
380
+ setErr(error instanceof Error ? error.message : String(error));
381
+ throw error;
382
+ }
383
+ },
384
+ onOpenChange: setConfirmReset
329
385
  })
330
386
  ]
331
387
  });
@@ -336,6 +392,7 @@ function AccessControlCard() {
336
392
  const [label, setLabel] = useState("");
337
393
  const [busy, setBusy] = useState(false);
338
394
  const [err, setErr] = useState(null);
395
+ const [removeTarget, setRemoveTarget] = useState(null);
339
396
  async function load() {
340
397
  try {
341
398
  const res = await fetch("/api/config/telegram/acl");
@@ -381,16 +438,12 @@ function AccessControlCard() {
381
438
  }
382
439
  async function remove(id) {
383
440
  setErr(null);
384
- try {
385
- const res = await fetch(`/api/config/telegram/acl/${id}`, { method: "DELETE" });
386
- if (!res.ok) {
387
- const j = await res.json().catch(() => ({}));
388
- throw new Error(j.error ?? res.statusText);
389
- }
390
- await load();
391
- } catch (e) {
392
- setErr(e.message);
441
+ const res = await fetch(`/api/config/telegram/acl/${id}`, { method: "DELETE" });
442
+ if (!res.ok) {
443
+ const j = await res.json().catch(() => ({}));
444
+ throw new Error(j.error ?? res.statusText);
393
445
  }
446
+ await load();
394
447
  }
395
448
  return /* @__PURE__ */ jsxs("section", {
396
449
  className: "rounded-lg border bg-card p-5",
@@ -434,10 +487,10 @@ function AccessControlCard() {
434
487
  u.role
435
488
  ]
436
489
  }),
437
- u.role !== "owner" && /* @__PURE__ */ jsx("button", {
438
- type: "button",
439
- onClick: () => void remove(u.userId),
440
- className: "ghost-btn text-xs text-rose-baziu",
490
+ u.role !== "owner" && /* @__PURE__ */ jsx(Button, {
491
+ variant: "danger",
492
+ className: "text-xs",
493
+ onClick: () => setRemoveTarget(u),
441
494
  children: "remove"
442
495
  })
443
496
  ]
@@ -445,19 +498,33 @@ function AccessControlCard() {
445
498
  }),
446
499
  /* @__PURE__ */ jsxs("form", {
447
500
  onSubmit: add,
448
- className: "flex flex-col gap-2 sm:flex-row sm:flex-wrap sm:items-center",
501
+ className: "flex flex-col gap-2 sm:flex-row sm:flex-wrap sm:items-end",
449
502
  children: [
450
- /* @__PURE__ */ jsx("input", {
451
- value: userId,
452
- onChange: (e) => setUserId(e.target.value),
453
- placeholder: "user id",
454
- className: "w-full rounded-md border bg-background px-2 py-1 font-mono text-sm sm:w-28"
503
+ /* @__PURE__ */ jsxs("label", {
504
+ className: "m-0 flex flex-col gap-1 text-xs font-medium text-foreground",
505
+ children: ["Telegram user ID", /* @__PURE__ */ jsx("input", {
506
+ value: userId,
507
+ onChange: (e) => setUserId(e.target.value),
508
+ placeholder: "123456789",
509
+ inputMode: "numeric",
510
+ className: "w-full rounded-md border bg-background px-2 py-1 font-mono text-sm sm:w-32"
511
+ })]
455
512
  }),
456
- /* @__PURE__ */ jsx("input", {
457
- value: label,
458
- onChange: (e) => setLabel(e.target.value),
459
- placeholder: "label (optional)",
460
- className: "w-full rounded-md border bg-background px-2 py-1 text-sm sm:w-40"
513
+ /* @__PURE__ */ jsxs("label", {
514
+ className: "m-0 flex flex-col gap-1 text-xs font-medium text-foreground",
515
+ children: [
516
+ "Label ",
517
+ /* @__PURE__ */ jsx("span", {
518
+ className: "font-normal text-muted-foreground",
519
+ children: "(optional)"
520
+ }),
521
+ /* @__PURE__ */ jsx("input", {
522
+ value: label,
523
+ onChange: (e) => setLabel(e.target.value),
524
+ placeholder: "e.g. Pat",
525
+ className: "w-full rounded-md border bg-background px-2 py-1 text-sm sm:w-40"
526
+ })
527
+ ]
461
528
  }),
462
529
  /* @__PURE__ */ jsx(Button, {
463
530
  variant: "ghost",
@@ -466,10 +533,36 @@ function AccessControlCard() {
466
533
  children: "add"
467
534
  }),
468
535
  err && /* @__PURE__ */ jsx("span", {
536
+ role: "alert",
469
537
  className: "text-xs text-danger",
470
538
  children: err
471
539
  })
472
540
  ]
541
+ }),
542
+ /* @__PURE__ */ jsx(ConfirmDialog, {
543
+ open: removeTarget !== null,
544
+ title: `Remove ${removeTarget?.label ?? removeTarget?.username ?? removeTarget?.userId ?? ""}?`,
545
+ description: /* @__PURE__ */ jsxs("p", { children: [
546
+ "Telegram user ",
547
+ /* @__PURE__ */ jsx("code", {
548
+ className: "font-mono",
549
+ children: removeTarget?.userId
550
+ }),
551
+ " immediately loses command and chat access. Their Telegram account is not changed, and they can be allowlisted again later."
552
+ ] }),
553
+ confirmLabel: "remove Telegram access",
554
+ onConfirm: async () => {
555
+ if (!removeTarget) return;
556
+ try {
557
+ await remove(removeTarget.userId);
558
+ } catch (error) {
559
+ setErr(error instanceof Error ? error.message : String(error));
560
+ throw error;
561
+ }
562
+ },
563
+ onOpenChange: (open) => {
564
+ if (!open) setRemoveTarget(null);
565
+ }
473
566
  })
474
567
  ]
475
568
  });
@@ -523,6 +616,7 @@ function MigrationBanner({ toChatId }) {
523
616
  children: busy ? "reconnecting…" : `Reconnect to ${toChatId}`
524
617
  }),
525
618
  err && /* @__PURE__ */ jsx("span", {
619
+ role: "alert",
526
620
  className: "ml-3 text-xs text-danger",
527
621
  children: err
528
622
  })
@@ -556,6 +650,7 @@ function PollingState({ polling }) {
556
650
  ]
557
651
  }),
558
652
  polling.error && /* @__PURE__ */ jsxs("p", {
653
+ role: "alert",
559
654
  className: "text-danger",
560
655
  children: ["error: ", polling.error]
561
656
  })
@@ -564,6 +659,7 @@ function PollingState({ polling }) {
564
659
  }
565
660
  function PreflightResult({ health }) {
566
661
  if (health.error) return /* @__PURE__ */ jsxs("div", {
662
+ role: "alert",
567
663
  className: "rounded-md border border-danger/25 bg-danger/10 px-3 py-2 text-sm",
568
664
  children: [
569
665
  /* @__PURE__ */ jsxs("p", {
@@ -581,11 +677,15 @@ function PreflightResult({ health }) {
581
677
  ]
582
678
  });
583
679
  if (!health.preflight) return /* @__PURE__ */ jsx("p", {
680
+ role: "status",
584
681
  className: "text-xs text-muted-foreground italic",
585
682
  children: "No preflight data."
586
683
  });
587
684
  const p = health.preflight;
588
685
  return /* @__PURE__ */ jsxs("ul", {
686
+ role: "status",
687
+ "aria-live": "polite",
688
+ "aria-atomic": "true",
589
689
  className: "space-y-1.5",
590
690
  children: [
591
691
  /* @__PURE__ */ jsxs(Check, {
@@ -1,5 +1,7 @@
1
- import { t as Route } from "./tokens-DO5BzNOn.js";
2
- import { t as ConfigPage } from "./ConfigPage-BKlh5vOU.js";
1
+ import { t as Route } from "./tokens-_2hptHP6.js";
2
+ import { t as Button } from "./Button-Dsnw22OF.js";
3
+ import { t as ConfirmDialog } from "./ConfirmDialog-C-MPYYSU.js";
4
+ import { t as ConfigPage } from "./ConfigPage-CiQ-gxmJ.js";
3
5
  import { useState } from "react";
4
6
  import { useRouter } from "@tanstack/react-router";
5
7
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -17,6 +19,8 @@ function TokensPage() {
17
19
  const [expiresDays, setExpiresDays] = useState("90");
18
20
  const [err, setErr] = useState(null);
19
21
  const [busy, setBusy] = useState(false);
22
+ const [revokeTokenTarget, setRevokeTokenTarget] = useState(null);
23
+ const [revokeSessionTarget, setRevokeSessionTarget] = useState(null);
20
24
  async function mint(e) {
21
25
  e.preventDefault();
22
26
  setErr(null);
@@ -43,17 +47,23 @@ function TokensPage() {
43
47
  setBusy(false);
44
48
  }
45
49
  }
46
- async function revoke(id) {
47
- await fetch(`/api/tokens/${id}`, { method: "DELETE" });
48
- await router.invalidate();
50
+ async function revoke(id, revokesCurrentSession) {
51
+ const response = await fetch(`/api/tokens/${encodeURIComponent(id)}`, { method: "DELETE" });
52
+ if (!response.ok && response.status !== 204) {
53
+ const body = await response.json().catch(() => ({}));
54
+ throw new Error(body.error ?? "Could not revoke API token");
55
+ }
56
+ if (revokesCurrentSession) window.location.assign("/login");
57
+ else await router.invalidate();
49
58
  }
50
- async function revokeSession(id) {
59
+ async function revokeSession(id, current) {
51
60
  const response = await fetch(`/api/sessions/${encodeURIComponent(id)}`, { method: "DELETE" });
52
61
  if (!response.ok) {
53
- setErr((await response.json().catch(() => ({}))).error ?? "Could not revoke browser session");
54
- return;
62
+ const body = await response.json().catch(() => ({}));
63
+ throw new Error(body.error ?? "Could not revoke browser session");
55
64
  }
56
- await router.invalidate();
65
+ if (current) window.location.assign("/login");
66
+ else await router.invalidate();
57
67
  }
58
68
  return /* @__PURE__ */ jsxs(ConfigPage, {
59
69
  active: "tokens",
@@ -109,10 +119,10 @@ function TokensPage() {
109
119
  className: "mt-1 block w-full rounded-md border bg-background px-3 py-2 text-sm sm:w-36"
110
120
  })]
111
121
  }),
112
- /* @__PURE__ */ jsx("button", {
122
+ /* @__PURE__ */ jsx(Button, {
123
+ variant: "primary",
113
124
  type: "submit",
114
125
  disabled: busy,
115
- className: "rounded-md bg-primary px-3 py-2 text-sm font-medium text-primary-foreground disabled:opacity-50",
116
126
  children: busy ? "creating…" : "create"
117
127
  })
118
128
  ]
@@ -128,6 +138,7 @@ function TokensPage() {
128
138
  })]
129
139
  }),
130
140
  err && /* @__PURE__ */ jsx("p", {
141
+ role: "alert",
131
142
  className: "text-sm text-danger",
132
143
  children: err
133
144
  })
@@ -202,10 +213,13 @@ function TokensPage() {
202
213
  className: "text-muted-foreground text-xs",
203
214
  children: t.expiresAt ? fmtTs(t.expiresAt) : "(never)"
204
215
  }),
205
- /* @__PURE__ */ jsx("td", { children: !t.revokedAt && !isBootstrap && /* @__PURE__ */ jsx("button", {
206
- type: "button",
207
- onClick: () => revoke(t.id),
208
- className: "rounded-md border px-2 py-1 text-xs text-danger hover:bg-danger/10",
216
+ /* @__PURE__ */ jsx("td", { children: !t.revokedAt && !isBootstrap && /* @__PURE__ */ jsx(Button, {
217
+ variant: "danger",
218
+ className: "text-xs",
219
+ onClick: () => {
220
+ setErr(null);
221
+ setRevokeTokenTarget(t);
222
+ },
209
223
  children: "revoke"
210
224
  }) })
211
225
  ]
@@ -272,16 +286,71 @@ function TokensPage() {
272
286
  className: "text-xs text-muted-foreground",
273
287
  children: fmtTs(session.absoluteExpiresAt)
274
288
  }),
275
- /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx("button", {
276
- type: "button",
277
- onClick: () => revokeSession(session.id),
278
- className: "rounded-md border px-2 py-1 text-xs text-danger hover:bg-danger/10",
289
+ /* @__PURE__ */ jsx("td", { children: /* @__PURE__ */ jsx(Button, {
290
+ variant: "danger",
291
+ className: "text-xs",
292
+ onClick: () => {
293
+ setErr(null);
294
+ setRevokeSessionTarget(session);
295
+ },
279
296
  children: "revoke"
280
297
  }) })
281
298
  ]
282
299
  }, session.id))] })]
283
300
  })
284
301
  })]
302
+ }),
303
+ /* @__PURE__ */ jsx(ConfirmDialog, {
304
+ open: revokeTokenTarget !== null,
305
+ title: `Revoke ${revokeTokenTarget?.label ?? ""}?`,
306
+ description: /* @__PURE__ */ jsxs("p", { children: [
307
+ "This permanently revokes device token",
308
+ " ",
309
+ /* @__PURE__ */ jsx("code", {
310
+ className: "font-mono",
311
+ children: revokeTokenTarget?.id
312
+ }),
313
+ " and every browser session created from it. Clients using it will be signed out and cannot reconnect with this credential.",
314
+ sessions.some((session) => session.current && session.deviceTokenId === revokeTokenTarget?.id) && " This includes the browser session you are using now."
315
+ ] }),
316
+ confirmLabel: "revoke token and sessions",
317
+ onConfirm: async () => {
318
+ if (!revokeTokenTarget) return;
319
+ try {
320
+ await revoke(revokeTokenTarget.id, sessions.some((session) => session.current && session.deviceTokenId === revokeTokenTarget.id));
321
+ } catch (error) {
322
+ setErr(error instanceof Error ? error.message : String(error));
323
+ throw error;
324
+ }
325
+ },
326
+ onOpenChange: (open) => {
327
+ if (!open) setRevokeTokenTarget(null);
328
+ }
329
+ }),
330
+ /* @__PURE__ */ jsx(ConfirmDialog, {
331
+ open: revokeSessionTarget !== null,
332
+ title: `Revoke ${revokeSessionTarget?.deviceLabel ?? ""} browser session?`,
333
+ description: /* @__PURE__ */ jsxs("p", { children: [
334
+ "This ends browser session ",
335
+ /* @__PURE__ */ jsx("code", {
336
+ className: "font-mono",
337
+ children: revokeSessionTarget?.id
338
+ }),
339
+ revokeSessionTarget?.current ? " and signs this browser out immediately." : ". The device token remains active for future logins."
340
+ ] }),
341
+ confirmLabel: revokeSessionTarget?.current ? "sign out this browser" : "revoke session",
342
+ onConfirm: async () => {
343
+ if (!revokeSessionTarget) return;
344
+ try {
345
+ await revokeSession(revokeSessionTarget.id, revokeSessionTarget.current);
346
+ } catch (error) {
347
+ setErr(error instanceof Error ? error.message : String(error));
348
+ throw error;
349
+ }
350
+ },
351
+ onOpenChange: (open) => {
352
+ if (!open) setRevokeSessionTarget(null);
353
+ }
285
354
  })
286
355
  ]
287
356
  });
@@ -2,7 +2,7 @@ import { n as createServerFn } from "../server.js";
2
2
  import { t as createSsrRpc } from "./createSsrRpc-6LHNEsSK.js";
3
3
  import { createFileRoute, lazyRouteComponent } from "@tanstack/react-router";
4
4
  //#region src/routes/config/tokens.tsx
5
- var $$splitComponentImporter = () => import("./tokens-CJM_0NDa.js");
5
+ var $$splitComponentImporter = () => import("./tokens-DDwtO15P.js");
6
6
  var fetchTokens = createServerFn({ method: "POST" }).validator((d) => d).handler(createSsrRpc("46e35c9f1afc79423cb49703b454ef684344db08ec19775efd70a8768c7837f1"));
7
7
  var Route = createFileRoute("/config/tokens")({
8
8
  validateSearch: (s) => ({ all: s.all === "1" ? "1" : void 0 }),
@@ -2,7 +2,7 @@ import { n as createServerFn } from "../server.js";
2
2
  import { t as createSsrRpc } from "./createSsrRpc-6LHNEsSK.js";
3
3
  import { createFileRoute, lazyRouteComponent, redirect } from "@tanstack/react-router";
4
4
  //#region src/routes/agents/$id/triggers.tsx
5
- var $$splitComponentImporter = () => import("./triggers-B87fycBl.js");
5
+ var $$splitComponentImporter = () => import("./triggers-CHk9O3rU.js");
6
6
  var fetchTriggers = createServerFn({ method: "POST" }).validator((d) => d).handler(createSsrRpc("57ebf437fdb3fcfc63b176e796a55f04bdfec0b230059673196e98d413d15c4d"));
7
7
  var Route = createFileRoute("/agents/$id/triggers")({
8
8
  loader: async ({ params }) => {