pi-braid-telegram 0.0.0-stage → 0.1.4
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/LICENSE +21 -0
- package/README.md +204 -2
- package/docs/live-update.md +190 -0
- package/docs/pause-control.md +151 -0
- package/docs/turn-complete-notify.md +110 -0
- package/package.json +60 -4
- package/src/index.ts +1853 -0
- package/src/lib/audio-normalize.ts +91 -0
- package/src/lib/decision-buttons.ts +574 -0
- package/src/lib/document.ts +203 -0
- package/src/lib/format.ts +809 -0
- package/src/lib/html-check.ts +280 -0
- package/src/lib/inbound-poller.ts +1248 -0
- package/src/lib/inbound-queue.ts +157 -0
- package/src/lib/local-time.ts +181 -0
- package/src/lib/notify/agent-delivery.ts +29 -0
- package/src/lib/notify/craft.ts +157 -0
- package/src/lib/notify/live-update.ts +716 -0
- package/src/lib/notify/model.ts +197 -0
- package/src/lib/notify/rate-limit.ts +44 -0
- package/src/lib/notify/turn-notify.ts +138 -0
- package/src/lib/pause-control.ts +425 -0
- package/src/lib/photo.ts +182 -0
- package/src/lib/poller-lock.ts +127 -0
- package/src/lib/session-role.ts +32 -0
- package/src/lib/state-paths.ts +164 -0
- package/src/lib/stt-keys.ts +211 -0
- package/src/lib/telegram-client.ts +699 -0
- package/src/lib/telegram-inbox.ts +203 -0
- package/src/lib/telegram-settings.ts +92 -0
- package/src/lib/tool-logic.ts +604 -0
- package/src/lib/transcribe.ts +574 -0
- package/src/lib/tts.ts +451 -0
- package/src/lib/venice-catalog-base-url.ts +45 -0
- package/src/lib/voice.ts +192 -0
- package/src/lib/watchdog-tunnel.ts +102 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# Turn-Complete Auto-Notify: Design Decisions
|
|
2
|
+
|
|
3
|
+
<!-- status: current -->
|
|
4
|
+
|
|
5
|
+
Status: **pending owner sign-off**. This list is the deliverable-1 surface; the
|
|
6
|
+
fixture tests in `packages/telegram/test/notify.test.mjs` pin the implemented
|
|
7
|
+
defaults. Any owner change to a default below is a config/env change, not code.
|
|
8
|
+
|
|
9
|
+
## Feature recap
|
|
10
|
+
|
|
11
|
+
When the agent finishes a turn with a completed plain-text answer (no trailing
|
|
12
|
+
tool call), a SECOND LLM call (the "crafting model") distills the answer into
|
|
13
|
+
an owner update capped at `braid.telegram.notifyMaxChars` (default 1200) and
|
|
14
|
+
sends it over Telegram through the SAME
|
|
15
|
+
outbound seam as `telegram_send` / `/telegram send`. The `[tg-end]` marker is
|
|
16
|
+
an INBOUND parse boundary only and never appears on outbound.
|
|
17
|
+
|
|
18
|
+
## Decision 1: which turns notify
|
|
19
|
+
|
|
20
|
+
**Implemented: completed-answer turns only.**
|
|
21
|
+
`shouldNotifyTurnEnd(event)` notifies iff the `turn_end` message is an assistant
|
|
22
|
+
message with non-empty text AND `stopReason !== "toolUse"`. A `toolUse`
|
|
23
|
+
stopReason means the model's last action was a trailing tool call (work
|
|
24
|
+
continues next turn) → no notify. This satisfies the brief's "NO crafting when
|
|
25
|
+
last tool call trailing".
|
|
26
|
+
Rejected alternatives:
|
|
27
|
+
|
|
28
|
+
- _Always_ (every turn, including mid-work tool turns) - would spam the owner.
|
|
29
|
+
- _Quiet-window_ (only during owner-defined quiet hours) - no owner-supplied
|
|
30
|
+
quiet-hours config exists; OBE once the owner defines one.
|
|
31
|
+
- _Per-session opt-in_ (agent decides each session) - the agent is the one
|
|
32
|
+
being notified about; it should not be the gatekeeper.
|
|
33
|
+
|
|
34
|
+
## Decision 2: opt-in vs always-on
|
|
35
|
+
|
|
36
|
+
**Implemented: opt-in via `BRAID_TG_NOTIFY_ENABLED=1` (default OFF).**
|
|
37
|
+
No unsolicited messages until the owner enables it. The telegram extension
|
|
38
|
+
already requires `BRAID_TG_BOT_TOKEN`, so this is the only extra flag. When the
|
|
39
|
+
flag is off, the `turn_end` listener is NOT registered at all (verified by
|
|
40
|
+
`test/index.test.mjs`).
|
|
41
|
+
|
|
42
|
+
## Decision 3: utility vs max-power model
|
|
43
|
+
|
|
44
|
+
**Implemented: session model by default, env override wins.**
|
|
45
|
+
`resolveNotifyModel()` (notify/model.ts): `BRAID_TG_NOTIFY_MODEL`
|
|
46
|
+
(`provider/model-id`) → else `ctx.model` (session model) → else first available
|
|
47
|
+
registry model. The call is key-ring-backed: the API key comes from
|
|
48
|
+
`ctx.modelRegistry.getApiKeyForProvider(provider)`, which
|
|
49
|
+
pi-braid-providers wires to the key-ring (`ring-lifecycle.ts` auth.resolve →
|
|
50
|
+
`getActiveKey`) - never the bot token.
|
|
51
|
+
Note: core's `/utility-model` role key (`/max-power-model` is a deprecated
|
|
52
|
+
alias of it) lives in core's global-state (unreachable from the standalone
|
|
53
|
+
telegram package without a cross-package import). The env override is the
|
|
54
|
+
telegram-native equivalent.
|
|
55
|
+
Owner call: if honoring the /utility-model role key is required, that needs the
|
|
56
|
+
core-extension placement (Architecture B) instead - documented as a follow-up.
|
|
57
|
+
|
|
58
|
+
## Decision 4: rate limit
|
|
59
|
+
|
|
60
|
+
**Implemented: sliding window, max 4/min by default.**
|
|
61
|
+
`SlidingWindowLimiter` (notify/rate-limit.ts), override via
|
|
62
|
+
`BRAID_TG_NOTIFY_MAX_PER_MIN`. Deterministic by explicit-timestamp `try(now)`.
|
|
63
|
+
Sliding window (vs fixed minute) so a turn at 59.9s does not immediately reset.
|
|
64
|
+
|
|
65
|
+
## Decision 5: content template
|
|
66
|
+
|
|
67
|
+
**Implemented: distilling prompt** (`buildNotifyPrompts` in notify/craft.ts):
|
|
68
|
+
"state what was done / key result, ≤ `braid.telegram.notifyMaxChars` chars
|
|
69
|
+
(default 1200), plain text, no greetings/no
|
|
70
|
+
sign-off/no markdown; reply DONE if no actionable content." The crafting model
|
|
71
|
+
produces the message; `truncateGuard` (same cap, ellipsis) is the guard-fallback
|
|
72
|
+
when crafting fails or returns something malformed. The model's output budget
|
|
73
|
+
scales with the cap (`craftMaxTokensFor`) so a long target is not cut mid-sentence.
|
|
74
|
+
|
|
75
|
+
## Decision 6: telegram_send / /telegram send reuse the same seam
|
|
76
|
+
|
|
77
|
+
`runTelegramSend` gained an optional `craft` hook. When text exceeds the
|
|
78
|
+
settings-driven send cap (`braid.telegram.sendMaxChars`, default 4096), the
|
|
79
|
+
crafting model produces the message (replacing the old dumb truncation);
|
|
80
|
+
the cap stays as the guard threshold. Short text skips crafting
|
|
81
|
+
(no model call). `/telegram send` now routes through `runTelegramSend` -
|
|
82
|
+
the exact same outbound path - so crafting, cap fallback, and
|
|
83
|
+
no-[tg-end] behavior are shared.
|
|
84
|
+
|
|
85
|
+
## Placement decision (why telegram, not a new core extension)
|
|
86
|
+
|
|
87
|
+
The brief leaned "a new small extension under packages/core/src/extensions/"
|
|
88
|
+
but allowed "or a new extension" with "read how existing extensions register
|
|
89
|
+
listeners and mirror it". Chosen: the notify feature lives in the TELEGRAM
|
|
90
|
+
package because:
|
|
91
|
+
|
|
92
|
+
- It owns the outbound seam + client/token/chatId - deliverable 3 ("same
|
|
93
|
+
outbound seam") is literal, with zero cross-package coupling.
|
|
94
|
+
- It already registers pi.on listeners in its factory (16f pattern); a
|
|
95
|
+
`turn_end` listener mirrors it exactly.
|
|
96
|
+
- The alternative (core notify extension + delivery sink registered by
|
|
97
|
+
telegram) requires a telegram→core import. It works today via the workspace
|
|
98
|
+
symlink but is a phantom dependency and makes the telegram test chain depend
|
|
99
|
+
on core's dist being freshly built - fragile under the "no package-lock diff"
|
|
100
|
+
gate. Avoided.
|
|
101
|
+
- The crafting LLM call reuses "our systems": `completeSimple` from
|
|
102
|
+
`@earendil-works/pi-ai/compat` (the exact path core's llm-call.ts wraps at
|
|
103
|
+
llm-call.ts:50) + `ctx.modelRegistry` for model + key-ring key.
|
|
104
|
+
|
|
105
|
+
## Forbidden-files check
|
|
106
|
+
|
|
107
|
+
- No packages/providers source changes by this task (a pre-existing,
|
|
108
|
+
unrelated working-tree modification was left untouched).
|
|
109
|
+
- No package-lock.json diff, no npm install, no git checkout/reset/stash.
|
|
110
|
+
- No changes to packages/core or packages/providers source.
|
package/package.json
CHANGED
|
@@ -1,6 +1,62 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-braid-telegram",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"description": "Bidirectional Telegram channel for pi-braid: telegram_send tool (outbound) + inbound long-poll injector (backward channel)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"files": [
|
|
7
|
+
"src/",
|
|
8
|
+
"docs/",
|
|
9
|
+
"README.md",
|
|
10
|
+
"LICENSE"
|
|
11
|
+
],
|
|
12
|
+
"exports": {
|
|
13
|
+
".": "./src/index.ts"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"pi-package",
|
|
17
|
+
"pi",
|
|
18
|
+
"pi-coding-agent",
|
|
19
|
+
"bot",
|
|
20
|
+
"extension",
|
|
21
|
+
"telegram",
|
|
22
|
+
"channel",
|
|
23
|
+
"messaging"
|
|
24
|
+
],
|
|
25
|
+
"pi": {
|
|
26
|
+
"extensions": [
|
|
27
|
+
"./src/index.ts"
|
|
28
|
+
]
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"prepublishOnly": "npm run typecheck",
|
|
32
|
+
"typecheck": "tsc --noEmit",
|
|
33
|
+
"build": "tsc -p tsconfig.build.json",
|
|
34
|
+
"test": "node test/run-tests.mjs",
|
|
35
|
+
"check:doc-index": "node ../../packages/core/scripts/check-doc-index.mjs",
|
|
36
|
+
"publish:local": "node ../../packages/core/scripts/publish-local.mjs telegram",
|
|
37
|
+
"prepack": "npm run build"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"typescript": "6.0.2",
|
|
41
|
+
"typebox": "1.1.38"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"@earendil-works/pi-ai": "*",
|
|
45
|
+
"@earendil-works/pi-coding-agent": "*",
|
|
46
|
+
"typebox": "*"
|
|
47
|
+
},
|
|
48
|
+
"author": "kifirkin",
|
|
49
|
+
"license": "MIT",
|
|
50
|
+
"repository": {
|
|
51
|
+
"type": "git",
|
|
52
|
+
"url": "git+https://github.com/kifirkin/pi-braid.git",
|
|
53
|
+
"directory": "packages/telegram"
|
|
54
|
+
},
|
|
55
|
+
"bugs": {
|
|
56
|
+
"url": "https://github.com/kifirkin/pi-braid/issues"
|
|
57
|
+
},
|
|
58
|
+
"homepage": "https://github.com/kifirkin/pi-braid/tree/main/packages/telegram",
|
|
59
|
+
"engines": {
|
|
60
|
+
"node": ">=22.19.0"
|
|
61
|
+
}
|
|
62
|
+
}
|