dsh-telegram-connector 0.0.0-stage → 0.13.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 (79) hide show
  1. package/CHANGELOG.md +984 -0
  2. package/COMPATIBILITY.md +169 -0
  3. package/LICENSE +21 -0
  4. package/README.md +533 -2
  5. package/cordis.patch.yml +19 -0
  6. package/docs/COMMANDS.md +305 -0
  7. package/docs/DESIGN.md +566 -0
  8. package/docs/STANDALONE.md +95 -0
  9. package/lib/about.d.ts +15 -0
  10. package/lib/about.js +42 -0
  11. package/lib/about.js.map +1 -0
  12. package/lib/bindings.d.ts +116 -0
  13. package/lib/bindings.js +163 -0
  14. package/lib/bindings.js.map +1 -0
  15. package/lib/bots.d.ts +70 -0
  16. package/lib/bots.js +157 -0
  17. package/lib/bots.js.map +1 -0
  18. package/lib/bridge.d.ts +49 -0
  19. package/lib/bridge.js +104 -0
  20. package/lib/bridge.js.map +1 -0
  21. package/lib/errors.d.ts +43 -0
  22. package/lib/errors.js +52 -0
  23. package/lib/errors.js.map +1 -0
  24. package/lib/help.d.ts +54 -0
  25. package/lib/help.js +662 -0
  26. package/lib/help.js.map +1 -0
  27. package/lib/index.d.ts +82 -0
  28. package/lib/index.js +5720 -0
  29. package/lib/index.js.map +1 -0
  30. package/lib/media.d.ts +38 -0
  31. package/lib/media.js +183 -0
  32. package/lib/media.js.map +1 -0
  33. package/lib/mirror.d.ts +71 -0
  34. package/lib/mirror.js +58 -0
  35. package/lib/mirror.js.map +1 -0
  36. package/lib/outbox.d.ts +82 -0
  37. package/lib/outbox.js +318 -0
  38. package/lib/outbox.js.map +1 -0
  39. package/lib/plugins.d.ts +121 -0
  40. package/lib/plugins.js +221 -0
  41. package/lib/plugins.js.map +1 -0
  42. package/lib/process.d.ts +42 -0
  43. package/lib/process.js +150 -0
  44. package/lib/process.js.map +1 -0
  45. package/lib/rate-limit.d.ts +36 -0
  46. package/lib/rate-limit.js +67 -0
  47. package/lib/rate-limit.js.map +1 -0
  48. package/lib/reactions.d.ts +59 -0
  49. package/lib/reactions.js +109 -0
  50. package/lib/reactions.js.map +1 -0
  51. package/lib/reference.d.ts +49 -0
  52. package/lib/reference.js +183 -0
  53. package/lib/reference.js.map +1 -0
  54. package/lib/render.d.ts +60 -0
  55. package/lib/render.js +589 -0
  56. package/lib/render.js.map +1 -0
  57. package/lib/sessions.d.ts +17 -0
  58. package/lib/sessions.js +28 -0
  59. package/lib/sessions.js.map +1 -0
  60. package/lib/slash.d.ts +41 -0
  61. package/lib/slash.js +117 -0
  62. package/lib/slash.js.map +1 -0
  63. package/lib/supervisor.d.ts +93 -0
  64. package/lib/supervisor.js +110 -0
  65. package/lib/supervisor.js.map +1 -0
  66. package/lib/telegram-prompt.d.ts +45 -0
  67. package/lib/telegram-prompt.js +93 -0
  68. package/lib/telegram-prompt.js.map +1 -0
  69. package/lib/telegram.d.ts +305 -0
  70. package/lib/telegram.js +219 -0
  71. package/lib/telegram.js.map +1 -0
  72. package/lib/time.d.ts +15 -0
  73. package/lib/time.js +33 -0
  74. package/lib/time.js.map +1 -0
  75. package/lib/updates.d.ts +110 -0
  76. package/lib/updates.js +360 -0
  77. package/lib/updates.js.map +1 -0
  78. package/package.json +69 -4
  79. package/skills/telegram-rich-text/SKILL.md +62 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,984 @@
1
+ # Changelog
2
+
3
+ ## 0.13.0
4
+
5
+ - **npm distribution.** The package is published as
6
+ `dsh-telegram-connector@<version>`; the registry tarball already contains
7
+ `lib/`, so installs no longer run a build script. The release workflow
8
+ publishes a tag with provenance, and `/system update connector` resolves npm
9
+ versions. GitHub tags remain supported for source installs and as the setup's
10
+ fallback.
11
+ - **Independent versioning.** The connector version is now plain semver
12
+ (`0.13.0`), not `<dsh>-<product>`. The DSH release it was tested against is a
13
+ row in `COMPATIBILITY.md`; a setup release no longer has to carry a matching
14
+ connector tag, and a connector release no longer needs a setup release.
15
+ - **`/system update connector` now updates.** It resolves the newest tag in the
16
+ connector repository (or `to <version>`), refuses a tag whose declared DSH
17
+ range excludes the running runtime, and asks the supervisor to install that
18
+ exact ref. Before, it only reinstalled the setup-pinned version.
19
+ - **`/system update penpot` and `/system update plugin <name>`.** Any
20
+ GitHub-installed bundle can move to its newest compatible tag through the
21
+ host plugin manager, wrapped in a rollback trial. A failed install puts the
22
+ previous version back immediately.
23
+ - **The update path is testable without a runtime.** Release discovery,
24
+ semver range checks and argument parsing live in `src/updates.ts` with unit
25
+ tests; the supervisor accepts the exact ref in the `/update` request.
26
+ - Standalone use is documented in `docs/STANDALONE.md`: the same plugin runs
27
+ without the supervisor or updater, and the commands that need them say so.
28
+ The bundle patch now reads `ALLOWED_USER_IDS`, `DSH_ADMIN_USER_ID`,
29
+ `DSH_PROVIDER` and `DSH_MODEL` from the environment, so a bare install needs
30
+ no patch edit.
31
+
32
+ ## 0.2.1-rc.5-0.12.11
33
+
34
+ Maintenance release; no connector change. Aligned with the setup fix that keeps
35
+ the Penpot access token across both .env files.
36
+
37
+ ## 0.2.1-rc.5-0.12.10
38
+
39
+ Maintenance release; no connector change. Aligned with the setup that pins the
40
+ API-only Penpot plugin 0.2.0.
41
+
42
+ ## 0.2.1-rc.5-0.12.9
43
+
44
+ Maintenance release; no connector change. Aligned with the setup fix that adds
45
+ the ufw LAN-to-bridge route for published container ports.
46
+
47
+ ## 0.2.1-rc.5-0.12.8
48
+
49
+ Maintenance release; no connector change. Aligned with the setup fix for the
50
+ Penpot database URI (credentials moved out of the URL).
51
+
52
+ ## 0.2.1-rc.5-0.12.7
53
+
54
+ Maintenance release; no connector change. Aligned with the setup fix for
55
+ ProtectHome and rootless Podman's runtime dir.
56
+
57
+ ## 0.2.1-rc.5-0.12.6
58
+
59
+ Maintenance release; no connector change. Aligned with the setup fix for the
60
+ numeric UID in the unit and the DESIGN environment override.
61
+
62
+ ## 0.2.1-rc.5-0.12.5
63
+
64
+ Maintenance release; no connector change. Aligned with the setup fix that
65
+ exposes /run/user/<uid> to the service for rootless Podman.
66
+
67
+ ## 0.2.1-rc.5-0.12.4
68
+
69
+ Maintenance release; no connector change. Aligned with the setup fix that moves
70
+ rootless Podman's runtime dir to /run/dsh.
71
+
72
+ ## 0.2.1-rc.5-0.12.3
73
+
74
+ Maintenance release; no connector change. Aligned with the setup fix that
75
+ installs `passt` (pasta) and enables lingering for rootless Podman.
76
+
77
+ ## 0.2.1-rc.5-0.12.2
78
+
79
+ Maintenance release; no connector change. Aligned with the setup fix that moves
80
+ the `dsh` home to the data directory for rootless Podman.
81
+
82
+ ## 0.2.1-rc.5-0.12.1
83
+
84
+ Maintenance release; no connector change. Aligned with the setup fix that adds
85
+ the ufw bridge rules Podman needs for the Penpot stack.
86
+
87
+ ## 0.2.1-rc.5-0.12.0
88
+
89
+ ### Changed
90
+
91
+ - **Controls are words only.** Buttons, dashboard cards, trial and update
92
+ cards, status lines, process rows and speaker markers no longer use emoji.
93
+ The first word carries the status (`committed`, `failed`, `queued`,
94
+ `waiting`); a bare exception is prefixed `error:`. Process rows read
95
+ `Read: path`, `Search: query`, `Skill: name`; task lists use `[x]` / `[ ]`.
96
+ - **Reactions are the documented exception.** Telegram only accepts emoji from
97
+ its fixed set, so `/reactions` keeps 👀, ✍ and 🙉 (and `/reactions allowed`
98
+ lists the valid set). No other surface uses them.
99
+ - The icon policy is in `docs/COMMANDS.md` and a test fails if a button label
100
+ contains an emoji.
101
+
102
+ ## 0.2.1-rc.5-0.11.1
103
+
104
+ ### Fixed
105
+
106
+ - **The typed confirmation stays available for scripts.** `/workspace remove
107
+ <name> confirm` and `/unbind confirm` execute without pressing the card;
108
+ `/dangerous cleanup confirm` and `/plugin confirm` already did. The card is
109
+ still the normal path.
110
+
111
+ ## 0.2.1-rc.5-0.11.0
112
+
113
+ ### Added
114
+
115
+ - **One confirmation card for consequential actions.** `/workspace remove`,
116
+ `/unbind`, `/dangerous cleanup`, plugin add/remove/enable/disable and the
117
+ dashboard **Restart** button now post a consequence summary with **Confirm**
118
+ and **Cancel**. Every press answers with a toast and the card is edited to the
119
+ result; the typed `confirm` forms remain as the scriptable fallback.
120
+ - **`/sync` reports progress.** It posts a live card (`checked 4/12`, `adopted 2`)
121
+ and refuses a second sync in the same group.
122
+ - **`/model` lists the runtime's models.** Without a route it queries the
123
+ runtime's model catalog, marks the current route and rejects a route outside
124
+ it.
125
+ - **Admin markers.** `/help`, `/man` and the Telegram menu mark admin-only
126
+ commands (`· admin`), with `/system status` called out as the open subcommand.
127
+ - **Release notes and a cross-version gate.** The setup-update card shows the DSH
128
+ delta, recent commit subjects and the rollback contract; a target that crosses
129
+ a DSH line or product major gets a separate **Cross anyway** confirmation.
130
+ - **Component Port sub-card.** It shows the current port, derived choices and a
131
+ **Back** button instead of the fixed 8090/8091/8092 triplet.
132
+
133
+ ### Fixed
134
+
135
+ - **`/archived` is reachable.** It was documented, listed in `/help` and never
136
+ dispatched; the only working spelling was `/list archived`. Both now work and
137
+ the menu lists `/archived`.
138
+ - **The setup-update card no longer denies `/system cancel`.** It says the
139
+ command still stops an accepted job, which is what the code does.
140
+ - **Deleting topics is previewed.** `/workspace remove` (alias `/workspace rm`)
141
+ and `/unbind` show how many topics and which ones go, then ask.
142
+ - **Canonical verbs.** `/workspace remove` is the documented form; `/plugin` with
143
+ no subcommand lists bundles like `/plugins`.
144
+ - **Actionable refusals.** A command used in the wrong topic names itself and its
145
+ home; the unauthorized reply names the fix.
146
+ - **Errors are sentences.** Updater failures no longer print raw JSON, and
147
+ truncated reports say they were truncated.
148
+ - **Copy and icons.** `/system status` uses plain labels, `/schedules` is marked
149
+ planned, and the button icon roles are documented.
150
+
151
+
152
+ ## 0.2.1-rc.5-0.11.0
153
+
154
+ Maintenance release; no connector change. Aligned with the setup fix for the
155
+ Penpot compose service names (`penpot-backend`/`penpot-exporter`).
156
+
157
+ ## 0.2.1-rc.5-0.10.6
158
+
159
+ Maintenance release; no connector change. Aligned with the setup fix for Podman
160
+ DNS (`aardvark-dns`) and `.env` ownership.
161
+
162
+ ## 0.2.1-rc.5-0.10.5
163
+
164
+ Maintenance release; no connector change. Aligned with the setup fix that reports
165
+ the deployed git manifest instead of "none".
166
+
167
+ ## 0.2.1-rc.5-0.10.4
168
+
169
+ Maintenance tag for the setup release; no connector code changed. The setup
170
+ pins this tag so the `apple-hig` skill fixes ship with a matching connector.
171
+
172
+ ## 0.2.1-rc.5-0.10.3
173
+
174
+ ### Changed
175
+
176
+ - **`/system update setup` now confirms before it does anything.** It posts a
177
+ card with the current and target version and the number of running sessions;
178
+ **Update now** starts the drain, **Cancel** closes it. A pending card expires
179
+ cleanly if dsh restarts instead of looking like a completed update.
180
+ - The card drops Cancel as soon as nothing is draining, and the accepted state
181
+ says the cancel button is gone.
182
+
183
+ ## 0.2.1-rc.5-0.10.2
184
+
185
+ ### Fixed
186
+
187
+ - **Take over no longer restarts dsh silently.** The button now asks for
188
+ confirmation and says plainly that the restart interrupts every running
189
+ session and tool call, not only the held one. Cancel is a separate button.
190
+ The API does not expose a per-session disposer to the connector, so a global
191
+ restart is still the only way to release a web UI handle.
192
+ - **An unusable publisher token names the reason.** The notice now includes
193
+ Telegram's error (for example `401: Unauthorized`), says the bot is ignored
194
+ until restart, and tells the user to check the token with @BotFather and
195
+ replace it in `DSH_TELEGRAM_PUBLISHER_TOKENS`.
196
+ - **"Delivery could not be confirmed" explains itself.** The notice now says
197
+ Telegram did not acknowledge before dsh stopped (usually a restart/update),
198
+ that the message may or may not have arrived, and to check the chat before
199
+ resending.
200
+ - **The update card loses its Cancel button before the hand-over.** When no
201
+ session is draining, the card says so and drops the keyboard immediately
202
+ instead of offering a cancel that cannot work; the accepted state says the
203
+ cancel button is gone.
204
+
205
+ ## 0.2.1-rc.5-0.10.1
206
+
207
+ Maintenance release; no connector change. Aligned with the setup 0.10.1
208
+ test-only fix.
209
+
210
+ ## 0.2.1-rc.5-0.10.0
211
+
212
+ Maintenance release; no connector code change. Aligned with the setup that
213
+ removes Docker: the agent gets rootless Podman, Penpot runs on rootful Podman.
214
+
215
+ ## 0.2.1-rc.5-0.9.5
216
+
217
+ ### Added
218
+
219
+ - **Telegram prompts carry their channel.** The prompt the agent receives starts
220
+ with `[via Telegram]`, so it can answer with chat steps instead of host
221
+ commands. Web UI prompts stay unmarked; the marker is part of the session
222
+ transcript, not of the Telegram message.
223
+
224
+ ## 0.2.1-rc.5-0.9.4
225
+
226
+ ### Fixed
227
+
228
+ - **A prompt sent while the setup update restarted is no longer discarded.**
229
+ The first Telegram batch after an update was refused wholesale with "send it
230
+ again". Plain prompts and attachments are now delivered (the session survived
231
+ the restart); only commands are refused, because a queued `/system …` or trial
232
+ confirmation refers to the state the update replaced.
233
+
234
+ ## 0.2.1-rc.5-0.9.3
235
+
236
+ Maintenance release; no connector change. Aligned with the setup cleanup of
237
+ stale `/system update all` text and the penpot 0.1.2 pin.
238
+
239
+ ## 0.2.1-rc.5-0.9.2
240
+
241
+ ### Fixed
242
+
243
+ - **Dashboard Status and Sessions were the same message.** On the dashboard
244
+ surface `/status` without a session fell through to the session list, so both
245
+ buttons printed the workspace dashboard. `/status` now reports the workspace
246
+ and runtime state (session count, model route, poller, timezone) and
247
+ `/sessions` lists the sessions.
248
+
249
+ ## 0.2.1-rc.5-0.9.1
250
+
251
+ ### Changed
252
+
253
+ - **Commands renamed, no aliases:** `/system update setup` (was `update all`),
254
+ `/system components` (was `manage`), `/dashboard` (was `/setsystem`),
255
+ `/archived` (was `/list archived`). `/about` is removed; `/system status`
256
+ prints the same state.
257
+ - **Dashboard card.** `/dashboard` posts inline buttons: in a group, New
258
+ session, Sync, Status and Sessions; in the bot chat, Status, Web link, Update
259
+ setup, Restart, Plugins and Components. Each button runs the typed command, so
260
+ permissions are identical; the deployment buttons are admin-only.
261
+ - **`/unbind`, `/dashboard` and `/dangerous cleanup` require admin**, matching
262
+ `/bind` and the rest of the deployment-wide commands.
263
+ - The "system topic" is called the dashboard throughout; help and docs use the
264
+ new names.
265
+
266
+ ## 0.2.1-rc.5-0.9.0
267
+
268
+ ### Changed
269
+
270
+ - The bot's help and error text describes the systemd deployment: `update all`
271
+ moves the setup checkout through the updater service (not an image through a
272
+ sidecar), rollback does not move the checkout or the DSH install, and the
273
+ firewall note no longer compares a published Docker port.
274
+ - A held session names the other process and says `sudo systemctl stop
275
+ dsh.service`; the no-supervisor and updater-unreachable hints point at
276
+ `journalctl -u dsh-updater.service` and `update.sh --tg-connector`.
277
+
278
+ ## 0.2.1-rc.5-0.8.2
279
+
280
+ Maintenance release; no connector change. Aligned with the setup fix that makes
281
+ DSH_PUBLIC_URL an accepted installer answer.
282
+
283
+ ## 0.2.1-rc.5-0.8.1
284
+
285
+ Maintenance release; no connector change. Aligned with the setup fix for the
286
+ native smoke workflow and the health probe's bind address.
287
+
288
+ ## 0.2.1-rc.5-0.8.0
289
+
290
+ Maintenance release; no connector change. Aligned with the setup release that
291
+ removes the Docker deployment mode and adds a CPU/RAM share to the systemd unit.
292
+
293
+ ## 0.2.1-rc.5-0.7.0
294
+
295
+ ### Fixed
296
+
297
+ - **Inline buttons now require the admin account.** Trial Commit/Roll back,
298
+ component Enable/Disable/Port, the update card's ✖ and Take over all change
299
+ the deployment for every user, but the callback handler checked only the
300
+ allowlist while the typed equivalents required `adminUserId`. Any allowlisted
301
+ member could restart the runtime or commit a rollback window. The gate now
302
+ matches `/system`: a non-admin press is answered with
303
+ "only the admin can do that" and does nothing.
304
+ - **`/commands --help` shows its help again.** The `/commands` branch ran before
305
+ the generic `--help` handler, so the flag was swallowed and the host catalog
306
+ printed instead. The handler now runs first on every surface.
307
+
308
+ ### Changed
309
+
310
+ - The accepted update card no longer says "cancelling is no longer possible": the
311
+ card's button is gone, but `/system cancel` still stops the job, and the card
312
+ now says so.
313
+ - `/workspaces` help says the startgroup link is printed only for a workspace
314
+ that has no group yet.
315
+
316
+ ## 0.2.1-rc.5-0.6.4
317
+
318
+ Aligned with the setup fix for `data/.runtime.json`, which the entrypoint wrote
319
+ without a pid (invalid JSON) after an editing slip.
320
+
321
+ ### Fixed
322
+
323
+ - **A malformed instance marker degrades to "unknown", never to a crash or a
324
+ phantom holder.** The pid is trusted only as a positive integer, so a marker
325
+ from a broken build cannot make `/system status` claim another runtime holds
326
+ the data directory, and cannot hide the real one. With the marker fixed, a
327
+ held session again distinguishes "another client in this runtime" (take-over
328
+ card) from "another process over this data directory" (stop it first).
329
+
330
+ ## 0.2.1-rc.5-0.6.3
331
+
332
+ Maintenance release; no connector change. Aligned with the setup patch that
333
+ makes the doctor fixture read the real invoking uid (CI runners are uid 1001)
334
+ and adds a test that pins the ownership mismatch itself.
335
+
336
+ ## 0.2.1-rc.5-0.6.2
337
+
338
+ Maintenance release; no connector change. Aligned with the setup patch that
339
+ removes the credential helper's YAML dependency (the setup CI has no global dsh)
340
+ and makes its new doctor test independent of the runner's Docker daemon.
341
+ Supersedes 0.2.1-rc.5-0.6.1, whose CI stayed red on the credential tests.
342
+
343
+ ## 0.2.1-rc.5-0.6.1
344
+
345
+ Maintenance release; no connector change. Aligned with the setup tag whose new
346
+ doctor test assumed a host without Docker — the CI runner has one, so the setup
347
+ released a patch with the test made deterministic.
348
+
349
+ ## 0.2.1-rc.5-0.6.0
350
+
351
+ Aligned with the setup release that adds `install.sh --doctor`, keeps the
352
+ deployed provider key on a repair run, and refuses to run two runtimes over one
353
+ data directory.
354
+
355
+ ### Fixed
356
+
357
+ - **A held session now says who holds it.** The refusal named "a web UI tab" for
358
+ every case, so a session the *bot itself* still held in another topic, or one
359
+ held by a second runtime over the same data directory, was blamed on a tab the
360
+ user did not have — and `/system restart now` could not fix either. The
361
+ connector now distinguishes the three cases: another topic (send there, or
362
+ `/forget` this binding), a live client in this runtime (a tab; restart
363
+ clears it), and another dsh process (stop it first; `./install.sh --doctor`
364
+ names it). The take-over card is only offered when a restart can deliver.
365
+ - **A refused prompt is not queued where it could never arrive.** When another
366
+ topic owns the session, replaying the prompt after a restart would hand it to
367
+ whichever topic resumed first. It is no longer journaled for that case.
368
+ - **A re-bound topic no longer keeps the previous session's handle.** `/sync`
369
+ replacing a dead binding, or a session being forgotten and re-minted in the
370
+ same topic, left a runtime that still owned the old session; the next prompt
371
+ resumed it and failed with an ownership error that pointed at a phantom tab.
372
+
373
+ ### Added
374
+
375
+ - **The runtime registry is repaired at boot.** The web UI lists the runtime's
376
+ workspace registry, while Telegram lists the connector's bindings; after a
377
+ crash or a storage reset those disagree, and the web UI shows no workspace
378
+ even though Telegram reports it and its sessions. A bound workspace whose
379
+ directory still exists is recreated, its sessions are re-attached, and the
380
+ control chat gets one notice. `/sync` does the same repair on demand instead
381
+ of answering "this composition exposes no workspace registry".
382
+ - **`/system status` shows both lists and who owns the data directory.**
383
+ `registry: N workspace(s) in the runtime · M bound to Telegram` makes the
384
+ disagreement visible before a prompt fails, and `data:` names a second live
385
+ runtime over the same directory (the one case a restart cannot clear).
386
+
387
+ ## 0.2.1-rc.5-0.5.1
388
+
389
+ Maintenance release; no connector change. Aligned with the setup tag whose CI is
390
+ green.
391
+
392
+ ## 0.2.1-rc.5-0.5.0
393
+
394
+ Maintenance release; no connector change. Aligned with the setup release that
395
+ configures git and installs Docker when the design stack needs it.
396
+
397
+ ## 0.2.1-rc.5-0.4.0
398
+
399
+ ### Added
400
+
401
+ - **`/firewall` — see and fix the ufw hole from Telegram.** A native install's
402
+ web UI is only as reachable as ufw allows, and the fix used to need SSH.
403
+ `/firewall` lists the ports the deployment serves with their networks and
404
+ marks each allowed or blocked; `/firewall allow <port>` (admin only) asks the
405
+ updater to allow it. The updater accepts only a port the deployment already
406
+ serves from its `.env` and runs the fixed `ufw allow from <network> to any
407
+ port <port> proto tcp` — never a command from the chat.
408
+ - A finished setup update now appends the same advisory to its report, so the
409
+ blocked state arrives without asking and without a `--status` command.
410
+ - Docker deployments get "nothing to do": a published port is DNATed before
411
+ ufw's `INPUT` chain sees it, so a rule there changes nothing.
412
+ ## 0.2.1-rc.5-0.3.0
413
+
414
+ Maintenance release; no connector change. Aligned with the setup release that
415
+ warns when ufw would block a native install's web UI.
416
+
417
+ ## 0.2.1-rc.5-0.2.2
418
+
419
+ Maintenance release; no connector change. Aligned with the setup fix for the design
420
+ plugin on native hosts.
421
+
422
+ ## 0.2.1-rc.5-0.2.1
423
+
424
+ Maintenance release; no connector change. Aligned with the setup fix for the
425
+ unattended install.
426
+
427
+ ## 0.2.1-rc.5-0.2.0
428
+
429
+ Maintenance release; no connector change. Aligned with the setup release that asks
430
+ for publisher bot tokens and names the downloaded checkout.
431
+
432
+ ## 0.2.1-rc.5-0.1.2
433
+
434
+ Maintenance release; no connector change. Aligned with the setup tag whose CI is
435
+ green.
436
+
437
+ ## 0.2.1-rc.5-0.1.1
438
+
439
+ Maintenance release; no connector change. Aligned with the setup fix for the
440
+ root re-run of the one-file install.
441
+
442
+ ## 0.2.1-rc.5-0.1.0
443
+
444
+ Maintenance release; no connector change. Aligned with the setup release that adds
445
+ the one-file (wget/curl) install.
446
+
447
+ ## 0.2.1-rc.5-0.0.0
448
+
449
+ Alignment release against DSH `0.2.1-rc.5`. No connector code change; the product
450
+ line restarts at `0.0.0` for the new DSH part.
451
+
452
+ ### Changed
453
+
454
+ - Rebuilt against `@deepseek-ai/dsh-agent`, `dsh-llm` and `dsh-session`
455
+ `0.2.1-rc.5`. Their published `lib/` is byte-identical to rc.2, and
456
+ `typecheck` plus 191 tests pass unchanged.
457
+ - Peer ranges left alone (`>=0.1.0-rc.6 <0.3.0-0`). rc.5 is inside them and the
458
+ loader evaluates prereleases, so the runtime needs no exact-version exemption.
459
+ - One `COMPATIBILITY.md` row added; the previous one is now `previous`.
460
+
461
+ ## 0.2.1-rc.2-0.8.0
462
+
463
+ ### Added
464
+
465
+ - **The command menu.** Telegram's menu above the input box was empty; it is now
466
+ published for the bot chat and for groups, from the same registry as `/help`,
467
+ so it cannot drift from the manual. Two calls on boot, one per scope.
468
+ - **`/system takechat`**: make the current private chat the control chat.
469
+ Notices, update reports and failure cards go there, and moving it is explicit.
470
+ - **`/bind` is documented** (`/help bind`) — it was a real command in no help.
471
+
472
+ ### Fixed
473
+
474
+ - **The control chat no longer follows the last DM.** It is claimed by the first
475
+ private chat and stays there; an allowed colleague writing to the bot could
476
+ earlier redirect someone else's notices — and the content in them — by
477
+ messaging once. Only the admin moves it, with `/system takechat`.
478
+ - **Attaching a group is administration.** `/bind` and `/workspace new|link|rm`
479
+ now need the admin: they decide what every user in a group can reach. The
480
+ first-run `?startgroup=` link still works before the bot chat is claimed, so a
481
+ fresh install cannot lock itself out.
482
+ - **A host command of the same name works in a session topic.** `/bind`,
483
+ `/cleanup` and `/archived` exist on both sides; the connector's reservation
484
+ used to refuse them outright instead of letting the host command run.
485
+ - **`agent/error` is redacted** before it reaches a group: a provider error can
486
+ quote the key it rejected.
487
+ - **A failed attachment is reported to the user**, not only to the agent in the
488
+ prompt.
489
+ - **`/plugin del` works** — it resolved in help but had no dispatcher.
490
+ - **`/unarchive` points at a command that works**: it said `/rename` "inside it",
491
+ where `/rename` is refused; it now gives the full form to run from the dashboard.
492
+ - **A hard cut never splits a surrogate pair**, so an emoji at the 4,096 boundary
493
+ stays one character.
494
+
495
+ ### Notes
496
+
497
+ - With no `DSH_ADMIN_USER_ID` and no claimed bot chat, any allowed user may
498
+ administer — otherwise a hand-written config could not bind its first group.
499
+ `/about` says which rule is in effect.
500
+ ## 0.2.1-rc.2-0.7.4
501
+
502
+ Maintenance release; no connector change. Aligned with the setup fix for the
503
+ native smoke workflow.
504
+
505
+ ## 0.2.1-rc.2-0.7.3
506
+
507
+ Maintenance release; no connector change. Aligned with the setup fix for the
508
+ native smoke workflow.
509
+
510
+ ## 0.2.1-rc.2-0.7.2
511
+
512
+ Maintenance release; no connector change. Aligned with the setup fix for the
513
+ native prepare working directory.
514
+
515
+ ## 0.2.1-rc.2-0.7.1
516
+
517
+ Maintenance release; no connector change. It exists because the setup repo ships
518
+ one aligned tag and 0.7.1 fixes that repository's native smoke workflow.
519
+
520
+ ## 0.2.1-rc.2-0.7.0
521
+
522
+ ### Added
523
+
524
+ - **One admin account.** `DSH_ADMIN_USER_ID` (connector config `adminUserId`)
525
+ names the account that may run `/system update|restart|rollback|confirm|cancel|manage`
526
+ and `/plugin add|remove|enable|disable`. Everyone in `ALLOWED_USER_IDS` keeps
527
+ full use of the agent and every session. Every allowed user could update or
528
+ roll back the deployment for everyone before this.
529
+ - **`/status` answers the two questions it could not.** `web: 127.0.0.1:<port>
530
+ answered 200|401|unreachable`, `key: set (OPENCODE_GO_API_KEY)|missing (…)`,
531
+ and the last agent error with its time. `/about` and `/system status` name the
532
+ admin and say how it was decided.
533
+ - **The bindings warning reaches the chat.** A `bindings.json` that cannot be
534
+ read is kept aside and announced once, with the recovery step, instead of
535
+ leaving every group answering "not attached" for no visible reason.
536
+
537
+ ### Fixed
538
+
539
+ - **`/system` and `/plugin` are guarded on both entry paths**, including the
540
+ inline-button callbacks.
541
+
542
+ ### Notes
543
+
544
+ - No lockout on upgrade: with no `DSH_ADMIN_USER_ID`, the owner of the bot chat
545
+ is the admin. New installs always set it (the installer defaults it to the
546
+ first allowed id).
547
+ - Native mode now runs a real install → update → uninstall in CI
548
+ (`.github/workflows/native-smoke.yml`, on every tag and weekly), and the image
549
+ is built on every release tag.
550
+
551
+ ## 0.2.1-rc.2-0.6.0
552
+
553
+ ### Fixed
554
+
555
+ - **A hung Bot API call no longer freezes a topic.** No `fetch` carried a
556
+ deadline, so one stalled connection left the topic's flush chain unsettled and
557
+ that topic stopped updating until the process restarted. Every call now has a
558
+ timeout: 60 s by default (`requestTimeoutSeconds`), the long poll extends
559
+ Telegram's own hold time, and downloads get their own
560
+ (`downloadTimeoutSeconds`, 120 s).
561
+ - **A mirrored turn survives a restart.** The answer lived only in the sink; a
562
+ restart inside the flush window lost it and the catch-up digest never saw it.
563
+ Mirrored turns are journaled and completed like Telegram turns.
564
+ - **`/system rollback` no longer promises what the supervisor refuses.** While
565
+ another operation was running the supervisor answered `200` and did nothing,
566
+ so the connector retired the card and the rollback became unreachable. The
567
+ route now answers `409` (or `202` when it accepts), `/status` reports `busy`,
568
+ and the connector checks before posting.
569
+ - **`/system cancel` stops the job, not just the card.** It asks the updater to
570
+ cancel the running `update.sh` (the sidecar also stops a job that exceeds
571
+ `DSH_UPDATE_TIMEOUT_SECONDS`, 30 minutes by default).
572
+ - **The update gate allows the recovery commands.** It matched on a prefix, so
573
+ `/system update all` slipped through while `/system restart` was blocked — the
574
+ reverse of what a stuck drain needs. The rule is now an explicit list with its
575
+ own tests.
576
+
577
+ - **A mirrored web answer arrives as its own message.** Releasing a session to
578
+ the web UI left the topic's sink in place, so the answer was appended to the
579
+ previous Telegram turn and edited into that message — which sits above the
580
+ echo, changes silently, and looks like no answer at all. A mirrored prompt now
581
+ resets the sink, and the answer is gated behind the echo so it cannot overtake
582
+ it. Covered by an integration test that drives the real plugin.
583
+ - **A reply is never dropped silently.** A refused chunk used to disappear: no
584
+ log, no retry, no notice. It is logged with Telegram's code, retried once as
585
+ plain text, and reported in the topic if that also fails.
586
+ - **A permission error no longer silences a group.** A 400 "not enough rights"
587
+ was classified as "bot is not a member", which marked the bot missing and
588
+ blocked the chat for an hour; the main bot was never re-checked. Only real
589
+ membership failures do that now.
590
+ - **Re-tapping the startgroup link no longer wipes a group.** Binding was not
591
+ idempotent: a second tap deleted every topic in the group, disposed live
592
+ agents mid-answer and dropped every binding. Re-linking the same workspace now
593
+ just prints the dashboard, a group that hosts another workspace is refused
594
+ instead of seized, and moving a workspace clears the old group's bindings
595
+ without deleting its history.
596
+ - **A prompt refused after a take-over is queued, not lost.** When the refusal
597
+ arrived as an `agent/error` (the agent already existed), the prompt was never
598
+ journaled, so the Take over button delivered nothing. It is journaled now and
599
+ the card is posted with the button.
600
+ - **`/sync` keeps a healthy topic.** Any probe error (429, 5xx, network) counted
601
+ as "topic deleted" and unbound the topic, leaked the agent and created a
602
+ duplicate. Only a definite "message thread not found" purges a binding now,
603
+ the runtime is disposed before the binding goes, and the summary counts the
604
+ ones it could not probe.
605
+ - **`/unarchive <id>` reuses the session's topic** instead of binding one session
606
+ to two topics (the mirror kept posting to the archived one).
607
+ - **A stuck `/system update all` drain can be cleared.** The update gate blocked
608
+ every message including `/system restart`; `/system cancel` and the recovery
609
+ commands now pass, and `/system cancel` is a text command, not just a button.
610
+ - **A corrupt or older `bindings.json` is kept, not overwritten.** It used to be
611
+ replaced by an empty document and then overwritten on the next save — every
612
+ binding gone, silently. It is now set aside as `bindings.json.corrupt-<ts>`
613
+ with a log line.
614
+ - **Long formatted replies stay formatted.** A chunk that fits 3,800 markdown
615
+ characters can exceed Telegram's 4,096 once converted to HTML (`/man` did), and
616
+ the whole chunk fell back to plain text. Splitting now checks the converted
617
+ length; `SAFE_LENGTH` is 3,400.
618
+
619
+ ### Added
620
+
621
+ - **`/web`** prints a signed link into the web UI for the same sessions, with
622
+ what handing a session over means. It is only available in the bot chat, so
623
+ the link never lands in a group. `/about` and `/system status` now name the web
624
+ root (without the token) and the declared peer range.
625
+ - `<command> --help` works in session topics too, as `/help` promised.
626
+
627
+ ### Tests
628
+
629
+ - `tests/binding.integration.test.ts`: re-linking a group changes nothing, a
630
+ group hosting another workspace is refused, moving a workspace clears the old
631
+ bindings, `/unarchive` reuses its topic, `/sync` keeps a topic on a 5xx.
632
+ - The harness can refuse a Bot API call (`failSend`), and `waitFor` awaits async
633
+ predicates.
634
+
635
+ ## 0.2.1-rc.2-0.4.11
636
+
637
+ - Diagnostics for the mirror: the user echo reaches Telegram but the answer does
638
+ not, and the decision points are silent. `mirror:` logs whether the topic was
639
+ claimed, and `flush:` logs every flush that actually sends. Temporary; remove
640
+ once the cause is known.
641
+
642
+ ## 0.2.1-rc.2-0.4.10
643
+
644
+ - A refused Telegram prompt is no longer lost. It is journaled and the reply
645
+ offers **Take over**: the supervisor restarts the runtime, every write handle is
646
+ released, and the boot replay delivers the queued text without a retype.
647
+ - The journal replay drops prompts older than an hour, so a take-over that was
648
+ never taken does not resurface days later.
649
+
650
+ ## 0.2.1-rc.2-0.4.9
651
+
652
+ - One delivery path for a topic. A mirrored web turn now feeds the same sink as
653
+ a Telegram turn — buffer, flush, edits, splitting, rich/HTML fallback — instead
654
+ of a second plain-text pipeline through the outbox. Net -219 lines.
655
+ - What differs is declared on the sink, not duplicated in code: the mirror echoes
656
+ the prompt (Telegram never saw it) and shows no process card (the web UI
657
+ already does).
658
+ - A session taken over by another client drops its stale agent, so the next
659
+ Telegram prompt resumes instead of reusing a handle that owns nothing.
660
+ - `MirrorQueue` and the mirror process-card machinery are gone.
661
+
662
+ ## 0.2.1-rc.2-0.4.8
663
+
664
+ - A failed Telegram prompt no longer silences the topic. The attempt created a
665
+ runtime entry before the runtime refused it, and "this topic has a runtime"
666
+ was enough to drop every web turn mirror. A topic is now claimed only by a
667
+ runtime that actually holds an agent and has not been taken over.
668
+ - The leftover entry from a failed attempt is dropped, so it cannot claim the
669
+ topic later either.
670
+
671
+ ## 0.2.1-rc.2-0.4.7
672
+
673
+ - A session held by another client now says so from both paths. The refusal came
674
+ from `resume` (the session exists on disk), which was outside the friendly
675
+ mapping, so the raw runtime error leaked to the chat.
676
+ - The advice is the one that works: the write handle is a kernel lock with no
677
+ expiry, and a closed tab does not always release it, so `/system restart now`
678
+ clears every handle. "Close the tab" was wrong when there was no tab.
679
+
680
+ ## 0.2.1-rc.2-0.4.6
681
+
682
+ - A session taken over by a web UI tab is mirrored into its topic again. The
683
+ connector used to keep streaming into an agent handle it no longer owned, so
684
+ the topic went silent while Telegram prompts failed with the ownership error
685
+ under a misleading "Process interrupted" card.
686
+ - The takeover is detected from a prompt the connector did not send, and the
687
+ session is marked foreign until a Telegram prompt lands again.
688
+ - The refusal now says what happened ("this session is open in a web UI tab,
689
+ so prompts from Telegram are refused until it closes") instead of looking
690
+ like a crash.
691
+
692
+ ## 0.2.1-rc.2-0.4.5
693
+
694
+ Maintenance release for the setup fix that reaches Penpot over the shared
695
+ network and no longer fails a component change on an unreachable probe. No
696
+ connector behavior change.
697
+
698
+ ## 0.2.1-rc.2-0.4.4
699
+
700
+ Maintenance release for the setup fix that stops a port change from starting a
701
+ stopped component. No connector behavior change.
702
+
703
+ ## 0.2.1-rc.2-0.4.3
704
+
705
+ Maintenance release for the setup change that installs the Penpot plugin when
706
+ the design component is enabled. No connector behavior change.
707
+
708
+ ## 0.2.1-rc.2-0.4.2
709
+
710
+ Maintenance release for the setup change that replaces the design MCP bridge
711
+ with the in-repo `penpot` CLI. No connector behavior change.
712
+
713
+ ## 0.2.1-rc.2-0.4.1
714
+
715
+ Maintenance release for the setup's local-build fix of the design stack. No
716
+ connector behavior change.
717
+
718
+ ## 0.2.1-rc.2-0.4.0
719
+
720
+ - `/system manage` lists the optional components the setup registers and posts a
721
+ card with Enable / Disable and Port buttons. The text form
722
+ `/system manage <component> <enable|disable|port> [<port>]` does the same
723
+ without a tap. The updater applies the change, restarts the runtime and
724
+ reports; the connector never touches Docker.
725
+
726
+ ## 0.2.1-rc.2-0.3.1
727
+
728
+ - Process cards no longer wait for a rate-limited main bot. A summary falls back
729
+ to the outbox, live-card creation is skipped instead of blocking the turn, and
730
+ a stale card is left for the next start rather than delaying shutdown or
731
+ startup for the 429 block to expire.
732
+
733
+ ## 0.2.1-rc.2-0.3.0
734
+
735
+ - `processMode: live` is the new default. One process card is created on the
736
+ first tool/command/skill row, edited during the turn, and finalised as a
737
+ collapsed `<details>` summary. `summary` still sends only the collapsed
738
+ summary after the turn; `off` hides process rows. Web-UI sessions follow the
739
+ same mode.
740
+ - Live process-card refs are persisted in bindings, closed with a warning after
741
+ a restart or graceful stop, and expired after 30 minutes of inactivity.
742
+ - Slash commands are detected only at the first non-whitespace character;
743
+ slashes later in a prompt are literal. `/commands@bot` is accepted and a
744
+ command addressed to another known bot is ignored. `//text` is a leading-only
745
+ escape.
746
+ - `/run <command> [args]` executes a host command even when a connector name
747
+ wins; `/skill <name> [args]` loads a user-invocable skill even when a host
748
+ command owns the name.
749
+ - Media sent with a skill is attached to that turn, including reply references.
750
+ Media sent with a command is staged for the next prompt instead of being
751
+ dropped; unknown slash commands stage it too. Albums are debounced as one
752
+ gesture.
753
+ - Failed command output and thrown command errors are redacted before posting;
754
+ successful command output is unchanged. Command output still stays out of the
755
+ model history, and replying to the result pulls it back in.
756
+ - `/commands` and `/skills` documentation now covers the collision escapes,
757
+ leading-only slash rule and media behaviour.
758
+
759
+ ## 0.2.1-rc.2-0.2.1
760
+
761
+ Maintenance release: ships with the setup's supervisor-test fix. No connector
762
+ behavior change.
763
+
764
+ ## 0.2.1-rc.2-0.2.0
765
+
766
+ Maintenance release aligned with the setup's two-mode installer. No connector
767
+ behavior change: the same code runs under the container and under the new native
768
+ systemd deployment.
769
+
770
+ ## 0.2.1-rc.2-0.1.19
771
+
772
+ - Tool calls, host commands and skill loads become short safe process rows.
773
+ Telegram sessions append one collapsed `<details>` summary per turn
774
+ (`processMode: summary`); web-UI-driven sessions get a live process card.
775
+ Raw tool output is never mirrored; command/path/query previews are redacted and
776
+ truncated, and credentials are masked.
777
+ - Session topics now bridge host commands dynamically with
778
+ `ctx.commands.list()` / `ctx.commands.execute()`; no allowlist means a command
779
+ from a newly installed plugin works without a connector release. The command
780
+ result is posted without creating a model message.
781
+ - `/commands` lists host commands, `/skills` lists user-invocable skills, and
782
+ `/<name>` loads a skill through the `dsh-tool-skill` gesture. Both lists are
783
+ read live from the session, so new skills also work without a connector
784
+ release.
785
+ - Connector commands keep precedence over host commands on a name collision.
786
+
787
+ ## 0.2.1-rc.2-0.1.18
788
+
789
+ - Fix the `telegram-rich-text` skill never loading: the registration omitted the
790
+ `source` field that the skills registry requires, so loading it failed with
791
+ `source must be a string`.
792
+ - Send a Markdown table as a fenced monospaced block, or as bullets when it is
793
+ too wide, instead of leaving the GFM table to the client. Clients that do not
794
+ render tables showed the raw pipe syntax; a code block and a list work
795
+ everywhere.
796
+
797
+ ## 0.2.1-rc.2-0.1.17
798
+
799
+ - Forwarded messages are now processed as their own context turn with a
800
+ `Forwarded from …` block. Forwarded rich messages are read from
801
+ `rich_message.blocks`; forwarded media is re-downloaded and attached.
802
+ - A reply to a forwarded message adds `(forwarded from …)` to the reference
803
+ block, so the model can tell that the quoted message was not written by the
804
+ current user.
805
+ - The poll filter now admits forwarded and rich messages that carry no `text`.
806
+
807
+ ## 0.2.1-rc.2-0.1.16
808
+
809
+ - Reply references now read `rich_message.blocks` as well as `text`/`caption`/
810
+ `quote`. A reply to a message the connector sent as a rich message (for
811
+ example the anchor test message) used to look like a plain prompt because
812
+ Telegram puts the content in `rich_message`, not `text`.
813
+ - The rich-block extractor flattens headings, paragraphs, tables and nested
814
+ inline text, skips layout metadata, and still truncates the quote to ~800
815
+ characters.
816
+
817
+ ## 0.2.1-rc.2-0.1.15
818
+
819
+ - Replying to an earlier message now adds it to the prompt as quoted reference
820
+ context. Same-chat replies use `reply_to_message`; cross-chat/topic replies use
821
+ `external_reply`.
822
+ - Referenced media is re-downloaded on every use (no cache), attached as
823
+ `ImageBlock`/`FileBlock`, and deduped against staged or newly sent media by
824
+ `file_id`.
825
+ - Download failures are written into the prompt, including the likely fixes
826
+ (re-upload, send as a file, grant the bot access to the source chat).
827
+ - A text reply is a normal acknowledgment turn; a media reply is an immediate
828
+ prompt with the new media as the task and the referenced media as context.
829
+ - Commands never attach referenced media.
830
+
831
+ ## 0.2.1-rc.2-0.1.14
832
+
833
+ - Photos, image documents, videos, video notes, audio, voice notes and
834
+ animations are downloaded through the Bot API and attached with DSH's
835
+ attachment service: images become `ImageBlock`s, everything else becomes a
836
+ `FileBlock` with a read-only path the agent can inspect.
837
+ - Captionless media is staged instead of starting a turn per file. Staged items
838
+ get the **🙉** reaction, and the next caption or text prompt downloads and
839
+ attaches the whole batch. The reaction is removed when the batch is used or
840
+ after 15 minutes.
841
+ - Albums are debounced by `media_group_id`, so a multi-photo upload is one
842
+ prompt, not one prompt per photo.
843
+ - `/reactions staged <emoji>` and `stagedReaction` configure the marker; the
844
+ default is 🙉.
845
+
846
+ ## 0.2.1-rc.2-0.1.13
847
+
848
+ - Every Telegram session gets a `telegram-surface` system-prompt section that
849
+ tells the model the user is reading in Telegram and that replies are sent as
850
+ rich messages. It asks for headings, lists, narrow tables, fenced code,
851
+ details, math and `<tg-time>`, and warns against MarkdownV2 escaping and
852
+ wrapping the whole answer in a code fence.
853
+ - The full formatting cheat sheet ships as `skills/telegram-rich-text/SKILL.md`
854
+ and is registered as the `telegram-rich-text` runtime skill, so it is loadable
855
+ on demand instead of inflating every prompt.
856
+ - The prompt section is installed on both newly created and resumed Telegram
857
+ agents, including sessions adopted from the web UI.
858
+
859
+ ## 0.2.1-rc.2-0.1.12
860
+
861
+ - Agent replies are sent as Telegram rich messages (Bot API 10.1+), so Markdown
862
+ tables, headings and lists render natively instead of arriving as raw source.
863
+ A rich message rejected by the API falls back to the HTML subset (a table
864
+ becomes a monospaced block or a key/value list) and finally to plain text.
865
+ - Message splitting is table-aware: a table split across messages repeats its
866
+ header and separator, so every chunk still renders as a table.
867
+ - The main bot sets a **read** reaction on an authorized prompt and a
868
+ **streaming** reaction on each reply part that may still be edited; the
869
+ streaming reaction is removed after the final flush, on agent error, and on
870
+ shutdown. Both emoji are configurable online with `/reactions` and persisted
871
+ in the bindings. Telegram's fixed reaction set is validated (`✓`, `✅` and
872
+ `⏳` are not allowed; defaults are 👀 and ✍).
873
+ - A rejected HTML payload now falls back to rendered plain text instead of
874
+ resending the Markdown source.
875
+
876
+ ## 0.2.1-rc.2-0.1.11
877
+
878
+ - A failed topic operation no longer latches topic management off for the rest
879
+ of the process. A transient 400/403 used to block `/new`, `/sync` and
880
+ `/unarchive` even after the permission or topic was fixed.
881
+ - `/new` now reports Telegram's actual error instead of only guessing that
882
+ `can_manage_topics` is missing.
883
+
884
+ ## 0.2.1-rc.2-0.1.10
885
+
886
+ Maintenance release aligned with the setup fix for the web UI bind address. No
887
+ connector behavior change.
888
+
889
+ ## 0.2.1-rc.2-0.1.9
890
+
891
+ - Mirror web-UI prompts and answers in log order; the answer used to read the
892
+ event envelope instead of `event.data.message` and was never posted.
893
+ - Do not mirror harness-injected `user/message` context (time readings, runtime
894
+ context, skill catalogs) as if the user had typed it.
895
+ - Match the claimed topic by group and thread, not thread id alone.
896
+
897
+ ## 0.2.1-rc.2-0.1.8
898
+
899
+ Maintenance target for the web-UI drain/cancel test. No behavior change.
900
+
901
+ ## 0.2.1-rc.2-0.1.7
902
+
903
+ - Boot fallback waits for a terminal update state instead of reading `applying`.
904
+ - Updater marks `reporting`/`reported`; the connector reports only if the updater
905
+ could not, and closes the update card with the final result.
906
+
907
+ ## 0.2.1-rc.2-0.1.6
908
+
909
+ - Fix the updater’s Telegram report (`fetch` option shadowed global `fetch`).
910
+ - If the updater cannot report, the booting connector sends the persisted result after 5s.
911
+ - Updater result files are written atomically.
912
+ - `/about` continues to show updater status.
913
+
914
+ ## 0.2.1-rc.2-0.1.5
915
+
916
+ - `/about` reports updater status (`ready`, `unreachable`, `disabled`, or `apply unavailable`) and the checkout tag.
917
+
918
+ ## 0.2.1-rc.2-0.1.4
919
+
920
+ Maintenance release for the self-reloading updater. No connector behavior change.
921
+
922
+ ## 0.2.1-rc.2-0.1.3
923
+
924
+ - Editable setup-update card: target, live drain blockers, and a Cancel button.
925
+ - Cancel is removed once the updater accepts; callbacks after that are refused.
926
+ - `/about`, `/help`, `/man` and `/system status` stay available while draining.
927
+ - Updater sends a “dsh is down” notice and strips ANSI from report logs.
928
+ - `/about` no longer prints the old peer-range line.
929
+
930
+ ## 0.2.1-rc.2-0.1.2
931
+
932
+ Maintenance target for the next setup-updater validation. No connector behavior
933
+ change.
934
+
935
+ ## 0.2.1-rc.2-0.1.1
936
+
937
+ Maintenance release used as the first live target for the setup updater. No
938
+ connector behavior change.
939
+
940
+ ## 0.2.1-rc.2-0.1.0
941
+
942
+ First DSH-aligned release with the updater sidecar. The DSH part matches the
943
+ tested runtime; the product part (`0.1.0`) is our compatible feature line.
944
+ Same-major updates may jump; crossing a major or DSH line requires the explicit
945
+ flag in the setup updater.
946
+
947
+ - Telegram sessions mount a DSH **agent preset** (default or `agentPreset`) on
948
+ create and the header's recorded preset on resume.
949
+ - `/system` namespace: `status`, `restart [now]`, `update connector [now]`,
950
+ `update all`, `confirm`, `rollback`; old commands removed.
951
+ - `/system update connector now` reinstalls without a trial.
952
+ - `/system update all` drains all agents (web UI included), blocks new prompts,
953
+ calls the updater sidecar, and rejects the queued downtime batch with
954
+ “update finished — send it again”.
955
+ - `/system status` lists sessions blocking a drain.
956
+
957
+ ## 0.1.0-rc.1
958
+
959
+ First release candidate for 0.1.0.
960
+
961
+ First public shape of the connector.
962
+
963
+ - Groups map to workspaces, forum topics to sessions, the private chat to the
964
+ control plane.
965
+ - Streaming replies, Markdown subset → Telegram HTML, fence-aware splitting.
966
+ - `/sync` adoption with per-session probing and history replay, paced to
967
+ Telegram's per-chat limits and announced in the system chat while waiting.
968
+ - Durable bindings; sessions are resumed, never re-minted on restart.
969
+ - Plugin surface: list, info, add/remove with inspect + confirmation,
970
+ enable/disable, build-script approval.
971
+ - Supervised restarts: `/restart` (trial), `/restart now`, `/confirm`,
972
+ `/rollback`, live trials for HMR changes, automatic rollback on crash, boot
973
+ failure, deadline or container restart.
974
+ - Self-update through the supervisor (`/update`).
975
+ - `/help`, `/man`, `<command> --help`, `/about`, `/timezone`.
976
+ - Per-group outbox: persisted FIFO with control priority, exactly-once delivery
977
+ (ambiguous outcomes are quarantined, never duplicated), queue status line, a
978
+ weekly saturation digest, and an owner notice when a message is lost so it is
979
+ never silent.
980
+ - Logical bridge: durable out/in journals for turns and prompts, with a
981
+ crash catch-up digest and prompt re-injection; the format is the boundary for
982
+ a future standalone bridge process.
983
+ - Optional publisher bots (`DSH_TELEGRAM_PUBLISHER_TOKENS`): send-only, per-bot
984
+ rate limits, proactive switching, membership checks and missing-member reports.