Skip to content

Commit f9aa1a8

Browse files
authored
Merge pull request #2 from llblab/dev
0.4.0: singleton locks & attachment handlers
2 parents 8f7135e + c26621b commit f9aa1a8

33 files changed

Lines changed: 2404 additions & 456 deletions

.agents/skills/evolve-context/scripts/_bootstrap

Lines changed: 0 additions & 41 deletions
This file was deleted.

.agents/skills/evolve-context/scripts/_self-test

Lines changed: 0 additions & 172 deletions
This file was deleted.

AGENTS.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
- Queued items have explicit kinds and lanes so prompt turns and synthetic control actions can share one ordering model
5959
- Keep queue admission contract explicit and validated: immediate commands execute without entering the queue, control commands enter the `control` lane, normal prompts enter the `default` lane, reaction-promoted prompts enter the `priority` lane, and queue append/planning paths should reject invalid kind/lane pairings predictably
6060
- Dispatch must still respect active turns, pending prompt dispatch, unsettled control-item execution, compaction, and pi pending-message state
61+
- Long-lived timers, pollers, and ownership watchers must not depend on live pi context objects after session replacement. Snapshot primitive identity such as `cwd` when installing a watcher, stop local timers during session shutdown, and catch stale-context status updates during async cleanup.
6162
- Prompt items should remain in the queue until `agent_start` consumes the dispatched turn; removing them earlier breaks active-turn binding, preview delivery, and end-of-turn follow-up behavior
6263
- In-flight `/model` switching is supported only for Telegram-owned active turns and is implemented as set-model plus synthetic continuation turn plus abort
6364
- If a tool call is active during in-flight `/model` switching, the abort is delayed until that tool finishes instead of interrupting the tool mid-flight
@@ -92,12 +93,12 @@
9293
## 6.3 Current Domain Ownership Snapshot
9394

9495
- Queue owns scheduling/lifecycle semantics: lane contracts, queue and active-turn stores, mutations, dispatch readiness/runtime, control/prompt enqueueing, session state appliers, and agent/tool lifecycle hooks; model owns model identity/thinking-level contracts, scoped resolution and CLI pattern parsing, current-model state/runtime helpers, in-flight switch state, restart eligibility, delayed abort decisions, Telegram-prefix-defaulted continuation prompt construction/queueing, and controller runtime binding over queue turns
95-
- Runtime owns session-local primitives and timers; pi owns direct SDK imports and bound extension API ports; config owns persisted bot/session pairing state, single-user authorization, and first-user pairing side effects; API owns Bot API transport shapes/helpers, temp-dir/inbound-limit/runtime-error helpers, and runtime-bound chat actions
96+
- Runtime owns session-local primitives and timers; locks owns shared `locks.json` singleton ownership, interactive takeover, stale same-`cwd` restart resume, session-replacement suspension, and ownership-drift shutdown; pi owns direct SDK imports and bound extension API ports; config owns persisted bot/session pairing state, single-user authorization, first-user pairing side effects, and inbound attachment handler config; API owns Bot API transport shapes/helpers, temp-dir/inbound-limit/runtime-error helpers, and runtime-bound chat actions
9697
- Preview owns streaming preview lifecycle and transports, defaulting reply metadata through the replies-domain helper when callers do not override it; replies owns final rendered-message delivery and reply parameters; rendering owns Telegram HTML Markdown/block/chunk/preview-snapshot formatting
97-
- Polling owns long-poll controller state/activity/loop wiring; updates owns callback/message/edit/reaction routing and queue/media/menu update adapters; registration owns pi tool/command/lifecycle-hook binding
98+
- Polling owns long-poll controller state/activity/loop wiring; updates owns callback/message/edit/reaction classification/execution; routing owns inbound update composition across menus, commands, media grouping, prompt queueing, edits, and paired authorization; handlers owns inbound attachment handler matching, command/tool invocation, prompt-text injection, and fallback behavior; registration owns pi tool/command/lifecycle-hook binding
9899
- Commands own slash-command parsing, execution-mode contracts, command target/control queue adapters, bot-command metadata/registration, and stop/compact/status/model/help side effects
99100
- Menu owns inline menu state/cache/building, callback/action runtimes, status/thinking/model UI support, and selection planning; status owns bridge status rendering, grouped pi-side diagnostic lines, and recent-event state
100-
- Turns own Telegram prompt turn-building/editing and prompt-prefix identity; media owns inbound text/file/media-group extraction and download assembly; attachments own outbound file queueing, narrow structural attachment turn targets, stat checks, limits, and delivery classification; setup owns token prompt, env fallback, and validation flow
101+
- Turns own Telegram prompt turn-building/editing, prompt-prefix identity, and attachment-handler output handoff into prompt content; media owns inbound text/file/media-group extraction and download assembly; attachments own outbound file queueing, narrow structural attachment turn targets, stat checks, limits, and delivery classification; setup owns token prompt, env fallback, and validation flow
101102

102103
## 6.4 Entrypoint And Import Boundaries
103104

@@ -124,7 +125,7 @@
124125
- `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()`
125126
- 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
126127
- Status/model/thinking controls are driven through Telegram inline keyboards and callback queries
127-
- Inbound files may become pi image inputs; outbound files must flow through `telegram_attach`
128+
- Inbound files may become pi image inputs or configured attachment-handler text before queueing; outbound files must flow through `telegram_attach`
128129

129130
## 9. Pre-Task Preparation Protocol
130131

BACKLOG.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
# Project Backlog
22

3-
## Open Backlog
3+
## Active Backlog
44

5-
No open implementation, validation, or documentation items are scheduled right now.
6-
7-
Completed delivery is recorded in [CHANGELOG.md](./CHANGELOG.md). Durable domain boundaries are documented in [AGENTS.md](./AGENTS.md) and [docs/architecture.md](./docs/architecture.md).
5+
_No active backlog items._
86

97
## Reopen Triggers
108

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## 0.4.0: Singleton Locks & Attachment Handlers
4+
5+
- `[Locks]` Added the shared `locks.json` singleton ownership standard and documented it in `docs/locks.md`. Telegram polling ownership now lives under `@llblab/pi-telegram` in `~/.pi/agent/locks.json`, while `telegram.json` remains pure bot/user configuration. `/telegram-connect` acquires the lock, replaces stale locks, or moves live external owners here through an interactive confirmation; `/telegram-disconnect` releases it. Session initialization reads ownership state, active owners stop local polling when `locks.json` no longer points at their own `pid`/`cwd`, session replacement via `/new` suspends polling/watchers without touching explicit ownership before resuming in the new session, and a reopened pi process resumes a stale same-`cwd` lock automatically. Impact: runtime locks can be reset or moved without deleting Telegram configuration, finding the previous pi instance, or crashing on stale extension contexts.
6+
- `[Attachment Handlers]` Added `telegram.json` inbound attachment handlers with MIME/type matching, safe command placeholder substitution, local tool invocation, compact `[attachments] <directory>` plus `[outputs]` prompt sections, and quiet omission of empty or failed handler output. Impact: common flows such as Telegram voice transcription can happen before the agent sees the turn while keeping source attachment paths visible.
7+
- `[Refactor]` Extracted inbound route composition from `index.ts` into `/lib/routing.ts`, keeping paired update execution, callback menus, command-or-prompt dispatch, media grouping, prompt enqueueing, queued edits, and attachment-handler turn building behind one cohesive route wiring boundary. Impact: the entrypoint stays smaller while high-risk Telegram update flow remains covered by runtime and invariant tests.
8+
39
## 0.3.0: Modular Runtime, Queue Controls, Diagnostics
410

511
### Runtime Architecture

0 commit comments

Comments
 (0)