praxis-agent 0.67.0 → 0.67.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.
@@ -378,7 +378,6 @@ export declare class ClaudeSessionService {
378
378
  private toolCapabilities;
379
379
  private capabilityToolNames;
380
380
  private teamRegistry;
381
- private logicalTailUuid;
382
381
  }
383
382
  export {};
384
383
  //# sourceMappingURL=session-service.d.ts.map
@@ -33,7 +33,7 @@ import { lastUserPrompt, projectTranscriptDisplay, unresolvedActiveToolCallIds,
33
33
  import { InMemoryTranscriptStore } from '../persistence/in-memory-transcript-store.js';
34
34
  import { NativeTranscriptStore, } from '../persistence/native-transcript-store.js';
35
35
  import { NativeSessionTranscript, } from './native-session-transcript.js';
36
- import { TurnPersistence } from './turn-persistence.js';
36
+ import { deriveTurnProjectionCursor, TurnPersistence, } from './turn-persistence.js';
37
37
  import { TurnAccounting } from './turn-accounting.js';
38
38
  import { CompactionAccounting } from './compaction-accounting.js';
39
39
  import { classifyCompactionError } from './compaction-errors.js';
@@ -2636,7 +2636,7 @@ export class ClaudeSessionService {
2636
2636
  const view = persistence.view();
2637
2637
  return {
2638
2638
  entries: [...view.projectionEntries],
2639
- tail: view.projectionTail,
2639
+ cursor: view.projectionCursor,
2640
2640
  };
2641
2641
  };
2642
2642
  const commitProjection = async (entries) => {
@@ -2797,7 +2797,7 @@ export class ClaudeSessionService {
2797
2797
  const flushRecoveryHookOutcomes = async () => {
2798
2798
  const entries = [];
2799
2799
  let history = projectionSnapshot().entries;
2800
- let parentUuid = this.logicalTailUuid(projectionSnapshot().tail);
2800
+ let parentUuid = projectionSnapshot().cursor.lastEntryId;
2801
2801
  for (const outcome of pendingRecoveryHookOutcomes) {
2802
2802
  const outcomeEntries = createClaudeHookAttachmentEntries(outcome, {
2803
2803
  ...this.translationContext(sessionId, projectionSnapshot()),
@@ -2806,9 +2806,8 @@ export class ClaudeSessionService {
2806
2806
  });
2807
2807
  entries.push(...outcomeEntries);
2808
2808
  history = [...history, ...outcomeEntries];
2809
- const lastEntry = outcomeEntries.at(-1);
2810
- if (typeof lastEntry?.uuid === 'string')
2811
- parentUuid = lastEntry.uuid;
2809
+ const batchCursor = deriveTurnProjectionCursor(outcomeEntries);
2810
+ parentUuid = batchCursor.lastEntryId ?? parentUuid;
2812
2811
  }
2813
2812
  if (entries.length === 0) {
2814
2813
  pendingRecoveryHookOutcomes.length = 0;
@@ -4479,7 +4478,7 @@ export class ClaudeSessionService {
4479
4478
  translationContext(sessionId, snapshot) {
4480
4479
  return {
4481
4480
  sessionId,
4482
- parentUuid: this.logicalTailUuid(snapshot.tail),
4481
+ parentUuid: snapshot.cursor.lastEntryId,
4483
4482
  cwd: this.activeCwd(),
4484
4483
  claudeVersion: this.options.claudeVersion,
4485
4484
  gitBranch: null,
@@ -5254,8 +5253,5 @@ export class ClaudeSessionService {
5254
5253
  }
5255
5254
  return factory(base, operations, sessionId, enabledTools);
5256
5255
  }
5257
- logicalTailUuid(tail) {
5258
- return tail.branchParentId ?? tail.lastEventId;
5259
- }
5260
5256
  }
5261
5257
  //# sourceMappingURL=session-service.js.map
@@ -2,10 +2,13 @@ import type { ModelMessage } from '../core/runtime.js';
2
2
  import type { TranscriptEvent } from '../core/transcript-event.js';
3
3
  import type { NativeTranscriptEntry } from '../native/schema.js';
4
4
  import type { NativeCompactionAppend, NativeInterruption, NativeMessageAppend, NativeSessionTranscriptLease } from './native-session-transcript.js';
5
- import type { NativeTranscriptTail } from '../persistence/native-transcript-store.js';
5
+ export interface TurnProjectionCursor {
6
+ readonly lastEntryId: string | null;
7
+ readonly entryCount: number;
8
+ }
6
9
  export interface TurnPersistenceView {
7
10
  readonly projectionEntries: readonly NativeTranscriptEntry[];
8
- readonly projectionTail: NativeTranscriptTail;
11
+ readonly projectionCursor: TurnProjectionCursor;
9
12
  readonly activeEvents: readonly TranscriptEvent[];
10
13
  readonly activeMessages: readonly ModelMessage[];
11
14
  readonly interruption: NativeInterruption;
@@ -47,7 +50,7 @@ export type TurnPersistenceReceipt = {
47
50
  export declare class TurnPersistence {
48
51
  private readonly input;
49
52
  private projectionEntries;
50
- private projectionTail;
53
+ private projectionCursor;
51
54
  private commitQueue;
52
55
  constructor(input: {
53
56
  readonly native: NativeSessionTranscriptLease;
@@ -58,5 +61,7 @@ export declare class TurnPersistence {
58
61
  commit(command: TurnPersistenceCommand): Promise<TurnPersistenceReceipt>;
59
62
  private commitCommand;
60
63
  private stageProjection;
64
+ private replaceProjection;
61
65
  }
66
+ export declare const deriveTurnProjectionCursor: (entries: readonly NativeTranscriptEntry[]) => TurnProjectionCursor;
62
67
  //# sourceMappingURL=turn-persistence.d.ts.map
@@ -1,32 +1,28 @@
1
1
  import { projectNativeSessionEntries } from './native-session-projection.js';
2
- const emptyProjectionTail = () => ({
3
- byteLength: 0,
4
- lastLineHash: null,
5
- lastEventId: null,
6
- newlineTerminated: true,
7
- });
8
2
  export class TurnPersistence {
9
3
  input;
10
4
  projectionEntries;
11
- projectionTail = emptyProjectionTail();
5
+ projectionCursor;
12
6
  commitQueue = Promise.resolve();
13
7
  constructor(input) {
14
8
  this.input = input;
15
9
  this.projectionEntries = structuredClone(input.initialProjectionEntries
16
10
  ? [...input.initialProjectionEntries]
17
11
  : projectNativeSessionEntries(input.native.activeEvents()));
12
+ this.projectionCursor = deriveTurnProjectionCursor(this.projectionEntries);
18
13
  }
19
14
  view() {
20
15
  return {
21
16
  projectionEntries: structuredClone(this.projectionEntries),
22
- projectionTail: structuredClone(this.projectionTail),
17
+ projectionCursor: structuredClone(this.projectionCursor),
23
18
  activeEvents: structuredClone(this.input.native.activeEvents()),
24
19
  activeMessages: structuredClone(this.input.native.activeMessages()),
25
20
  interruption: structuredClone(this.input.native.interruption()),
26
21
  };
27
22
  }
28
23
  refresh() {
29
- this.projectionEntries = structuredClone(projectNativeSessionEntries(this.input.native.activeEvents()));
24
+ const entries = projectNativeSessionEntries(this.input.native.activeEvents());
25
+ this.replaceProjection(entries);
30
26
  return this.view();
31
27
  }
32
28
  commit(command) {
@@ -49,14 +45,10 @@ export class TurnPersistence {
49
45
  switch (command.kind) {
50
46
  case 'projection': {
51
47
  const staged = this.stageProjection(command.entries);
52
- this.projectionEntries = staged.entries;
53
- this.projectionTail = staged.tail;
54
- const lastProjectionId = [...command.entries]
55
- .reverse()
56
- .find((entry) => typeof entry.uuid === 'string')?.uuid;
48
+ this.replaceProjection(staged.entries, staged.cursor);
57
49
  return {
58
50
  kind: 'projection',
59
- lastProjectionId: typeof lastProjectionId === 'string' ? lastProjectionId : null,
51
+ lastProjectionId: staged.cursor.lastEntryId,
60
52
  };
61
53
  }
62
54
  case 'messages': {
@@ -67,8 +59,7 @@ export class TurnPersistence {
67
59
  : this.stageProjection(command.projectionEntries);
68
60
  const eventId = await this.input.native.appendMessages(command.input);
69
61
  if (staged) {
70
- this.projectionEntries = staged.entries;
71
- this.projectionTail = staged.tail;
62
+ this.replaceProjection(staged.entries, staged.cursor);
72
63
  }
73
64
  return { kind: 'messages', eventId };
74
65
  }
@@ -90,25 +81,22 @@ export class TurnPersistence {
90
81
  if (entries.length === 0)
91
82
  throw new Error('Cannot append an empty projection');
92
83
  const stagedEntries = [...this.projectionEntries, ...entries];
93
- const lastUuidValue = [...entries]
94
- .reverse()
95
- .find((entry) => typeof entry.uuid === 'string')?.uuid;
96
- const lastUuid = typeof lastUuidValue === 'string' ? lastUuidValue : undefined;
97
- const byteLength = this.projectionTail.byteLength + entries.length;
98
84
  return {
99
85
  entries: stagedEntries,
100
- tail: {
101
- ...this.projectionTail,
102
- byteLength,
103
- lastLineHash: `projection:${byteLength}`,
104
- lastEventId: typeof lastUuid === 'string'
105
- ? lastUuid
106
- : this.projectionTail.lastEventId,
107
- ...(this.projectionTail.branchParentId === undefined
108
- ? {}
109
- : { branchParentId: null }),
110
- },
86
+ cursor: deriveTurnProjectionCursor(stagedEntries),
111
87
  };
112
88
  }
89
+ replaceProjection(entries, cursor = deriveTurnProjectionCursor(entries)) {
90
+ this.projectionEntries = structuredClone([...entries]);
91
+ this.projectionCursor = structuredClone(cursor);
92
+ }
113
93
  }
94
+ export const deriveTurnProjectionCursor = (entries) => {
95
+ let lastEntryId = null;
96
+ for (const entry of entries) {
97
+ if (typeof entry.uuid === 'string' && entry.uuid.length > 0)
98
+ lastEntryId = entry.uuid;
99
+ }
100
+ return { lastEntryId, entryCount: entries.length };
101
+ };
114
102
  //# sourceMappingURL=turn-persistence.js.map
@@ -1 +1 @@
1
- {"schema_version":"1.0","source_revision":"git:044ea290901a55dd5e343e78bdcd6a63d0455a00","source_dirty":false,"artifact_sha256":"sha256:272099586a6fe68b899e7ec80e182b404afe590341a24cb90196eebe90d3ce29"}
1
+ {"schema_version":"1.0","source_revision":"git:dc131bb8a371077329b97b3da87c4af7c15301f2","source_dirty":false,"artifact_sha256":"sha256:ea1838f9bf68da8966f2b3dbc5a994e2719c55bc511f3b064e71fdd64cc82f7f"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "praxis-agent",
3
- "version": "0.67.0",
3
+ "version": "0.67.1",
4
4
  "description": "Local-first, single-user general agent for the command line.",
5
5
  "license": "MIT",
6
6
  "author": "wuqisen",