live: heartbeat sync 2026-10-30T21:32:40-07:00 (Refs #11)
This commit is contained in:
1 parent
d03fe57bbd
commit
d627368f71
13 files changed
+280
-26
No files matched your search
@@ -0,0 +1,70 @@
|
||||
---
|
||||
name: omp-session-journal-cursor-access
|
||||
description: "Read a live omp session's transcript mid-run from an extension (cursor = journal entry id via ctx.sessionManager), with the entry-type noise list, append lag, and the ctx.setInterval metronome."
|
||||
---
|
||||
|
||||
# Reading the live session journal from an extension
|
||||
|
||||
Use when an extension must summarise/narrate/index **everything said since some point**
|
||||
rather than reacting to one event payload, or when you need a durable "where I left off"
|
||||
pointer into a session. Verified 2026-10-30 with a throwaway probe under `omp -p`
|
||||
(v18.12.5), 1 s ticks over a two-tool-round run.
|
||||
|
||||
## The accessor (no plugin install needed)
|
||||
|
||||
`ctx.sessionManager` is on every `ExtensionContext` (`ReadonlySessionManager`,
|
||||
`@oh-my-pi/pi-coding-agent/dist/types/extensibility/extensions/types.d.ts:485`):
|
||||
|
||||
```
|
||||
getEntries() getBranch() getEntry(id) getLeafId() getLeafEntry()
|
||||
SessionMessageEntry = { id, type: "message", message: AgentMessage }
|
||||
```
|
||||
|
||||
- **The cursor is an entry id.** Persist `getLeafId()` (or the id of the last entry you
|
||||
actually consumed); "everything since" = entries after that id. Advance is O(1).
|
||||
- **`getEntries()` grows mid-run** — proven by a timer, with no handler help:
|
||||
`entries=3 → 6 → 7 → 9 → 11` while `idle=false`, leaf ids rotating.
|
||||
- **Append lags `message_end` by ~0.5–1 s.** So "the live edge" always under-reads by a
|
||||
second. Consume only up to the last id you actually read; the sub-second tail rides into
|
||||
the next window. Never advance past what you read.
|
||||
- **`ctx.setInterval(cb, ms)` / `ctx.setTimeout`** (`types.d.ts:555-572`): throws contained,
|
||||
`unref`'d, auto-cleared on `session_shutdown`. Use these, never raw `setInterval`.
|
||||
`ctx.isIdle()` is the cheap "is this session even working" guard.
|
||||
|
||||
## The journal is not the conversation (allowlist, never denylist)
|
||||
|
||||
`agent_end` reported `msgs=6` while the journal held `11` entries. Bookkeeping types in the
|
||||
union: `custom` (zero content, ~3 per tool round), `model_usage`, `thinking_level_change`,
|
||||
`mode_change`, `model_change`, `service_tier_change`, `label`, `title_change`,
|
||||
`ttsr_injection`, `session_init`, `credential_pin`, `reset_boundary`. Speech-relevant:
|
||||
`message` (roles `user` / `assistant` / `toolResult`) and, as context, `compaction` /
|
||||
`branch_summary`. New types appear on the harness's own schedule → an allowlist keeps them
|
||||
silent until someone decides they are speech.
|
||||
|
||||
Re-export the per-message readers instead of re-parsing content: an assistant message's
|
||||
narration-flagged `thinking` part is **answer text**, unflagged `thinking` is deliberation
|
||||
(`narration: true` discriminator).
|
||||
|
||||
## Robustness rules that came out of the failure modes
|
||||
|
||||
- Empty window ⇒ leave the cursor where it was (nothing new must not read as news).
|
||||
- Cursor id no longer in the journal (compaction, branch rewrite) ⇒ treat as "from the top
|
||||
of what is left", never as "nothing" — a lost pointer must not mute a session forever.
|
||||
`session_compact` and `session_branch` are dispatched events if you want to re-anchor eagerly.
|
||||
|
||||
## Probe recipe (proves any of the above in ~60 s, touches nothing live)
|
||||
|
||||
Project-local extensions load without installing: write `<run-dir>/.omp/extensions/probe.js`
|
||||
(default-export `function (pi)`), log to an absolute path, then
|
||||
|
||||
```bash
|
||||
: > /tmp/probe.log
|
||||
timeout 220 omp -p --thinking off --cwd <run-dir> \
|
||||
"Run these bash commands strictly one after the other: first: sleep 7; echo FIRST. then: sleep 7; echo SECOND. Then reply: FIRST SECOND"
|
||||
```
|
||||
|
||||
Register the tick inside `session_start` (`ctx.setInterval(() => stamp(info(ctx)), 1000)`),
|
||||
and give every entry you expect to exclude a speech-shaped payload with a sentinel word —
|
||||
an absence assertion with an empty producer proves nothing. Do NOT pass `--no-session`:
|
||||
the journal is the thing under test. Teardown: nothing to undo (no plugin link, no
|
||||
`~/.omp/plugins/package.json` write) — delete the run dir.
|
||||
Reference in new issue
Block a user