@sympoies/dsh-telegram 0.0.0-bootstrap.0 → 0.6.1

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 (194) hide show
  1. package/LICENSE +1 -2
  2. package/NOTICE +19 -0
  3. package/README.md +588 -2
  4. package/cordis.patch.yml +14 -0
  5. package/lib/access.d.ts +76 -0
  6. package/lib/access.d.ts.map +1 -0
  7. package/lib/access.js +137 -0
  8. package/lib/access.js.map +1 -0
  9. package/lib/client.js +835 -0
  10. package/lib/commands.d.ts +51 -0
  11. package/lib/commands.d.ts.map +1 -0
  12. package/lib/commands.js +83 -0
  13. package/lib/commands.js.map +1 -0
  14. package/lib/config.d.ts +125 -0
  15. package/lib/config.d.ts.map +1 -0
  16. package/lib/config.js +97 -0
  17. package/lib/config.js.map +1 -0
  18. package/lib/diagnostics.d.ts +58 -0
  19. package/lib/diagnostics.d.ts.map +1 -0
  20. package/lib/diagnostics.js +59 -0
  21. package/lib/diagnostics.js.map +1 -0
  22. package/lib/failures.d.ts +71 -0
  23. package/lib/failures.d.ts.map +1 -0
  24. package/lib/failures.js +139 -0
  25. package/lib/failures.js.map +1 -0
  26. package/lib/harness/host.d.ts +106 -0
  27. package/lib/harness/host.d.ts.map +1 -0
  28. package/lib/harness/host.js +142 -0
  29. package/lib/harness/host.js.map +1 -0
  30. package/lib/harness/message.d.ts +45 -0
  31. package/lib/harness/message.d.ts.map +1 -0
  32. package/lib/harness/message.js +28 -0
  33. package/lib/harness/message.js.map +1 -0
  34. package/lib/harness/model-selection.d.ts +82 -0
  35. package/lib/harness/model-selection.d.ts.map +1 -0
  36. package/lib/harness/model-selection.js +103 -0
  37. package/lib/harness/model-selection.js.map +1 -0
  38. package/lib/harness/questions-seam.d.ts +34 -0
  39. package/lib/harness/questions-seam.d.ts.map +1 -0
  40. package/lib/harness/questions-seam.js +45 -0
  41. package/lib/harness/questions-seam.js.map +1 -0
  42. package/lib/harness/types.d.ts +108 -0
  43. package/lib/harness/types.d.ts.map +1 -0
  44. package/lib/harness/types.js +23 -0
  45. package/lib/harness/types.js.map +1 -0
  46. package/lib/index.d.ts +65 -0
  47. package/lib/index.d.ts.map +1 -0
  48. package/lib/index.js +977 -0
  49. package/lib/index.js.map +1 -0
  50. package/lib/interact/approvals.d.ts +59 -0
  51. package/lib/interact/approvals.d.ts.map +1 -0
  52. package/lib/interact/approvals.js +132 -0
  53. package/lib/interact/approvals.js.map +1 -0
  54. package/lib/interact/pending.d.ts +56 -0
  55. package/lib/interact/pending.d.ts.map +1 -0
  56. package/lib/interact/pending.js +89 -0
  57. package/lib/interact/pending.js.map +1 -0
  58. package/lib/interact/questions.d.ts +100 -0
  59. package/lib/interact/questions.d.ts.map +1 -0
  60. package/lib/interact/questions.js +255 -0
  61. package/lib/interact/questions.js.map +1 -0
  62. package/lib/interact/surface.d.ts +33 -0
  63. package/lib/interact/surface.d.ts.map +1 -0
  64. package/lib/interact/surface.js +39 -0
  65. package/lib/interact/surface.js.map +1 -0
  66. package/lib/interact/text-capture.d.ts +38 -0
  67. package/lib/interact/text-capture.d.ts.map +1 -0
  68. package/lib/interact/text-capture.js +75 -0
  69. package/lib/interact/text-capture.js.map +1 -0
  70. package/lib/media/collect.d.ts +157 -0
  71. package/lib/media/collect.d.ts.map +1 -0
  72. package/lib/media/collect.js +235 -0
  73. package/lib/media/collect.js.map +1 -0
  74. package/lib/media/extractor.d.ts +117 -0
  75. package/lib/media/extractor.d.ts.map +1 -0
  76. package/lib/media/extractor.js +207 -0
  77. package/lib/media/extractor.js.map +1 -0
  78. package/lib/media/intake.d.ts +57 -0
  79. package/lib/media/intake.d.ts.map +1 -0
  80. package/lib/media/intake.js +115 -0
  81. package/lib/media/intake.js.map +1 -0
  82. package/lib/media/limits.d.ts +69 -0
  83. package/lib/media/limits.d.ts.map +1 -0
  84. package/lib/media/limits.js +97 -0
  85. package/lib/media/limits.js.map +1 -0
  86. package/lib/media/ocr.d.ts +66 -0
  87. package/lib/media/ocr.d.ts.map +1 -0
  88. package/lib/media/ocr.js +131 -0
  89. package/lib/media/ocr.js.map +1 -0
  90. package/lib/media/screenshot.d.ts +57 -0
  91. package/lib/media/screenshot.d.ts.map +1 -0
  92. package/lib/media/screenshot.js +101 -0
  93. package/lib/media/screenshot.js.map +1 -0
  94. package/lib/media/vision.d.ts +60 -0
  95. package/lib/media/vision.d.ts.map +1 -0
  96. package/lib/media/vision.js +74 -0
  97. package/lib/media/vision.js.map +1 -0
  98. package/lib/render/clamp.d.ts +34 -0
  99. package/lib/render/clamp.d.ts.map +1 -0
  100. package/lib/render/clamp.js +65 -0
  101. package/lib/render/clamp.js.map +1 -0
  102. package/lib/render/escape.d.ts +15 -0
  103. package/lib/render/escape.d.ts.map +1 -0
  104. package/lib/render/escape.js +17 -0
  105. package/lib/render/escape.js.map +1 -0
  106. package/lib/reply/activity.d.ts +31 -0
  107. package/lib/reply/activity.d.ts.map +1 -0
  108. package/lib/reply/activity.js +88 -0
  109. package/lib/reply/activity.js.map +1 -0
  110. package/lib/reply/rich-stream.d.ts +173 -0
  111. package/lib/reply/rich-stream.d.ts.map +1 -0
  112. package/lib/reply/rich-stream.js +286 -0
  113. package/lib/reply/rich-stream.js.map +1 -0
  114. package/lib/reply/split-markdown.d.ts +21 -0
  115. package/lib/reply/split-markdown.d.ts.map +1 -0
  116. package/lib/reply/split-markdown.js +87 -0
  117. package/lib/reply/split-markdown.js.map +1 -0
  118. package/lib/reply/turn-bridge.d.ts +143 -0
  119. package/lib/reply/turn-bridge.d.ts.map +1 -0
  120. package/lib/reply/turn-bridge.js +182 -0
  121. package/lib/reply/turn-bridge.js.map +1 -0
  122. package/lib/router.d.ts +415 -0
  123. package/lib/router.d.ts.map +1 -0
  124. package/lib/router.js +663 -0
  125. package/lib/router.js.map +1 -0
  126. package/lib/secrets.d.ts +30 -0
  127. package/lib/secrets.d.ts.map +1 -0
  128. package/lib/secrets.js +51 -0
  129. package/lib/secrets.js.map +1 -0
  130. package/lib/session/bindings.d.ts +81 -0
  131. package/lib/session/bindings.d.ts.map +1 -0
  132. package/lib/session/bindings.js +170 -0
  133. package/lib/session/bindings.js.map +1 -0
  134. package/lib/session/history.d.ts +50 -0
  135. package/lib/session/history.d.ts.map +1 -0
  136. package/lib/session/history.js +127 -0
  137. package/lib/session/history.js.map +1 -0
  138. package/lib/session/models.d.ts +99 -0
  139. package/lib/session/models.d.ts.map +1 -0
  140. package/lib/session/models.js +123 -0
  141. package/lib/session/models.js.map +1 -0
  142. package/lib/session/permission.d.ts +83 -0
  143. package/lib/session/permission.d.ts.map +1 -0
  144. package/lib/session/permission.js +107 -0
  145. package/lib/session/permission.js.map +1 -0
  146. package/lib/session/picker.d.ts +49 -0
  147. package/lib/session/picker.d.ts.map +1 -0
  148. package/lib/session/picker.js +107 -0
  149. package/lib/session/picker.js.map +1 -0
  150. package/lib/session/preferences.d.ts +55 -0
  151. package/lib/session/preferences.d.ts.map +1 -0
  152. package/lib/session/preferences.js +102 -0
  153. package/lib/session/preferences.js.map +1 -0
  154. package/lib/session/recovery.d.ts +66 -0
  155. package/lib/session/recovery.d.ts.map +1 -0
  156. package/lib/session/recovery.js +112 -0
  157. package/lib/session/recovery.js.map +1 -0
  158. package/lib/session/runner.d.ts +223 -0
  159. package/lib/session/runner.d.ts.map +1 -0
  160. package/lib/session/runner.js +260 -0
  161. package/lib/session/runner.js.map +1 -0
  162. package/lib/session/workspaces.d.ts +28 -0
  163. package/lib/session/workspaces.d.ts.map +1 -0
  164. package/lib/session/workspaces.js +53 -0
  165. package/lib/session/workspaces.js.map +1 -0
  166. package/lib/telegram/addressing.d.ts +39 -0
  167. package/lib/telegram/addressing.d.ts.map +1 -0
  168. package/lib/telegram/addressing.js +81 -0
  169. package/lib/telegram/addressing.js.map +1 -0
  170. package/lib/telegram/albums.d.ts +46 -0
  171. package/lib/telegram/albums.d.ts.map +1 -0
  172. package/lib/telegram/albums.js +104 -0
  173. package/lib/telegram/albums.js.map +1 -0
  174. package/lib/telegram/api.d.ts +238 -0
  175. package/lib/telegram/api.d.ts.map +1 -0
  176. package/lib/telegram/api.js +518 -0
  177. package/lib/telegram/api.js.map +1 -0
  178. package/lib/telegram/poller.d.ts +59 -0
  179. package/lib/telegram/poller.d.ts.map +1 -0
  180. package/lib/telegram/poller.js +94 -0
  181. package/lib/telegram/poller.js.map +1 -0
  182. package/lib/telegram/types.d.ts +130 -0
  183. package/lib/telegram/types.d.ts.map +1 -0
  184. package/lib/telegram/types.js +9 -0
  185. package/lib/telegram/types.js.map +1 -0
  186. package/lib/telegram/typing.d.ts +47 -0
  187. package/lib/telegram/typing.d.ts.map +1 -0
  188. package/lib/telegram/typing.js +91 -0
  189. package/lib/telegram/typing.js.map +1 -0
  190. package/lib/versions.d.ts +63 -0
  191. package/lib/versions.d.ts.map +1 -0
  192. package/lib/versions.js +135 -0
  193. package/lib/versions.js.map +1 -0
  194. package/package.json +94 -10
package/lib/client.js ADDED
@@ -0,0 +1,835 @@
1
+ window.__ModuleLoader__.load({
2
+ id: "@sympoies/dsh-telegram",
3
+ factory: (require) => {
4
+ var module = { exports: {} };
5
+ var exports = module.exports;
6
+ try {
7
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
8
+ } catch (e) { /* environments without Symbol support */ }
9
+ "use strict";
10
+ var __defProp = Object.defineProperty;
11
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
+ var __getOwnPropNames = Object.getOwnPropertyNames;
13
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
14
+ var __export = (target, all) => {
15
+ for (var name2 in all)
16
+ __defProp(target, name2, { get: all[name2], enumerable: true });
17
+ };
18
+ var __copyProps = (to, from, except, desc) => {
19
+ if (from && typeof from === "object" || typeof from === "function") {
20
+ for (let key of __getOwnPropNames(from))
21
+ if (!__hasOwnProp.call(to, key) && key !== except)
22
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
23
+ }
24
+ return to;
25
+ };
26
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
27
+
28
+ // src/client/index.tsx
29
+ var index_exports = {};
30
+ __export(index_exports, {
31
+ apply: () => apply,
32
+ inject: () => inject,
33
+ name: () => name
34
+ });
35
+ module.exports = __toCommonJS(index_exports);
36
+
37
+ // src/client/panel.tsx
38
+ var import_react = require("react");
39
+
40
+ // src/client/fields.tsx
41
+ var import_jsx_runtime = require("react/jsx-runtime");
42
+ var TEXT = {
43
+ primary: "var(--dsw-alias-label-primary, currentColor)",
44
+ secondary: "var(--dsw-alias-label-secondary, #6b7280)",
45
+ tertiary: "var(--dsw-alias-label-tertiary, #9ca3af)"
46
+ };
47
+ var FILL = {
48
+ /** High contrast against the page. Near-black in light, near-white in dark. */
49
+ brand: "var(--dsw-alias-brand-primary, #4d6bfe)",
50
+ /** The shell's own action blue, for a control that is switched on. */
51
+ action: "var(--dsw-alias-button-info-fill, #4176e6)",
52
+ surface: "var(--dsw-alias-bg-layer-1, transparent)",
53
+ /** A neutral track: a border token reads as a faint fill in both themes. */
54
+ neutral: "var(--dsw-alias-border-l2, rgba(128,128,128,0.45))"
55
+ };
56
+ var COLOR = {
57
+ text: TEXT.primary,
58
+ muted: TEXT.secondary,
59
+ faint: TEXT.tertiary,
60
+ border: "var(--dsw-alias-border-l1, rgba(128,128,128,0.28))",
61
+ borderStrong: "var(--dsw-alias-border-l2, rgba(128,128,128,0.45))",
62
+ surface: FILL.surface,
63
+ accent: FILL.brand,
64
+ danger: "var(--dsw-alias-state-error-primary, #dc2626)",
65
+ success: "var(--dsw-alias-state-success-primary, #16a34a)",
66
+ warn: "var(--dsw-alias-state-warn-primary, #d97706)"
67
+ };
68
+ function Section(props) {
69
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { style: { marginBottom: 28 }, children: [
70
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
71
+ "h3",
72
+ {
73
+ style: {
74
+ margin: "0 0 12px",
75
+ fontSize: 13,
76
+ fontWeight: 600,
77
+ letterSpacing: "0.04em",
78
+ textTransform: "uppercase",
79
+ color: COLOR.faint
80
+ },
81
+ children: props.title
82
+ }
83
+ ),
84
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
85
+ "div",
86
+ {
87
+ style: {
88
+ border: `1px solid ${COLOR.border}`,
89
+ borderRadius: 10,
90
+ background: COLOR.surface,
91
+ overflow: "hidden"
92
+ },
93
+ children: props.children
94
+ }
95
+ )
96
+ ] });
97
+ }
98
+ function Row(props) {
99
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
100
+ "div",
101
+ {
102
+ style: {
103
+ display: "flex",
104
+ gap: 16,
105
+ alignItems: "flex-start",
106
+ padding: "14px 16px",
107
+ borderBottom: `1px solid ${COLOR.border}`
108
+ },
109
+ children: [
110
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { flex: "1 1 auto", minWidth: 0 }, children: [
111
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8, color: COLOR.text, fontSize: 14 }, children: [
112
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: props.label }),
113
+ props.overridden ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
114
+ "span",
115
+ {
116
+ style: {
117
+ fontSize: 11,
118
+ padding: "1px 6px",
119
+ borderRadius: 999,
120
+ color: COLOR.accent,
121
+ border: `1px solid ${COLOR.accent}`,
122
+ opacity: 0.85
123
+ },
124
+ children: props.overriddenLabel ?? "changed"
125
+ }
126
+ ) : null,
127
+ props.overridden && props.onReset ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", onClick: props.onReset, style: linkButtonStyle, children: props.resetLabel ?? "Reset" }) : null
128
+ ] }),
129
+ props.hint ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { marginTop: 4, fontSize: 12, lineHeight: 1.5, color: COLOR.muted }, children: props.hint }) : null
130
+ ] }),
131
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { flex: "0 0 auto", display: "flex", alignItems: "center", gap: 8 }, children: props.children })
132
+ ]
133
+ }
134
+ );
135
+ }
136
+ function TextInput(props) {
137
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
138
+ "input",
139
+ {
140
+ type: props.type ?? "text",
141
+ value: props.value,
142
+ placeholder: props.placeholder ?? "",
143
+ disabled: props.disabled ?? false,
144
+ onChange: (event) => props.onChange(event.target.value),
145
+ onBlur: props.onCommit ?? (() => void 0),
146
+ onKeyDown: (event) => {
147
+ if (event.key === "Enter") props.onCommit?.();
148
+ },
149
+ style: {
150
+ width: props.width ?? 220,
151
+ padding: "6px 10px",
152
+ fontSize: 13,
153
+ color: COLOR.text,
154
+ background: "transparent",
155
+ border: `1px solid ${props.invalid ? COLOR.danger : COLOR.borderStrong}`,
156
+ borderRadius: 6,
157
+ outline: "none",
158
+ opacity: props.disabled ? 0.5 : 1
159
+ }
160
+ }
161
+ );
162
+ }
163
+ function NumberInput(props) {
164
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
165
+ "input",
166
+ {
167
+ type: "number",
168
+ defaultValue: String(props.value),
169
+ disabled: props.disabled ?? false,
170
+ min: props.min ?? 0,
171
+ onBlur: (event) => {
172
+ const next = Number(event.target.value);
173
+ if (Number.isFinite(next) && Number.isInteger(next) && next >= (props.min ?? 0)) {
174
+ if (next !== props.value) props.onCommit(next);
175
+ }
176
+ },
177
+ style: {
178
+ width: 110,
179
+ padding: "6px 10px",
180
+ fontSize: 13,
181
+ color: COLOR.text,
182
+ background: "transparent",
183
+ border: `1px solid ${COLOR.borderStrong}`,
184
+ borderRadius: 6,
185
+ outline: "none",
186
+ opacity: props.disabled ? 0.5 : 1
187
+ }
188
+ },
189
+ props.value
190
+ );
191
+ }
192
+ function Toggle(props) {
193
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
194
+ "button",
195
+ {
196
+ type: "button",
197
+ role: "switch",
198
+ "aria-checked": props.checked,
199
+ disabled: props.disabled ?? false,
200
+ onClick: () => props.onChange(!props.checked),
201
+ style: {
202
+ boxSizing: "border-box",
203
+ // border-box plus these numbers leaves a 34x16 content box, so the
204
+ // knob's travel below is exactly its width.
205
+ width: 40,
206
+ height: 22,
207
+ padding: 2,
208
+ // Never transparent: a track whose colour happens to match the page
209
+ // would otherwise stop reading as a control at all. Off keeps a visible
210
+ // edge; on, the fill already carries the shape.
211
+ border: `1px solid ${props.checked ? "transparent" : COLOR.border}`,
212
+ borderRadius: 999,
213
+ // Blue rather than the brand neutral: "on" should be a colour, not a
214
+ // shade that inverts with the theme and reads as neither state.
215
+ background: props.checked ? FILL.action : FILL.neutral,
216
+ cursor: props.disabled ? "default" : "pointer",
217
+ opacity: props.disabled ? 0.5 : 1,
218
+ transition: "background 120ms ease"
219
+ },
220
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
221
+ "span",
222
+ {
223
+ style: {
224
+ display: "block",
225
+ width: 16,
226
+ height: 16,
227
+ borderRadius: "50%",
228
+ // White on both tracks now: the blue is dark enough in either theme
229
+ // for a white knob to carry the contrast, which is also the shape
230
+ // every other switch anyone has used has.
231
+ background: "#fff",
232
+ border: "1px solid rgba(0, 0, 0, 0.12)",
233
+ boxSizing: "border-box",
234
+ boxShadow: "0 1px 2px rgba(0, 0, 0, 0.2)",
235
+ transform: props.checked ? "translateX(18px)" : "translateX(0)",
236
+ transition: "transform 120ms ease"
237
+ }
238
+ }
239
+ )
240
+ }
241
+ );
242
+ }
243
+ function Select(props) {
244
+ const groups = [...new Set(props.options.map((option) => option.group ?? ""))];
245
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
246
+ "select",
247
+ {
248
+ value: props.value,
249
+ disabled: props.disabled ?? false,
250
+ onChange: (event) => props.onChange(event.target.value),
251
+ style: {
252
+ width: props.width ?? 240,
253
+ padding: "6px 8px",
254
+ fontSize: 13,
255
+ color: COLOR.text,
256
+ // A transparent select shows the page through its own popup on some
257
+ // platforms; a real surface keeps it readable in both themes.
258
+ background: FILL.surface,
259
+ border: `1px solid ${COLOR.borderStrong}`,
260
+ borderRadius: 6,
261
+ outline: "none",
262
+ opacity: props.disabled ? 0.5 : 1
263
+ },
264
+ children: groups.map((group) => {
265
+ const members = props.options.filter((option) => (option.group ?? "") === group);
266
+ const items = members.map((option) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: option.value, children: option.label }, option.value));
267
+ return group === "" ? items : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("optgroup", { label: group, children: items }, group);
268
+ })
269
+ }
270
+ );
271
+ }
272
+ function Button(props) {
273
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
274
+ "button",
275
+ {
276
+ type: "button",
277
+ onClick: props.onClick,
278
+ disabled: props.disabled ?? false,
279
+ style: {
280
+ padding: "6px 12px",
281
+ fontSize: 13,
282
+ color: props.tone === "danger" ? COLOR.danger : COLOR.text,
283
+ background: "transparent",
284
+ border: `1px solid ${props.tone === "danger" ? COLOR.danger : COLOR.borderStrong}`,
285
+ borderRadius: 6,
286
+ cursor: props.disabled ? "default" : "pointer",
287
+ opacity: props.disabled ? 0.45 : 1
288
+ },
289
+ children: props.children
290
+ }
291
+ );
292
+ }
293
+ function Note(props) {
294
+ const color = props.tone === "good" ? COLOR.success : props.tone === "warn" ? COLOR.warn : props.tone === "bad" ? COLOR.danger : COLOR.muted;
295
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontSize: 12, lineHeight: 1.6, color }, children: props.children });
296
+ }
297
+ var linkButtonStyle = {
298
+ padding: 0,
299
+ fontSize: 11,
300
+ color: COLOR.muted,
301
+ background: "transparent",
302
+ border: "none",
303
+ cursor: "pointer",
304
+ textDecoration: "underline"
305
+ };
306
+
307
+ // src/client/panel.tsx
308
+ var import_jsx_runtime2 = require("react/jsx-runtime");
309
+ function TelegramPanel({ scope, remote, t }) {
310
+ const snapshot = useSettingsSnapshot(scope);
311
+ const [failure, setFailure] = (0, import_react.useState)();
312
+ const write = (0, import_react.useCallback)(
313
+ (field, value2) => {
314
+ setFailure(void 0);
315
+ void scope.set(field, value2).catch((error) => {
316
+ setFailure(error instanceof Error ? error.message : String(error));
317
+ });
318
+ },
319
+ [scope]
320
+ );
321
+ const clear = (0, import_react.useCallback)(
322
+ (field) => {
323
+ setFailure(void 0);
324
+ void scope.unset(field).catch((error) => {
325
+ setFailure(error instanceof Error ? error.message : String(error));
326
+ });
327
+ },
328
+ [scope]
329
+ );
330
+ if (snapshot.status === "loading") return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Page, { t, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Note, { tone: "info", children: t("loading") }) });
331
+ if (snapshot.status === "unavailable" || snapshot.mode === "memory") {
332
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Page, { t, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Note, { tone: "warn", children: t("unavailable") }) });
333
+ }
334
+ const value = snapshot.value;
335
+ if (!value) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Page, { t, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Note, { tone: "info", children: t("loading") }) });
336
+ const locked = !snapshot.writable;
337
+ const overridden = (field) => isOverridden(snapshot.user, field);
338
+ const writeNested = (parent, patch) => write(parent, { ...value[parent], ...patch });
339
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Page, { t, children: [
340
+ locked ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Note, { tone: "warn", children: t("readonly") }) : null,
341
+ failure ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Note, { tone: "bad", children: t("saveFailed", { reason: failure }) }) : null,
342
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Section, { title: t("connectionTitle"), children: [
343
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
344
+ Row,
345
+ {
346
+ label: t("enabled"),
347
+ hint: t("enabledHint"),
348
+ overridden: overridden("enabled"),
349
+ overriddenLabel: t("overridden"),
350
+ resetLabel: t("reset"),
351
+ onReset: () => clear("enabled"),
352
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
353
+ Toggle,
354
+ {
355
+ checked: value.enabled,
356
+ disabled: locked,
357
+ onChange: (next) => write("enabled", next)
358
+ }
359
+ )
360
+ }
361
+ ),
362
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(TokenRow, { ref_: value.tokenRef, remote, t, locked }),
363
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
364
+ Row,
365
+ {
366
+ label: t("tokenRef"),
367
+ hint: t("tokenRefHint"),
368
+ overridden: overridden("tokenRef"),
369
+ overriddenLabel: t("overridden"),
370
+ resetLabel: t("reset"),
371
+ onReset: () => clear("tokenRef"),
372
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CommittedText, { value: value.tokenRef, disabled: locked, onCommit: (next) => write("tokenRef", next) })
373
+ }
374
+ ),
375
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
376
+ Row,
377
+ {
378
+ label: t("baseUrl"),
379
+ hint: t("baseUrlHint"),
380
+ overridden: overridden("baseUrl"),
381
+ overriddenLabel: t("overridden"),
382
+ resetLabel: t("reset"),
383
+ onReset: () => clear("baseUrl"),
384
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CommittedText, { value: value.baseUrl, disabled: locked, onCommit: (next) => write("baseUrl", next) })
385
+ }
386
+ )
387
+ ] }),
388
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Section, { title: t("accessTitle"), children: [
389
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { padding: "12px 16px", borderBottom: "1px solid var(--dsw-alias-border-l1, rgba(128,128,128,0.28))" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Note, { tone: "warn", children: t("accessWarning") }) }),
390
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
391
+ AllowListRow,
392
+ {
393
+ ids: value.allowFrom,
394
+ locked,
395
+ overridden: overridden("allowFrom"),
396
+ t,
397
+ onCommit: (ids) => write("allowFrom", ids),
398
+ onReset: () => clear("allowFrom")
399
+ }
400
+ )
401
+ ] }),
402
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Section, { title: t("mediaTitle"), children: [
403
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
404
+ Row,
405
+ {
406
+ label: t("mediaEnabled"),
407
+ hint: t("mediaHint"),
408
+ overridden: overridden("media"),
409
+ overriddenLabel: t("overridden"),
410
+ resetLabel: t("reset"),
411
+ onReset: () => clear("media"),
412
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
413
+ Toggle,
414
+ {
415
+ checked: value.media.enabled,
416
+ disabled: locked,
417
+ onChange: (next) => writeNested("media", { enabled: next })
418
+ }
419
+ )
420
+ }
421
+ ),
422
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
423
+ VisionModelRow,
424
+ {
425
+ value: value.media.visionModel ?? "",
426
+ remote,
427
+ t,
428
+ disabled: locked || !value.media.enabled,
429
+ onChange: (next) => writeNested("media", { visionModel: next })
430
+ }
431
+ )
432
+ ] }),
433
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Section, { title: t("screenTitle"), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
434
+ Row,
435
+ {
436
+ label: t("screenshotEnabled"),
437
+ hint: t("screenshotHint"),
438
+ overridden: overridden("screenshot"),
439
+ overriddenLabel: t("overridden"),
440
+ resetLabel: t("reset"),
441
+ onReset: () => clear("screenshot"),
442
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
443
+ Toggle,
444
+ {
445
+ checked: value.screenshot.enabled,
446
+ disabled: locked,
447
+ onChange: (next) => writeNested("screenshot", { enabled: next })
448
+ }
449
+ )
450
+ }
451
+ ) }),
452
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Section, { title: t("repliesTitle"), children: [
453
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
454
+ Row,
455
+ {
456
+ label: t("streamingEnabled"),
457
+ hint: t("streamingHint"),
458
+ overridden: overridden("streaming"),
459
+ overriddenLabel: t("overridden"),
460
+ resetLabel: t("reset"),
461
+ onReset: () => clear("streaming"),
462
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
463
+ Toggle,
464
+ {
465
+ checked: value.streaming.enabled,
466
+ disabled: locked,
467
+ onChange: (next) => writeNested("streaming", { enabled: next })
468
+ }
469
+ )
470
+ }
471
+ ),
472
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Row, { label: t("throttle"), hint: t("throttleHint"), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
473
+ NumberInput,
474
+ {
475
+ value: value.streaming.throttleMs,
476
+ disabled: locked,
477
+ onCommit: (next) => writeNested("streaming", { throttleMs: next })
478
+ }
479
+ ) })
480
+ ] }),
481
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Section, { title: t("advancedTitle"), children: [
482
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
483
+ Row,
484
+ {
485
+ label: t("cwd"),
486
+ hint: t("cwdHint"),
487
+ overridden: overridden("cwd"),
488
+ overriddenLabel: t("overridden"),
489
+ resetLabel: t("reset"),
490
+ onReset: () => clear("cwd"),
491
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CommittedText, { value: value.cwd ?? "", width: 280, disabled: locked, onCommit: (next) => write("cwd", next) })
492
+ }
493
+ ),
494
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Row, { label: t("longPoll"), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
495
+ NumberInput,
496
+ {
497
+ value: value.longPollSeconds,
498
+ min: 1,
499
+ disabled: locked,
500
+ onCommit: (next) => write("longPollSeconds", next)
501
+ }
502
+ ) }),
503
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Row, { label: t("timeout"), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
504
+ NumberInput,
505
+ {
506
+ value: value.timeoutMs,
507
+ min: 1e3,
508
+ disabled: locked,
509
+ onCommit: (next) => write("timeoutMs", next)
510
+ }
511
+ ) })
512
+ ] })
513
+ ] });
514
+ }
515
+ function Page(props) {
516
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { maxWidth: 720, padding: "8px 4px 40px" }, children: [
517
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { style: { margin: "0 0 6px", fontSize: 20, color: "var(--dsw-alias-label-primary, currentColor)" }, children: props.t("heading") }),
518
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { margin: "0 0 24px", fontSize: 13, color: "var(--dsw-alias-label-secondary, #6b7280)" }, children: props.t("subheading") }),
519
+ props.children
520
+ ] });
521
+ }
522
+ function presentToken(state, locked) {
523
+ if (state.kind === "checking") {
524
+ return { hint: "tokenChecking", editable: false, retryable: false, removable: false };
525
+ }
526
+ if (state.kind === "unknown") {
527
+ return {
528
+ hint: "tokenCheckFailed",
529
+ params: { reason: state.reason },
530
+ editable: false,
531
+ retryable: true,
532
+ removable: false
533
+ };
534
+ }
535
+ if (!state.writable) {
536
+ return {
537
+ hint: state.source === "env" ? "tokenFromEnvironment" : "tokenReadOnly",
538
+ editable: false,
539
+ retryable: false,
540
+ removable: false
541
+ };
542
+ }
543
+ return {
544
+ hint: state.configured ? "tokenConfigured" : "tokenMissing",
545
+ editable: !locked,
546
+ retryable: false,
547
+ removable: state.configured && !locked
548
+ };
549
+ }
550
+ function TokenRow(props) {
551
+ const { ref_, remote, t } = props;
552
+ const [state, setState] = (0, import_react.useState)({ kind: "checking" });
553
+ const [draft, setDraft] = (0, import_react.useState)("");
554
+ const [saved, setSaved] = (0, import_react.useState)(false);
555
+ const [failure, setFailure] = (0, import_react.useState)();
556
+ const refresh = (0, import_react.useCallback)(() => {
557
+ setState({ kind: "checking" });
558
+ void remote.credentials.describe({ refs: [ref_] }).then((answer) => {
559
+ if (!answer.result.ok) {
560
+ return setState({ kind: "unknown", reason: answer.result.error.message });
561
+ }
562
+ const info = answer.result.value.credentials[ref_];
563
+ if (!info) {
564
+ return setState({ kind: "known", configured: false, writable: true });
565
+ }
566
+ setState({
567
+ kind: "known",
568
+ configured: info.configured,
569
+ writable: info.writable,
570
+ ...info.source !== void 0 ? { source: info.source } : {}
571
+ });
572
+ }).catch((error) => {
573
+ setState({ kind: "unknown", reason: error instanceof Error ? error.message : String(error) });
574
+ });
575
+ }, [remote, ref_]);
576
+ (0, import_react.useEffect)(refresh, [refresh]);
577
+ const view = presentToken(state, props.locked);
578
+ const save = () => {
579
+ if (draft === "") return;
580
+ setFailure(void 0);
581
+ void remote.credentials.set({ ref: ref_, value: draft }).then((answer) => {
582
+ if (!answer.result.ok) return setFailure(answer.result.error.message);
583
+ setDraft("");
584
+ setSaved(true);
585
+ refresh();
586
+ }).catch((error) => setFailure(error instanceof Error ? error.message : String(error)));
587
+ };
588
+ const remove = () => {
589
+ setFailure(void 0);
590
+ void remote.credentials.unset({ ref: ref_ }).then((answer) => {
591
+ if (!answer.result.ok) return setFailure(answer.result.error.message);
592
+ setSaved(false);
593
+ refresh();
594
+ }).catch((error) => setFailure(error instanceof Error ? error.message : String(error)));
595
+ };
596
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Row, { label: t("tokenTitle"), hint: t(view.hint, view.params), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", flexDirection: "column", alignItems: "flex-end", gap: 6 }, children: [
597
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: 8 }, children: [
598
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
599
+ TextInput,
600
+ {
601
+ type: "password",
602
+ value: draft,
603
+ onChange: setDraft,
604
+ onCommit: save,
605
+ placeholder: t("tokenPlaceholder"),
606
+ disabled: !view.editable
607
+ }
608
+ ),
609
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Button, { onClick: save, disabled: !view.editable || draft === "", children: t("tokenSave") })
610
+ ] }),
611
+ view.retryable ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Button, { onClick: refresh, children: t("tokenRetry") }) : null,
612
+ view.removable ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Button, { onClick: remove, tone: "danger", children: t("tokenClear") }) : null,
613
+ saved ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Note, { tone: "good", children: t("tokenSaved") }) : null,
614
+ failure ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Note, { tone: "bad", children: failure }) : null
615
+ ] }) });
616
+ }
617
+ function VisionModelRow(props) {
618
+ const { remote, t } = props;
619
+ const [groups, setGroups] = (0, import_react.useState)();
620
+ const [failed, setFailed] = (0, import_react.useState)(false);
621
+ (0, import_react.useEffect)(() => {
622
+ let stale = false;
623
+ void remote.llm.models({}).then((answer) => {
624
+ if (stale) return;
625
+ if (!answer.result.ok) return setFailed(true);
626
+ setGroups(answer.result.value.groups);
627
+ }).catch(() => {
628
+ if (!stale) setFailed(true);
629
+ });
630
+ return () => {
631
+ stale = true;
632
+ };
633
+ }, [remote]);
634
+ const options = (0, import_react.useMemo)(() => {
635
+ const listed = [{ value: "", label: t("visionModelNone") }];
636
+ for (const group of groups ?? []) {
637
+ for (const model of group.models) {
638
+ listed.push({
639
+ value: `${group.id}/${model.id}`,
640
+ label: model.name ?? model.id,
641
+ group: group.name ?? group.id
642
+ });
643
+ }
644
+ }
645
+ if (props.value !== "" && !listed.some((option) => option.value === props.value)) {
646
+ listed.push({ value: props.value, label: props.value, group: t("visionModelUnavailable") });
647
+ }
648
+ return listed;
649
+ }, [groups, props.value, t]);
650
+ const hint = failed ? t("visionModelUnreadable") : groups === void 0 ? t("visionModelLoading") : t("visionModelHint");
651
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Row, { label: t("visionModel"), hint, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
652
+ Select,
653
+ {
654
+ value: props.value,
655
+ options,
656
+ disabled: props.disabled || groups === void 0,
657
+ onChange: props.onChange,
658
+ width: 260
659
+ }
660
+ ) });
661
+ }
662
+ function AllowListRow(props) {
663
+ const stored = (0, import_react.useMemo)(() => props.ids.join(", "), [props.ids]);
664
+ const [draft, setDraft] = (0, import_react.useState)(stored);
665
+ const [invalid, setInvalid] = (0, import_react.useState)(false);
666
+ (0, import_react.useEffect)(() => {
667
+ setDraft(stored);
668
+ setInvalid(false);
669
+ }, [stored]);
670
+ const commit = () => {
671
+ const parsed = parseIds(draft);
672
+ if (!parsed) return setInvalid(true);
673
+ setInvalid(false);
674
+ if (parsed.join(",") !== props.ids.join(",")) props.onCommit(parsed);
675
+ };
676
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
677
+ Row,
678
+ {
679
+ label: props.t("allowFrom"),
680
+ hint: invalid ? props.t("allowFromInvalid") : props.t("allowFromHint"),
681
+ overridden: props.overridden,
682
+ overriddenLabel: props.t("overridden"),
683
+ resetLabel: props.t("reset"),
684
+ onReset: props.onReset,
685
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
686
+ TextInput,
687
+ {
688
+ value: draft,
689
+ onChange: setDraft,
690
+ onCommit: commit,
691
+ disabled: props.locked,
692
+ invalid,
693
+ width: 240,
694
+ placeholder: "562660734, 12345678"
695
+ }
696
+ )
697
+ }
698
+ );
699
+ }
700
+ function CommittedText(props) {
701
+ const [draft, setDraft] = (0, import_react.useState)(props.value);
702
+ (0, import_react.useEffect)(() => setDraft(props.value), [props.value]);
703
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
704
+ TextInput,
705
+ {
706
+ value: draft,
707
+ onChange: setDraft,
708
+ onCommit: () => {
709
+ if (draft !== props.value) props.onCommit(draft);
710
+ },
711
+ disabled: props.disabled ?? false,
712
+ ...props.width !== void 0 ? { width: props.width } : {}
713
+ }
714
+ );
715
+ }
716
+ function useSettingsSnapshot(scope) {
717
+ const [snapshot, setSnapshot] = (0, import_react.useState)(() => scope.getSnapshot());
718
+ (0, import_react.useEffect)(() => {
719
+ setSnapshot(scope.getSnapshot());
720
+ return scope.subscribe(() => setSnapshot(scope.getSnapshot()));
721
+ }, [scope]);
722
+ return snapshot;
723
+ }
724
+ function isOverridden(user, field) {
725
+ if (typeof user !== "object" || user === null) return false;
726
+ return Object.hasOwn(user, field);
727
+ }
728
+ function parseIds(text) {
729
+ const trimmed = text.trim();
730
+ if (trimmed === "") return [];
731
+ const ids = [];
732
+ for (const part of trimmed.split(",")) {
733
+ const id = Number(part.trim());
734
+ if (!Number.isInteger(id) || id <= 0) return void 0;
735
+ ids.push(id);
736
+ }
737
+ return ids;
738
+ }
739
+
740
+ // src/client/locale.ts
741
+ var locales = {
742
+ en: {
743
+ nav: "Telegram",
744
+ heading: "Telegram",
745
+ subheading: "Talk to the agent from Telegram, with real formatting and answerable questions.",
746
+ loading: "Reading configuration\u2026",
747
+ unavailable: "This browser cannot reach the settings document, so nothing here can be changed. Settings are loopback-only \u2014 open the harness on the machine running it.",
748
+ readonly: "The settings document is read-only in this deployment.",
749
+ connectionTitle: "Connection",
750
+ enabled: "Connected",
751
+ enabledHint: "Turn off to disconnect the bot without removing the plugin.",
752
+ tokenTitle: "Bot token",
753
+ tokenChecking: "Checking\u2026",
754
+ tokenCheckFailed: "Could not check the stored token: {reason}",
755
+ tokenRetry: "Check again",
756
+ tokenReadOnly: "This credential is read-only in this deployment.",
757
+ tokenConfigured: "A token is stored.",
758
+ tokenMissing: "No token yet. Create a bot with @BotFather and paste its token here.",
759
+ tokenFromEnvironment: "Supplied by the environment, so it cannot be changed here.",
760
+ tokenPlaceholder: "Paste a bot token",
761
+ tokenSave: "Save token",
762
+ tokenClear: "Remove token",
763
+ tokenSaved: "Token saved. Reconnecting.",
764
+ tokenRef: "Credential reference",
765
+ tokenRefHint: "Where the token is stored. Change it only to keep several bots apart.",
766
+ baseUrl: "Bot API address",
767
+ baseUrlHint: "Change only when routing through a proxy.",
768
+ accessTitle: "Access",
769
+ accessWarning: "Anyone allowed here can make the agent run commands on this machine. Leave the list empty to hand the bot to one person with the claim code printed on the console.",
770
+ allowFrom: "Allowed Telegram user ids",
771
+ allowFromHint: "Comma separated. Empty enables the one-time claim flow. Send /whoami to find an id.",
772
+ allowFromInvalid: "Enter numeric user ids separated by commas.",
773
+ mediaTitle: "Attachments",
774
+ mediaEnabled: "Read images and text files",
775
+ mediaHint: "Off replies that attachments are not accepted.",
776
+ visionModel: "Model that reads images",
777
+ visionModelHint: "Chosen from the models added in Settings \u2192 Models. It must accept images \u2014 no DeepSeek model does. An image is read in a session of its own, and only what it says joins your conversation, which therefore keeps its own model and tools.",
778
+ visionModelNone: "Send the image to the conversation itself",
779
+ visionModelLoading: "Reading the configured models\u2026",
780
+ visionModelUnreadable: "Could not read the configured models. Add one in Settings \u2192 Models.",
781
+ visionModelUnavailable: "No longer configured",
782
+ screenTitle: "Screen",
783
+ screenshotEnabled: "Allow /screenshot",
784
+ screenshotHint: "Sends a picture of this machine's screen to the chat. Off by default \u2014 a screen holds whatever happens to be on it. On macOS the harness also needs Screen Recording permission.",
785
+ repliesTitle: "Replies",
786
+ streamingEnabled: "Stream the answer as it is written",
787
+ streamingHint: "Off sends each reply once, when it is finished.",
788
+ throttle: "Minimum gap between edits (ms)",
789
+ throttleHint: "Telegram rate-limits rapid edits to one chat. Below about a second invites that.",
790
+ advancedTitle: "Advanced",
791
+ cwd: "Working directory for new conversations",
792
+ cwdHint: "Empty uses the directory the harness was started in.",
793
+ longPoll: "Long-poll seconds",
794
+ timeout: "Request timeout (ms)",
795
+ overridden: "changed",
796
+ reset: "Reset",
797
+ saveFailed: "That change was not saved: {reason}"
798
+ }
799
+ };
800
+
801
+ // src/client/index.tsx
802
+ var import_jsx_runtime3 = require("react/jsx-runtime");
803
+ var name = "@sympoies/dsh-telegram";
804
+ var inject = ["slots", "locale", "settingsScope"];
805
+ var NAMESPACE = "telegram";
806
+ var NAV_ORDER = 61;
807
+ function apply(ctx) {
808
+ ctx.effect(() => {
809
+ ctx.locale.register(NAMESPACE, locales);
810
+ }, "dsh-telegram: locales");
811
+ const translate = ctx.locale.bind(NAMESPACE);
812
+ const scope = ctx.settingsScope.bind({ namespace: NAMESPACE });
813
+ const connection = ctx.get("connection");
814
+ const Section2 = function TelegramSection() {
815
+ if (!connection) return null;
816
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(TelegramPanel, { scope, remote: connection.api, t: translate });
817
+ };
818
+ ctx.slots.inject(
819
+ "settings.section",
820
+ () => ctx.slots.register(
821
+ {
822
+ name: "settings.section",
823
+ id: NAMESPACE,
824
+ order: NAV_ORDER,
825
+ label: () => translate("nav"),
826
+ locale: NAMESPACE
827
+ },
828
+ Section2
829
+ )
830
+ );
831
+ }
832
+
833
+ return module.exports;
834
+ }
835
+ });