@llblab/pi-kit 0.1.12 → 0.1.13
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/CHANGELOG.md +4 -0
- package/README.md +1 -1
- package/node_modules/@llblab/pi-telegram/CHANGELOG.md +8 -0
- package/node_modules/@llblab/pi-telegram/docs/activity.md +9 -2
- package/node_modules/@llblab/pi-telegram/docs/architecture.md +3 -2
- package/node_modules/@llblab/pi-telegram/lib/activity.ts +29 -0
- package/node_modules/@llblab/pi-telegram/lib/bindings.ts +57 -6
- package/node_modules/@llblab/pi-telegram/lib/inbound.ts +1 -1
- package/node_modules/@llblab/pi-telegram/lib/lifecycle.ts +50 -0
- package/node_modules/@llblab/pi-telegram/lib/pi.ts +15 -0
- package/node_modules/@llblab/pi-telegram/package.json +4 -4
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@llblab/pi-kit` are documented here.
|
|
4
4
|
|
|
5
|
+
## 0.1.13 - 2026-08-30
|
|
6
|
+
|
|
7
|
+
- `Telegram Minor Release`: Advances `@llblab/pi-telegram` to `0.40.0`, requiring Pi 0.84.4 and adopting native compaction-failure, mid-run compaction, terminal-message, and local UI-prompt lifecycle contracts while increasing bounded inbound text output to 24,000 characters.
|
|
8
|
+
|
|
5
9
|
## 0.1.12 - 2026-08-28
|
|
6
10
|
|
|
7
11
|
- `Codex Usage Release`: Advances `@llblab/pi-codex-usage` to `0.9.4`, reducing automatic OpenAI quota polling by increasing the refresh interval from 30 to 60 seconds while preserving the local countdown responsiveness.
|
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
| `@llblab/pi-actors` | `0.50.0` | Extension and Skills |
|
|
10
10
|
| `@llblab/pi-codex-usage` | `0.9.4` | Extension |
|
|
11
11
|
| `@llblab/pi-grow-loop` | `0.7.3` | Extension and Skills |
|
|
12
|
-
| `@llblab/pi-telegram` | `0.
|
|
12
|
+
| `@llblab/pi-telegram` | `0.40.0` | Extension and Skills |
|
|
13
13
|
|
|
14
14
|
Versions are exact by design. Updating an extension does not change an installed kit until this repository explicitly advances that dependency and publishes a new kit version.
|
|
15
15
|
|
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
> Each release keeps at most 8 outcome records of at most 512 characters.
|
|
4
4
|
|
|
5
|
+
## 0.40.0: Pi 0.84.4 Lifecycle Alignment
|
|
6
|
+
|
|
7
|
+
- `Pi Compatibility`: Requires `@earendil-works/pi-coding-agent`, `pi-agent-core`, and `pi-ai` 0.84.4 or newer, aligning the bridge and its validation runtime with native compaction-failure, mid-run compaction, message-finalization, and UI-prompt lifecycle contracts.
|
|
8
|
+
- `Compaction Failure`: Handles `session_compact_failed` immediately by clearing compacting state, stopping observer-owned typing, releasing deferred queue work, abandoning stale activity, and reporting automatic failure or cancellation without duplicating manual `/compact` errors.
|
|
9
|
+
- `Compaction Chronology`: Distinguishes terminal assistant output awaiting Telegram delivery from mid-run tool continuation. Post-answer notices remain ordered after the final reply, while tool-result threshold compaction is reported in place before the next assistant response.
|
|
10
|
+
- `Local UI Waiting`: Pauses Telegram typing while Pi waits on extension-owned local select, confirm, input, editor, or custom prompts and emits coalesced `ui-prompt-start` / `ui-prompt-end` Activity boundaries before resuming active-turn typing.
|
|
11
|
+
- `Inbound Context`: Raises successful inbound handler and built-in text attachment output from 12,000 to 24,000 characters while retaining the 1 MB built-in file admission ceiling and explicit truncation evidence.
|
|
12
|
+
|
|
5
13
|
## 0.39.5: Auto-Compaction Notice Chronology Hotfix
|
|
6
14
|
|
|
7
15
|
- `Turn Chronology`: Defers observed automatic-compaction notices while a Telegram turn is still active, preserving the same causal order shown by the terminal: final answer, compaction started, then compaction completed. Abandoned compactions and session shutdown discard deferred notices instead of leaking them into a later turn.
|
|
@@ -96,7 +96,7 @@ Source classification follows evidence, not guesses:
|
|
|
96
96
|
|
|
97
97
|
Automatic retries, overflow compaction retries, and tool continuations inherit the current activity identity/source until `agent_settled`. A new unrelated `agent_start` after settlement allocates a new activity id.
|
|
98
98
|
|
|
99
|
-
A standalone compaction owns a temporary activity
|
|
99
|
+
A standalone compaction owns a temporary activity until `session_compact` or `session_compact_failed`. Native failure or cancellation immediately abandons that identity, clears compacting state, releases deferred queue work, and stops observer-owned typing; the five-minute observer timeout remains a compatibility fallback for a host that never emits a terminal compaction event. A late `session_compact` after abandonment is ignored and cannot attach to the next run. Compaction inside an existing agent activity never clears that agent's identity.
|
|
100
100
|
|
|
101
101
|
## Event Contract
|
|
102
102
|
|
|
@@ -151,6 +151,12 @@ export type TelegramActivityEvent = TelegramActivityEnvelope & (
|
|
|
151
151
|
type: "compaction-end";
|
|
152
152
|
reason: "manual" | "threshold" | "overflow" | "unknown";
|
|
153
153
|
}
|
|
154
|
+
| {
|
|
155
|
+
type: "ui-prompt-start";
|
|
156
|
+
kind: "select" | "confirm" | "input" | "editor" | "custom";
|
|
157
|
+
title?: string;
|
|
158
|
+
}
|
|
159
|
+
| { type: "ui-prompt-end" }
|
|
154
160
|
| { type: "agent-end" }
|
|
155
161
|
| { type: "agent-settled" }
|
|
156
162
|
);
|
|
@@ -250,7 +256,8 @@ The bridge maps Pi hooks as follows:
|
|
|
250
256
|
- `agent_start`: allocate or reuse activity identity and emit `agent-start` after Telegram queue consumption establishes active-turn ownership.
|
|
251
257
|
- `message_update.assistantMessageEvent`: normalize text/reasoning/provider boundaries.
|
|
252
258
|
- `tool_execution_start/update/end`: emit executed tool events.
|
|
253
|
-
- `session_before_compact` / `session_compact`: emit compaction boundaries and preserve activity identity across retry compaction
|
|
259
|
+
- `session_before_compact` / `session_compact` / `session_compact_failed`: emit successful compaction boundaries, abandon failed or cancelled work immediately, and preserve activity identity across retry compaction. Mid-run threshold compaction stays between tool results and the next assistant response, while terminal assistant output awaiting transport keeps later notices behind its final reply. A missing or unrecognized reason maps to `unknown` rather than guessing.
|
|
260
|
+
- `ui_prompt_start` / `ui_prompt_end`: emit one coalesced waiting span for extension-owned local UI, pause Telegram typing while Pi waits for the operator, and resume active-turn typing when the prompt closes.
|
|
254
261
|
- `agent_end`: emit low-level run completion but keep identity alive for retry/follow-up work.
|
|
255
262
|
- `agent_settled`: emit terminal settlement, flush pending terminal segments, and release activity identity.
|
|
256
263
|
- `session_shutdown`: stop dispatch, clear pending normalization state, and invalidate delivery generation through the existing delivery lifecycle.
|
|
@@ -315,14 +315,15 @@ Queue and menu mutations are reachable through Telegram updates handled by the c
|
|
|
315
315
|
|
|
316
316
|
### Compaction And Typing Status
|
|
317
317
|
|
|
318
|
-
Manual `/compact` requires inline confirmation because accidental taps are disruptive. Confirmed manual compaction and auto-compaction both set the bridge compaction flag, block queued prompt dispatch, retain that flag in explicit diagnostics, and clear it on compact completion, timeout fallback, or session shutdown. Pi owns its terminal compaction lifecycle; pi-telegram keeps `Active` scoped to Telegram-owned work and otherwise preserves the stable connected/leader/follower role.
|
|
318
|
+
Manual `/compact` requires inline confirmation because accidental taps are disruptive. Confirmed manual compaction and auto-compaction both set the bridge compaction flag, block queued prompt dispatch, retain that flag in explicit diagnostics, and clear it on native compact completion or failure, timeout fallback, or session shutdown. Pi owns its terminal compaction lifecycle; pi-telegram keeps `Active` scoped to Telegram-owned work and otherwise preserves the stable connected/leader/follower role. Mid-run threshold compaction reports notices in place between tool output and the next assistant response; compaction observed after terminal assistant output waits for final Telegram delivery so transport chronology matches the terminal.
|
|
319
319
|
|
|
320
320
|
Native typing during compaction follows connected-instance activity rather than terminal status:
|
|
321
321
|
|
|
322
322
|
- Confirmed manual `/compact` starts a native `typing` keepalive in the command target and stops it on completion/failure.
|
|
323
323
|
- Automatic/session compaction with an active Telegram turn reuses that turn's target.
|
|
324
324
|
- Automatic/session compaction without an active Telegram turn uses the connected instance's assigned target; an unconnected instance sends nothing.
|
|
325
|
-
- Thread-targeted typing is sent to the concrete thread and mirrored to `All` as the aggregate activity surface; completion, timeout, and shutdown stop the keyed loop.
|
|
325
|
+
- Thread-targeted typing is sent to the concrete thread and mirrored to `All` as the aggregate activity surface; completion, native failure, timeout, and shutdown stop the keyed loop.
|
|
326
|
+
- Pi `ui_prompt_start` pauses active-turn typing while an extension-owned local prompt waits for the operator; `ui_prompt_end` emits the matching Activity boundary and resumes typing.
|
|
326
327
|
|
|
327
328
|
At every connected instance `agent_start`, the lifecycle binding starts Telegram's native `…typing` indicator in that instance's assigned target, whether the run came from Telegram, the local TUI, or an autonomous continuation such as Grow Loop. Terminal `Active` remains Telegram-turn-specific; the native indicator answers the separate question of whether the instance is doing agent work. Each loop keeps one action in flight, while the leader API runtime coalesces identical chat/thread/action calls across local and follower traffic for two seconds; expired gates prune opportunistically and at most 256 currently active keys are retained. A Telegram 429 response opens the exact action's shared `retry_after` suppression window without scheduling delayed retries or projecting expected activity throttling as a terminal status error. Assistant message start/update hooks still re-arm it during Telegram-owned turns so transient provider/model errors do not leave a continuing run without activity feedback, and agent/session completion stops it.
|
|
328
329
|
|
|
@@ -85,6 +85,12 @@ export type TelegramActivityPayload =
|
|
|
85
85
|
type: "compaction-end";
|
|
86
86
|
reason: "manual" | "threshold" | "overflow" | "unknown";
|
|
87
87
|
}
|
|
88
|
+
| {
|
|
89
|
+
type: "ui-prompt-start";
|
|
90
|
+
kind: "select" | "confirm" | "input" | "editor" | "custom";
|
|
91
|
+
title?: string;
|
|
92
|
+
}
|
|
93
|
+
| { type: "ui-prompt-end" }
|
|
88
94
|
| { type: "agent-end" }
|
|
89
95
|
| { type: "agent-settled" };
|
|
90
96
|
|
|
@@ -440,6 +446,12 @@ export function createTelegramActivityBridgeRuntime(deps: {
|
|
|
440
446
|
onCompactionAbandoned() {
|
|
441
447
|
getRuntime()?.onCompactionAbandoned();
|
|
442
448
|
},
|
|
449
|
+
onUiPromptStart(kind, title) {
|
|
450
|
+
getRuntime()?.onUiPromptStart(kind, title);
|
|
451
|
+
},
|
|
452
|
+
onUiPromptEnd() {
|
|
453
|
+
getRuntime()?.onUiPromptEnd();
|
|
454
|
+
},
|
|
443
455
|
onAgentEnd() {
|
|
444
456
|
getRuntime()?.onAgentEnd();
|
|
445
457
|
},
|
|
@@ -502,6 +514,11 @@ export interface TelegramActivityRuntime {
|
|
|
502
514
|
reason: "manual" | "threshold" | "overflow" | "unknown",
|
|
503
515
|
) => void;
|
|
504
516
|
onCompactionAbandoned: () => void;
|
|
517
|
+
onUiPromptStart: (
|
|
518
|
+
kind: "select" | "confirm" | "input" | "editor" | "custom",
|
|
519
|
+
title?: string,
|
|
520
|
+
) => void;
|
|
521
|
+
onUiPromptEnd: () => void;
|
|
505
522
|
onAgentEnd: () => void;
|
|
506
523
|
onAgentSettled: () => void;
|
|
507
524
|
onSessionShutdown: () => void;
|
|
@@ -533,6 +550,7 @@ export function createTelegramActivityRuntime(deps: {
|
|
|
533
550
|
let pendingAssistantSegment: PendingAssistantSegment | undefined;
|
|
534
551
|
let compactionInProgress = false;
|
|
535
552
|
let compactionOwnedActivity = false;
|
|
553
|
+
let uiPromptInProgress = false;
|
|
536
554
|
const ensureActivity = (
|
|
537
555
|
activeTelegramTarget?: TelegramActivityTarget,
|
|
538
556
|
): string => {
|
|
@@ -592,6 +610,7 @@ export function createTelegramActivityRuntime(deps: {
|
|
|
592
610
|
pendingAssistantSegment = undefined;
|
|
593
611
|
compactionInProgress = false;
|
|
594
612
|
compactionOwnedActivity = false;
|
|
613
|
+
uiPromptInProgress = false;
|
|
595
614
|
};
|
|
596
615
|
const abandonCompaction = (): void => {
|
|
597
616
|
if (!compactionInProgress) return;
|
|
@@ -685,6 +704,16 @@ export function createTelegramActivityRuntime(deps: {
|
|
|
685
704
|
onCompactionAbandoned() {
|
|
686
705
|
abandonCompaction();
|
|
687
706
|
},
|
|
707
|
+
onUiPromptStart(kind, title) {
|
|
708
|
+
if (!activityId || uiPromptInProgress) return;
|
|
709
|
+
uiPromptInProgress = true;
|
|
710
|
+
emit({ type: "ui-prompt-start", kind, title });
|
|
711
|
+
},
|
|
712
|
+
onUiPromptEnd() {
|
|
713
|
+
if (!activityId || !uiPromptInProgress) return;
|
|
714
|
+
uiPromptInProgress = false;
|
|
715
|
+
emit({ type: "ui-prompt-end" });
|
|
716
|
+
},
|
|
688
717
|
onAgentEnd() {
|
|
689
718
|
if (activityId) emit({ type: "agent-end" });
|
|
690
719
|
},
|
|
@@ -1012,8 +1012,9 @@ export function registerTelegramLifecycleRuntimeHooks({
|
|
|
1012
1012
|
const agentStartWithDedupReset = Lifecycle.createAgentStartDedupHook(
|
|
1013
1013
|
agentLifecycleHooks.onAgentStart,
|
|
1014
1014
|
);
|
|
1015
|
+
let uiPromptActive = false;
|
|
1015
1016
|
const startAgentActivityTypingLoop = (ctx: Pi.ExtensionContext): boolean => {
|
|
1016
|
-
if (!canSendAgentActivity(ctx)) return false;
|
|
1017
|
+
if (uiPromptActive || !canSendAgentActivity(ctx)) return false;
|
|
1017
1018
|
const turn = activeTurnRuntime.get();
|
|
1018
1019
|
const target = turn?.target ?? proactivePushTargetGetter();
|
|
1019
1020
|
promptDispatchRuntime.startTypingLoop(ctx, turn?.chatId ?? target?.chatId, {
|
|
@@ -1022,12 +1023,15 @@ export function registerTelegramLifecycleRuntimeHooks({
|
|
|
1022
1023
|
return true;
|
|
1023
1024
|
};
|
|
1024
1025
|
const startActiveTurnTypingLoop = (ctx: Pi.ExtensionContext): void => {
|
|
1026
|
+
if (uiPromptActive) return;
|
|
1025
1027
|
const turn = activeTurnRuntime.get();
|
|
1026
1028
|
promptDispatchRuntime.startTypingLoop(ctx, turn?.chatId, {
|
|
1027
1029
|
target: turn?.target,
|
|
1028
1030
|
});
|
|
1029
1031
|
};
|
|
1030
1032
|
let observedAutomaticCompaction = false;
|
|
1033
|
+
let agentRunActive = false;
|
|
1034
|
+
let terminalAssistantMessagePendingDelivery = false;
|
|
1031
1035
|
const deferredAutomaticCompactionNotices: string[] = [];
|
|
1032
1036
|
const sendCompactionNotice = async (text: string): Promise<void> => {
|
|
1033
1037
|
const turn = activeTurnRuntime.get();
|
|
@@ -1094,6 +1098,9 @@ export function registerTelegramLifecycleRuntimeHooks({
|
|
|
1094
1098
|
activityVerbosityRuntime?.reset();
|
|
1095
1099
|
assistantOutputRuntime.stop();
|
|
1096
1100
|
observedAutomaticCompaction = false;
|
|
1101
|
+
agentRunActive = false;
|
|
1102
|
+
terminalAssistantMessagePendingDelivery = false;
|
|
1103
|
+
uiPromptActive = false;
|
|
1097
1104
|
deferredAutomaticCompactionNotices.length = 0;
|
|
1098
1105
|
compactionObserver.onSessionShutdown();
|
|
1099
1106
|
if (event.reason === "quit" && disconnectOnQuit) {
|
|
@@ -1116,7 +1123,10 @@ export function registerTelegramLifecycleRuntimeHooks({
|
|
|
1116
1123
|
activityRuntime.onCompactionStart(Pi.getSessionCompactionReason(event));
|
|
1117
1124
|
compactionObserver.onSessionBeforeCompact(event, ctx);
|
|
1118
1125
|
if (shouldNotify) {
|
|
1119
|
-
if (
|
|
1126
|
+
if (
|
|
1127
|
+
activeTurnRuntime.has() &&
|
|
1128
|
+
terminalAssistantMessagePendingDelivery
|
|
1129
|
+
) {
|
|
1120
1130
|
deferredAutomaticCompactionNotices.push(
|
|
1121
1131
|
Commands.TELEGRAM_COMPACTION_STARTED_MARKDOWN,
|
|
1122
1132
|
);
|
|
@@ -1135,10 +1145,7 @@ export function registerTelegramLifecycleRuntimeHooks({
|
|
|
1135
1145
|
compactionObserver.onSessionCompact(event, ctx);
|
|
1136
1146
|
if (observedAutomaticCompaction) {
|
|
1137
1147
|
observedAutomaticCompaction = false;
|
|
1138
|
-
if (
|
|
1139
|
-
activeTurnRuntime.has() ||
|
|
1140
|
-
deferredAutomaticCompactionNotices.length > 0
|
|
1141
|
-
) {
|
|
1148
|
+
if (deferredAutomaticCompactionNotices.length > 0) {
|
|
1142
1149
|
deferredAutomaticCompactionNotices.push(
|
|
1143
1150
|
Commands.TELEGRAM_COMPACTION_COMPLETED_MARKDOWN,
|
|
1144
1151
|
);
|
|
@@ -1149,8 +1156,28 @@ export function registerTelegramLifecycleRuntimeHooks({
|
|
|
1149
1156
|
}
|
|
1150
1157
|
}
|
|
1151
1158
|
},
|
|
1159
|
+
async onSessionCompactFailed(event, ctx) {
|
|
1160
|
+
if (!isSessionContextActive(ctx)) return;
|
|
1161
|
+
const shouldNotify = observedAutomaticCompaction;
|
|
1162
|
+
const deferredNotices = deferredAutomaticCompactionNotices.splice(0);
|
|
1163
|
+
const shouldDefer =
|
|
1164
|
+
deferredNotices.length > 0 ||
|
|
1165
|
+
(activeTurnRuntime.has() && terminalAssistantMessagePendingDelivery);
|
|
1166
|
+
compactionObserver.onSessionCompactFailed(event, ctx);
|
|
1167
|
+
if (!shouldNotify) return;
|
|
1168
|
+
const notice = event.aborted
|
|
1169
|
+
? "**⚠️ Compaction cancelled.**"
|
|
1170
|
+
: "**⚠️ Compaction failed.**";
|
|
1171
|
+
if (shouldDefer) {
|
|
1172
|
+
deferredAutomaticCompactionNotices.push(...deferredNotices, notice);
|
|
1173
|
+
} else {
|
|
1174
|
+
await sendCompactionNotice(notice);
|
|
1175
|
+
}
|
|
1176
|
+
},
|
|
1152
1177
|
async onAgentStart(event, ctx) {
|
|
1153
1178
|
if (!isSessionContextActive(ctx)) return;
|
|
1179
|
+
agentRunActive = true;
|
|
1180
|
+
terminalAssistantMessagePendingDelivery = false;
|
|
1154
1181
|
await agentStartWithDedupReset(event, ctx);
|
|
1155
1182
|
activityRuntime.onAgentStart(activeTurnRuntime.get()?.target);
|
|
1156
1183
|
startAgentActivityTypingLoop(ctx);
|
|
@@ -1195,8 +1222,31 @@ export function registerTelegramLifecycleRuntimeHooks({
|
|
|
1195
1222
|
}
|
|
1196
1223
|
await messageActivityHooks.onMessageUpdate(event, ctx);
|
|
1197
1224
|
},
|
|
1225
|
+
onMessageEnd(event, ctx) {
|
|
1226
|
+
if (!isSessionContextActive(ctx)) return;
|
|
1227
|
+
terminalAssistantMessagePendingDelivery =
|
|
1228
|
+
event.message.role === "assistant" &&
|
|
1229
|
+
event.message.stopReason !== "toolUse" &&
|
|
1230
|
+
event.message.stopReason !== "error" &&
|
|
1231
|
+
event.message.stopReason !== "aborted";
|
|
1232
|
+
},
|
|
1233
|
+
onUiPromptStart(event, ctx) {
|
|
1234
|
+
if (!isSessionContextActive(ctx)) return;
|
|
1235
|
+
uiPromptActive = true;
|
|
1236
|
+
typing.stop();
|
|
1237
|
+
activityRuntime.onUiPromptStart(event.kind, event.title);
|
|
1238
|
+
updateStatus(ctx);
|
|
1239
|
+
},
|
|
1240
|
+
onUiPromptEnd(_event, ctx) {
|
|
1241
|
+
if (!isSessionContextActive(ctx)) return;
|
|
1242
|
+
uiPromptActive = false;
|
|
1243
|
+
activityRuntime.onUiPromptEnd();
|
|
1244
|
+
if (agentRunActive) startAgentActivityTypingLoop(ctx);
|
|
1245
|
+
updateStatus(ctx);
|
|
1246
|
+
},
|
|
1198
1247
|
async onAgentEnd(event, ctx) {
|
|
1199
1248
|
if (!isSessionContextActive(ctx)) return;
|
|
1249
|
+
agentRunActive = false;
|
|
1200
1250
|
activityRuntime.onAgentEnd();
|
|
1201
1251
|
await agentLifecycleHooks.onAgentEnd(event, ctx);
|
|
1202
1252
|
if (deferredAutomaticCompactionNotices.length > 0) {
|
|
@@ -1204,6 +1254,7 @@ export function registerTelegramLifecycleRuntimeHooks({
|
|
|
1204
1254
|
if (!isSessionContextActive(ctx)) return;
|
|
1205
1255
|
await flushDeferredAutomaticCompactionNotices();
|
|
1206
1256
|
}
|
|
1257
|
+
terminalAssistantMessagePendingDelivery = false;
|
|
1207
1258
|
},
|
|
1208
1259
|
async onAgentSettled(event, ctx) {
|
|
1209
1260
|
if (!isSessionContextActive(ctx)) return;
|
|
@@ -19,7 +19,7 @@ import { getTelegramVoiceTranscriptionProviders } from "./voice.ts";
|
|
|
19
19
|
|
|
20
20
|
const DEFAULT_INBOUND_HANDLER_TIMEOUT_MS = 120_000;
|
|
21
21
|
const INBOUND_HANDLER_REGISTRY_KEY = "__piTelegramInboundHandlers__";
|
|
22
|
-
const MAX_INBOUND_HANDLER_OUTPUT_LENGTH =
|
|
22
|
+
const MAX_INBOUND_HANDLER_OUTPUT_LENGTH = 24_000;
|
|
23
23
|
const MAX_INBOUND_HANDLER_FAILURE_STREAM_LENGTH = 4_000;
|
|
24
24
|
|
|
25
25
|
type TelegramInboundCommandTemplateConfig =
|
|
@@ -16,13 +16,17 @@ import type {
|
|
|
16
16
|
ExtensionAPI,
|
|
17
17
|
ExtensionContext,
|
|
18
18
|
InputEvent,
|
|
19
|
+
MessageEndEvent,
|
|
19
20
|
SessionBeforeCompactEvent,
|
|
20
21
|
SessionCompactEvent,
|
|
22
|
+
SessionCompactFailedEvent,
|
|
21
23
|
SessionShutdownEvent,
|
|
22
24
|
SessionStartEvent,
|
|
23
25
|
ToolExecutionEndEvent,
|
|
24
26
|
ToolExecutionStartEvent,
|
|
25
27
|
ToolExecutionUpdateEvent,
|
|
28
|
+
UIPromptEndEvent,
|
|
29
|
+
UIPromptStartEvent,
|
|
26
30
|
} from "./pi.ts";
|
|
27
31
|
|
|
28
32
|
let resetTransportReplyDedupFn: (() => void) | undefined;
|
|
@@ -78,6 +82,10 @@ export interface TelegramLifecycleRegistrationDeps {
|
|
|
78
82
|
event: SessionCompactEvent,
|
|
79
83
|
ctx: ExtensionContext,
|
|
80
84
|
) => Promise<void> | void;
|
|
85
|
+
onSessionCompactFailed?: (
|
|
86
|
+
event: SessionCompactFailedEvent,
|
|
87
|
+
ctx: ExtensionContext,
|
|
88
|
+
) => Promise<void> | void;
|
|
81
89
|
onBeforeAgentStart: (
|
|
82
90
|
event: TelegramBeforeAgentStartEvent,
|
|
83
91
|
ctx: ExtensionContext,
|
|
@@ -113,6 +121,18 @@ export interface TelegramLifecycleRegistrationDeps {
|
|
|
113
121
|
},
|
|
114
122
|
ctx: ExtensionContext,
|
|
115
123
|
) => Promise<void>;
|
|
124
|
+
onMessageEnd?: (
|
|
125
|
+
event: MessageEndEvent,
|
|
126
|
+
ctx: ExtensionContext,
|
|
127
|
+
) => Promise<void> | void;
|
|
128
|
+
onUiPromptStart?: (
|
|
129
|
+
event: UIPromptStartEvent,
|
|
130
|
+
ctx: ExtensionContext,
|
|
131
|
+
) => Promise<void> | void;
|
|
132
|
+
onUiPromptEnd?: (
|
|
133
|
+
event: UIPromptEndEvent,
|
|
134
|
+
ctx: ExtensionContext,
|
|
135
|
+
) => Promise<void> | void;
|
|
116
136
|
onAgentEnd: (event: AgentEndEvent, ctx: ExtensionContext) => Promise<void>;
|
|
117
137
|
onAgentSettled?: (
|
|
118
138
|
event: AgentSettledEvent,
|
|
@@ -416,6 +436,10 @@ export interface TelegramCompactionObserverRuntime<TContext> {
|
|
|
416
436
|
ctx: TContext,
|
|
417
437
|
) => void;
|
|
418
438
|
onSessionCompact: (event: SessionCompactEvent, ctx: TContext) => void;
|
|
439
|
+
onSessionCompactFailed: (
|
|
440
|
+
event: SessionCompactFailedEvent,
|
|
441
|
+
ctx: TContext,
|
|
442
|
+
) => void;
|
|
419
443
|
onSessionShutdown: () => void;
|
|
420
444
|
}
|
|
421
445
|
|
|
@@ -471,6 +495,16 @@ export function createTelegramCompactionObserverRuntime<TContext>(
|
|
|
471
495
|
deps.updateStatus(ctx);
|
|
472
496
|
requestDispatch();
|
|
473
497
|
},
|
|
498
|
+
onSessionCompactFailed: (_event, ctx) => {
|
|
499
|
+
clearFallbackTimer();
|
|
500
|
+
if (deps.isContextActive && !deps.isContextActive(ctx)) return;
|
|
501
|
+
deps.setCompactionInProgress(false);
|
|
502
|
+
if (typingStartedByObserver) deps.stopTypingLoop?.();
|
|
503
|
+
typingStartedByObserver = false;
|
|
504
|
+
deps.updateStatus(ctx);
|
|
505
|
+
deps.onCompactionAbandoned?.();
|
|
506
|
+
requestDispatch();
|
|
507
|
+
},
|
|
474
508
|
onSessionShutdown: () => {
|
|
475
509
|
clearFallbackTimer();
|
|
476
510
|
if (typingStartedByObserver) deps.stopTypingLoop?.();
|
|
@@ -590,6 +624,10 @@ export function registerTelegramLifecycleHooks(
|
|
|
590
624
|
if (!isActive(ctx)) return;
|
|
591
625
|
await deps.onSessionCompact?.(event, ctx);
|
|
592
626
|
});
|
|
627
|
+
pi.on("session_compact_failed", async (event, ctx) => {
|
|
628
|
+
if (!isActive(ctx)) return;
|
|
629
|
+
await deps.onSessionCompactFailed?.(event, ctx);
|
|
630
|
+
});
|
|
593
631
|
// The Pi SDK still types this result as a string; compatible runtimes may
|
|
594
632
|
// preserve ordered system prompt blocks through the same public hook.
|
|
595
633
|
const registerBeforeAgentStart = pi.on.bind(pi) as unknown as (
|
|
@@ -630,6 +668,18 @@ export function registerTelegramLifecycleHooks(
|
|
|
630
668
|
if (!isActive(ctx)) return;
|
|
631
669
|
await deps.onMessageUpdate(event, ctx);
|
|
632
670
|
});
|
|
671
|
+
pi.on("message_end", async (event, ctx) => {
|
|
672
|
+
if (!isActive(ctx)) return;
|
|
673
|
+
await deps.onMessageEnd?.(event, ctx);
|
|
674
|
+
});
|
|
675
|
+
pi.on("ui_prompt_start", async (event, ctx) => {
|
|
676
|
+
if (!isActive(ctx)) return;
|
|
677
|
+
await deps.onUiPromptStart?.(event, ctx);
|
|
678
|
+
});
|
|
679
|
+
pi.on("ui_prompt_end", async (event, ctx) => {
|
|
680
|
+
if (!isActive(ctx)) return;
|
|
681
|
+
await deps.onUiPromptEnd?.(event, ctx);
|
|
682
|
+
});
|
|
633
683
|
pi.on("agent_end", async (event, ctx) => {
|
|
634
684
|
if (!isActive(ctx)) return;
|
|
635
685
|
await deps.onAgentEnd(event, ctx);
|
|
@@ -14,11 +14,14 @@ import {
|
|
|
14
14
|
type ExtensionCommandContext,
|
|
15
15
|
type ExtensionContext,
|
|
16
16
|
type InputEvent,
|
|
17
|
+
type MessageEndEvent,
|
|
17
18
|
type SessionBeforeCompactEvent,
|
|
18
19
|
type SessionCompactEvent,
|
|
19
20
|
type SessionShutdownEvent,
|
|
20
21
|
type SessionStartEvent,
|
|
21
22
|
type SlashCommandInfo,
|
|
23
|
+
type UIPromptEndEvent,
|
|
24
|
+
type UIPromptStartEvent,
|
|
22
25
|
SettingsManager,
|
|
23
26
|
} from "@earendil-works/pi-coding-agent";
|
|
24
27
|
|
|
@@ -32,13 +35,25 @@ export type {
|
|
|
32
35
|
ExtensionCommandContext,
|
|
33
36
|
ExtensionContext,
|
|
34
37
|
InputEvent,
|
|
38
|
+
MessageEndEvent,
|
|
35
39
|
SessionBeforeCompactEvent,
|
|
36
40
|
SessionCompactEvent,
|
|
37
41
|
SessionShutdownEvent,
|
|
38
42
|
SessionStartEvent,
|
|
39
43
|
SlashCommandInfo,
|
|
44
|
+
UIPromptEndEvent,
|
|
45
|
+
UIPromptStartEvent,
|
|
40
46
|
};
|
|
41
47
|
|
|
48
|
+
export interface SessionCompactFailedEvent {
|
|
49
|
+
type: "session_compact_failed";
|
|
50
|
+
reason: "manual" | "threshold" | "overflow";
|
|
51
|
+
errorMessage?: string;
|
|
52
|
+
aborted: boolean;
|
|
53
|
+
willRetry: boolean;
|
|
54
|
+
fromExtension: boolean;
|
|
55
|
+
}
|
|
56
|
+
|
|
42
57
|
export interface ToolExecutionStartEvent {
|
|
43
58
|
type: "tool_execution_start";
|
|
44
59
|
toolCallId: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@llblab/pi-telegram",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.40.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -71,9 +71,9 @@
|
|
|
71
71
|
"image": "https://raw.githubusercontent.com/llblab/pi-telegram/main/screenshot.png"
|
|
72
72
|
},
|
|
73
73
|
"peerDependencies": {
|
|
74
|
-
"@earendil-works/pi-agent-core": ">=0.
|
|
75
|
-
"@earendil-works/pi-ai": ">=0.
|
|
76
|
-
"@earendil-works/pi-coding-agent": ">=0.
|
|
74
|
+
"@earendil-works/pi-agent-core": ">=0.84.4",
|
|
75
|
+
"@earendil-works/pi-ai": ">=0.84.4",
|
|
76
|
+
"@earendil-works/pi-coding-agent": ">=0.84.4",
|
|
77
77
|
"@sinclair/typebox": "*"
|
|
78
78
|
},
|
|
79
79
|
"devDependencies": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@llblab/pi-kit",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.13",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"@llblab/pi-actors": "0.50.0",
|
|
44
44
|
"@llblab/pi-codex-usage": "0.9.4",
|
|
45
45
|
"@llblab/pi-grow-loop": "0.7.3",
|
|
46
|
-
"@llblab/pi-telegram": "0.
|
|
46
|
+
"@llblab/pi-telegram": "0.40.0"
|
|
47
47
|
},
|
|
48
48
|
"bundledDependencies": [
|
|
49
49
|
"@llblab/pi-actors",
|