Commit Graph

85 Commits

Author SHA1 Message Date
Peter Steinberger a69e7682c1 refactor(test): dedupe channel and monitor action suites 2026-02-18 04:49:22 +00:00
Peter Steinberger b8b43175c5 style: align formatting with oxfmt 0.33 2026-02-18 01:34:35 +00:00
Peter Steinberger 31f9be126c style: run oxfmt and fix gate failures 2026-02-18 01:29:02 +00:00
Tyler Yust 087dca8fa9
fix(subagent): harden read-tool overflow guards and sticky reply threading (#19508)
* fix(gateway): avoid premature agent.wait completion on transient errors

* fix(agent): preemptively guard tool results against context overflow

* fix: harden tool-result context guard and add message_id metadata

* fix: use importOriginal in session-key mock to include DEFAULT_ACCOUNT_ID

The run.skill-filter test was mocking ../../routing/session-key.js with only
buildAgentMainSessionKey and normalizeAgentId, but the module also exports
DEFAULT_ACCOUNT_ID which is required transitively by src/web/auth-store.ts.

Switch to importOriginal pattern so all real exports are preserved alongside
the mocked functions.

* pi-runner: guard accumulated tool-result overflow in transformContext

* PI runner: compact overflowing tool-result context

* Subagent: harden tool-result context recovery

* Enhance tool-result context handling by adding support for legacy tool outputs and improving character estimation for message truncation. This includes a new function to create legacy tool results and updates to existing functions to better manage context overflow scenarios.

* Enhance iMessage handling by adding reply tag support in send functions and tests. This includes modifications to prepend or rewrite reply tags based on provided replyToId, ensuring proper message formatting for replies.

* Enhance message delivery across multiple channels by implementing sticky reply context for chunked messages. This includes preserving reply references in Discord, Telegram, and iMessage, ensuring that follow-up messages maintain their intended reply targets. Additionally, improve handling of reply tags in system prompts and tests to support consistent reply behavior.

* Enhance read tool functionality by implementing auto-paging across chunks when no explicit limit is provided, scaling output budget based on model context window. Additionally, add tests for adaptive reading behavior and capped continuation guidance for large outputs. Update related functions to support these features.

* Refine tool-result context management by stripping oversized read-tool details payloads during compaction, ensuring repeated read calls do not bypass context limits. Introduce new utility functions for handling truncation content and enhance character estimation for tool results. Add tests to validate the removal of excessive details in context overflow scenarios.

* Refine message delivery logic in Matrix and Telegram by introducing a flag to track if a text chunk was sent. This ensures that replies are only marked as delivered when a text chunk has been successfully sent, improving the accuracy of reply handling in both channels.

* fix: tighten reply threading coverage and prep fixes (#19508) (thanks @tyler6204)
2026-02-17 15:32:52 -08:00
Nimrod Gutman 9f907320c3 Revert "fix: handle forum/topics in Telegram DM thread routing (#17980)"
This reverts commit e20b87f1ba.
2026-02-17 11:17:30 +02:00
cpojer 600022cdcc
chore: Fix types in tests 24/N. 2026-02-17 14:30:36 +09:00
cpojer d0cb8c19b2
chore: wtf. 2026-02-17 13:36:48 +09:00
Sebastian ed11e93cf2 chore(format) 2026-02-16 23:20:16 -05:00
Sebastian 78c3e5166b test(telegram): cover getFile file-too-big errors 2026-02-16 22:10:59 -05:00
cpojer 43c97d18aa
chore: Fix types in tests 17/N. 2026-02-17 12:00:29 +09:00
cpojer 90ef2d6bdf
chore: Update formatting. 2026-02-17 09:18:40 +09:00
8BlT e20b87f1ba fix: handle forum/topics in Telegram DM thread routing (#17980)
resolveTelegramThreadSpec now checks isForum in the non-group path.
DMs with forum/topics enabled return scope 'forum' so each topic
gets its own session, while plain DM threads keep scope 'dm'.
2026-02-17 00:00:51 +01:00
Brandon Wise 01b37f1d32 fix(telegram): handle large file getFile errors gracefully
Catch GrammyError when getFile fails for files >20MB (Telegram Bot API limit).
Log warning, skip attachment, but continue processing message text.

- Add FILE_TOO_BIG_RE regex to detect 'file is too big' errors
- Add isFileTooBigError() and isRetryableGetFileError() helpers
- Skip retrying permanent 400 errors (they'll fail every time)
- Log specific warning for file size limit errors
- Return null so message text is still processed

Fixes #18518
2026-02-16 23:51:09 +01:00
Seb Slight 0cff8bc4e6
fix(telegram): include DM topic thread id in replies (#18586) 2026-02-16 17:02:59 -05:00
Ayaan Zaidi 16327f21da
feat(telegram): support inline button styles (#18241)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 239cb3552e
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-16 22:48:47 +05:30
Peter Steinberger a177f7b9fe refactor(tests): dedupe slack telegram and web monitor setup 2026-02-16 17:06:40 +00:00
Ayaan Zaidi b6a9741ba4
refactor(telegram): simplify send/dispatch/target handling (#17819)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: fcb7aeeca3
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-16 14:00:34 +05:30
Vignesh Natarajan 6957354d48 fix (telegram/whatsapp): use account-scoped pairing allowlists 2026-02-15 19:10:06 -08:00
Peter Steinberger 35c5d2be5c refactor(telegram): share group allowFrom resolution 2026-02-16 02:27:01 +00:00
Peter Steinberger 6b65a055e6 refactor(telegram): dedupe media download 2026-02-15 16:22:06 +00:00
Garnet Liu cc0bfa0f39
fix(telegram): restore thread_id=1 handling for DMs (regression from 19b8416a8) (openclaw#10942) thanks @garnetlyx
Verified:
- pnpm install --frozen-lockfile
- pnpm build
- pnpm test:macmini

Co-authored-by: garnetlyx <12513503+garnetlyx@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-02-15 10:21:18 -06:00
Mr. Guy e927fd1e35
fix: allow agent workspace directories in media local roots (#17136)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 7545ef1e19
Co-authored-by: MisterGuy420 <255743668+MisterGuy420@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-02-15 10:53:45 -05:00
Ayaan Zaidi a69e82765f fix(telegram): stream replies in-place without duplicate final sends 2026-02-15 20:32:51 +05:30
yinghaosang 80abb5ab98
fix(telegram): stop dropping voice messages on getFile network errors (#16136) (#16154)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: fbcd7849e4
Co-authored-by: yinghaosang <261132136+yinghaosang@users.noreply.github.com>
Co-authored-by: obviyus <22031114+obviyus@users.noreply.github.com>
Reviewed-by: @obviyus
2026-02-15 14:50:55 +05:30
Divanoli Mydeen Pitchai 1055e71c4b
fix(telegram): auto-wrap .md file references in backticks to prevent URL previews (#8649)
* fix(telegram): auto-wrap file references with TLD extensions to prevent URL previews

Telegram's auto-linker aggressively treats filenames like HEARTBEAT.md,
README.md, main.go, script.py as URLs and generates domain registrar previews.

This fix adds comprehensive protection for file extensions that share TLDs:
- High priority: .md, .go, .py, .pl, .ai, .sh
- Medium priority: .io, .tv, .fm, .am, .at, .be, .cc, .co

Implementation:
- Added wrapFileReferencesInHtml() in format.ts
- Runs AFTER markdown→HTML conversion
- Tokenizes HTML to respect tag boundaries
- Skips content inside <code>, <pre>, <a> tags (no nesting issues)
- Applied to all rendering paths: renderTelegramHtmlText, markdownToTelegramHtml,
  markdownToTelegramChunks, and delivery.ts fallback

Addresses review comments:
- P1: Now handles chunked rendering paths correctly
- P2: No longer wraps inside existing code blocks (token-based parsing)
- No lookbehinds used (broad Node compatibility)

Includes comprehensive test suite in format.wrap-md.test.ts

AI-assisted: true

* fix(telegram): prevent URL previews for file refs with TLD extensions

Two layers were causing spurious link previews for file references like
`README.md`, `backup.sh`, `main.go`:

1. **markdown-it linkify** converts `README.md` to
   `<a href="http://README.md">README.md</a>` (.md = Moldova TLD)
2. **Telegram auto-linker** treats remaining bare text as URLs

## Changes

### Primary fix: suppress auto-linkified file refs in buildTelegramLink
- Added `isAutoLinkedFileRef()` helper that detects when linkify auto-
  generated a link from a bare filename (href = "http://" + label)
- Rejects paths with domain-like segments (dots in non-final path parts)
- Modified `buildTelegramLink()` to return null for these, so file refs
  stay as plain text and get wrapped in `<code>` by the wrapper

### Safety-net: de-linkify in wrapFileReferencesInHtml
- Added pre-pass that catches auto-linkified anchors in pre-rendered HTML
- Handles edge cases where HTML is passed directly (textMode: "html")
- Reuses `isAutoLinkedFileRef()` logic — no duplication

### Bug fixes discovered during review
- **Fixed `isClosing` bug (line 169)**: the check `match[1] === "/"`
  was wrong — the regex `(<\/?)}` captures `<` or `</`, so closing
  tags were never detected. Changed to `match[1] === "</"`. This was
  causing `inCode/inPre/inAnchor` to stay stuck at true after any
  opening tag, breaking file ref wrapping after closing tags.
- **Removed double `wrapFileReferencesInHtml` call**: `renderTelegramHtmlText`
  was calling `markdownToTelegramHtml` (which wraps) then wrapping again.

### Test coverage (+12 tests, 26 total)
- `.sh` filenames (original issue #6932 mentioned backup.sh)
- Auto-linkified anchor replacement
- Auto-linkified path anchor replacement
- Explicit link preservation (different label)
- File ref after closing anchor tag (exercises isClosing fix)
- Multiple file types in single message
- Real URL preservation
- Explicit markdown link preservation
- File ref after real URL in same message
- Chunked output file ref wrapping

Closes #6932

* test(telegram): add comprehensive edge case coverage for file ref wrapping

Add 16 edge case tests covering:
- File refs inside bold/italic tags
- Fenced code blocks (no double-wrap)
- Domain-like paths preserved as links (example.com/README.md)
- GitHub URLs with file paths
- wrapFileRefs: false behavior
- All TLD extensions (.ai, .io, .tv, .fm)
- Non-TLD extensions not wrapped (.png, .css, .js)
- File ref position (start, end, multiple in sequence)
- Nested paths without domain segments
- Version-like paths (v1.0/README.md wraps, example.com/v1.0/README.md links)
- Hyphens and underscores in filenames
- Uppercase extensions

* fix(telegram): use regex literal and depth counters for tag tracking

Code review fixes:
1. Replace RegExp constructor with regex literal for autoLinkedAnchor
   - Avoids double-escaping issues with \s
   - Uses backreference \1 to match href=label pattern directly

2. Replace boolean toggles with depth counters for tag nesting
   - codeDepth, preDepth, anchorDepth track nesting levels
   - Correctly handles nested tags like <pre><code>...</code></pre>
   - Prevents wrapping inside any level of protected tags

Add 4 tests for edge cases:
- Nested code tags (depth tracking)
- Multiple anchor tags in sequence
- Auto-linked anchor with backreference match
- Anchor with different href/label (no match)

* fix(telegram): add escapeHtml and escapeRegex for defense in depth

Code review fixes:
1. Escape filename with escapeHtml() before inserting into <code> tags
   - Prevents HTML injection if regex ever matches unsafe chars
   - Defense in depth (current regex already limits to safe chars)

2. Escape extensions with escapeRegex() before joining into pattern
   - Prevents regex breakage if extensions contain metacharacters
   - Future-proofs against extensions like 'c++' or 'd.ts'

Add tests documenting regex safety boundaries:
- Filenames with special chars (&, <, >) don't match
- Only [a-zA-Z0-9_.\-./] chars are captured

* fix(telegram): catch orphaned single-letter TLD patterns

When text like 'R&D.md' doesn't match the main file pattern (because &
breaks the character class), the 'D.md' part can still be auto-linked
by Telegram as a domain (https://d.md/).

Add second pass to catch orphaned TLD patterns like 'D.md', 'R.io', 'X.ai'
that follow non-alphanumeric characters and wrap them in <code> tags.

Pattern: ([^a-zA-Z0-9]|^)([A-Za-z]\.(?:extensions))(?=[^a-zA-Z0-9/]|$)

Tests added:
- 'wraps orphaned TLD pattern after special character' (R&D.md → R&<code>D.md</code>)
- 'wraps orphaned single-letter TLD patterns' (X.ai, R.io)

* refactor(telegram): remove popular domain TLDs from file extension list

Remove .ai, .io, .tv, .fm from FILE_EXTENSIONS_WITH_TLD because:
- These are commonly used as real domains (x.ai, vercel.io, github.io)
- Rarely used as actual file extensions
- Users are more likely referring to websites than files

Keep: md, sh, py, go, pl (common file extensions, rarely intentional domains)
Keep: am, at, be, cc, co (less common as intentional domain references)

Update tests to reflect the change:
- Add test for supported extensions (.am, .at, .be, .cc, .co)
- Add test verifying popular TLDs stay as links

* fix(telegram): prevent orphaned TLD wrapping inside HTML tags

Code review fixes:

1. Orphaned TLD pass now checks if match is inside HTML tag
   - Uses lastIndexOf('<') vs lastIndexOf('>') to detect tag context
   - Skips wrapping when between < and > (inside attributes)
   - Prevents invalid HTML like <a href="...&<code>D.md</code>">

2. textMode: 'html' now trusts caller markup
   - Returns text unchanged instead of wrapping
   - Caller owns HTML structure in this mode

Tests added:
- 'does not wrap orphaned TLD inside href attributes'
- 'does not wrap orphaned TLD inside any HTML attribute'
- 'does not wrap in HTML mode (trusts caller markup)'

* refactor(telegram): use snapshot for orphaned TLD offset clarity

Use explicit snapshot variable when checking tag positions in orphaned
TLD pass. While JavaScript's replace() doesn't mutate during iteration,
this makes intent explicit and adds test coverage for multi-TLD HTML.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(telegram): prevent orphaned TLD wrapping inside code/pre tags

- Add depth tracking for code/pre tags in orphaned TLD pass
- Fix test to expect valid HTML output
- 55 tests now covering nested tag scenarios

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(telegram): clamp depth counters and add anchor tracking to orphaned pass

- Clamp depth counters at 0 for malformed HTML with stray closing tags
- Add anchor depth tracking to orphaned TLD pass to prevent wrapping
  inside link text (e.g., <a href="...">R&D.md</a>)
- 57 tests covering all edge cases

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(telegram): keep .co domains linked and wrap punctuated file refs

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-02-14 00:51:47 +01:00
Denis Rybnikov 582732391a fix(telegram): avoid nested reply quote misclassification 2026-02-09 22:43:29 +05:30
Denis Rybnikov b430998c2f fix(telegram): clean tsgo/format regressions 2026-02-09 22:43:29 +05:30
Denis Rybnikov 1c1d7fa0e5 fix(telegram): make quote parsing/types CI-safe 2026-02-09 22:43:29 +05:30
Denis Rybnikov a4b38ce886 fix(telegram): preserve inbound quote context and avoid QUOTE_TEXT_INVALID 2026-02-09 22:43:29 +05:30
Christian Klotz ddedb56c01 fix(telegram): pass parentPeer for forum topic binding inheritance (#9789)
Fixes #9545 and #9351.

When a message comes from a Telegram forum topic, the peer ID includes
the topic suffix (e.g., `-1001234567890:topic:99`). Users configure
bindings with the base group ID, which previously did not match.

This adds `parentPeer` to `resolveAgentRoute()` calls for forum groups,
enabling binding inheritance from the parent group to all topics.

- Extract `buildTelegramParentPeer()` helper in bot/helpers.ts
- Pass parentPeer in bot-message-context.ts, bot-handlers.ts,
  bot-native-commands.ts, and bot.ts (reaction handler)
- Add tests for forum topic routing and topic precedence
2026-02-05 18:25:03 +00:00
Christian Klotz 96abc1c864
Telegram: remove @ts-nocheck from bot.ts, fix duplicate error handler, harden sticker caching (#9077)
* Telegram: remove @ts-nocheck from bot.ts and bot-message-dispatch.ts

- bot/types.ts: TelegramContext.me uses UserFromGetMe (Grammy) instead of manual inline type
- bot.ts: remove 6 unsafe casts (as any, as unknown, as object), use Grammy types directly
- bot.ts: remove dead message_thread_id access on reactions (not in Telegram Bot API)
- bot.ts: remove resolveThreadSessionKeys import (no longer needed for reactions)
- bot-message-dispatch.ts: replace ': any' with DispatchTelegramMessageParams type
- bot-message-dispatch.ts: add sticker.fileId guard before cache access
- bot.test.ts: update reaction tests, remove dead DM thread-reaction test

* Telegram: remove duplicate bot.catch handler (only the last one runs in Grammy)

* Telegram: remove @ts-nocheck from bot.ts, fix duplicate error handler, harden sticker caching (#9077)
2026-02-04 22:35:51 +00:00
Ayaan Zaidi 78fd194722 fix: telegram forward metadata + cron delivery guard (#8392) (thanks @Glucksberg) 2026-02-04 16:43:20 +05:30
Glucksberg b2361292e7 fix: trim legacy signature fallback, type fromChatType as union 2026-02-04 16:43:20 +05:30
Glucksberg 57566c5e4d fix(telegram): include forward_from_chat metadata in forwarded message context (#8133)
Extract missing metadata from forwarded Telegram messages:

- Add fromChatType to TelegramForwardedContext, capturing the original
  chat type (channel/supergroup/group) from forward_from_chat.type
  and forward_origin.chat/sender_chat.type
- Add fromMessageId to capture the original message ID from channel forwards
- Read author_signature from forward_origin objects (modern API),
  preferring it over the deprecated forward_signature field
- Pass ForwardedFromChatType and ForwardedFromMessageId through to
  the inbound context payload
- Add test coverage for forward_origin channel/chat types, including
  author_signature extraction and fromChatType propagation
2026-02-04 16:43:20 +05:30
Christian Klotz da6de49815
Telegram: use Grammy types directly, add typed Probe/Audit to plugin interface (#8403)
* Telegram: replace duplicated types with Grammy imports, add Probe/Audit generics to plugin interface

* Telegram: remove legacy forward metadata (deprecated in Bot API 7.0), simplify required-field checks

* Telegram: clean up remaining legacy references and unnecessary casts

* Telegram: keep RequestInit parameter type in proxy fetch (addresses review feedback)

* Telegram: add exhaustiveness guard to resolveForwardOrigin switch
2026-02-04 10:09:28 +00:00
cpojer 935a0e5708
chore: Enable `typescript/no-explicit-any` rule. 2026-02-02 16:18:09 +09:00
cpojer baa1e95b9d
chore: Enable `no-unnecessary-template-expression` lint rule. 2026-02-02 15:37:05 +09:00
Ayaan Zaidi 0bc8a592a6 fix: inline telegram thread scope type 2026-02-02 09:26:59 +05:30
Ayaan Zaidi 1d7dd5f261 fix: require thread specs for telegram sends 2026-02-02 09:26:59 +05:30
Ayaan Zaidi 19b8416a81 fix: unify telegram thread handling 2026-02-02 09:26:59 +05:30
Peter Steinberger 9d2784cdb9 test: speed up telegram suites 2026-02-01 22:23:16 +00:00
cpojer f06dd8df06
chore: Enable "experimentalSortImports" in Oxfmt and reformat all imorts. 2026-02-01 10:03:47 +09:00
Ayaan Zaidi 37721ebd7c fix: restore telegram draft streaming partials 2026-01-31 22:46:19 +05:30
cpojer 5ceff756e1
chore: Enable "curly" rule to avoid single-statement if confusion/errors. 2026-01-31 16:19:20 +09:00
cpojer 15792b153f
chore: Enable more lint rules, disable some that trigger a lot. Will clean up later. 2026-01-31 16:04:04 +09:00
Peter Steinberger 9a7160786a refactor: rename to openclaw 2026-01-30 03:16:21 +01:00
Ayaan Zaidi 718bc3f9c8
fix: avoid silent telegram empty replies (#3796) (#3796) 2026-01-29 11:34:47 +05:30
kiranjd 0761652701 fix(telegram): handle empty reply array in notifyEmptyResponse
Previous fix only checked skippedEmpty > 0, but when model returns
content: [] no payloads are created at all. Now also checks
replies.length === 0 to catch this case.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 11:13:39 +05:30
kiranjd a2d06e75b0 fix(telegram): notify users when agent returns empty response
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-29 11:13:39 +05:30
Lukin 78722d0b4f fix(telegram): add video_note support to Telegram channel
- Add msg.video_note to media extraction chain in bot/delivery.ts
- Add placeholder detection for video notes in bot-message-context.ts
- Video notes (rounded square video messages) are now processed and downloaded like regular videos

Fixes issue where video note messages were silently dropped because they weren't in the media handling logic.
2026-01-29 10:07:21 +05:30