@llblab/pi-kit 0.34.2 → 0.34.3
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/BACKLOG.md +1 -0
- package/CHANGELOG.md +4 -0
- package/README.md +1 -1
- package/node_modules/@llblab/pi-telegram/CHANGELOG.md +5 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/bindings.js +2 -1
- package/node_modules/@llblab/pi-telegram/dist/lib/runtime.d.ts +2 -0
- package/node_modules/@llblab/pi-telegram/dist/lib/runtime.js +19 -1
- package/node_modules/@llblab/pi-telegram/dist/package.json +1 -1
- package/node_modules/@llblab/pi-telegram/docs/architecture.md +1 -1
- package/node_modules/@llblab/pi-telegram/lib/bindings.ts +2 -1
- package/node_modules/@llblab/pi-telegram/lib/runtime.ts +25 -3
- package/node_modules/@llblab/pi-telegram/package.json +1 -1
- package/package.json +2 -2
package/BACKLOG.md
CHANGED
|
@@ -4,6 +4,7 @@ Package pins, resource order and bundled runtime ownership remain authoritative
|
|
|
4
4
|
|
|
5
5
|
## Carried checks
|
|
6
6
|
|
|
7
|
+
- **Installed 0.34.3 typing smoke (operator-owned):** After separately authorized installation/reload of both peers, verify native typing during streaming, UI prompts and compaction without recurring local authorization churn. Check actual client versions, including iOS; successful HTTP issuance and synthetic tests do not prove client visibility. Use disposable sessions and preserve accepted work.
|
|
7
8
|
- **Installed 0.34.2 smoke (operator-owned):** After separately authorized installation/reload, verify Pi 1.2 custom-message completions no longer raise the Telegram prompt-hook error, adjacent button matrices retain their rows and callbacks, and native Windows Codex CLI fallback works on an actual Windows host. Use disposable settings; package validation and synthetic SDK probes do not certify installed clients or authorize live fault injection.
|
|
8
9
|
- **Installed 0.34.0 Telegram smoke (operator-owned):** After separately authorized installation/reload of both peers, verify per-prompt Steer, canonical thumbs-up/thumbs-down/fire controls with other reactions ignored, reconnection after a deleted tab, follower `/start` Restore and first-click leader Restore confirmation with separately proven old-tab cleanup. Unknown creation can leave an extra tab; do not erase accepted work or replay uncertain input. Package/CI validation does not certify live clients.
|
|
9
10
|
- **Installed 0.31.0 Telegram smoke (operator-owned):** After separately authorized installation/reload of every Pi process together (bus protocol v3), confirm an idle leader makes no periodic `state.json` or `telegram.json.transaction` writes, a frozen leader is replaced by its follower, and switching Threaded Mode off takes followers offline. Packed validation does not certify running clients.
|
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.34.3: Telegram Typing Continuity
|
|
6
|
+
|
|
7
|
+
- `Telegram typing`: Advances only the exact Telegram pin to `0.56.4`. Streaming keepalives preserve the same owner's in-flight typing request, while session, transport and target changes still revoke old authority. Compaction cannot claim an existing agent loop. Other pins, package membership and resource order are unchanged; client-specific typing visibility remains a live check.
|
|
8
|
+
|
|
5
9
|
## 0.34.2: Telegram Compatibility and Windows Usage Updates
|
|
6
10
|
|
|
7
11
|
- `Telegram`: Advances the exact pin to `0.56.3`, adding adjacent button matrices with preserved row grouping and fixing Pi 1.2 custom-message starts without a user prompt. Legacy prompt events and voice syntax remain supported; no client-rendering fallback is added.
|
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ Package links lead to the owning repositories for usage, documentation, issues,
|
|
|
18
18
|
| [`@llblab/pi-codex-usage`](https://github.com/llblab/pi-codex-usage) | `0.13.1` | OpenAI/legacy Codex subscription quota and Business credit status, with persistent priority Fast toggle mirrored in Telegram |
|
|
19
19
|
| [`@llblab/pi-grow-loop`](https://github.com/llblab/pi-grow-loop) | `0.9.0` | Visible continuation scheduling and bounded worker Skills through compiled, manifest-owned resources |
|
|
20
20
|
| [`@llblab/pi-state-flow`](https://github.com/llblab/pi-state-flow) | `0.26.4` | Scoped context/memory compiler with step-independent current memory, stable Passive/Active modes and visible blocked-state status |
|
|
21
|
-
| [`@llblab/pi-telegram`](https://github.com/llblab/pi-telegram) | `0.56.
|
|
21
|
+
| [`@llblab/pi-telegram`](https://github.com/llblab/pi-telegram) | `0.56.4` | Telegram companion with per-prompt Steer, queued controls, Reroute/Restore, recoverable connections, previews, follower Threads, files, and voice |
|
|
22
22
|
| [`@llblab/skills`](https://github.com/llblab/skills) | `1.15.0` | Portable workflows for engineering, review, design, context maintenance, and other focused tasks |
|
|
23
23
|
|
|
24
24
|
Versions are exact by design. An upstream release does not change an installed kit until this repository explicitly advances the dependency and publishes a new kit version. Runtime defects and package-specific feature requests belong in the linked repository; package selection and kit installation issues belong here.
|
|
@@ -4,6 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 0.56.4: Typing Keepalive Continuity
|
|
8
|
+
|
|
9
|
+
- `Typing continuity`: Streaming updates keep the current work's pending presence request alive instead of cancelling it through repeated loop replacement. Explicit starts, session or transport changes, Thread changes and stopping still revoke the previous action; compaction cannot claim an existing agent loop.
|
|
10
|
+
- `Windows validation`: Grouped Restore fixtures control album debounce after both originals are admitted and await chooser publication, so slow filesystem work cannot accidentally split their input group. Exact source, receipt and readiness assertions remain intact; production debounce and routing behavior are unchanged.
|
|
11
|
+
|
|
7
12
|
## 0.56.3: Button Matrices and Custom-Message Starts
|
|
8
13
|
|
|
9
14
|
- `Button grammar`: Adjacent complete JSON/CML cells and matrices now compose one button surface in source order instead of dropping fenced controls or truncating footer controls. Each matrix contributes its existing rows; horizontal grouping, disabled controls and callback semantics remain unchanged. Invalid fenced groups register no callbacks. This extends button syntax only; rendering mode and voice syntax are unchanged.
|
|
@@ -847,7 +847,7 @@ export function registerTelegramLifecycleRuntimeHooks({ pi, publicationRuntime,
|
|
|
847
847
|
return false;
|
|
848
848
|
const turn = activeTurnRuntime.get();
|
|
849
849
|
const target = turn?.target ?? proactivePushTargetGetter();
|
|
850
|
-
return (promptDispatchRuntime.startTypingLoop(ctx, turn?.chatId ?? target?.chatId, { target }) !== false);
|
|
850
|
+
return (promptDispatchRuntime.startTypingLoop(ctx, turn?.chatId ?? target?.chatId, { target, ensure: true }) !== false);
|
|
851
851
|
};
|
|
852
852
|
const startActiveTurnTypingLoop = (ctx) => {
|
|
853
853
|
if (uiPromptActive)
|
|
@@ -855,6 +855,7 @@ export function registerTelegramLifecycleRuntimeHooks({ pi, publicationRuntime,
|
|
|
855
855
|
const turn = activeTurnRuntime.get();
|
|
856
856
|
promptDispatchRuntime.startTypingLoop(ctx, turn?.chatId, {
|
|
857
857
|
target: turn?.target,
|
|
858
|
+
ensure: true,
|
|
858
859
|
});
|
|
859
860
|
};
|
|
860
861
|
let observedAutomaticCompaction = false;
|
|
@@ -119,6 +119,7 @@ export interface TelegramTypingLoopStarterDeps<TContext> extends TelegramRuntime
|
|
|
119
119
|
}
|
|
120
120
|
export declare function createTelegramTypingLoopStarter<TContext>(deps: TelegramTypingLoopStarterDeps<TContext>): (ctx: TContext, chatId?: number, options?: {
|
|
121
121
|
target?: TelegramTypingLoopTarget;
|
|
122
|
+
ensure?: boolean;
|
|
122
123
|
}) => boolean;
|
|
123
124
|
/** The whole typing-loop state; only `transitionTelegramTypingLoop` produces a new one. */
|
|
124
125
|
export interface TelegramTypingMachineState {
|
|
@@ -214,6 +215,7 @@ export interface TelegramPromptDispatchRuntimeDeps<TContext> extends TelegramTyp
|
|
|
214
215
|
export interface TelegramPromptDispatchRuntime<TContext> {
|
|
215
216
|
startTypingLoop: (ctx: TContext, chatId?: number, options?: {
|
|
216
217
|
target?: TelegramTypingLoopTarget;
|
|
218
|
+
ensure?: boolean;
|
|
217
219
|
}) => boolean | void;
|
|
218
220
|
onPromptDispatchStart: (ctx: TContext, chatId?: number, target?: TelegramTypingLoopTarget) => void;
|
|
219
221
|
onPromptDispatchFailure: (ctx: TContext, message: string) => void;
|
|
@@ -161,6 +161,7 @@ function updateTelegramRuntimeStatusSafely(updateStatus, ctx, options) {
|
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
163
|
export function createTelegramTypingLoopStarter(deps) {
|
|
164
|
+
let currentOwner;
|
|
164
165
|
return (ctx, chatId, options) => {
|
|
165
166
|
const sessionGeneration = deps.getSessionGeneration?.();
|
|
166
167
|
const transportAuthority = deps.getTransportAuthority?.();
|
|
@@ -177,9 +178,24 @@ export function createTelegramTypingLoopStarter(deps) {
|
|
|
177
178
|
// Queue dispatch precedes agent_start: only an explicit destination permits Threaded presence, never chat fallback.
|
|
178
179
|
if (!canContinue())
|
|
179
180
|
return false;
|
|
181
|
+
const resolvedChatId = chatId ?? deps.getDefaultChatId();
|
|
182
|
+
if (resolvedChatId === undefined || resolvedChatId === 0)
|
|
183
|
+
return false;
|
|
184
|
+
// Streaming updates ensure presence without revoking the same owner's pending HTTP/IPC action.
|
|
185
|
+
// Explicit starts still replace the loop, including a new turn on the same session and Thread.
|
|
186
|
+
if (options?.ensure && currentOwner?.canContinue() &&
|
|
187
|
+
(deps.getSessionGeneration
|
|
188
|
+
? Object.is(currentOwner.sessionGeneration, sessionGeneration)
|
|
189
|
+
: Object.is(currentOwner.ctx, ctx)) &&
|
|
190
|
+
Object.is(currentOwner.transportAuthority, transportAuthority) &&
|
|
191
|
+
currentOwner.chatId === resolvedChatId && currentOwner.threadId === target?.threadId)
|
|
192
|
+
return false;
|
|
193
|
+
const owner = { ctx, sessionGeneration, transportAuthority, chatId: resolvedChatId,
|
|
194
|
+
threadId: target?.threadId, canContinue };
|
|
195
|
+
currentOwner = owner;
|
|
180
196
|
let active = true;
|
|
181
197
|
return deps.typing.start({
|
|
182
|
-
chatId:
|
|
198
|
+
chatId: resolvedChatId,
|
|
183
199
|
target,
|
|
184
200
|
intervalMs: deps.intervalMs ?? TELEGRAM_TYPING_ACTION_INTERVAL_MS,
|
|
185
201
|
sendTypingAction: async (targetChatId, actionOptions) => {
|
|
@@ -219,6 +235,8 @@ export function createTelegramTypingLoopStarter(deps) {
|
|
|
219
235
|
shouldContinue: canContinue,
|
|
220
236
|
onStopped: () => {
|
|
221
237
|
active = false;
|
|
238
|
+
if (currentOwner === owner)
|
|
239
|
+
currentOwner = undefined;
|
|
222
240
|
},
|
|
223
241
|
});
|
|
224
242
|
};
|
|
@@ -681,7 +681,7 @@ Native typing during compaction follows connected-instance activity rather than
|
|
|
681
681
|
- Thread-targeted typing is sent only to the concrete thread. Aggregate `All` mirroring is intentionally omitted because duplicating every keepalive multiplies shared-chat flood pressure. Compaction completion, failure, or timeout stops only a loop actually started by the compaction observer; a pre-existing agent-owned loop remains active. Ownership is sticky across a repeated compaction start, whose shared-loop start reports `false` for the observer's own running loop. Authority loss and shutdown still stop the keyed loop.
|
|
682
682
|
- Pi `ui_prompt_start` pauses typing while an extension-owned local prompt waits for the operator; `ui_prompt_end` emits the matching Activity boundary and resumes typing whenever agent or compaction work remains unsettled.
|
|
683
683
|
|
|
684
|
-
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. Queue dispatch carries the queued turn's exact target into typing before `agent_start`, rather than reducing it to a chat ID. In Threaded Mode, missing or invalid Thread targets are refused before starting a loop or invoking the API; mode changes also invalidate a captured Classic chat-only loop. A rejected start never replaces an existing valid Thread loop. The starter also requires the captured Pi context and session generation to remain current at start, queued send, tick and late failure boundaries, even if the transport epoch is unchanged; replacing a context object in place cannot revive old activity. Message activity hooks capture generation across awaited preview work, and agent-start bindings recheck it before post-await activity/typing, so an obsolete finally or continuation cannot acquire replacement ownership. The typing sender carries its captured loop/context/generation/transport assertion as process-local call authority: direct API issuance rechecks it after queued work, and the follower caller rechecks it after registration waits and immediately before socket issuance without putting callbacks in IPC data. Automatic typing uses one HTTP attempt with no transport-family fallback or delayed replay, including forwarded calls; a future keepalive is a fresh owner-checked attempt. An already issued HTTP/RPC cannot be retroactively unsent. Each loop refreshes its exact target every three seconds and keeps one action in flight. The leader API runtime coalesces identical chat/thread/action calls for two seconds, permits at most one concurrent chat action per chat, and shares a Telegram 429 `retry_after` fence across every Thread key in that chat; expired gates prune opportunistically and each gate family retains at most 256 active keys. Suppression never schedules a delayed retry. A failed typing action remains a structured diagnostic but cannot project `error` onto an otherwise healthy connected/leader/follower status. Assistant message start/update hooks still re-arm typing during Telegram-owned turns so transient provider/model errors do not leave a continuing run without activity feedback, and agent/session completion stops it.
|
|
684
|
+
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. Streaming keepalives reuse a valid typing owner with the same session generation, transport and target rather than revoking its pending HTTP/IPC action. Fresh context wrappers may reuse that owner within a proven generation; without generation evidence, context identity must match. Explicit queue dispatch and Telegram prompt handoff still replace the owner. Queue dispatch carries the queued turn's exact target into typing before `agent_start`, rather than reducing it to a chat ID. In Threaded Mode, missing or invalid Thread targets are refused before starting a loop or invoking the API; mode changes also invalidate a captured Classic chat-only loop. A rejected start never replaces an existing valid Thread loop. The starter also requires the captured Pi context and session generation to remain current at start, queued send, tick and late failure boundaries, even if the transport epoch is unchanged; replacing a context object in place cannot revive old activity. Message activity hooks capture generation across awaited preview work, and agent-start bindings recheck it before post-await activity/typing, so an obsolete finally or continuation cannot acquire replacement ownership. The typing sender carries its captured loop/context/generation/transport assertion as process-local call authority: direct API issuance rechecks it after queued work, and the follower caller rechecks it after registration waits and immediately before socket issuance without putting callbacks in IPC data. Automatic typing uses one HTTP attempt with no transport-family fallback or delayed replay, including forwarded calls; a future keepalive is a fresh owner-checked attempt. An already issued HTTP/RPC cannot be retroactively unsent. Each loop refreshes its exact target every three seconds and keeps one action in flight. The leader API runtime coalesces identical chat/thread/action calls for two seconds, permits at most one concurrent chat action per chat, and shares a Telegram 429 `retry_after` fence across every Thread key in that chat; expired gates prune opportunistically and each gate family retains at most 256 active keys. Suppression never schedules a delayed retry. A failed typing action remains a structured diagnostic but cannot project `error` onto an otherwise healthy connected/leader/follower status. Assistant message start/update hooks still re-arm typing during Telegram-owned turns so transient provider/model errors do not leave a continuing run without activity feedback, and agent/session completion stops it.
|
|
685
685
|
|
|
686
686
|
### Rendering And Delivery
|
|
687
687
|
|
|
@@ -1538,7 +1538,7 @@ export function registerTelegramLifecycleRuntimeHooks({
|
|
|
1538
1538
|
promptDispatchRuntime.startTypingLoop(
|
|
1539
1539
|
ctx,
|
|
1540
1540
|
turn?.chatId ?? target?.chatId,
|
|
1541
|
-
{ target },
|
|
1541
|
+
{ target, ensure: true },
|
|
1542
1542
|
) !== false
|
|
1543
1543
|
);
|
|
1544
1544
|
};
|
|
@@ -1547,6 +1547,7 @@ export function registerTelegramLifecycleRuntimeHooks({
|
|
|
1547
1547
|
const turn = activeTurnRuntime.get();
|
|
1548
1548
|
promptDispatchRuntime.startTypingLoop(ctx, turn?.chatId, {
|
|
1549
1549
|
target: turn?.target,
|
|
1550
|
+
ensure: true,
|
|
1550
1551
|
});
|
|
1551
1552
|
};
|
|
1552
1553
|
let observedAutomaticCompaction = false;
|
|
@@ -364,8 +364,16 @@ export function createTelegramTypingLoopStarter<TContext>(
|
|
|
364
364
|
): (
|
|
365
365
|
ctx: TContext,
|
|
366
366
|
chatId?: number,
|
|
367
|
-
options?: { target?: TelegramTypingLoopTarget },
|
|
367
|
+
options?: { target?: TelegramTypingLoopTarget; ensure?: boolean },
|
|
368
368
|
) => boolean {
|
|
369
|
+
let currentOwner: {
|
|
370
|
+
ctx: TContext;
|
|
371
|
+
sessionGeneration: number | undefined;
|
|
372
|
+
transportAuthority: string | number | undefined;
|
|
373
|
+
chatId: number;
|
|
374
|
+
threadId: number | undefined;
|
|
375
|
+
canContinue: () => boolean;
|
|
376
|
+
} | undefined;
|
|
369
377
|
return (ctx, chatId, options) => {
|
|
370
378
|
const sessionGeneration = deps.getSessionGeneration?.();
|
|
371
379
|
const transportAuthority = deps.getTransportAuthority?.();
|
|
@@ -382,9 +390,22 @@ export function createTelegramTypingLoopStarter<TContext>(
|
|
|
382
390
|
(target?.threadId !== undefined && Number.isSafeInteger(target.threadId) && target.threadId > 0));
|
|
383
391
|
// Queue dispatch precedes agent_start: only an explicit destination permits Threaded presence, never chat fallback.
|
|
384
392
|
if (!canContinue()) return false;
|
|
393
|
+
const resolvedChatId = chatId ?? deps.getDefaultChatId();
|
|
394
|
+
if (resolvedChatId === undefined || resolvedChatId === 0) return false;
|
|
395
|
+
// Streaming updates ensure presence without revoking the same owner's pending HTTP/IPC action.
|
|
396
|
+
// Explicit starts still replace the loop, including a new turn on the same session and Thread.
|
|
397
|
+
if (options?.ensure && currentOwner?.canContinue() &&
|
|
398
|
+
(deps.getSessionGeneration
|
|
399
|
+
? Object.is(currentOwner.sessionGeneration, sessionGeneration)
|
|
400
|
+
: Object.is(currentOwner.ctx, ctx)) &&
|
|
401
|
+
Object.is(currentOwner.transportAuthority, transportAuthority) &&
|
|
402
|
+
currentOwner.chatId === resolvedChatId && currentOwner.threadId === target?.threadId) return false;
|
|
403
|
+
const owner = { ctx, sessionGeneration, transportAuthority, chatId: resolvedChatId,
|
|
404
|
+
threadId: target?.threadId, canContinue };
|
|
405
|
+
currentOwner = owner;
|
|
385
406
|
let active = true;
|
|
386
407
|
return deps.typing.start({
|
|
387
|
-
chatId:
|
|
408
|
+
chatId: resolvedChatId,
|
|
388
409
|
target,
|
|
389
410
|
intervalMs: deps.intervalMs ?? TELEGRAM_TYPING_ACTION_INTERVAL_MS,
|
|
390
411
|
sendTypingAction: async (targetChatId, actionOptions) => {
|
|
@@ -419,6 +440,7 @@ export function createTelegramTypingLoopStarter<TContext>(
|
|
|
419
440
|
shouldContinue: canContinue,
|
|
420
441
|
onStopped: () => {
|
|
421
442
|
active = false;
|
|
443
|
+
if (currentOwner === owner) currentOwner = undefined;
|
|
422
444
|
},
|
|
423
445
|
});
|
|
424
446
|
};
|
|
@@ -722,7 +744,7 @@ export interface TelegramPromptDispatchRuntime<TContext> {
|
|
|
722
744
|
startTypingLoop: (
|
|
723
745
|
ctx: TContext,
|
|
724
746
|
chatId?: number,
|
|
725
|
-
options?: { target?: TelegramTypingLoopTarget },
|
|
747
|
+
options?: { target?: TelegramTypingLoopTarget; ensure?: boolean },
|
|
726
748
|
) => boolean | void;
|
|
727
749
|
onPromptDispatchStart: (ctx: TContext, chatId?: number, target?: TelegramTypingLoopTarget) => void;
|
|
728
750
|
onPromptDispatchFailure: (ctx: TContext, message: string) => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@llblab/pi-kit",
|
|
3
|
-
"version": "0.34.
|
|
3
|
+
"version": "0.34.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"@llblab/pi-codex-usage": "0.13.1",
|
|
48
48
|
"@llblab/pi-grow-loop": "0.9.0",
|
|
49
49
|
"@llblab/pi-state-flow": "0.26.4",
|
|
50
|
-
"@llblab/pi-telegram": "0.56.
|
|
50
|
+
"@llblab/pi-telegram": "0.56.4",
|
|
51
51
|
"@llblab/skills": "1.15.0"
|
|
52
52
|
},
|
|
53
53
|
"bundledDependencies": [
|