dsh-tg-bridge 1.5.1 → 1.5.3

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.
package/README.md CHANGED
@@ -216,9 +216,9 @@ node ~/.dsh/tg-bridge/say.mjs --thought "checking why the watchdog fired twice"
216
216
  ```
217
217
 
218
218
  The note is appended to `~/.dsh/tg-bridge/thoughts/<chat>_<thread>.jsonl`; the progress
219
- message shows the last two as `💭` lines. Inside a turn the chat and thread come from
220
- `DSH_TG_CHAT` / `DSH_TG_THREAD`, so the command needs no ids. `--thought` never sends a
221
- Telegram message on its own.
219
+ message shows the last two as `💭` lines. The command needs no ids: it falls back to the
220
+ newest turn's thought file, because tool shells do not inherit the bridge environment.
221
+ `--thought` never sends a Telegram message on its own.
222
222
 
223
223
  ### Goals and tasks
224
224
 
package/bridge.mjs CHANGED
@@ -955,7 +955,7 @@ async function startProgress(chatId, threadId, lang = 'ru') {
955
955
  }
956
956
  };
957
957
 
958
- const schedule = () => {
958
+ function schedule() {
959
959
  dirty = true;
960
960
  if (timer) return;
961
961
  timer = setTimeout(async () => {
@@ -965,7 +965,7 @@ async function startProgress(chatId, threadId, lang = 'ru') {
965
965
  await edit(body());
966
966
  }, 3500);
967
967
  timer.unref?.();
968
- };
968
+ }
969
969
 
970
970
  return {
971
971
  /** Keep the clock moving during long model thinking: the elapsed time is
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-tg-bridge",
3
- "version": "1.5.1",
3
+ "version": "1.5.3",
4
4
  "description": "Telegram bridge for DeepSeek Harness: text, voice, photos and project-per-topic sessions without opening the desktop app",
5
5
  "type": "module",
6
6
  "main": "plugin-bridge.mjs",
package/say.mjs CHANGED
@@ -7,14 +7,14 @@
7
7
  //
8
8
  // node say.mjs --steer <job-id> "text"
9
9
  // node say.mjs --chat <chat-id> [--thread <id>] "text"
10
- // node say.mjs --thought "short note" (chat/thread come from DSH_TG_CHAT/DSH_TG_THREAD)
10
+ // node say.mjs --thought "short note" (no ids needed)
11
11
  //
12
12
  // `--thought` does not send a message: it appends to the turn's thought file,
13
13
  // and the live progress message shows the last two notes as 💭 lines.
14
14
  //
15
15
  // With `--steer` the chat/thread come from the job file and an ack marker is
16
16
  // written, which suppresses the bridge's fallback line.
17
- import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
17
+ import { appendFileSync, existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from 'node:fs';
18
18
  import { homedir } from 'node:os';
19
19
  import { join } from 'node:path';
20
20
 
@@ -63,6 +63,21 @@ function parse(argv) {
63
63
  return out;
64
64
  }
65
65
 
66
+ function activeThoughtFile() {
67
+ try {
68
+ const files = readdirSync(THOUGHTS)
69
+ .filter((name) => name.endsWith('.jsonl'))
70
+ .map((name) => ({ name, mtime: statSync(join(THOUGHTS, name)).mtimeMs }))
71
+ .sort((a, b) => b.mtime - a.mtime);
72
+ if (!files.length) return null;
73
+ const [chat, thread] = files[0].name.replace(/\.jsonl$/, '').split('_');
74
+ if (!Number(chat)) return null;
75
+ return { chatId: Number(chat), threadId: Number(thread) || 0 };
76
+ } catch {
77
+ return null;
78
+ }
79
+ }
80
+
66
81
  async function main() {
67
82
  const args = parse(process.argv.slice(2));
68
83
  if (!args.text) usage();
@@ -70,6 +85,15 @@ async function main() {
70
85
  let chatId = args.chatId || Number(process.env.DSH_TG_CHAT || 0);
71
86
  let threadId = args.threadId || Number(process.env.DSH_TG_THREAD || 0);
72
87
  let jobPath = '';
88
+ // Tool shells do not inherit the bridge's env, so fall back to the thought
89
+ // file the bridge touched at the start of the newest turn.
90
+ if (!chatId && args.thought) {
91
+ const active = activeThoughtFile();
92
+ if (active) {
93
+ chatId = active.chatId;
94
+ threadId = active.threadId;
95
+ }
96
+ }
73
97
  if (args.steer) {
74
98
  const found = jobOf(args.steer);
75
99
  if (!found) {