@llblab/pi-telegram 0.26.10 → 0.26.12
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/AGENTS.md +2 -2
- package/BACKLOG.md +15 -2
- package/CHANGELOG.md +11 -0
- package/docs/activity.md +1 -1
- package/docs/architecture.md +1 -1
- package/docs/outbound.md +1 -1
- package/docs/ui-style.md +1 -0
- package/lib/activity-verbosity.ts +13 -8
- package/lib/menu-settings.ts +1 -1
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -89,7 +89,7 @@ The core product loop is mobile continuation: start or supervise work in the ter
|
|
|
89
89
|
- Instance thread names are provisioner-authored identity metadata, not model-authored output. Fresh Threaded Mode threads select one of five curated compact 4-6 letter Latin names for the assigned slot letter using provisioning timestamp entropy, then create the Telegram thread with that thread name immediately. The title is the thread name itself, not `{slot} {threadName}` or `{slot} — {threadName}`. Do not register or reintroduce an agent-facing thread rename tool; removing the extra rename prompt/tool turn is an intentional simplicity constraint. Thread names must mirror into terminal status, live diagnostics, and `[telegram|thread:name]` through one target-aware current-instance identity resolver. Registered follower/leader metadata takes precedence over a stale shared record for the same target, with the record used only as fallback; do not hide a valid baked/custom thread name behind old slot-prefix validation. A follower that later becomes leader keeps its existing name; leadership changes are transport role changes, not identity resets.
|
|
90
90
|
- Telegram private-chat Threaded Mode treats `All` as an aggregate/control surface, not a durable `General` thread or process launcher, and leader activation proactively creates or reuses its private-DM thread. When the owner writes in an unknown thread, the leader reclaims and routes the first one only if it lacks an active binding; later unknown threads remain intact and receive an in-thread chooser to reroute the captured prompt or restore a stale binding. Destructive cleanup requires explicit confirmation through `thread-reconciler`; another Pi instance still requires a manually started process followed by `/telegram-connect`. Without Threaded Mode, process the message through classic routing.
|
|
91
91
|
- Telegram extension work should not hold Pi's core agent lifecycle hostage once Pi has produced the semantic result. For Telegram-originated turns, final Telegram delivery, attachment upload, and transport cleanup are extension-owned side effects; schedule them off the critical `agent_end` path when ordering can still be preserved, record failures as runtime events, and keep dispatch of the next Telegram turn behind the delivery task when needed to avoid interleaving previews/finals. Treat a low-level error `agent_end` as retryable while its Telegram turn remains active; only a later successful `agent_end` or Pi's `agent_settled` boundary may finalize and release that turn. Public activity handlers run through isolated asynchronous per-handler queues; lifecycle hooks enqueue normalized events and never await consumer work. Proactive push defaults enabled and requires explicit `assistant.proactivePush: false` to opt out. While enabled, core delivery projects each completed Pi-visible assistant text block from local/autonomous work once and in order; bind admitted blocks to the exact target, profile/token transport stamp, direct leader epoch or follower registration generation, and session generation. Token deltas, hidden reasoning, tool traffic, stale authority, and Telegram-owned turns never enter that projection.
|
|
92
|
-
- Core thinking/tool visibility is controlled by file-backed `assistant.activity: "quiet" | "thinking" | "tools" | "verbose"`; every Pi instance reloads the shared config at `agent-start` before admitting activity so process-local cache cannot broaden the selected class. It defaults to `verbose` when absent and remains separate from proactive public prose and assistant Markdown: provider-exposed thinking uses only a durable ordinary HTML expandable blockquote, while completed executed tools use native Rich Messages whose closed `<Tool>: <status>` root details contain an open-by-default
|
|
92
|
+
- Core thinking/tool visibility is controlled by file-backed `assistant.activity: "quiet" | "thinking" | "tools" | "verbose"`; every Pi instance reloads the shared config at `agent-start` before admitting activity so process-local cache cannot broaden the selected class. It defaults to `verbose` when absent and remains separate from proactive public prose and assistant Markdown: provider-exposed thinking uses only a durable ordinary HTML expandable blockquote, while completed executed tools use native Rich Messages whose closed `<Tool>: <status>` root details preserve sentence case while uppercasing an initial two- or three-letter repeated prefix, then contain an open-by-default `arguments` child plus closed `update`, `result`, or `error` children with lowercase monospaced labels and JSON pre blocks; treat each label as one quote-free outer JSON key and add no icon, list marker, or heading emphasis. Thinking renders inline Markdown as Telegram HTML without spending a separate header row; `verbose` enables both classes, and every activity send/edit disables Telegram link previews while technical evidence also neutralizes HTTP(S) auto-link detection as a client-safe fallback. Keep it compact by default, exact-target/transport-generation fenced, start-order preserving, boundary-aware, memory/transport bounded, and non-blocking; final delivery waits for admitted technical activity only inside the extension-owned background task, and session replacement abandons queued old-generation work without waiting on old transport. Read legacy `assistant.activityVerbosity` only when `assistant.activity` is absent and remove it on the next Settings write. Never invent unavailable provider-private thinking or replay a possibly committed technical message.
|
|
93
93
|
- Telegram runtime state should be treated as event-driven reconciliation of extension assumptions against observable Telegram signals, not as a full Telegram bot read-model and not as a reason to query Telegram on every action. Keep a local assumption model for bot identity/capabilities, pairing assumptions, thread support, known thread lifecycle, bound instance targets, reservations, and transport health. Invalidate and reconcile the relevant slice on meaningful events: startup/reload, lifecycle service messages, stale-send/API errors, setup/pairing changes, follower register/prune, explicit status/debug requests, and bounded low-frequency leader health ticks. `lib/sync.ts` owns sync slices, observation intake, invalidation triggers, status/debug freshness, and reconciliation scheduling; it must not promise complete bot-state mirroring because Bot API lacks a complete topic listing surface. `lib/thread-reconciler.ts` owns pure Threaded Mode lifecycle planning and should become the only policy authority for destructive thread cleanup decisions. `threads` owns current Telegram UI thread/tab binding primitives and thread-name helpers mapped to Bot API topic transport, `status` renders projections, and `index.ts` only wires ports. `tmp/telegram/logs.jsonl` is a session-local redacted runtime evidence stream for race debugging and resets on extension start / runtime scope changes; it is diagnostics only, not routing/provisioning authority. `state.json` should be an observable/debug snapshot aligned with `/telegram-status` (extension runtime, bot capabilities including `bot.lastSlot`, runtime role, live roster projection, reservations, diagnostics), not routing/provisioning authority. Because every process on one Telegram profile shares this file, only the active transport lock owner may persist it; followers read current state and gain write authority only after promotion. Status-only writes must refresh disk-backed bindings before serialization so a stale loaded snapshot cannot erase newer leader state. Live bus/runtime state is authoritative; file reservations and fresh capability observations may be startup hints/collision guards only; stale snapshots must re-probe before suppressing bus/topic behavior. Do not persist stale/offline/failed thread target history as source of truth.
|
|
94
94
|
- Thread bindings are bidirectional. From the Pi-instance side, an instance knows and preserves its target, slot, thread name, lifecycle state, and direct-delivery defaults. From the Telegram-client/bot side, the bridge observes thread creation/close/reopen/stale-send signals and reconciles them into instance binding state. Lifecycle transitions that affect operator understanding should be Telegram-visible when a live transport remains: every successful follower registration/re-registration gets a compact connected notice in the assigned thread, while heartbeat pruning stays silent because it is only liveness suspicion. These notices should use the instance thread name when known and fall back to the slot letter only while the thread is still unnamed. New unknown or command-created temporary threads receive the complete forward plus replace/restore control set and remain preserved until the user chooses one. Successful forward deletes the chooser and temporary thread; successful replace/restore always deletes the chooser, rebinds the temporary thread, and deletes only the replaced old thread. Any destructive cleanup must go through `thread-reconciler`. Unknown `forum_topic_created` service events are observations, not destructive cleanup proof.
|
|
95
95
|
- The multi-instance bus uses private bot DMs with Telegram private-chat Threaded Mode enabled for the bot. No supergroup, group, or forum configuration is needed; the thread chat is always the private chat with the paired owner. Threaded capability checks must use bot/private-chat evidence such as `getMe.has_topics_enabled`, incoming `message_thread_id`, and topic operation success/failure; do not use group chat metadata as the control-plane truth for Telegram private-chat Threaded Mode.
|
|
@@ -215,7 +215,7 @@ The canonical detailed ownership map lives in [`docs/architecture.md`](./docs/ar
|
|
|
215
215
|
- Pi integration depends on lifecycle hooks such as `before_agent_start`, `agent_start`, `message_start`, `message_update`, and `agent_end`
|
|
216
216
|
- `ctx.ui.input()` provides placeholder text rather than an editable prefilled value; when a real default must appear already filled in, prefer `ctx.ui.editor()`
|
|
217
217
|
- For `/telegram-setup`, prefer the locally saved bot token over environment variables on repeat setup runs; env vars are the bootstrap path when no local token exists, and persisted `telegram.json` writes must remain atomic plus private because status/setup/polling paths may read it concurrently; keep same-parent temp-file replacement and retry only bounded transient destination-contention errors (`EPERM`, `EACCES`, `EBUSY`) rather than deleting the live config or weakening transaction serialization
|
|
218
|
-
- Command help plus prompt-template commands and status/model/thinking/queue controls are driven through `/start`'s Telegram inline application menu and callback queries; the Queue button shows the queued-item count, model-menu scope/pagination controls stay at the top under Main menu, the model pagination indicator opens a compact page picker, and thinking-menu text stays a compact heading because the current level is marked by button state; `/status`, `/model`, `/thinking`, and `/queue` are hidden compatibility shortcuts
|
|
218
|
+
- Settings value descriptions must follow their visible chooser order (rows top-to-bottom, shared-row values left-to-right); `(default)` annotates the actual default in place and never reorders the list. Command help plus prompt-template commands and status/model/thinking/queue controls are driven through `/start`'s Telegram inline application menu and callback queries; the Queue button shows the queued-item count, model-menu scope/pagination controls stay at the top under Main menu, the model pagination indicator opens a compact page picker, and thinking-menu text stays a compact heading because the current level is marked by button state; `/status`, `/model`, `/thinking`, and `/queue` are hidden compatibility shortcuts
|
|
219
219
|
- Shared inline-keyboard structure belongs to `keyboard`; application-control button labels, callback data, and callback behavior stay in `menu`/`menu-model`/`menu-thinking`/`menu-status`/`menu-queue` while core queue mechanics stay in `queue`
|
|
220
220
|
- Telegram `/settings` options should open nested detail submenus by default: boolean options show a description plus Back, `on`, and `off`; list options show Back plus selectable values. One-shot actions such as syncing may run directly without a submenu when there is no meaningful choice or description step.
|
|
221
221
|
- Inline UI labels and dialogs follow [`docs/ui-style.md`](./docs/ui-style.md): action buttons use emoji plus capitalized action text, state & navigation buttons show state and lead to a submenu, first-level submenus start with `⬆️ Main menu` while deeper submenus start with `⬆️ Back`, boolean toggles use Capitalized horizontal `On`/`Off` with green active `On`, yellow active `Off`, and black inactive dots, tabs use capitalized labels with purple default-state and yellow elevated-state active dots and black inactive dots, vertical option lists mark only the current value green, accepted generated prompt buttons apply Telegram's green `success` style to the exact selected choice without changing its label, and confirmation dialogs use a single bold text-only question with emoji on buttons only.
|
package/BACKLOG.md
CHANGED
|
@@ -2,14 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
_This backlog tracks only open release-relevant work: hotfixes, bounded maintenance, live runtime verification, evidence-gated Telegram client follow-ups, and upstream Pi API blockers. Completed outcomes and validation evidence belong in `CHANGELOG.md`, not in this queue._
|
|
4
4
|
|
|
5
|
-
## P0 —
|
|
5
|
+
## P0 — Monospaced Tool Evidence Keys
|
|
6
|
+
|
|
7
|
+
Context: nested `arguments`, `update`, `result`, and `error` summaries already behave like quote-free outer JSON keys. Rendering the lowercase label itself as inline code completes that semantic relationship without reintroducing icons, markers, or extra height.
|
|
8
|
+
|
|
9
|
+
Open work:
|
|
10
|
+
|
|
11
|
+
- [x] Render every nested tool evidence summary as one lowercase monospaced label, retaining omission suffixes inside the same code span.
|
|
12
|
+
- [x] Preserve root styling, Arguments open-by-default behavior, collapsed secondary evidence, JSON blocks, and all delivery guarantees.
|
|
13
|
+
- [x] Update focused regressions, durable UI documentation, changelog, and package metadata.
|
|
14
|
+
- [ ] Pass live Telegram smoke plus two fresh Linux/macOS/Windows matrices before release.
|
|
15
|
+
|
|
16
|
+
Done when: child keys read as compact code-like metadata, hierarchy and behavior remain unchanged, live clients confirm the style, and the guarded hotfix release completes.
|
|
17
|
+
|
|
18
|
+
## P1 — Windows Graceful Disconnect Test Budget
|
|
6
19
|
|
|
7
20
|
Context: the graceful follower-disconnect integration overrides the production 30-second bus budget with 500 milliseconds even though the path persists cleanup intent, performs close/delete operations, updates binding state, and returns an authenticated response. A loaded Windows runner exceeded that artificial deadline while the same focused path completes promptly under normal scheduling.
|
|
8
21
|
|
|
9
22
|
Open work:
|
|
10
23
|
|
|
11
24
|
- [x] Give this integration-only bus round trip a realistic bounded timeout without changing production transport defaults, retries, cleanup ordering, or assertions.
|
|
12
|
-
- [
|
|
25
|
+
- [x] Validate repeatedly and across hosted platforms before publishing `0.26.10`.
|
|
13
26
|
|
|
14
27
|
Done when: slow Windows scheduling can complete the real graceful cleanup path, genuine hangs remain bounded, exact cleanup evidence stays asserted, and Linux/macOS/Windows CI passes.
|
|
15
28
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.26.12: Monospaced Tool Evidence Keys
|
|
4
|
+
|
|
5
|
+
- `Tool Evidence Typography`: Rendered nested `arguments`, `update`, `result`, and `error` summaries as lowercase inline code, including any dropped-update suffix in the same span. Impact: child labels read as compact quote-free outer JSON keys while root styling, disclosure state, evidence blocks, message height, and delivery guarantees remain unchanged.
|
|
6
|
+
|
|
7
|
+
## 0.26.11: Compact Tool Hierarchy And Ordered Settings Copy
|
|
8
|
+
|
|
9
|
+
- `Tool Evidence Hierarchy`: Restyled nested Rich evidence summaries as plain lowercase labels (`arguments`, `update`, `result`, `error`) without icons, list markers, or heading emphasis. Arguments still open with the root and secondary evidence remains collapsed. Impact: child nodes read as quote-free outer JSON keys without adding message height or changing evidence behavior.
|
|
10
|
+
- `Tool Root Labels`: Preserved a leading run of two or three repeated ASCII letters as uppercase while retaining ordinary sentence casing elsewhere (`ffgrep` → `FFgrep`, `fffind` → `FFFind`, `bash` → `Bash`). Impact: recognizable tool prefixes survive compact root formatting without introducing per-tool aliases.
|
|
11
|
+
- `Settings Copy Order`: Ordered every Settings value description by its visible controls rather than placing the default first; Draft previews now describes `on` before `off (default)`. Added parity coverage across all built-in Settings details. Impact: explanatory copy and chooser controls scan in the same direction while default metadata remains truthful in place.
|
|
12
|
+
- `Windows Release Gates`: Rechecked the generic integration predicate at its deadline, gave only queued model-menu completion a five-second budget, and allowed the full-Pi parent fixture ten seconds for graceful shutdown. Impact: loaded Windows runners can complete the asserted event-loop and process-cleanup paths while genuine hangs, exit failures, and child polling remain bounded failures.
|
|
13
|
+
|
|
3
14
|
## 0.26.10: Windows Graceful Disconnect Test Budget
|
|
4
15
|
|
|
5
16
|
- `Windows CI`: Expanded only the graceful follower-disconnect integration's bus-response budget from 500 milliseconds to five seconds. Impact: loaded Windows runners can complete persisted cleanup intent, close/delete operations, binding mutation, and the authenticated response without changing the production 30-second transport default, retry policy, cleanup ordering, or exact assertions.
|
package/docs/activity.md
CHANGED
|
@@ -180,7 +180,7 @@ Pi provider events use `thinking_*`; the public product term is `reasoning`. The
|
|
|
180
180
|
|
|
181
181
|
Tool activity uses Pi's executed-tool lifecycle (`tool_execution_start/update/end`), not provider `toolcall_*` payloads. Provider tool-call boundaries are used only to classify preceding assistant prose. This prevents duplicate tool rows and reports actual execution results.
|
|
182
182
|
|
|
183
|
-
`args`, `update`, and `result` may contain paths, source text, command output, or other sensitive data. They are available to trusted local extension code but must not be rendered wholesale by default. Core `quiet` mode renders none of them. Visible tool modes redact known secret shapes, truncate every evidence field, and place completed tool evidence in native Rich Messages with an open-by-default
|
|
183
|
+
`args`, `update`, and `result` may contain paths, source text, command output, or other sensitive data. They are available to trusted local extension code but must not be rendered wholesale by default. Core `quiet` mode renders none of them. Visible tool modes redact known secret shapes, truncate every evidence field, and place completed tool evidence in native Rich Messages with an open-by-default `arguments` child plus closed `update`/`result`/`error` details; child summaries use lowercase monospaced labels without icons, list markers, or heading emphasis, like quote-free outer JSON keys, while their evidence remains in JSON pre blocks.
|
|
184
184
|
|
|
185
185
|
## Delivery Context
|
|
186
186
|
|
package/docs/architecture.md
CHANGED
|
@@ -315,7 +315,7 @@ Queue reactions are shortcut controls for waiting turns. Promotion reactions (`
|
|
|
315
315
|
|
|
316
316
|
When `assistant.proactivePush` is enabled and this instance has exact direct or follower transport authority, completed public assistant text blocks from local/autonomous work are sent once and in source order to the instance's authorized target. Visible commentary/checkpoints and the final block use the configured Rich or HTML renderer. Proactive projection excludes reasoning, tool traffic, token deltas, local prompt text, Telegram-owned turns, and stale generations. Each admitted block remains fenced to its exact target, profile/token stamp, leader epoch or follower registration generation, and session generation; non-idempotent acknowledgement ambiguity never authorizes replay.
|
|
317
317
|
|
|
318
|
-
`assistant.activity` is an independent bridge-owned projection over normalized Activity events. Each process reloads the shared file-backed setting at `agent-start` before activity admission, so multi-instance mode cannot continue projecting a stale broader process-local selection. Omitted values resolve to `verbose`, while invalid values fail closed to `quiet`; `thinking` and `tools` select one technical class, while `verbose` enables both. Provider-exposed thinking uses persistent ordinary HTML containing only a standard expandable blockquote with a bounded redacted latest-text window and inline Markdown rendered as Telegram HTML. Completed executed tools use native Rich Messages: each closed
|
|
318
|
+
`assistant.activity` is an independent bridge-owned projection over normalized Activity events. Each process reloads the shared file-backed setting at `agent-start` before activity admission, so multi-instance mode cannot continue projecting a stale broader process-local selection. Omitted values resolve to `verbose`, while invalid values fail closed to `quiet`; `thinking` and `tools` select one technical class, while `verbose` enables both. Provider-exposed thinking uses persistent ordinary HTML containing only a standard expandable blockquote with a bounded redacted latest-text window and inline Markdown rendered as Telegram HTML. Completed executed tools use native Rich Messages: each closed `<Tool>: <status>` root details node uses sentence case with a preserved uppercase two- or three-letter repeated prefix, then the native disclosure chevron reveals an open-by-default `arguments` child plus closed retained `update N` and `result`/`error` child details with lowercase monospaced, marker-free summaries and JSON pre blocks; known-safe Rich rejections fall back to the previous HTML disclosure. The projection captures the exact target and transport stamp at activity admission, serializes updates, preserves tool-start order, closes coalescing across assistant/thinking boundaries, bounds retained text/update memory plus edit frames and message/tool size, disables previews and HTTP(S) auto-link recognition inside technical evidence, and never replays a possibly committed send. Session generations own independent queues, so replacement drops queued old work without waiting on an old call. Both proactive prose and active-turn final delivery wait for the admitted activity queue inside their extension-owned delivery tasks, preserving technical-before-semantic ordering without delaying Pi lifecycle completion. Settlement, replacement, disconnect, failure, or stale authority clears only local ownership; already-sent activity messages remain in chat.
|
|
319
319
|
|
|
320
320
|
Telegram prompt guidance is context- and authority-aware. Only an exact direct owner or live registered follower exposes the three pi-telegram model tools, their active-tool metadata, and the compact local bridge suffix. Disconnect or authority loss removes those surfaces for subsequent requests without touching foreign tools; reconnect/recovery restores only the pi-telegram subset that was active before suspension, including across same-process reload. Telegram-originated turns receive a compact pointer to `telegram_help` plus dynamic prompt blocks such as `[voice] delivery: automatic voice`; full voice/button/direct-delivery/Threaded Mode syntax stays in the help tool rather than every system prompt.
|
|
321
321
|
|
package/docs/outbound.md
CHANGED
|
@@ -17,7 +17,7 @@ Proactive blocks use `assistant.rendering` independently of voice policy. Rich m
|
|
|
17
17
|
`assistant.activity` defaults to `verbose` when absent and accepts four modes: `quiet`, `thinking`, `tools`, and `verbose`. Explicit stored values remain unchanged; invalid values fail closed to `quiet`. Every Pi instance reloads this shared file-backed mode at `agent-start`, so a setting changed from one thread applies to subsequent runs in the other live instances without requiring process reload. `thinking` shows only provider-exposed thinking, `tools` shows only completed executed tools, and `verbose` shows both without mixing technical UI into assistant Markdown.
|
|
18
18
|
|
|
19
19
|
- Provider-exposed thinking updates one persistent ordinary HTML message containing only a standard Telegram `<blockquote expandable>` with a bounded redacted latest-text window. Omitting a separate icon/level header saves one chat row while the disclosure's unique shape remains recognizable. Inline Markdown emphasis and code render as Telegram HTML instead of leaking raw markers. The bridge sends the message once, edits it only as thinking grows, and leaves the disclosure in chat; it never uses Rich drafts/Rich Messages. Providers that expose no thinking produce none.
|
|
20
|
-
- Completed executed tools use native `sendRichMessage` block objects. Each tool is one closed root details node summarized as bold `<Tool>:` plus monospaced `<status>`;
|
|
20
|
+
- Completed executed tools use native `sendRichMessage` block objects. Each tool is one closed root details node summarized as bold `<Tool>:` plus monospaced `<status>`; root labels remain sentence-case except that a leading two- or three-character repeated-letter prefix stays uppercase (`fffind` → `FFFind`). The native disclosure chevron identifies the row, and opening it immediately reveals the open `arguments` child plus separate closed retained `update N`, `result`, or `error` child details. Each child summary is one lowercase monospaced label—visually a quote-free outer JSON key with no icon, list marker, or heading emphasis—and contains one preformatted `json` block. Updates remain chronological, dropped-update counts appear in the first retained update summary, and arrays of object entries keep the denser `[{ ... }, { ... }]` layout. A known-safe Rich HTTP 400 rejection falls back once to the previous expandable HTML representation; ambiguous non-idempotent outcomes never replay.
|
|
21
21
|
- Thinking `sendMessage`/`editMessageText` disables link previews and breaks HTTP(S) auto-link recognition inside evidence. Rich tool messages set `skip_entity_detection: true`, so URL-like arguments, updates, and results remain literal code. Consecutive tools coalesce by editing one message only while target, activity, generation, ordering boundary, tool count, and serialized-size bounds still match. Assistant or thinking content closes the batch. A non-idempotent send with unknown commit state is never replayed; failed or ambiguous edits start no fallback send.
|
|
22
22
|
|
|
23
23
|
Thinking retains only a bounded latest-text window, tool updates retain only a bounded latest-entry window, and a session reset abandons queued old-generation work without making the replacement session wait for an old transport call. Final-answer delivery waits for the admitted activity queue inside the extension-owned background delivery task, so completed technical evidence cannot be overtaken by the semantic answer and Pi lifecycle completion remains non-blocking.
|
package/docs/ui-style.md
CHANGED
|
@@ -207,6 +207,7 @@ Rules:
|
|
|
207
207
|
- Start with a bold heading or, for dialogs, a bold question.
|
|
208
208
|
- Setting detail cards may include an emoji in the heading, then a colon and the current value in `<code>`.
|
|
209
209
|
- Explain what the setting does and what the options mean only as much as needed.
|
|
210
|
+
- Order setting value descriptions exactly like the chooser: rows top-to-bottom and values in a shared row left-to-right. Keep `(default)` on the actual default wherever it falls; default status never changes order.
|
|
210
211
|
- Keep descriptions short and clear.
|
|
211
212
|
|
|
212
213
|
Examples:
|
|
@@ -166,8 +166,13 @@ function renderThinkingActivityEvidenceHtml(text: string): string {
|
|
|
166
166
|
});
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
-
function
|
|
170
|
-
|
|
169
|
+
function formatToolActivityLabel(label: string): string {
|
|
170
|
+
if (label.length === 0) return label;
|
|
171
|
+
const repeatedPrefix = label.match(/^([a-z])\1*/iu)?.[0] ?? "";
|
|
172
|
+
if (repeatedPrefix.length === 2 || repeatedPrefix.length === 3) {
|
|
173
|
+
return `${repeatedPrefix.toUpperCase()}${label.slice(repeatedPrefix.length)}`;
|
|
174
|
+
}
|
|
175
|
+
return `${label[0]!.toUpperCase()}${label.slice(1)}`;
|
|
171
176
|
}
|
|
172
177
|
|
|
173
178
|
function renderToolActivityHtml(tool: ToolActivity): string {
|
|
@@ -189,7 +194,7 @@ function renderToolActivityHtml(tool: ToolActivity): string {
|
|
|
189
194
|
: "done"
|
|
190
195
|
: "running";
|
|
191
196
|
return [
|
|
192
|
-
`<b>${escapeHtml(
|
|
197
|
+
`<b>${escapeHtml(formatToolActivityLabel(tool.name))}:</b> <code>${status}</code>`,
|
|
193
198
|
`<blockquote expandable>${escapeActivityEvidenceHtml(evidence.join("\n\n"))}</blockquote>`,
|
|
194
199
|
].join("\n");
|
|
195
200
|
}
|
|
@@ -207,7 +212,7 @@ function createToolActivityDetail(
|
|
|
207
212
|
): TelegramInputRichBlock {
|
|
208
213
|
return {
|
|
209
214
|
type: "details",
|
|
210
|
-
summary: { type: "
|
|
215
|
+
summary: { type: "code", text: summary },
|
|
211
216
|
blocks: [{ type: "pre", text, language: "json" }],
|
|
212
217
|
...(isOpen ? { is_open: true as const } : {}),
|
|
213
218
|
};
|
|
@@ -222,7 +227,7 @@ function renderToolActivityRichBlocks(
|
|
|
222
227
|
: "done"
|
|
223
228
|
: "running";
|
|
224
229
|
const evidenceBlocks: TelegramInputRichBlock[] = [
|
|
225
|
-
createToolActivityDetail("
|
|
230
|
+
createToolActivityDetail("arguments", tool.args, true),
|
|
226
231
|
];
|
|
227
232
|
tool.updates.forEach((update, index) => {
|
|
228
233
|
const number = tool.droppedUpdates + index + 1;
|
|
@@ -231,12 +236,12 @@ function renderToolActivityRichBlocks(
|
|
|
231
236
|
? ` (${tool.droppedUpdates} earlier omitted)`
|
|
232
237
|
: "";
|
|
233
238
|
evidenceBlocks.push(
|
|
234
|
-
createToolActivityDetail(`
|
|
239
|
+
createToolActivityDetail(`update ${number}${omitted}`, update),
|
|
235
240
|
);
|
|
236
241
|
});
|
|
237
242
|
if (tool.complete && tool.result !== undefined) {
|
|
238
243
|
evidenceBlocks.push(
|
|
239
|
-
createToolActivityDetail(tool.isError ? "
|
|
244
|
+
createToolActivityDetail(tool.isError ? "error" : "result", tool.result),
|
|
240
245
|
);
|
|
241
246
|
}
|
|
242
247
|
return [
|
|
@@ -245,7 +250,7 @@ function renderToolActivityRichBlocks(
|
|
|
245
250
|
summary: [
|
|
246
251
|
{
|
|
247
252
|
type: "bold",
|
|
248
|
-
text: `${
|
|
253
|
+
text: `${formatToolActivityLabel(tool.name)}:`,
|
|
249
254
|
},
|
|
250
255
|
" ",
|
|
251
256
|
{ type: "code", text: status },
|
package/lib/menu-settings.ts
CHANGED
|
@@ -202,8 +202,8 @@ export function buildDraftPreviewsSettingsText(enabled: boolean): string {
|
|
|
202
202
|
"",
|
|
203
203
|
"Show live answer drafts while the model is answering.",
|
|
204
204
|
"",
|
|
205
|
-
"<code>-</code> <code>off</code> (default): show native active status, then send one final answer.",
|
|
206
205
|
"<code>-</code> <code>on</code>: stream safe Telegram Rich Draft frames before the final answer.",
|
|
206
|
+
"<code>-</code> <code>off</code> (default): show native active status, then send one final answer.",
|
|
207
207
|
].join("\n");
|
|
208
208
|
}
|
|
209
209
|
|