praxis-agent 0.42.1 → 0.43.1

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 (40) hide show
  1. package/README.md +28 -37
  2. package/dist/application/native-session-projection.d.ts +4 -0
  3. package/dist/application/native-session-projection.js +135 -0
  4. package/dist/application/session-service.d.ts +0 -1
  5. package/dist/application/session-service.js +9 -170
  6. package/dist/cli/interactive.js +112 -156
  7. package/dist/cli/tui/ansi-frame-renderer.d.ts +2 -0
  8. package/dist/cli/tui/ansi-frame-renderer.js +109 -21
  9. package/dist/cli/tui/ansi-surface.d.ts +6 -22
  10. package/dist/cli/tui/ansi-surface.js +6 -126
  11. package/dist/cli/tui/ansi-theme.d.ts +3 -2
  12. package/dist/cli/tui/ansi-theme.js +22 -1
  13. package/dist/cli/tui/quiet-choice-rows.d.ts +26 -0
  14. package/dist/cli/tui/quiet-choice-rows.js +302 -0
  15. package/dist/cli/tui/quiet-frame-adapter.d.ts +18 -0
  16. package/dist/cli/tui/quiet-frame-adapter.js +90 -0
  17. package/dist/cli/tui/quiet-frame.d.ts +43 -0
  18. package/dist/cli/tui/quiet-frame.js +346 -0
  19. package/dist/cli/tui/quiet-operational-rows.d.ts +17 -0
  20. package/dist/cli/tui/quiet-operational-rows.js +413 -0
  21. package/dist/cli/tui/quiet-screen-projector.d.ts +25 -0
  22. package/dist/cli/tui/quiet-screen-projector.js +110 -0
  23. package/dist/cli/tui/quiet-settings-rows.d.ts +17 -0
  24. package/dist/cli/tui/quiet-settings-rows.js +490 -0
  25. package/dist/cli/tui/status-line.d.ts +15 -9
  26. package/dist/cli/tui/status-line.js +15 -6
  27. package/dist/cli/tui/theme.js +20 -20
  28. package/dist/cli/tui/transcript-viewport.d.ts +5 -0
  29. package/dist/cli/tui/transcript-viewport.js +213 -78
  30. package/dist/cli/tui/tui-row-ir.js +4 -4
  31. package/dist/cli-runtime.d.ts +1 -0
  32. package/dist/cli-runtime.js +4 -2
  33. package/dist/maintenance/self-update-transaction.d.ts +39 -0
  34. package/dist/maintenance/self-update-transaction.js +356 -0
  35. package/dist/maintenance/self-update.d.ts +4 -0
  36. package/dist/maintenance/self-update.js +29 -20
  37. package/dist/persistence/in-memory-transcript-store.js +1 -7
  38. package/dist/persistence/native-transcript-store.d.ts +0 -9
  39. package/dist/persistence/native-transcript-store.js +4 -38
  40. package/package.json +3 -2
package/README.md CHANGED
@@ -45,6 +45,7 @@ praxis --version
45
45
 
46
46
  Release tarballs, SBOMs, SHA-256 checksums, and build attestations are attached
47
47
  to every [GitHub release](https://github.com/Forest-Isle/Praxis/releases).
48
+ Use `praxis update` for transactional self-updates; see [Getting Started](https://github.com/Forest-Isle/Praxis/blob/main/docs/GETTING_STARTED.md) for recovery and verification details.
48
49
 
49
50
  ## Quick start
50
51
 
@@ -88,10 +89,13 @@ troubleshooting. Run `praxis --help` for the authoritative command surface.
88
89
 
89
90
  ## What Praxis provides
90
91
 
91
- - **Local agent runtime** — Claude-style responsive TUI with a fixed fullscreen
92
- viewport, non-shrinking composer/status area, and complete bounded welcome
93
- surface with the reusable P-loop + spark Praxis mark and ANSI/no-color
94
- fallbacks, plus a shared-command
92
+ - **Local agent runtime** — C+ Quiet Operator responsive TUI with a linear
93
+ `you>`/`praxis>` conversation, compact stable tool rows, responsive density,
94
+ terminal-native background, and a minimal composer/status row. Interactive
95
+ surfaces share the same presentation across terminals, with English
96
+ permission/configuration choices and a taught `❯` / Up/Down / Enter / Esc
97
+ interaction grammar, plus a
98
+ shared-command
95
99
  slash palette, tabbed help and shortcut surfaces, searchable resume picker,
96
100
  restored active-branch conversation history, streaming and expandable
97
101
  thinking, grouped multi-file reads, globally expandable tool results,
@@ -106,26 +110,8 @@ troubleshooting. Run `praxis --help` for the authoritative command surface.
106
110
  skills/hooks flow, provider-free per-session `/color` prompt-bar styling,
107
111
  `/mcp`, `/memory` shared instruction and auto-memory
108
112
  access, and live extension-reload controls,
109
- plus a framework-free runtime kernel that atomically publishes streaming
110
- frames and keeps status/busy transitions deterministic, with a unified
111
- framework-free TuiStore that retains runtime and composer state together,
112
- with a shared semantic transcript Row IR for renderer-neutral layout and
113
- stable incremental updates,
114
- backed by the authoritative grapheme/Markdown viewport layout so narrow and
115
- Unicode-heavy transcripts wrap consistently across renderers,
116
- and an independent ANSI fullscreen frame renderer with alternate-screen
117
- lifecycle, synchronized output, and dirty-row diffing,
118
- opt-in TTY wiring with automatic Ink fallback on renderer failure,
119
- with complex overlays and dialogs intentionally remaining on the mature Ink
120
- surface until their semantic ANSI projections are complete,
121
- while welcome and identity intros also remain on Ink for a complete first
122
- frame,
123
- and a pure FocusStack that centralizes overlay/dialog precedence and Esc
124
- cancellation routing,
125
- plus a generation-aware effect runner that drops stale asynchronous results
126
- and aborts cleanly on replacement or unmount,
127
- with ANSI fullscreen text styles derived from the active semantic theme and
128
- automatic no-color/screen-reader suppression,
113
+ plus automatic fallback when a terminal renderer fails, screen-reader
114
+ support, and no-color output,
129
115
  cursor/history composer, provider-free `/cost` usage and pricing summaries,
130
116
  with a hermetic PTY smoke covering real `runInteractive` ANSI entry,
131
117
  resize-safe lifecycle, and Ctrl-C restoration,
@@ -204,6 +190,9 @@ troubleshooting. Run `praxis --help` for the authoritative command surface.
204
190
  - **Provider-neutral models** — native Anthropic Messages and OpenAI-compatible
205
191
  streaming adapters with explicit capability checks, metering controls, and
206
192
  a bounded absolute deadline for every provider attempt.
193
+ - **Transactional self-update** — `praxis update` verifies the package before
194
+ installing it, rejects concurrent updates, and can roll back after an
195
+ interruption or crash.
207
196
 
208
197
  Detailed feature status and executable evidence live in the
209
198
  [parity matrix](https://github.com/Forest-Isle/Praxis/blob/main/docs/PARITY_MATRIX.md),
@@ -211,17 +200,17 @@ not in this entry-point README.
211
200
 
212
201
  ## Documentation
213
202
 
214
- | Need | Document |
215
- | ------------------------------------------ | ------------------------------------------------------------------------------------------ |
216
- | Install and run the first session | [Getting Started](https://github.com/Forest-Isle/Praxis/blob/main/docs/GETTING_STARTED.md) |
217
- | Common commands and environment variables | [CLI Reference](https://github.com/Forest-Isle/Praxis/blob/main/docs/CLI_REFERENCE.md) |
218
- | Find all user and maintainer documentation | [Documentation Index](https://github.com/Forest-Isle/Praxis/blob/main/docs/README.md) |
219
- | Understand module and data-flow boundaries | [Architecture](https://github.com/Forest-Isle/Praxis/blob/main/docs/ARCHITECTURE.md) |
220
- | Review security assumptions | [Threat Model](https://github.com/Forest-Isle/Praxis/blob/main/docs/THREAT_MODEL.md) |
221
- | Check Claude Code parity | [Parity Matrix](https://github.com/Forest-Isle/Praxis/blob/main/docs/PARITY_MATRIX.md) |
222
- | Review interactive TUI design and evidence | [TUI Parity](https://github.com/Forest-Isle/Praxis/blob/main/docs/TUI_PARITY.md) |
223
- | Build, test, and contribute | [Contributing](https://github.com/Forest-Isle/Praxis/blob/main/CONTRIBUTING.md) |
224
- | Verify release and supply-chain controls | [Release Contract](https://github.com/Forest-Isle/Praxis/blob/main/docs/RELEASE.md) |
203
+ | Need | Document |
204
+ | ------------------------------------------ | ------------------------------------------------------------------------------------------------ |
205
+ | Install and run the first session | [Getting Started](https://github.com/Forest-Isle/Praxis/blob/main/docs/GETTING_STARTED.md) |
206
+ | Common commands and environment variables | [CLI Reference](https://github.com/Forest-Isle/Praxis/blob/main/docs/CLI_REFERENCE.md) |
207
+ | Find all user and maintainer documentation | [Documentation Index](https://github.com/Forest-Isle/Praxis/blob/main/docs/README.md) |
208
+ | Understand module and data-flow boundaries | [Architecture](https://github.com/Forest-Isle/Praxis/blob/main/docs/ARCHITECTURE.md) |
209
+ | Review security assumptions | [Threat Model](https://github.com/Forest-Isle/Praxis/blob/main/docs/THREAT_MODEL.md) |
210
+ | Check Claude Code parity | [Parity Matrix](https://github.com/Forest-Isle/Praxis/blob/main/docs/PARITY_MATRIX.md) |
211
+ | Review interactive TUI design and evidence | [Quiet Operator Spec](https://github.com/Forest-Isle/Praxis/blob/main/docs/TUI_REDESIGN_SPEC.md) |
212
+ | Build, test, and contribute | [Contributing](https://github.com/Forest-Isle/Praxis/blob/main/CONTRIBUTING.md) |
213
+ | Verify release and supply-chain controls | [Release Contract](https://github.com/Forest-Isle/Praxis/blob/main/docs/RELEASE.md) |
225
214
 
226
215
  ## Project boundary
227
216
 
@@ -257,8 +246,10 @@ npm run check
257
246
  transcript, and session profile.
258
247
  `npm run test:native:deletion` adds an emitted-output deletion gate. These are
259
248
  implemented profile checks, not qualification of the full native package.
260
- `npm run test:performance` runs the native projection scaling and regression
261
- budgets; the retained-render p95 budget remains 50 ms.
249
+ `npm run test:performance` enforces TUI projection scaling, doubling ratios
250
+ `<=3.25`, the absolute 120k median budget of `<1000 ms`, and deterministic
251
+ injected regression protection, plus Quiet Operator input echo `<50 ms` and
252
+ normal/low-capability full-frame p95 budgets of `<16.7/<33 ms`.
262
253
  `npm run check` also enforces the corresponding source dependency direction.
263
254
  `npm run test:core-completion` runs the 56-story #402 audit and reports
264
255
  implemented, qualified, blocked, deferred, and out-of-scope states separately;
@@ -0,0 +1,4 @@
1
+ import type { TranscriptEvent } from '../core/transcript-event.js';
2
+ import type { NativeTranscriptEntry } from '../native/schema.js';
3
+ export declare function projectNativeSessionEntries(events: readonly TranscriptEvent[]): NativeTranscriptEntry[];
4
+ //# sourceMappingURL=native-session-projection.d.ts.map
@@ -0,0 +1,135 @@
1
+ export function projectNativeSessionEntries(events) {
2
+ const entries = [];
3
+ for (const event of events) {
4
+ if (event.kind === 'context-boundary') {
5
+ entries.push({
6
+ type: 'system',
7
+ uuid: event.id,
8
+ parentUuid: event.parentId,
9
+ subtype: 'compact_boundary',
10
+ logicalParentUuid: event.logicalParentId,
11
+ compactMetadata: {
12
+ trigger: event.trigger,
13
+ preTokens: event.preTokens,
14
+ postTokens: event.postTokens,
15
+ durationMs: event.durationMs,
16
+ },
17
+ });
18
+ continue;
19
+ }
20
+ if (event.kind === 'context-summary') {
21
+ entries.push({
22
+ type: 'user',
23
+ uuid: event.id,
24
+ parentUuid: event.parentId,
25
+ isCompactSummary: true,
26
+ message: { role: 'user', content: event.summary },
27
+ });
28
+ continue;
29
+ }
30
+ if (event.kind !== 'messages')
31
+ continue;
32
+ let parentUuid = event.parentId;
33
+ event.messages.forEach((message, index) => {
34
+ const uuid = index === event.messages.length - 1 ? event.id : `${event.id}:${index}`;
35
+ if (message.role === 'user' && typeof message.content === 'string') {
36
+ const agentMatch = message.content.match(/^<praxis-agent-setting>([^<]+)<\/praxis-agent-setting>$/u);
37
+ if (agentMatch?.[1]) {
38
+ entries.push({
39
+ type: 'agent-setting',
40
+ agentSetting: agentMatch[1],
41
+ uuid,
42
+ parentUuid,
43
+ sessionId: event.sessionId,
44
+ });
45
+ parentUuid = uuid;
46
+ return;
47
+ }
48
+ const nameMatch = message.content.match(/^<praxis-session-name>([^<]+)<\/praxis-session-name>$/u);
49
+ if (nameMatch?.[1]) {
50
+ entries.push({
51
+ type: 'custom-title',
52
+ customTitle: nameMatch[1],
53
+ uuid,
54
+ parentUuid,
55
+ sessionId: event.sessionId,
56
+ });
57
+ parentUuid = uuid;
58
+ return;
59
+ }
60
+ const match = message.content.match(/^<praxis-file-history>([\s\S]*)<\/praxis-file-history>$/u);
61
+ if (match?.[1]) {
62
+ try {
63
+ const operational = JSON.parse(match[1]);
64
+ if (operational &&
65
+ typeof operational === 'object' &&
66
+ typeof operational.type === 'string' &&
67
+ (operational.type === 'file-history-snapshot' ||
68
+ operational.type === 'file-history-delta')) {
69
+ entries.push({
70
+ ...operational,
71
+ uuid,
72
+ parentUuid,
73
+ sessionId: event.sessionId,
74
+ });
75
+ parentUuid = uuid;
76
+ return;
77
+ }
78
+ }
79
+ catch {
80
+ // Keep malformed operational markers visible as ordinary native user messages.
81
+ }
82
+ }
83
+ }
84
+ if (message.role === 'tool') {
85
+ entries.push({
86
+ type: 'user',
87
+ uuid,
88
+ parentUuid,
89
+ message: {
90
+ role: 'user',
91
+ content: [
92
+ {
93
+ type: 'tool_result',
94
+ tool_use_id: message.toolCallId,
95
+ content: message.content,
96
+ is_error: message.isError,
97
+ },
98
+ ],
99
+ },
100
+ });
101
+ parentUuid = uuid;
102
+ return;
103
+ }
104
+ if (message.role === 'assistant') {
105
+ const content = [];
106
+ if (message.content)
107
+ content.push({ type: 'text', text: message.content });
108
+ for (const call of message.toolCalls ?? [])
109
+ content.push({
110
+ type: 'tool_use',
111
+ id: call.id,
112
+ name: call.name,
113
+ input: call.input,
114
+ });
115
+ entries.push({
116
+ type: 'assistant',
117
+ uuid,
118
+ parentUuid,
119
+ message: { role: 'assistant', content },
120
+ });
121
+ parentUuid = uuid;
122
+ return;
123
+ }
124
+ entries.push({
125
+ type: message.role,
126
+ uuid,
127
+ parentUuid,
128
+ message: { role: message.role, content: message.content },
129
+ });
130
+ parentUuid = uuid;
131
+ });
132
+ }
133
+ return entries;
134
+ }
135
+ //# sourceMappingURL=native-session-projection.js.map
@@ -299,7 +299,6 @@ export declare class ClaudeSessionService {
299
299
  compact(sessionId: string, signal?: AbortSignal, selection?: ManualCompactSelection): Promise<ManualCompactResult>;
300
300
  fork(parentSessionId: string, sessionId?: string, resumeSessionAt?: string): Promise<ForkResult>;
301
301
  ensureFork(parentSessionId: string, sessionId: string, checkpoint?: SessionForkCheckpoint): Promise<ForkResult>;
302
- private nativeForkEntries;
303
302
  rewindFiles(sessionId: string, userMessageId: string): Promise<void>;
304
303
  rewindPoints(sessionId: string): Promise<RewindPoint[]>;
305
304
  setPermissionMode(sessionId: string, permissionMode: ClaudePermissionMode): Promise<void>;
@@ -8,10 +8,10 @@ import { formatClaudeCompactSummary } from '../native/compaction.js';
8
8
  import { isClaudeAgentId } from '../native/sidechain.js';
9
9
  import { assertNativeDataPlane, resolveDataPlanePaths, resolveScheduledTaskFile, } from '../persistence/data-plane.js';
10
10
  import { downloadClaudeFileResources, } from '../native/file-resources.js';
11
- import { createClaudeNativeFork } from '../native/fork.js';
12
11
  import { selectClaudeActiveTranscript } from '../native/history.js';
13
12
  import { ClaudeFileHistory } from '../native/file-history.js';
14
13
  import { getClaudeAgentSetting, projectClaudeModelMessages, } from '../native/projection.js';
14
+ import { projectNativeSessionEntries } from './native-session-projection.js';
15
15
  import { classifyClaudeInterruption, } from '../native/interruption.js';
16
16
  import { findUnresolvedClaudeToolCalls, getClaudeContentBlocks, } from '../native/tool-links.js';
17
17
  import { createClaudeAgentSettingEntry, createClaudeHookAttachmentEntries, createClaudeLastPromptEntry, createClaudeRuleAttachmentEntry, translateProviderEvents, } from '../native/translation.js';
@@ -21,146 +21,6 @@ import { BackgroundTaskRuntime, } from './background-task-runtime.js';
21
21
  import { backgroundAgentNotificationMarkers, } from './background-agent-manager.js';
22
22
  import { usageCostUsd } from '../core/usage.js';
23
23
  import { isSessionId } from '../core/session.js';
24
- /** Project authoritative native events for legacy-only session helpers. */
25
- function projectNativeEvents(events) {
26
- const entries = [];
27
- for (const event of events) {
28
- if (event.kind === 'context-boundary') {
29
- entries.push({
30
- type: 'system',
31
- uuid: event.id,
32
- parentUuid: event.parentId,
33
- subtype: 'compact_boundary',
34
- logicalParentUuid: event.logicalParentId,
35
- compactMetadata: {
36
- trigger: event.trigger,
37
- preTokens: event.preTokens,
38
- postTokens: event.postTokens,
39
- durationMs: event.durationMs,
40
- },
41
- });
42
- continue;
43
- }
44
- if (event.kind === 'context-summary') {
45
- entries.push({
46
- type: 'user',
47
- uuid: event.id,
48
- parentUuid: event.parentId,
49
- isCompactSummary: true,
50
- message: { role: 'user', content: event.summary },
51
- });
52
- continue;
53
- }
54
- if (event.kind !== 'messages')
55
- continue;
56
- let parentUuid = event.parentId;
57
- event.messages.forEach((message, index) => {
58
- // Native event parent links target the event ID. Assign that ID to the
59
- // final projected message so the next event and memory watermark attach
60
- // to the visible tail of this event; intermediate messages get stable
61
- // derived IDs within the event.
62
- const uuid = index === event.messages.length - 1 ? event.id : `${event.id}:${index}`;
63
- if (message.role === 'user' && typeof message.content === 'string') {
64
- const agentMatch = message.content.match(/^<praxis-agent-setting>([^<]+)<\/praxis-agent-setting>$/u);
65
- if (agentMatch?.[1]) {
66
- entries.push({
67
- type: 'agent-setting',
68
- agentSetting: agentMatch[1],
69
- uuid,
70
- parentUuid,
71
- sessionId: event.sessionId,
72
- });
73
- parentUuid = uuid;
74
- return;
75
- }
76
- const nameMatch = message.content.match(/^<praxis-session-name>([^<]+)<\/praxis-session-name>$/u);
77
- if (nameMatch?.[1]) {
78
- entries.push({
79
- type: 'custom-title',
80
- customTitle: nameMatch[1],
81
- uuid,
82
- parentUuid,
83
- sessionId: event.sessionId,
84
- });
85
- parentUuid = uuid;
86
- return;
87
- }
88
- const match = message.content.match(/^<praxis-file-history>([\s\S]*)<\/praxis-file-history>$/u);
89
- if (match?.[1]) {
90
- try {
91
- const operational = JSON.parse(match[1]);
92
- if (operational &&
93
- typeof operational === 'object' &&
94
- typeof operational.type === 'string' &&
95
- (operational.type === 'file-history-snapshot' ||
96
- operational.type === 'file-history-delta')) {
97
- entries.push({
98
- ...operational,
99
- uuid,
100
- parentUuid,
101
- sessionId: event.sessionId,
102
- });
103
- parentUuid = uuid;
104
- return;
105
- }
106
- }
107
- catch {
108
- // Keep malformed operational markers visible as ordinary native
109
- // user messages; the authoritative transcript remains valid.
110
- }
111
- }
112
- }
113
- if (message.role === 'tool') {
114
- entries.push({
115
- type: 'user',
116
- uuid,
117
- parentUuid,
118
- message: {
119
- role: 'user',
120
- content: [
121
- {
122
- type: 'tool_result',
123
- tool_use_id: message.toolCallId,
124
- content: message.content,
125
- is_error: message.isError,
126
- },
127
- ],
128
- },
129
- });
130
- parentUuid = uuid;
131
- return;
132
- }
133
- if (message.role === 'assistant') {
134
- const content = [];
135
- if (message.content)
136
- content.push({ type: 'text', text: message.content });
137
- for (const call of message.toolCalls ?? [])
138
- content.push({
139
- type: 'tool_use',
140
- id: call.id,
141
- name: call.name,
142
- input: call.input,
143
- });
144
- entries.push({
145
- type: 'assistant',
146
- uuid,
147
- parentUuid,
148
- message: { role: 'assistant', content },
149
- });
150
- parentUuid = uuid;
151
- return;
152
- }
153
- entries.push({
154
- type: message.role,
155
- uuid,
156
- parentUuid,
157
- message: { role: message.role, content: message.content },
158
- });
159
- parentUuid = uuid;
160
- });
161
- }
162
- return entries;
163
- }
164
24
  import { ContextBudget, estimateModelRequestTokens, isPromptTooLongError, } from '../core/context-budget.js';
165
25
  import { ContextEngine } from './context-engine.js';
166
26
  import { TurnMemoryCoordinator } from './turn-memory-coordinator.js';
@@ -1935,7 +1795,7 @@ export class ClaudeSessionService {
1935
1795
  const sourceStore = this.store(sessionId);
1936
1796
  const relocated = await sourceStore.withLease(async (lease) => {
1937
1797
  const snapshot = await lease.load();
1938
- if (snapshot.entries.length === 0) {
1798
+ if (snapshot.records.length === 0) {
1939
1799
  throw new Error(`Claude session not found: ${sessionId}`);
1940
1800
  }
1941
1801
  await mkdir(targetPaths.projectRoot, { recursive: true });
@@ -2112,7 +1972,7 @@ export class ClaudeSessionService {
2112
1972
  : branchEvents[targetIndex - 1])?.id;
2113
1973
  }
2114
1974
  else {
2115
- memorySelection = await this.selectMemoryPreservedCompact(sessionId, projectNativeEvents(branchEvents));
1975
+ memorySelection = await this.selectMemoryPreservedCompact(sessionId, projectNativeSessionEntries(branchEvents));
2116
1976
  if (memorySelection) {
2117
1977
  messages = [
2118
1978
  memorySelection.memoryMessage,
@@ -2311,35 +2171,13 @@ export class ClaudeSessionService {
2311
2171
  return { sessionId, parentSessionId };
2312
2172
  }
2313
2173
  }
2314
- async nativeForkEntries(parentSessionId, sessionId, resumeSessionAt, sourceEntryCount) {
2315
- const sourceResult = await this.store(parentSessionId).withLease((lease) => lease.load());
2316
- if (sourceResult.status === 'conflict') {
2317
- throw new Error(`Claude transcript fork conflict: ${sourceResult.reason}`);
2318
- }
2319
- const source = sourceResult.value;
2320
- if (source.entries.length === 0) {
2321
- throw new Error(`Claude session not found: ${parentSessionId}`);
2322
- }
2323
- if (sourceEntryCount !== undefined &&
2324
- (sourceEntryCount <= 0 || sourceEntryCount > source.entries.length)) {
2325
- throw new Error('Claude handoff source checkpoint is no longer available');
2326
- }
2327
- return createClaudeNativeFork({
2328
- source: sourceEntryCount === undefined
2329
- ? source.entries
2330
- : source.entries.slice(0, sourceEntryCount),
2331
- sourceSessionId: parentSessionId,
2332
- sessionId,
2333
- ...(resumeSessionAt === undefined ? {} : { resumeSessionAt }),
2334
- });
2335
- }
2336
2174
  async rewindFiles(sessionId, userMessageId) {
2337
2175
  const transcript = new NativeSessionTranscript({
2338
2176
  sessionId,
2339
2177
  store: this.store(sessionId),
2340
2178
  });
2341
2179
  await transcript.withLease({ kind: 'resume' }, async (lease) => {
2342
- const projected = projectNativeEvents(lease.activeEvents()).filter((entry) => entry.type === 'file-history-snapshot' ||
2180
+ const projected = projectNativeSessionEntries(lease.activeEvents()).filter((entry) => entry.type === 'file-history-snapshot' ||
2343
2181
  entry.type === 'file-history-delta');
2344
2182
  if (projected.length === 0)
2345
2183
  throw new Error(`Native session has no file history: ${sessionId}`);
@@ -2641,7 +2479,7 @@ export class ClaudeSessionService {
2641
2479
  const runUnderLease = async (lease, nativeLease) => {
2642
2480
  const loadedSnapshot = await lease.load();
2643
2481
  let snapshot = {
2644
- entries: projectNativeEvents(nativeLease.activeEvents()),
2482
+ entries: projectNativeSessionEntries(nativeLease.activeEvents()),
2645
2483
  tail: loadedSnapshot.tail,
2646
2484
  };
2647
2485
  const activeTurnMessages = () => {
@@ -2649,7 +2487,7 @@ export class ClaudeSessionService {
2649
2487
  // after each append so memory/compaction sees the live branch.
2650
2488
  snapshot = {
2651
2489
  ...snapshot,
2652
- entries: projectNativeEvents(nativeLease.activeEvents()),
2490
+ entries: projectNativeSessionEntries(nativeLease.activeEvents()),
2653
2491
  };
2654
2492
  return nativeLease.activeMessages();
2655
2493
  };
@@ -3654,7 +3492,7 @@ export class ClaudeSessionService {
3654
3492
  }
3655
3493
  }
3656
3494
  const memorySelection = sessionMemory
3657
- ? await this.selectMemoryPreservedCompact(sessionId, projectNativeEvents(activeNativeLease.activeEvents()))
3495
+ ? await this.selectMemoryPreservedCompact(sessionId, projectNativeSessionEntries(activeNativeLease.activeEvents()))
3658
3496
  : null;
3659
3497
  if (memorySelection) {
3660
3498
  compactableMessages = [
@@ -4350,7 +4188,8 @@ export class ClaudeSessionService {
4350
4188
  }
4351
4189
  const memorySnapshot = activeTurnMessages();
4352
4190
  const nativeMemoryMessageId = nativeLease
4353
- ? projectNativeEvents(nativeLease.activeEvents()).at(-1)?.uuid
4191
+ ? projectNativeSessionEntries(nativeLease.activeEvents()).at(-1)
4192
+ ?.uuid
4354
4193
  : undefined;
4355
4194
  const providerVisibleMessages = [
4356
4195
  ...contextMessages,