71 lines
3.8 KiB
Markdown
71 lines
3.8 KiB
Markdown
---
|
||
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.
|