pi-braid-telegram 0.1.4 → 0.1.5
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 +17 -0
- package/build-info.json +9 -0
- package/package.json +8 -6
- package/src/lib/format.ts +17 -4
package/README.md
CHANGED
|
@@ -4,6 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
Bidirectional Telegram channel for pi-braid.
|
|
6
6
|
|
|
7
|
+
```bash
|
|
8
|
+
pi install npm:pi-braid-telegram
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
One command, no clone, no build: `pi install` registers the package with pi and installs it under pi's npm directory.
|
|
12
|
+
|
|
7
13
|
- **Outbound**: `telegram_send` tool - the agent sends text messages to the
|
|
8
14
|
owner (or voice notes once a TTS source is configured). Messages are LONG by
|
|
9
15
|
default: plain text sends verbatim up to the cap (`braid.telegram.sendMaxChars`
|
|
@@ -96,6 +102,17 @@ Or register the workspace in `~/.pi/agent/settings.json`:
|
|
|
96
102
|
- A bot token from @BotFather; optionally `BRAID_TG_CHAT_ID` / `BRAID_TG_ALLOWED_USERS` for the
|
|
97
103
|
allow-list.
|
|
98
104
|
|
|
105
|
+
## Settings cadence
|
|
106
|
+
|
|
107
|
+
Settings live in `~/.pi/agent/settings.json`. `braid.telegram.pauseStateFile`
|
|
108
|
+
is captured as the callback write target when the extension loads. `getPauseState()`
|
|
109
|
+
resolves its read path per call, so restart after changing the setting to keep
|
|
110
|
+
reads and writes aligned. `braid.telegram.tts` is loaded into the voice hook at
|
|
111
|
+
extension load; restart after changing its source, rate, or voices.
|
|
112
|
+
The send and notification caps (`braid.telegram.sendMaxChars` and
|
|
113
|
+
`braid.telegram.notifyMaxChars`) are re-read per operation and change without
|
|
114
|
+
a restart.
|
|
115
|
+
|
|
99
116
|
## Environment variables
|
|
100
117
|
|
|
101
118
|
| Var | Purpose | Required |
|
package/build-info.json
ADDED
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-braid-telegram",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Bidirectional Telegram channel for pi-braid: telegram_send tool (outbound) + inbound long-poll injector (backward channel)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|
|
7
7
|
"src/",
|
|
8
8
|
"docs/",
|
|
9
9
|
"README.md",
|
|
10
|
-
"LICENSE"
|
|
10
|
+
"LICENSE",
|
|
11
|
+
"build-info.json"
|
|
11
12
|
],
|
|
12
13
|
"exports": {
|
|
13
14
|
".": "./src/index.ts"
|
|
@@ -34,16 +35,17 @@
|
|
|
34
35
|
"test": "node test/run-tests.mjs",
|
|
35
36
|
"check:doc-index": "node ../../packages/core/scripts/check-doc-index.mjs",
|
|
36
37
|
"publish:local": "node ../../packages/core/scripts/publish-local.mjs telegram",
|
|
37
|
-
"prepack": "npm run build"
|
|
38
|
+
"prepack": "npm run build && node ../../packages/core/scripts/pack-provenance.mjs write",
|
|
39
|
+
"postpack": "node ../../packages/core/scripts/pack-provenance.mjs remove"
|
|
38
40
|
},
|
|
39
41
|
"devDependencies": {
|
|
40
42
|
"typescript": "6.0.2",
|
|
41
43
|
"typebox": "1.1.38"
|
|
42
44
|
},
|
|
43
45
|
"peerDependencies": {
|
|
44
|
-
"@earendil-works/pi-ai": "
|
|
45
|
-
"@earendil-works/pi-coding-agent": "
|
|
46
|
-
"typebox": "
|
|
46
|
+
"@earendil-works/pi-ai": "^1.2.0",
|
|
47
|
+
"@earendil-works/pi-coding-agent": "^1.2.0",
|
|
48
|
+
"typebox": "^1.1.38"
|
|
47
49
|
},
|
|
48
50
|
"author": "kifirkin",
|
|
49
51
|
"license": "MIT",
|
package/src/lib/format.ts
CHANGED
|
@@ -27,7 +27,11 @@ import type {
|
|
|
27
27
|
TelegramSendResult,
|
|
28
28
|
ParseMode,
|
|
29
29
|
} from "./telegram-client.js";
|
|
30
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
TELEGRAM_HTML_TAGS,
|
|
32
|
+
checkTelegramHtml,
|
|
33
|
+
parseTelegramTagAt,
|
|
34
|
+
} from "./html-check.js";
|
|
31
35
|
|
|
32
36
|
/** Telegram hard cap for a single text message (https://core.telegram.org/bots/api#sendmessage). */
|
|
33
37
|
export const TELEGRAM_MAX_TEXT_LENGTH = 4096;
|
|
@@ -145,17 +149,26 @@ export function isBalancedMarkdown(text: string): boolean {
|
|
|
145
149
|
// attribute value is part of the tag, so `<a href="a>b">` is one token and is
|
|
146
150
|
// removed whole rather than truncated at the first `>`.
|
|
147
151
|
|
|
148
|
-
/** True when the text contains
|
|
152
|
+
/** True when the text contains a tag Telegram's HTML parser accepts.
|
|
153
|
+
*
|
|
154
|
+
* Tag-shaped is not enough: auto-selecting HTML for a body carrying `<n>` or
|
|
155
|
+
* `<b/>` makes Telegram reject the whole message ("Unsupported start tag"),
|
|
156
|
+
* while as a plain body the same characters reach the reader literally. Only
|
|
157
|
+
* a token whose name is in Telegram's tag set and whose syntax the parser
|
|
158
|
+
* accepts is a signal the body was authored as HTML.
|
|
159
|
+
*/
|
|
149
160
|
export function hasHtmlTags(text: string): boolean {
|
|
150
161
|
return findTagToken(text) !== null;
|
|
151
162
|
}
|
|
152
163
|
|
|
153
|
-
/** First tag-shaped token
|
|
164
|
+
/** First tag-shaped token Telegram would accept, or null. */
|
|
154
165
|
function findTagToken(text: string): { start: number; end: number } | null {
|
|
155
166
|
let i = text.indexOf("<");
|
|
156
167
|
while (i !== -1) {
|
|
157
168
|
const tag = parseTelegramTagAt(text, i);
|
|
158
|
-
if (tag
|
|
169
|
+
if (tag && tag.error === undefined && TELEGRAM_HTML_TAGS.has(tag.name)) {
|
|
170
|
+
return { start: i, end: tag.end };
|
|
171
|
+
}
|
|
159
172
|
i = text.indexOf("<", i + 1);
|
|
160
173
|
}
|
|
161
174
|
return null;
|