dsh-telegram-bot 0.1.0 → 0.1.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 (4) hide show
  1. package/README.md +21 -24
  2. package/client.js +7 -50
  3. package/index.js +14 -38
  4. package/package.json +4 -4
package/README.md CHANGED
@@ -14,26 +14,26 @@ The bot connects to Telegram, enforces the allowlists, and bridges DSH agent ses
14
14
  - **Allowed chats** — Telegram chat ids or `@channelnames`; empty means private chats only.
15
15
  - **Enable bot** toggle.
16
16
  - **Restart bot** button — reapplies the saved settings and restarts long polling.
17
- - **Quick controls on the Plugins page** — the bundle's detail page shows token state, access counts, and the same restart button. The bundle switch itself is the on/off control; turning the plugin off unmounts it and aborts polling.
17
+ - **Plugins page** — the bundle page is informational and points to Settings → Telegram. The bundle switch above it is the plugin on/off control; turning it off unmounts the runtime and aborts polling.
18
18
  - **Agent bridge** — an ordinary text message in a session topic starts a DSH agent turn in that session, with assistant text streamed back.
19
- - **DM topics** — `/sessions` in **All** is the single place for DSH sessions: choose a workspace, then create a new session in it or open an existing one. The selected session continues in its own topic.
19
+ - **DM topics** — `/sessions` in **All** is the single place for DSH sessions: choose a workspace, then create a new session in it or open an existing one. The selected session continues in its own topic. Requires **Threaded mode** in @BotFather → Bot Settings.
20
20
  - **All and System topics** — All is Telegram's default topic and the management hub; System receives bot lifecycle notifications, mirrored into All.
21
- - **Thinking and tool calls** — reasoning deltas and tool calls are mirrored into the topic, with independent **Show model thinking** / **Show tool calls** switches.
21
+ - **Thinking and tool calls** — reasoning deltas and tool calls are mirrored into the topic, with independent **Show model thinking** / **Show tool calls** switches. Thinking is a 10-line rolling window; the tool-call message shows the last ten calls.
22
22
  - **Commands** — `/start`, `/help`, `/sessions`, `/stop`, `/status`, `/current`, `/menu`, `/rename`, `/last`, `/restart`, `/id`, `/ping`.
23
23
  - **Approval prompts** — when a tool asks for approval, the session topic gets a styled prompt with **Deny** and **Allow** inline buttons; the decision resolves the exact pending request.
24
24
  - **Session controls** — an inline 2×2 panel in each session topic: **Model** (Flash/Pro), **Effort** (off/low/high/max), **Mode** (permission preset), and **Context** (window, last request usage, and cache-hit percentage). Telegram reply keyboards are chat-wide, so the controls are a per-topic inline panel rather than a bottom keyboard.
25
- - **Recovery** — `/last [n]` shows the latest assistant answer(s) from the bound session, useful after switching between Web and Telegram. `/rename <name>` changes the Telegram topic title; `/restart` restarts the Telegram runtime; `/menu` reposts the bottom controls.
25
+ - **Recovery** — `/last [n]` shows the latest assistant answer(s) from the bound session, useful after switching between Web and Telegram. `/rename <name>` changes the Telegram topic title; `/restart` restarts the Telegram runtime; `/menu` opens the inline session controls.
26
26
  - **Language** — bot messages and the Telegram command menu default to English; a Settings selector switches them to Russian.
27
27
  - **Formatting** — assistant Markdown (headings, bold, lists, code, links, tables) is converted to Telegram MarkdownV2.
28
- - **Command hints** — the runtime publishes the list with `setMyCommands`, so Telegram shows the commands and descriptions when the user types `/`. English is the default; Russian clients get localized descriptions.
28
+ - **Command hints** — the runtime publishes the list with `setMyCommands`, so Telegram shows the commands and descriptions when the user types `/`. The descriptions follow the selected Bot language; English is the default.
29
29
  - English and Russian page copy; Russian is registered as an optional language pack.
30
30
 
31
31
  ## Install
32
32
 
33
- From this checkout:
33
+ From this checkout, run in the repository root:
34
34
 
35
35
  ```sh
36
- npx @deepseek-ai/dsh plugin --profile web add /home/boobaw/dsh-plugin-tg-bot
36
+ npx @deepseek-ai/dsh plugin --profile web add .
37
37
  ```
38
38
 
39
39
  After publishing to npm:
@@ -44,7 +44,7 @@ npx @deepseek-ai/dsh plugin --profile web add dsh-telegram-bot
44
44
 
45
45
  `dsh plugin add` installs the package and selects its bundle in `dsh.profile.bundles` when the package declares `dsh.bundle`. Restart `dsh web` if the running profile does not pick the new bundle up through HMR.
46
46
 
47
- Then open **Settings → Telegram** (or **Plugins → dsh-telegram-bot**) in the Web UI.
47
+ Then open **Settings → Telegram** (or **Plugins → Telegram Bot**) in the Web UI.
48
48
 
49
49
  ## Configure
50
50
 
@@ -67,10 +67,11 @@ The token field reports only whether a token is configured. A token supplied by
67
67
  ### First run
68
68
 
69
69
  1. Create a bot with [@BotFather](https://t.me/BotFather) and save its token in **Settings → Telegram**.
70
- 2. Open the bot chat, tap the bot name and enable **Topics**. **All** is Telegram's default topic; the bot creates **System** for lifecycle notifications.
71
- 3. Send `/start` in **All**. With an empty user list the bot replies with your user id and chat id.
72
- 4. Add your user id to **Allowed users** and press **Save** (or **Restart bot**).
73
- 5. In **All** send `/sessions` to create a new session or pick an existing DSH session. The dialog continues in its own topic.
70
+ 2. In @BotFather open the bot's **Bot Settings → Threaded mode** and enable it. Without this, private-chat topics cannot be created.
71
+ 3. Open the bot chat, tap the bot name and enable **Topics**. **All** is Telegram's default topic; the bot creates **System** for lifecycle notifications.
72
+ 4. Send `/start` in **All**. With an empty user list the bot replies with your user id and chat id, plus the Threaded-mode reminder.
73
+ 5. Add your user id to **Allowed users** and press **Save** (or **Restart bot**).
74
+ 6. In **All** send `/sessions` to create a new session or pick an existing DSH session. The dialog continues in its own topic.
74
75
 
75
76
  The runtime starts only when **Enable bot** is on, a token is configured, and the profile process is running. It logs connection and polling diagnostics with the `[telegram]` prefix. Runtime state is at `$DSH_HOME/telegram/status.json`, and the topic → session mapping is at `$DSH_HOME/telegram/state.json` (neither contains the token).
76
77
 
@@ -127,15 +128,13 @@ No browser and no port are opened. `Ctrl+C` stops the process; `$DSH_HOME/telegr
127
128
 
128
129
  ## Plugins page
129
130
 
130
- The bundle detail page in **Plugins** renders a compact card with:
131
+ The bundle detail page in **Plugins** is a short informational panel:
131
132
 
132
- - token state and the current number of allowed users/chats;
133
- - **Restart bot**;
134
- - a pointer to **Settings → Telegram** for editing the full lists.
133
+ - it points to **Settings → Telegram** for token, access lists, language and display options;
134
+ - it lists the manual configuration files for headless setups;
135
+ - it does not duplicate the settings controls.
135
136
 
136
- There is deliberately no bot on/off switch on this page: the bundle switch above the card disables the whole plugin, and the runtime's `ctx.effect` cleanup aborts polling when it unmounts. **Settings → Telegram → Enable bot** remains a soft pause that keeps the plugin loaded.
137
-
138
- The full page remains in Settings because allowlist editing needs room for chips and validation.
137
+ The bundle switch above the panel is the plugin on/off control. **Settings → Telegram → Enable bot** is a soft pause that keeps the plugin loaded but stops polling.
139
138
 
140
139
  ## Security
141
140
 
@@ -178,11 +177,9 @@ A Git URL or tarball also works for DSH (`dsh plugin add github:you/dsh-telegram
178
177
 
179
178
  ## Roadmap
180
179
 
181
- 1. Approval and question answerers with inline buttons.
182
- 2. Tool-call cards and richer streaming presentation.
183
- 3. File attachments and voice input.
184
- 4. Model/preset selection from the chat.
185
- 5. Multiple chats and group/topic routing.
180
+ 1. File attachments and voice input.
181
+ 2. Multiple chats and group/topic routing.
182
+ 3. Richer tool-result summaries.
186
183
 
187
184
  ## License
188
185
 
package/client.js CHANGED
@@ -10,7 +10,7 @@ window.__ModuleLoader__.load({
10
10
  const { Button, SettingsSecretField, Switch } = primitives
11
11
  const h = React.createElement
12
12
 
13
- /** Loader row id / settings namespace, equal to the package name. */
13
+ /** Loader row id / settings namespace; the npm package name is dsh-telegram-bot. */
14
14
  const NS = 'telegram-bot'
15
15
  /** Default credential reference holding the Telegram bot token. */
16
16
  const DEFAULT_TOKEN_REF = 'TELEGRAM_BOT_TOKEN'
@@ -51,7 +51,6 @@ window.__ModuleLoader__.load({
51
51
  saving: 'Saving…',
52
52
  saved: 'Saved.',
53
53
  restart: 'Restart bot',
54
- restarting: 'Restarting…',
55
54
  restartRequested: 'Restart requested. Check Telegram or the DSH log.',
56
55
  restartFailed: 'The Host did not accept the restart request.',
57
56
  bundleSummary: 'Telegram bot',
@@ -61,20 +60,6 @@ window.__ModuleLoader__.load({
61
60
  pluginConfigSettings: 'plugin settings (cordis.patch.yml)',
62
61
  pluginConfigToken: 'bot token (credential store)',
63
62
  pluginConfigEnv: 'token fallback for headless deployments',
64
- running: 'Running',
65
- stopped: 'Stopped',
66
- runtimeMissingShort: 'Host not loaded',
67
- on: 'On',
68
- off: 'Off',
69
- pluginRuntimeHint: 'Runtime state from this DSH process. Turning the bundle off stops polling.',
70
- pluginQuickControls: 'Quick controls',
71
- pluginDisplay: 'Display',
72
- bundleSettingsHint: 'Full allowlists are in Settings → Telegram.',
73
- tokenConfiguredShort: 'token configured',
74
- tokenMissingShort: 'no token',
75
- usersShort: 'users',
76
- chatsShort: 'chats',
77
- bundleDisableHint: 'Turning the plugin off in Plugins stops polling.',
78
63
  hostNeedsRestart: 'The Telegram runtime is not loaded in this DSH process yet. Restart dsh web once; after that this page can restart the bot.',
79
64
  discard: 'Discard',
80
65
  saveFailed: 'The Host did not accept these values.',
@@ -121,7 +106,6 @@ window.__ModuleLoader__.load({
121
106
  saving: 'Сохранение…',
122
107
  saved: 'Сохранено.',
123
108
  restart: 'Перезапустить бота',
124
- restarting: 'Перезапуск…',
125
109
  restartRequested: 'Запрошен перезапуск. Проверьте Telegram или лог DSH.',
126
110
  restartFailed: 'Host не принял запрос на перезапуск.',
127
111
  bundleSummary: 'Telegram-бот',
@@ -131,20 +115,6 @@ window.__ModuleLoader__.load({
131
115
  pluginConfigToken: 'токен бота (credential store)',
132
116
  pluginConfigEnv: 'fallback токена для headless',
133
117
  pluginPageLocation: 'Открой Settings → Telegram, чтобы настроить плагин.',
134
- running: 'Работает',
135
- stopped: 'Остановлен',
136
- runtimeMissingShort: 'Host не загружен',
137
- on: 'Вкл',
138
- off: 'Выкл',
139
- pluginRuntimeHint: 'Состояние runtime в этом процессе DSH. Выключение bundle останавливает polling.',
140
- pluginQuickControls: 'Быстрые настройки',
141
- pluginDisplay: 'Отображение',
142
- bundleSettingsHint: 'Полные списки доступа — в Settings → Telegram.',
143
- tokenConfiguredShort: 'токен настроен',
144
- tokenMissingShort: 'нет токена',
145
- usersShort: 'пользователей',
146
- chatsShort: 'чатов',
147
- bundleDisableHint: 'Выключение плагина в Plugins останавливает polling.',
148
118
  hostNeedsRestart: 'Telegram runtime ещё не загружен в этот процесс DSH. Перезапусти dsh web один раз; после этого кнопка рестарта заработает.',
149
119
  discard: 'Отменить',
150
120
  saveFailed: 'Host не принял эти значения.',
@@ -189,22 +159,9 @@ window.__ModuleLoader__.load({
189
159
  .dtb-message{min-height:20px;font-size:12px;line-height:20px}
190
160
  .dtb-messageOk{color:var(--dsw-alias-state-success-primary)}
191
161
  .dtb-messageError{color:var(--dsw-alias-state-error-primary)}
192
- .dtb-bundle{display:flex;flex-direction:column;gap:12px}
193
162
  .dtb-plugin{display:flex;flex-direction:column;gap:16px;padding-top:4px}
194
- .dtb-pluginTop{display:flex;flex-direction:column;gap:8px}
195
- .dtb-bundleMeta{display:flex;flex-wrap:wrap;align-items:center;gap:8px}
196
- .dtb-pluginGrid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
197
- .dtb-stat{display:flex;flex-direction:column;gap:2px;padding:10px 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-1)}
198
- .dtb-statLabel{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}
199
- .dtb-statValue{font-size:15px;line-height:22px;font-weight:600}
200
- .dtb-pluginSection{display:flex;flex-direction:column;gap:10px}
201
- .dtb-pluginSectionTitle{margin:0;font-size:13px;font-weight:600;line-height:20px}
202
- .dtb-pluginControls{display:flex;flex-direction:column;gap:10px}
203
- .dtb-pluginControl{display:flex;align-items:center;justify-content:space-between;gap:16px}
204
- .dtb-pluginActions{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
205
163
  .dtb-notice{margin:0;padding:10px 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}
206
164
  .dtb-loading{padding:16px 0;color:var(--dsw-alias-label-tertiary);font-size:13px}
207
- .dtb-note{margin:0;color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:17px}
208
165
  @media (max-width:560px){.dtb-toggleRow{align-items:flex-start;flex-direction:column;gap:8px}.dtb-footer{align-items:stretch;flex-direction:column}.dtb-footerActions{justify-content:flex-end}}
209
166
  `
210
167
 
@@ -715,11 +672,11 @@ window.__ModuleLoader__.load({
715
672
 
716
673
 
717
674
  /**
718
- * Compact controls on the Plugins page's bundle detail. The full allowlists
719
- * stay in Settings → Telegram; this card owns the restart and token/status
720
- * summary. The bundle switch itself is the plugin's on/off control.
721
- * @param props - locale reader, settings form, credential operations, view.
722
- * @returns the summary line or the quick controls.
675
+ * Informational card on the Plugins page's bundle detail. All controls live
676
+ * in Settings → Telegram; this card only points there and lists the manual
677
+ * configuration files. The bundle switch is the plugin's on/off control.
678
+ * @param props - locale reader and slot view.
679
+ * @returns the summary line or the settings pointer.
723
680
  */
724
681
  function BundleSettings(props) {
725
682
  const { t, view } = props
@@ -809,7 +766,7 @@ window.__ModuleLoader__.load({
809
766
  name: 'plugins.bundle.config',
810
767
  key: 'dsh-telegram-bot',
811
768
  locale: NS,
812
- inject: () => ({ t, form, token }),
769
+ inject: () => ({ t }),
813
770
  },
814
771
  BundleSettings,
815
772
  ),
package/index.js CHANGED
@@ -1,14 +1,10 @@
1
1
  /**
2
2
  * Host half of dsh-telegram-bot.
3
3
  *
4
- * It owns two things:
5
- * - the editable settings namespace (`enabled`, allowlists, restart request);
6
- * - a deliberately small Telegram long-polling runtime, so the Restart button
7
- * and the allowlists do something real before the full agent bridge lands.
8
- *
9
- * The runtime answers only a handful of diagnostic commands. Wiring Telegram
10
- * chats to DSH agents is the next step; keeping this layer small means a bad
11
- * token or a conflicting poller can never take the Host down.
4
+ * It owns the editable settings namespace, the Telegram long-polling runtime,
5
+ * the DM-topic session browser, and the bridge between Telegram topics and
6
+ * DSH agent sessions. Keeping the runtime isolated means a bad token or a
7
+ * conflicting poller cannot take the Host down.
12
8
  */
13
9
  import z from '@deepseek-ai/schemastery'
14
10
  import { mkdir, readFile, rename, writeFile } from 'node:fs/promises'
@@ -18,13 +14,11 @@ import { homedir } from 'node:os'
18
14
  import { basename, join, resolve } from 'node:path'
19
15
  import telegramifyMarkdown from 'telegramify-markdown'
20
16
 
21
- /** Loader row id; keep it equal to the package name and the client namespace. */
17
+ /** Loader row id and settings namespace; the npm package name stays dsh-telegram-bot. */
22
18
  export const name = 'telegram-bot'
23
19
 
24
20
  /** Default credential reference holding the bot token. */
25
21
  const DEFAULT_TOKEN_REF = 'TELEGRAM_BOT_TOKEN'
26
- /** Telegram Bot API root; the token is appended per request. */
27
- const API_ROOT = 'https://api.telegram.org'
28
22
  /** Long-poll timeout requested from Telegram, in seconds. */
29
23
  const POLL_TIMEOUT_SECONDS = 25
30
24
  /** Pause after a failed poll before trying again, in milliseconds. */
@@ -436,7 +430,7 @@ let runtimeStatus = {
436
430
  transport: 'https-ipv4',
437
431
  version: '0.3.0',
438
432
  agentBridge: 'v1',
439
- codeRevision: 'format-4',
433
+ codeRevision: 'threaded-mode',
440
434
  lastPollAt: 0,
441
435
  lastMessageAt: 0,
442
436
  lastChatId: null,
@@ -540,7 +534,6 @@ export function apply(ctx, config) {
540
534
  thinkingMessageId: null,
541
535
  thinkingTimer: null,
542
536
  thinkingLastText: '',
543
- thinkingIsStatus: false,
544
537
  tools: [],
545
538
  toolMessageId: null,
546
539
  toolTimer: null,
@@ -577,19 +570,6 @@ export function apply(ctx, config) {
577
570
  await persistState()
578
571
  }
579
572
 
580
- /**
581
- * Remove one topic's session binding without deleting the session.
582
- * @param chat - chat bridge state.
583
- */
584
- async function unbindSession(chat) {
585
- const sessionId = chat.sessionId
586
- chat.sessionId = undefined
587
- chat.boundAgent = undefined
588
- delete state.threads[chat.key]
589
- if (typeof sessionId === 'string') delete state.sessions[sessionId]
590
- await persistState()
591
- }
592
-
593
573
  /** @returns the configured session working directory. */
594
574
  function cwdOf() {
595
575
  const configured = readLive(config.cwd, process.cwd())
@@ -1004,7 +984,7 @@ export function apply(ctx, config) {
1004
984
  }
1005
985
 
1006
986
  /**
1007
- * Send one HTML-safe diagnostic message.
987
+ * Send one HTML-formatted message.
1008
988
  * @param chatId - target chat.
1009
989
  * @param text - message body.
1010
990
  * @param signal - runtime lifetime.
@@ -1499,7 +1479,6 @@ export function apply(ctx, config) {
1499
1479
  chat.thinkingText = ''
1500
1480
  chat.thinkingLastText = ''
1501
1481
  chat.thinkingMessageId = null
1502
- chat.thinkingIsStatus = false
1503
1482
  chat.tools = []
1504
1483
  chat.toolLastText = ''
1505
1484
  chat.toolMessageId = null
@@ -1625,7 +1604,6 @@ export function apply(ctx, config) {
1625
1604
  }
1626
1605
  if (frame.type === 'chunk' && frame.chunk?.type === 'reasoning-delta') {
1627
1606
  if (readLive(config.showThinking, true) !== true) return
1628
- chat.thinkingIsStatus = false
1629
1607
  chat.thinkingText += frame.chunk.text
1630
1608
  scheduleThinking(chat)
1631
1609
  return
@@ -1669,7 +1647,7 @@ export function apply(ctx, config) {
1669
1647
  }
1670
1648
 
1671
1649
  /**
1672
- * Flush the final assistant text, replacing or splitting the placeholder.
1650
+ * Flush the final assistant text into the first answer message and split it.
1673
1651
  * @param chat - chat bridge state.
1674
1652
  */
1675
1653
  async function finalizeChat(chat) {
@@ -1922,7 +1900,7 @@ export function apply(ctx, config) {
1922
1900
  return [
1923
1901
  [
1924
1902
  { text: `🤖 ${modelLabel(current.model)}`, callback_data: 'o:model' },
1925
- { text: `🧠 ${tr('Effort', 'Режим')}: ${effortLabel(current.reasoningEffort)}`, callback_data: 'o:effort' },
1903
+ { text: `🧠 ${tr('Effort', 'Усилие')}: ${effortLabel(current.reasoningEffort)}`, callback_data: 'o:effort' },
1926
1904
  ],
1927
1905
  [
1928
1906
  { text: `🛡 ${permissionLabel(permission)}`, callback_data: 'o:mode' },
@@ -2103,7 +2081,7 @@ export function apply(ctx, config) {
2103
2081
  const message = messageOf(error).toLowerCase()
2104
2082
  if (message.includes('duplicate') || message.includes('already')) continue
2105
2083
  if (message.includes('forum') || message.includes('topic')) {
2106
- throw new Error(tr('Enable Topics in the bot chat: tap the bot name → Topics.', 'Включи Topics в чате с ботом: имя бота сверху → Topics.'))
2084
+ throw new Error(tr('Enable Threaded mode in @BotFather → Bot Settings, then enable Topics in the bot chat (tap the bot name → Topics).', 'Включи Threaded mode в @BotFather → Bot Settings, затем включи Topics в чате с ботом (имя бота сверху → Topics).'))
2107
2085
  }
2108
2086
  throw error
2109
2087
  }
@@ -2484,8 +2462,7 @@ export function apply(ctx, config) {
2484
2462
  }
2485
2463
 
2486
2464
  /**
2487
- * Answer one authorized message. This is intentionally a diagnostic surface
2488
- * until the DSH Agent bridge replaces it.
2465
+ * Handle one authorized Telegram message and dispatch its command or prompt.
2489
2466
  * @param message - Telegram message.
2490
2467
  * @param signal - runtime lifetime.
2491
2468
  * @param type - Telegram update key, for diagnostics.
@@ -2533,8 +2510,8 @@ export function apply(ctx, config) {
2533
2510
  await send(
2534
2511
  chat.id,
2535
2512
  tr(
2536
- `Setup mode.\nYour user id: <code>${from.id}</code>\nYour chat id: <code>${chat.id}</code>\n\nAdd the user id to <b>Settings → Telegram → Allowed users</b>, then press Restart.`,
2537
- `Режим настройки.\nТвой user id: <code>${from.id}</code>\nТвой chat id: <code>${chat.id}</code>\n\nДобавь user id в <b>Settings → Telegram → Allowed users</b> и нажми Restart.`,
2513
+ `Setup mode.\nYour user id: <code>${from.id}</code>\nYour chat id: <code>${chat.id}</code>\n\nAdd the user id to <b>Settings → Telegram → Allowed users</b>, then press Restart.\n\nBefore opening sessions, enable <b>Threaded mode</b> in @BotFather → Bot Settings.`,
2514
+ `Режим настройки.\nТвой user id: <code>${from.id}</code>\nТвой chat id: <code>${chat.id}</code>\n\nДобавь user id в <b>Settings → Telegram → Allowed users</b> и нажми Restart.\n\nПеред открытием сессий включи <b>Threaded mode</b> в @BotFather → Bot Settings.`,
2538
2515
  ),
2539
2516
  signal,
2540
2517
  threadId,
@@ -2581,6 +2558,7 @@ export function apply(ctx, config) {
2581
2558
  (inSession
2582
2559
  ? `${tr('Current session', 'Текущая сессия')}: <code>${chatState.sessionId}</code>\n`
2583
2560
  : `${tr('Global topic. Choose a session or create a new one.', 'Глобальный чат. Выбери сессию или создай новую.')}\n`) +
2561
+ `\n<b>${tr('First run', 'Первый запуск')}:</b> @BotFather → Bot Settings → <b>Threaded mode</b> → ${tr('Enable', 'Включить')}.\n` +
2584
2562
  `${tr('Commands', 'Команды')}: /sessions, /current, /menu, /rename, /last, /stop, /restart, /status, /id, /ping.`,
2585
2563
  signal,
2586
2564
  threadId,
@@ -2944,5 +2922,3 @@ export function apply(ctx, config) {
2944
2922
  'dsh-telegram-bot: runtime',
2945
2923
  )
2946
2924
  }
2947
-
2948
- export { preprocessTables, toTelegramMarkdown, splitAnswerText, fitAnswerText }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-telegram-bot",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Telegram sessions, topics, model controls and approvals for DeepSeek Harness.",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -52,10 +52,10 @@
52
52
  "license": "MIT",
53
53
  "repository": {
54
54
  "type": "git",
55
- "url": "git+https://github.com/boobaw/dsh-telegram-bot.git"
55
+ "url": "git+https://github.com/Boobaw/dsh-telegram-bot.git"
56
56
  },
57
- "homepage": "https://github.com/boobaw/dsh-telegram-bot#readme",
57
+ "homepage": "https://github.com/Boobaw/dsh-telegram-bot#readme",
58
58
  "bugs": {
59
- "url": "https://github.com/boobaw/dsh-telegram-bot/issues"
59
+ "url": "https://github.com/Boobaw/dsh-telegram-bot/issues"
60
60
  }
61
61
  }