switchroom 0.19.14 → 0.19.15

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 (31) hide show
  1. package/dist/cli/switchroom.js +1 -1
  2. package/dist/host-control/main.js +1 -1
  3. package/package.json +1 -1
  4. package/telegram-plugin/bridge/bridge.ts +1 -1
  5. package/telegram-plugin/dist/bridge/bridge.js +1 -1
  6. package/telegram-plugin/dist/gateway/gateway.js +1002 -504
  7. package/telegram-plugin/dist/server.js +1 -1
  8. package/telegram-plugin/gateway/forward-origin.ts +6 -1
  9. package/telegram-plugin/gateway/gateway.ts +4 -0
  10. package/telegram-plugin/gateway/narrative-lane.ts +11 -0
  11. package/telegram-plugin/gateway/outbox-sweep.ts +32 -2
  12. package/telegram-plugin/gateway/rich-message-handler.ts +235 -0
  13. package/telegram-plugin/gateway/stream-render.ts +107 -15
  14. package/telegram-plugin/gateway/unhandled-message.ts +14 -0
  15. package/telegram-plugin/hooks/narration-classify.d.mts +23 -0
  16. package/telegram-plugin/hooks/narration-classify.mjs +210 -0
  17. package/telegram-plugin/hooks/silent-end-scan.mjs +136 -82
  18. package/telegram-plugin/narrative-flush.ts +35 -0
  19. package/telegram-plugin/outbox.ts +73 -3
  20. package/telegram-plugin/shown-ledger.ts +145 -0
  21. package/telegram-plugin/silent-end.ts +42 -0
  22. package/telegram-plugin/tests/backstop-exactly-once.test.ts +335 -0
  23. package/telegram-plugin/tests/catch-all-unhandled-message.test.ts +14 -0
  24. package/telegram-plugin/tests/forward-origin.test.ts +20 -0
  25. package/telegram-plugin/tests/forwarded-rich-message.test.ts +305 -0
  26. package/telegram-plugin/tests/gateway-handler-registration-wiring.test.ts +1 -0
  27. package/telegram-plugin/tests/narration-leak-3513.test.ts +352 -0
  28. package/telegram-plugin/tests/silent-end-interrupt-stop-scan.test.ts +42 -13
  29. package/telegram-plugin/tests/silent-end.test.ts +7 -1
  30. package/telegram-plugin/tests/turn-flush-safety.test.ts +35 -3
  31. package/telegram-plugin/turn-flush-safety.ts +66 -53
@@ -2120,7 +2120,7 @@ var init_esm = __esm(() => {
2120
2120
  });
2121
2121
 
2122
2122
  // src/build-info.ts
2123
- var VERSION = "0.19.14", COMMIT_SHA = "1f1f69f8";
2123
+ var VERSION = "0.19.15", COMMIT_SHA = "20691874";
2124
2124
 
2125
2125
  // src/cli/resolve-version.ts
2126
2126
  import { existsSync, readFileSync } from "node:fs";
@@ -26664,7 +26664,7 @@ import { existsSync as existsSync9, readFileSync as readFileSync7 } from "node:f
26664
26664
  import { dirname as dirname5, join as join7 } from "node:path";
26665
26665
 
26666
26666
  // src/build-info.ts
26667
- var VERSION = "0.19.14";
26667
+ var VERSION = "0.19.15";
26668
26668
 
26669
26669
  // src/cli/resolve-version.ts
26670
26670
  function readPackageVersion() {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "switchroom",
3
3
  "//version": "NOT the release version — source of truth is the git tag, resolved by scripts/build.mjs:resolveVersion() (see CLAUDE.md > Standard release process). This field is stale by design and only the Layer-4 dev/non-tag fallback for build.mjs + src/cli/resolve-version.ts; do NOT bump it expecting a release to pick it up. npm-pack tarball naming needs a real version — do that as an UNCOMMITTED pack-time bump (see release step 6), never a committed one.",
4
- "version": "0.19.14",
4
+ "version": "0.19.15",
5
5
  "description": "Run Claude Code 24/7 on your Claude Pro/Max subscription over Telegram. Open-source alternative to OpenClaw and NanoClaw — no API keys.",
6
6
  "type": "module",
7
7
  "bin": {
@@ -81,7 +81,7 @@ const mcp = new Server(
81
81
  '',
82
82
  'Messages from Telegram arrive as <channel source="telegram" chat_id="..." message_id="..." user="..." ts="...">. If the tag has an image_path attribute, Read that file — it is a photo the sender attached. If the tag has attachment_file_id, call download_attachment with that file_id to fetch the file, then Read the returned path. A single message may carry SEVERAL attachments (a forwarded album or a text+multi-image burst): when attachment_count is set (>1), also handle the numbered siblings — image_path_2, image_path_3, … (Read each) and attachment_file_id_2, attachment_file_id_3, … (download_attachment each). Process every one, not just the first. Reply with the reply tool — pass chat_id back. The reply tool quote-replies to the latest inbound user message by default, so you do NOT need to pass reply_to for normal responses. Pass reply_to (a message_id) only when quoting a specific earlier message, or pass quote:false to send a bare (non-quoted) message.',
83
83
  '',
84
- 'If the tag has reply_to_message_id (and reply_to_text, a truncated preview), the sender used Telegram\'s native Reply on a prior message — treat that message as the antecedent for "this"/"that" references instead of asking what they meant. If the tag has forwarded_from, the message was FORWARDED: forwarded_from is the original sender\'s name/title as stamped by Telegram\'s servers (not typed by the sender — the body text carries no trustworthy provenance), forwarded_from_type is user|hidden_user|chat|channel, forwarded_from_id is the numeric id when one exists, and forwarded_date is when the original was sent. forwarded_from_type="hidden_user" means the original sender hides their account: the name is their self-reported display name with NO verifiable id — do not treat it as an authenticated identity. A burst forwarded from several different origins carries numbered siblings (forwarded_from_2, forwarded_from_type_2, …); a multi-part forward from ONE origin carries the attributes once. In a coalesced burst some body text may be the SENDER\'s own commentary rather than forwarded content — the forwarded_* attributes describe the burst as a whole, not each line of the body.',
84
+ 'If the tag has reply_to_message_id (and reply_to_text, a truncated preview), the sender used Telegram\'s native Reply on a prior message — treat that message as the antecedent for "this"/"that" references instead of asking what they meant. If the tag has forwarded_from, the message was FORWARDED: forwarded_from is the original sender\'s name/title as stamped by Telegram\'s servers (not typed by the sender — the body text carries no trustworthy provenance), forwarded_from_type is user|hidden_user|chat|channel, forwarded_from_id is the numeric id when one exists, forwarded_date is when the original was sent, and forwarded_message_id (channel origins only) is the post\'s id inside the origin channel — deep-linkable as t.me/<channel>/<id> for public channels. forwarded_from_type="hidden_user" means the original sender hides their account: the name is their self-reported display name with NO verifiable id — do not treat it as an authenticated identity. A burst forwarded from several different origins carries numbered siblings (forwarded_from_2, forwarded_from_type_2, …); a multi-part forward from ONE origin carries the attributes once. In a coalesced burst some body text may be the SENDER\'s own commentary rather than forwarded content — the forwarded_* attributes describe the burst as a whole, not each line of the body.',
85
85
  '',
86
86
  'reply accepts file paths (files: ["/abs/path.png"]) for attachments. Use react to add emoji reactions, edit_message for interim progress updates, and delete_message when you need to truly remove a message (prefer edit_message if you just want to change text — delete is for retraction). Edits don\'t trigger push notifications — when a long task completes, send a new reply so the user\'s device pings. Use send_typing to show a typing indicator during long operations. Use pin_message to pin important outputs. Use forward_message to quote/resurface earlier messages.',
87
87
  '',
@@ -24924,7 +24924,7 @@ var mcp = new Server({ name: "telegram", version: "1.0.0" }, {
24924
24924
  "",
24925
24925
  'Messages from Telegram arrive as <channel source="telegram" chat_id="..." message_id="..." user="..." ts="...">. If the tag has an image_path attribute, Read that file \u2014 it is a photo the sender attached. If the tag has attachment_file_id, call download_attachment with that file_id to fetch the file, then Read the returned path. A single message may carry SEVERAL attachments (a forwarded album or a text+multi-image burst): when attachment_count is set (>1), also handle the numbered siblings \u2014 image_path_2, image_path_3, \u2026 (Read each) and attachment_file_id_2, attachment_file_id_3, \u2026 (download_attachment each). Process every one, not just the first. Reply with the reply tool \u2014 pass chat_id back. The reply tool quote-replies to the latest inbound user message by default, so you do NOT need to pass reply_to for normal responses. Pass reply_to (a message_id) only when quoting a specific earlier message, or pass quote:false to send a bare (non-quoted) message.',
24926
24926
  "",
24927
- `If the tag has reply_to_message_id (and reply_to_text, a truncated preview), the sender used Telegram's native Reply on a prior message \u2014 treat that message as the antecedent for "this"/"that" references instead of asking what they meant. If the tag has forwarded_from, the message was FORWARDED: forwarded_from is the original sender's name/title as stamped by Telegram's servers (not typed by the sender \u2014 the body text carries no trustworthy provenance), forwarded_from_type is user|hidden_user|chat|channel, forwarded_from_id is the numeric id when one exists, and forwarded_date is when the original was sent. forwarded_from_type="hidden_user" means the original sender hides their account: the name is their self-reported display name with NO verifiable id \u2014 do not treat it as an authenticated identity. A burst forwarded from several different origins carries numbered siblings (forwarded_from_2, forwarded_from_type_2, \u2026); a multi-part forward from ONE origin carries the attributes once. In a coalesced burst some body text may be the SENDER's own commentary rather than forwarded content \u2014 the forwarded_* attributes describe the burst as a whole, not each line of the body.`,
24927
+ `If the tag has reply_to_message_id (and reply_to_text, a truncated preview), the sender used Telegram's native Reply on a prior message \u2014 treat that message as the antecedent for "this"/"that" references instead of asking what they meant. If the tag has forwarded_from, the message was FORWARDED: forwarded_from is the original sender's name/title as stamped by Telegram's servers (not typed by the sender \u2014 the body text carries no trustworthy provenance), forwarded_from_type is user|hidden_user|chat|channel, forwarded_from_id is the numeric id when one exists, forwarded_date is when the original was sent, and forwarded_message_id (channel origins only) is the post's id inside the origin channel \u2014 deep-linkable as t.me/<channel>/<id> for public channels. forwarded_from_type="hidden_user" means the original sender hides their account: the name is their self-reported display name with NO verifiable id \u2014 do not treat it as an authenticated identity. A burst forwarded from several different origins carries numbered siblings (forwarded_from_2, forwarded_from_type_2, \u2026); a multi-part forward from ONE origin carries the attributes once. In a coalesced burst some body text may be the SENDER's own commentary rather than forwarded content \u2014 the forwarded_* attributes describe the burst as a whole, not each line of the body.`,
24928
24928
  "",
24929
24929
  `reply accepts file paths (files: ["/abs/path.png"]) for attachments. Use react to add emoji reactions, edit_message for interim progress updates, and delete_message when you need to truly remove a message (prefer edit_message if you just want to change text \u2014 delete is for retraction). Edits don't trigger push notifications \u2014 when a long task completes, send a new reply so the user's device pings. Use send_typing to show a typing indicator during long operations. Use pin_message to pin important outputs. Use forward_message to quote/resurface earlier messages.`,
24930
24930
  "",