@senad-d/observme 0.1.0

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.
Files changed (111) hide show
  1. package/.env.example +57 -0
  2. package/CHANGELOG.md +52 -0
  3. package/LICENSE +21 -0
  4. package/ObservMe-Production-Docs/00-README.md +79 -0
  5. package/ObservMe-Production-Docs/01-requirements-and-scope.md +207 -0
  6. package/ObservMe-Production-Docs/02-reference-architecture.md +306 -0
  7. package/ObservMe-Production-Docs/03-pi-event-and-session-model.md +266 -0
  8. package/ObservMe-Production-Docs/04-telemetry-semantic-conventions.md +722 -0
  9. package/ObservMe-Production-Docs/05-otel-pipeline-and-collector.md +355 -0
  10. package/ObservMe-Production-Docs/06-security-privacy-redaction.md +294 -0
  11. package/ObservMe-Production-Docs/07-extension-implementation-blueprint.md +447 -0
  12. package/ObservMe-Production-Docs/08-query-grafana-integration.md +276 -0
  13. package/ObservMe-Production-Docs/09-dashboards-alerts-slos.md +640 -0
  14. package/ObservMe-Production-Docs/10-testing-release-operations.md +319 -0
  15. package/ObservMe-Production-Docs/11-deployment-runbooks.md +203 -0
  16. package/ObservMe-Production-Docs/12-configuration-reference.md +337 -0
  17. package/ObservMe-Production-Docs/13-source-notes.md +33 -0
  18. package/ObservMe-Production-Docs/pi-session-format.md +427 -0
  19. package/README.md +356 -0
  20. package/SECURITY.md +45 -0
  21. package/dashboards/observme-agent-node-graphs.json +250 -0
  22. package/dashboards/observme-agents.json +1880 -0
  23. package/dashboards/observme-alerts.yaml +113 -0
  24. package/dashboards/observme-branches-compactions.json +1042 -0
  25. package/dashboards/observme-cost.json +1254 -0
  26. package/dashboards/observme-errors.json +1659 -0
  27. package/dashboards/observme-export-health.json +1802 -0
  28. package/dashboards/observme-latency.json +1494 -0
  29. package/dashboards/observme-llm-conversations.json +730 -0
  30. package/dashboards/observme-logs-llm.json +644 -0
  31. package/dashboards/observme-models.json +933 -0
  32. package/dashboards/observme-overview.json +2129 -0
  33. package/dashboards/observme-slo-health.json +737 -0
  34. package/dashboards/observme-slos.yaml +56 -0
  35. package/dashboards/observme-tools.json +902 -0
  36. package/dashboards/observme-trace-journey.json +1793 -0
  37. package/docs/STRUCTURE.md +49 -0
  38. package/docs/agent-subagent-observability-requirements.md +997 -0
  39. package/docs/compatibility-matrix.md +39 -0
  40. package/docs/configuration-tui-design-standard.md +767 -0
  41. package/docs/configuration.md +38 -0
  42. package/docs/review-validation.md +115 -0
  43. package/docs/validation-flow.md +117 -0
  44. package/examples/collector.yaml +123 -0
  45. package/examples/observme.yaml +131 -0
  46. package/img/demo.gif +0 -0
  47. package/img/icon.svg +47 -0
  48. package/package.json +103 -0
  49. package/src/commands/obs-agents-runtime.ts +150 -0
  50. package/src/commands/obs-agents.ts +491 -0
  51. package/src/commands/obs-args.ts +63 -0
  52. package/src/commands/obs-backfill.ts +1334 -0
  53. package/src/commands/obs-command-support.ts +43 -0
  54. package/src/commands/obs-cost.ts +228 -0
  55. package/src/commands/obs-diagnostics.ts +22 -0
  56. package/src/commands/obs-errors.ts +156 -0
  57. package/src/commands/obs-health.ts +301 -0
  58. package/src/commands/obs-link.ts +90 -0
  59. package/src/commands/obs-logs.ts +194 -0
  60. package/src/commands/obs-loki-summary.ts +184 -0
  61. package/src/commands/obs-session.ts +259 -0
  62. package/src/commands/obs-status.ts +359 -0
  63. package/src/commands/obs-tools.ts +274 -0
  64. package/src/commands/obs-trace.ts +411 -0
  65. package/src/commands/obs.ts +211 -0
  66. package/src/config/bootstrap-project-config.ts +300 -0
  67. package/src/config/defaults.ts +143 -0
  68. package/src/config/load-config.ts +631 -0
  69. package/src/config/project-paths.ts +61 -0
  70. package/src/config/schema.ts +405 -0
  71. package/src/config/validate.ts +456 -0
  72. package/src/constants.ts +4 -0
  73. package/src/diagnostics/sanitize.ts +6 -0
  74. package/src/extension.ts +38 -0
  75. package/src/otel/logs.ts +160 -0
  76. package/src/otel/metrics.ts +165 -0
  77. package/src/otel/otlp-endpoint.ts +10 -0
  78. package/src/otel/sdk.ts +114 -0
  79. package/src/otel/shutdown.ts +102 -0
  80. package/src/otel/traces.ts +166 -0
  81. package/src/pi/agent-lineage.ts +378 -0
  82. package/src/pi/agent-tree-tracker.ts +258 -0
  83. package/src/pi/event-handlers/agent-turn.ts +155 -0
  84. package/src/pi/event-handlers/lifecycle.ts +642 -0
  85. package/src/pi/event-handlers/llm.ts +115 -0
  86. package/src/pi/event-handlers/session-events.ts +159 -0
  87. package/src/pi/event-handlers/tool-bash.ts +275 -0
  88. package/src/pi/handler-internals.ts +2154 -0
  89. package/src/pi/handler-runtime.ts +633 -0
  90. package/src/pi/handler-types.ts +261 -0
  91. package/src/pi/handlers.ts +75 -0
  92. package/src/pi/subagent-spawn.ts +975 -0
  93. package/src/pi/subagent-types.ts +29 -0
  94. package/src/privacy/content-capture.ts +104 -0
  95. package/src/privacy/hash.ts +93 -0
  96. package/src/privacy/redact.ts +619 -0
  97. package/src/privacy/secret-patterns.ts +185 -0
  98. package/src/privacy/truncate.ts +69 -0
  99. package/src/query/grafana-readiness.ts +164 -0
  100. package/src/query/grafana-transport.ts +481 -0
  101. package/src/query/grafana.ts +371 -0
  102. package/src/query/loki.ts +332 -0
  103. package/src/query/prometheus.ts +388 -0
  104. package/src/query/tempo.ts +332 -0
  105. package/src/safety/sensitive-input.ts +208 -0
  106. package/src/semconv/attributes.ts +279 -0
  107. package/src/semconv/metrics.ts +146 -0
  108. package/src/semconv/spans.ts +19 -0
  109. package/src/semconv/values.ts +13 -0
  110. package/src/util/bounded-map.ts +97 -0
  111. package/tsconfig.json +15 -0
@@ -0,0 +1,427 @@
1
+ # Session File Format
2
+
3
+ Sessions are stored as JSONL (JSON Lines) files. Each line is a JSON object with a `type` field. Session entries form a tree structure via `id`/`parentId` fields, enabling in-place branching without creating new files.
4
+
5
+ ## File Location
6
+
7
+ ```
8
+ ~/.pi/agent/sessions/--<path>--/<timestamp>_<uuid>.jsonl
9
+ ```
10
+
11
+ Where `<path>` is the working directory with `/` replaced by `-`.
12
+
13
+ ## Deleting Sessions
14
+
15
+ Sessions can be removed by deleting their `.jsonl` files under `~/.pi/agent/sessions/`.
16
+
17
+ Pi also supports deleting sessions interactively from `/resume` (select a session and press `Ctrl+D`, then confirm). When available, pi uses the `trash` CLI to avoid permanent deletion.
18
+
19
+ ## Session Version
20
+
21
+ Sessions have a version field in the header:
22
+
23
+ - **Version 1**: Linear entry sequence (legacy, auto-migrated on load)
24
+ - **Version 2**: Tree structure with `id`/`parentId` linking
25
+ - **Version 3**: Renamed `hookMessage` role to `custom` (extensions unification)
26
+
27
+ Existing sessions are automatically migrated to the current version (v3) when loaded.
28
+
29
+ ## Source Files
30
+
31
+ Source on GitHub ([pi-mono](https://github.com/earendil-works/pi-mono)):
32
+ - [`packages/coding-agent/src/core/session-manager.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/session-manager.ts) - Session entry types and SessionManager
33
+ - [`packages/coding-agent/src/core/messages.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/coding-agent/src/core/messages.ts) - Extended message types (BashExecutionMessage, CustomMessage, etc.)
34
+ - [`packages/ai/src/types.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/ai/src/types.ts) - Base message types (UserMessage, AssistantMessage, ToolResultMessage)
35
+ - [`packages/agent/src/types.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/agent/src/types.ts) - AgentMessage union type
36
+
37
+ For TypeScript definitions in your project, inspect `node_modules/@earendil-works/pi-coding-agent/dist/` and `node_modules/@earendil-works/pi-ai/dist/`.
38
+
39
+ ## Message Types
40
+
41
+ Session entries contain `AgentMessage` objects. Understanding these types is essential for parsing sessions and writing extensions.
42
+
43
+ ### Content Blocks
44
+
45
+ Messages contain arrays of typed content blocks:
46
+
47
+ ```typescript
48
+ interface TextContent {
49
+ type: "text";
50
+ text: string;
51
+ }
52
+
53
+ interface ImageContent {
54
+ type: "image";
55
+ data: string; // base64 encoded
56
+ mimeType: string; // e.g., "image/jpeg", "image/png"
57
+ }
58
+
59
+ interface ThinkingContent {
60
+ type: "thinking";
61
+ thinking: string;
62
+ thinkingSignature?: string;
63
+ redacted?: boolean;
64
+ }
65
+
66
+ interface ToolCall {
67
+ type: "toolCall";
68
+ id: string;
69
+ name: string;
70
+ arguments: Record<string, any>;
71
+ thoughtSignature?: string;
72
+ }
73
+ ```
74
+
75
+ ### Base Message Types (from pi-ai)
76
+
77
+ ```typescript
78
+ interface UserMessage {
79
+ role: "user";
80
+ content: string | (TextContent | ImageContent)[];
81
+ timestamp: number; // Unix ms
82
+ }
83
+
84
+ interface AssistantMessage {
85
+ role: "assistant";
86
+ content: (TextContent | ThinkingContent | ToolCall)[];
87
+ api: string;
88
+ provider: string;
89
+ model: string;
90
+ responseModel?: string;
91
+ responseId?: string;
92
+ diagnostics?: any[];
93
+ usage: Usage;
94
+ stopReason: "stop" | "length" | "toolUse" | "error" | "aborted";
95
+ errorMessage?: string;
96
+ timestamp: number;
97
+ }
98
+
99
+ interface ToolResultMessage {
100
+ role: "toolResult";
101
+ toolCallId: string;
102
+ toolName: string;
103
+ content: (TextContent | ImageContent)[];
104
+ details?: any; // Tool-specific metadata
105
+ isError: boolean;
106
+ timestamp: number;
107
+ }
108
+
109
+ interface Usage {
110
+ input: number;
111
+ output: number;
112
+ cacheRead: number;
113
+ cacheWrite: number;
114
+ cacheWrite1h?: number;
115
+ reasoning?: number;
116
+ totalTokens: number;
117
+ cost: {
118
+ input: number;
119
+ output: number;
120
+ cacheRead: number;
121
+ cacheWrite: number;
122
+ total: number;
123
+ };
124
+ }
125
+ ```
126
+
127
+ ### Extended Message Types (from pi-coding-agent)
128
+
129
+ ```typescript
130
+ interface BashExecutionMessage {
131
+ role: "bashExecution";
132
+ command: string;
133
+ output: string;
134
+ exitCode: number | undefined;
135
+ cancelled: boolean;
136
+ truncated: boolean;
137
+ fullOutputPath?: string;
138
+ excludeFromContext?: boolean; // true for !! prefix commands
139
+ timestamp: number;
140
+ }
141
+
142
+ interface CustomMessage {
143
+ role: "custom";
144
+ customType: string; // Extension identifier
145
+ content: string | (TextContent | ImageContent)[];
146
+ display: boolean; // Show in TUI
147
+ details?: any; // Extension-specific metadata
148
+ timestamp: number;
149
+ }
150
+
151
+ interface BranchSummaryMessage {
152
+ role: "branchSummary";
153
+ summary: string;
154
+ fromId: string; // Entry we branched from
155
+ timestamp: number;
156
+ }
157
+
158
+ interface CompactionSummaryMessage {
159
+ role: "compactionSummary";
160
+ summary: string;
161
+ tokensBefore: number;
162
+ timestamp: number;
163
+ }
164
+ ```
165
+
166
+ ### AgentMessage Union
167
+
168
+ ```typescript
169
+ type AgentMessage =
170
+ | UserMessage
171
+ | AssistantMessage
172
+ | ToolResultMessage
173
+ | BashExecutionMessage
174
+ | CustomMessage
175
+ | BranchSummaryMessage
176
+ | CompactionSummaryMessage;
177
+ ```
178
+
179
+ ## Entry Base
180
+
181
+ All entries (except `SessionHeader`) extend `SessionEntryBase`:
182
+
183
+ ```typescript
184
+ interface SessionEntryBase {
185
+ type: string;
186
+ id: string; // 8-char hex ID
187
+ parentId: string | null; // Parent entry ID (null for first entry)
188
+ timestamp: string; // ISO timestamp
189
+ }
190
+ ```
191
+
192
+ ## Entry Types
193
+
194
+ ### SessionHeader
195
+
196
+ First line of the file. Metadata only, not part of the tree (no `id`/`parentId`).
197
+
198
+ ```json
199
+ {"type":"session","version":3,"id":"uuid","timestamp":"2024-12-03T14:00:00.000Z","cwd":"/path/to/project"}
200
+ ```
201
+
202
+ For sessions with a parent (created via `/fork`, `/clone`, or `newSession({ parentSession })`):
203
+
204
+ ```json
205
+ {"type":"session","version":3,"id":"uuid","timestamp":"2024-12-03T14:00:00.000Z","cwd":"/path/to/project","parentSession":"/path/to/original/session.jsonl"}
206
+ ```
207
+
208
+ ### SessionMessageEntry
209
+
210
+ A message in the conversation. The `message` field contains an `AgentMessage`.
211
+
212
+ ```json
213
+ {"type":"message","id":"a1b2c3d4","parentId":null,"timestamp":"2024-12-03T14:00:01.000Z","message":{"role":"user","content":"Hello"}}
214
+ {"type":"message","id":"b2c3d4e5","parentId":"a1b2c3d4","timestamp":"2024-12-03T14:00:02.000Z","message":{"role":"assistant","content":[{"type":"text","text":"Hi!"}],"provider":"anthropic","model":"claude-sonnet-4-5","usage":{...},"stopReason":"stop"}}
215
+ {"type":"message","id":"c3d4e5f6","parentId":"b2c3d4e5","timestamp":"2024-12-03T14:00:03.000Z","message":{"role":"toolResult","toolCallId":"call_123","toolName":"bash","content":[{"type":"text","text":"output"}],"isError":false}}
216
+ ```
217
+
218
+ ### ModelChangeEntry
219
+
220
+ Emitted when the user switches models mid-session.
221
+
222
+ ```json
223
+ {"type":"model_change","id":"d4e5f6a7","parentId":"c3d4e5f6","timestamp":"2024-12-03T14:05:00.000Z","provider":"openai","modelId":"gpt-4o"}
224
+ ```
225
+
226
+ ### ThinkingLevelChangeEntry
227
+
228
+ Emitted when the user changes the thinking/reasoning level.
229
+
230
+ ```json
231
+ {"type":"thinking_level_change","id":"e5f6a7b8","parentId":"d4e5f6a7","timestamp":"2024-12-03T14:06:00.000Z","thinkingLevel":"high"}
232
+ ```
233
+
234
+ ### CompactionEntry
235
+
236
+ Created when context is compacted. Stores a summary of earlier messages.
237
+
238
+ ```json
239
+ {"type":"compaction","id":"f6a7b8c9","parentId":"e5f6a7b8","timestamp":"2024-12-03T14:10:00.000Z","summary":"User discussed X, Y, Z...","firstKeptEntryId":"c3d4e5f6","tokensBefore":50000}
240
+ ```
241
+
242
+ Optional fields:
243
+ - `details`: Implementation-specific data (e.g., `{ readFiles: string[], modifiedFiles: string[] }` for default, or custom data for extensions)
244
+ - `fromHook`: `true` if generated by an extension, `false`/`undefined` if pi-generated (legacy field name)
245
+
246
+ ### BranchSummaryEntry
247
+
248
+ Created when switching branches via `/tree` with an LLM generated summary of the left branch up to the common ancestor. Captures context from the abandoned path.
249
+
250
+ ```json
251
+ {"type":"branch_summary","id":"a7b8c9d0","parentId":"a1b2c3d4","timestamp":"2024-12-03T14:15:00.000Z","fromId":"f6a7b8c9","summary":"Branch explored approach A..."}
252
+ ```
253
+
254
+ Optional fields:
255
+ - `details`: File tracking data (`{ readFiles: string[], modifiedFiles: string[] }`) for default, or custom data for extensions
256
+ - `fromHook`: `true` if generated by an extension, `false`/`undefined` if pi-generated (legacy field name)
257
+
258
+ ### CustomEntry
259
+
260
+ Extension state persistence. Does NOT participate in LLM context.
261
+
262
+ ```json
263
+ {"type":"custom","id":"b8c9d0e1","parentId":"a7b8c9d0","timestamp":"2024-12-03T14:20:00.000Z","customType":"my-extension","data":{"count":42}}
264
+ ```
265
+
266
+ Use `customType` to identify your extension's entries on reload. Custom entries are for extension state and do not have a public custom-entry renderer API. If an extension needs visible custom content, use `custom_message` plus `pi.registerMessageRenderer(customType, renderer)`.
267
+
268
+ ### CustomMessageEntry
269
+
270
+ Extension-injected messages that DO participate in LLM context.
271
+
272
+ ```json
273
+ {"type":"custom_message","id":"c9d0e1f2","parentId":"b8c9d0e1","timestamp":"2024-12-03T14:25:00.000Z","customType":"my-extension","content":"Injected context...","display":true}
274
+ ```
275
+
276
+ Fields:
277
+ - `content`: String or `(TextContent | ImageContent)[]` (same as UserMessage)
278
+ - `display`: `true` = show in TUI with distinct styling, `false` = hidden
279
+ - `details`: Optional extension-specific metadata (not sent to LLM)
280
+
281
+ ### LabelEntry
282
+
283
+ User-defined bookmark/marker on an entry.
284
+
285
+ ```json
286
+ {"type":"label","id":"d0e1f2a3","parentId":"c9d0e1f2","timestamp":"2024-12-03T14:30:00.000Z","targetId":"a1b2c3d4","label":"checkpoint-1"}
287
+ ```
288
+
289
+ Set `label` to `undefined` to clear a label.
290
+
291
+ ### SessionInfoEntry
292
+
293
+ Session metadata (e.g., user-defined display name). Set via `/name`, `--name` / `-n`, or `pi.setSessionName()` in extensions.
294
+
295
+ ```json
296
+ {"type":"session_info","id":"e1f2a3b4","parentId":"d0e1f2a3","timestamp":"2024-12-03T14:35:00.000Z","name":"Refactor auth module"}
297
+ ```
298
+
299
+ The session name is displayed in the session selector (`/resume`) instead of the first message when set.
300
+
301
+ ## Tree Structure
302
+
303
+ Entries form a tree:
304
+ - First entry has `parentId: null`
305
+ - Each subsequent entry points to its parent via `parentId`
306
+ - Branching creates new children from an earlier entry
307
+ - The "leaf" is the current position in the tree
308
+
309
+ ```
310
+ [user msg] ─── [assistant] ─── [user msg] ─── [assistant] ─┬─ [user msg] ← current leaf
311
+
312
+ └─ [branch_summary] ─── [user msg] ← alternate branch
313
+ ```
314
+
315
+ ## Context Building
316
+
317
+ `getBranch()` walks from the current leaf to the root and returns the active branch entries in path order, including non-message entries.
318
+
319
+ `buildSessionContext()` walks the active path and produces the message list for the LLM while honoring compaction:
320
+
321
+ 1. Collects all entries on the active path.
322
+ 2. Extracts current model and thinking level settings from the path.
323
+ 3. If a `CompactionEntry` is on the path:
324
+ - Emits the compaction summary first.
325
+ - Then includes messages from `firstKeptEntryId` to the compaction.
326
+ - Then includes messages after the compaction.
327
+ 4. Converts selected entries to messages:
328
+ - `message` -> stored `AgentMessage`
329
+ - `compaction` -> `compactionSummary`
330
+ - `branch_summary` -> `branchSummary`
331
+ - `custom_message` -> `CustomMessage`
332
+ - `custom` -> no context message
333
+
334
+ ## Parsing Example
335
+
336
+ ```typescript
337
+ import { readFileSync } from "fs";
338
+
339
+ const lines = readFileSync("session.jsonl", "utf8").trim().split("\n");
340
+
341
+ for (const line of lines) {
342
+ const entry = JSON.parse(line);
343
+
344
+ switch (entry.type) {
345
+ case "session":
346
+ console.log(`Session v${entry.version ?? 1}: ${entry.id}`);
347
+ break;
348
+ case "message":
349
+ console.log(`[${entry.id}] ${entry.message.role}: ${JSON.stringify(entry.message.content)}`);
350
+ break;
351
+ case "compaction":
352
+ console.log(`[${entry.id}] Compaction: ${entry.tokensBefore} tokens summarized`);
353
+ break;
354
+ case "branch_summary":
355
+ console.log(`[${entry.id}] Branch from ${entry.fromId}`);
356
+ break;
357
+ case "custom":
358
+ console.log(`[${entry.id}] Custom (${entry.customType}): ${JSON.stringify(entry.data)}`);
359
+ break;
360
+ case "custom_message":
361
+ console.log(`[${entry.id}] Extension message (${entry.customType}): ${entry.content}`);
362
+ break;
363
+ case "label":
364
+ console.log(`[${entry.id}] Label "${entry.label}" on ${entry.targetId}`);
365
+ break;
366
+ case "model_change":
367
+ console.log(`[${entry.id}] Model: ${entry.provider}/${entry.modelId}`);
368
+ break;
369
+ case "thinking_level_change":
370
+ console.log(`[${entry.id}] Thinking: ${entry.thinkingLevel}`);
371
+ break;
372
+ }
373
+ }
374
+ ```
375
+
376
+ ## SessionManager API
377
+
378
+ Key methods for working with sessions programmatically.
379
+
380
+ ### Static Creation Methods
381
+ - `SessionManager.create(cwd, sessionDir?)` - New session
382
+ - `SessionManager.open(path, sessionDir?)` - Open existing session file
383
+ - `SessionManager.continueRecent(cwd, sessionDir?)` - Continue most recent or create new
384
+ - `SessionManager.inMemory(cwd?)` - No file persistence
385
+ - `SessionManager.forkFrom(sourcePath, targetCwd, sessionDir?)` - Fork session from another project
386
+
387
+ ### Static Listing Methods
388
+ - `SessionManager.list(cwd, sessionDir?, onProgress?)` - List sessions for a directory
389
+ - `SessionManager.listAll(onProgress?)` - List all sessions across all projects
390
+
391
+ ### Instance Methods - Session Management
392
+ - `newSession(options?)` - Start a new session (options: `{ parentSession?: string }`)
393
+ - `setSessionFile(path)` - Switch to a different session file
394
+ - `createBranchedSession(leafId)` - Extract branch to new session file
395
+
396
+ ### Instance Methods - Appending (all return entry ID)
397
+ - `appendMessage(message)` - Add message
398
+ - `appendThinkingLevelChange(level)` - Record thinking change
399
+ - `appendModelChange(provider, modelId)` - Record model change
400
+ - `appendCompaction(summary, firstKeptEntryId, tokensBefore, details?, fromHook?)` - Add compaction
401
+ - `appendCustomEntry(customType, data?)` - Extension state (not in context)
402
+ - `appendSessionInfo(name)` - Set session display name
403
+ - `appendCustomMessageEntry(customType, content, display, details?)` - Extension message (in context)
404
+ - `appendLabelChange(targetId, label)` - Set/clear label
405
+
406
+ ### Instance Methods - Tree Navigation
407
+ - `getLeafId()` - Current position
408
+ - `getLeafEntry()` - Get current leaf entry
409
+ - `getEntry(id)` - Get entry by ID
410
+ - `getBranch(fromId?)` - Walk from entry to root
411
+ - `getTree()` - Get full tree structure
412
+ - `getChildren(parentId)` - Get direct children
413
+ - `getLabel(id)` - Get label for entry
414
+ - `branch(entryId)` - Move leaf to earlier entry
415
+ - `resetLeaf()` - Reset leaf to null (before any entries)
416
+ - `branchWithSummary(entryId, summary, details?, fromHook?)` - Branch with context summary
417
+
418
+ ### Instance Methods - Context & Info
419
+ - `buildSessionContext()` - Get messages, thinkingLevel, and model for LLM
420
+ - `getEntries()` - All entries (excluding header)
421
+ - `getHeader()` - Session header metadata
422
+ - `getSessionName()` - Get display name from latest session_info entry
423
+ - `getCwd()` - Working directory
424
+ - `getSessionDir()` - Session storage directory
425
+ - `getSessionId()` - Session UUID
426
+ - `getSessionFile()` - Session file path (undefined for in-memory)
427
+ - `isPersisted()` - Whether session is saved to disk