Commit Graph
8 Commits
Author SHA1 Message Date
lyuksovannyy 7b3a4bece3 Correct the unread badge after jumping away from the newest messages
Publish plugin / publish (push) Successful in 3s
2026-10-12 19:27:44 +02:00
lyuksovannyyandClaude Opus 5.5 f58e157b70 [no bump] Shift plugin icon index down by one
Publish plugin / publish (push) Successful in 4s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 14:20:24 +02:00
lyuksovannyyandClaude Opus 5.5 b885f2179f [no bump] Move technical docs to docs/, add icon and PNG export tool
Publish plugin / publish (push) Successful in 4s
README now carries the icon, TL;DR, description and features; the
technical sections live in docs/. tools/icon_png.py renders
images/icon.svg to a square PNG (512x512 by default, --resolution N).
plugin.json points at the plugin's own icon.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 14:16:37 +02:00
lyuksovannyyandClaude Opus 5.5 af23d2e682 Keep the chat on a far-back summary card after its anchor loads
Publish plugin / publish (push) Successful in 3s
With an offset the newest analyzed message is usually outside the loaded
window, so placement asks the chat to load it first. That path could leave the
view away from the card while offset 0 always worked:

- Placement gave up after ~3 s (25 x 120 ms) and asked for the anchor only
  once. scrollToMessageId drops the request while waitingForGetDifference, and
  a load can be superseded. It now waits ~10 s and re-requests every ~2 s.
- Loading a far anchor makes ChatActivity run its own postponed scroll, and a
  cache-then-server reload can re-scroll or replace the list. Either can land
  after the jump. Settle checks at 0.25/0.7/1.5/3 s re-jump if the card row is
  outside the visible range, and re-place the card if a reload dropped it.
  They stop as soon as the user drags the list.

Also logs each run's count/offset, the fetched id range, pre-stream failures,
load requests, placement and jumps to the diagnostics file, since bulletin-only
errors previously left no trace.

Verified on device with count 1000, offset 1000: anchor loaded on the first
retry, card placed after it and the chat jumped there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:52:24 +02:00
lyuksovannyyandClaude Opus 5.5 16bf8de84c Inject the summary card only once the answer starts streaming
Publish plugin / publish (push) Successful in 3s
Pressing Summarize used to inject a status card immediately, at a guessed
anchor, and move it once the fetch returned. Any failure before the model
answered (fetch error, empty history, unreachable host, bad key, HTTP error)
then left an error bubble in the chat and had already scrolled the user away
from where they were reading.

The pipeline is now fetch -> stream -> card. A bulletin acknowledges the
press; every failure before the first chunk is a bulletin only and leaves the
chat untouched. On the first chunk the card is created with its final anchor
and virtual id and placed strictly after the newest analyzed message. If that
message is not loaded, the chat is asked to load it and placement retries; the
card never falls back to the chat bottom. Placement then hard-jumps the layout
manager to the card's row: scrollToMessageId only smooth-scrolls from cell
positions that are stale right after an insert. The provisional anchor and
reanchor() machinery is gone.

The row is reserved with INSERT .. DO NOTHING, so re-summarizing a saved range
no longer blanks its text before the new answer arrives; a fresh row whose
stream breaks is deleted instead of left empty.

Also:
- Finished summaries end with #aisummaries as a native TL_iv.textHashtag
  (rendered by RichMessageLayout like a hashtag entity) and carry a plain-text
  body with a TL_messageEntityHashtag.
- Deleting a card (MessagesController.deleteMessages, all overloads) removes
  its saved row and the card, with a "Summary deleted" bulletin.
- Settings show the saved summary count and approximate size, and a confirmed
  "Clear all summaries" action.
- Version 1.1.0.

Verified on device: no card before streaming, correct placement and jump,
restore on reopen, deletion, and the hashtag rendering. Telegram's search is
server-side, so local cards do not appear in its results.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 23:19:06 +02:00
lyuksovannyy fc76a20420 version bump & auto-bump hooks
Publish plugin / publish (push) Successful in 4s
2026-09-19 17:33:28 +02:00
lyuksovannyy 196da742de Implement Chat Summaries plugin
Replace the sample plugin with an AI chat summarizer that renders its
output as a native RichMessage injected into the chat.

Summarization pipeline:
- Fetch chat/topic history via paginated TL requests.
- Send a system prompt, the user's instructions and an anonymized JSON
  transcript as three separate roles. Only message text and attachment
  names leave the device; senders and message ids are replaced by
  indices, and out-of-range reply parents are included with negative ids
  so replies keep their context.
- Stream the response over SSE, reading reasoning from reasoning_content,
  reasoning or inline <think> tags.
- Substitute the model's {userN}/{msgN} placeholders back into real names
  and deep links. Placeholders are used instead of Markdown links because
  a half-streamed link renders as broken literal text.

Rendering:
- Compile Markdown into TL_iv page blocks (headings, lists, quotes, code,
  dividers, inline styles) since the app's own converter works off
  Android Spanned spans rather than Markdown source.
- Show progress stages immediately on click, animate reasoning while it
  streams, then collapse it into a tappable details block.
- Attribute the card to a client-side mock sender and insert it directly
  after the newest analyzed message, scrolling it into view.

Persistence:
- Store summaries in SQLite keyed by (dialog, topic, anchor) and
  re-inject them when the chat is reopened.

Also add tools/release.py and a Gitea workflow that builds, verifies and
publishes dist/<id>.plugin to the Releases tab, and extend
tools/verify_bundle.py to 104 offline checks covering the transcript,
streaming, rendering, injection and storage behaviour.
2026-09-12 23:52:15 +02:00
exteraGramPlugins a3b0b264c1 Initial commit 2026-09-12 02:03:47 +00:00