pi-posthorse 0.10.11 → 0.10.12

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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/rollover.ts +32 -16
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-posthorse",
3
- "version": "0.10.11",
3
+ "version": "0.10.12",
4
4
  "type": "module",
5
5
  "description": "Posthorse: fresh context, same journey. No-summary context rollover for Pi, with sparse budget reminders, handoffs, notes, and history.",
6
6
  "keywords": [
package/src/rollover.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type {
2
2
  BoundaryResult,
3
- ContextEvent,
3
+ ContextWithSystemEvent,
4
4
  ExtensionAPI,
5
5
  ExtensionContext,
6
6
  SessionBeforeCompactEvent,
@@ -113,25 +113,41 @@ function staleReminderPredicate(
113
113
  isReminderType(message.customType) &&
114
114
  (!enabled || !reminderMatches(message.details, fingerprint));
115
115
  }
116
+ function retainedTailEnd(
117
+ messages: ContextWithSystemEvent["messages"],
118
+ start: number,
119
+ count: number,
120
+ ): number | undefined {
121
+ let remaining = count;
122
+ for (let index = start; index < messages.length; index += 1) {
123
+ if (messages[index]?.role !== "system") {
124
+ remaining -= 1;
125
+ }
126
+ if (remaining === 0) {
127
+ return index + 1;
128
+ }
129
+ }
130
+ return undefined;
131
+ }
116
132
  function chronologicalRetainedTail(
117
- messages: ContextEvent["messages"],
133
+ messages: ContextWithSystemEvent["messages"],
118
134
  ctx: ExtensionContext,
119
135
  stale: StaleReminderPredicate,
120
- ): ContextEvent["messages"] {
121
- const first = messages[0];
122
- if (
123
- messages.length >= 2 &&
124
- first?.role === "compactionSummary" &&
125
- hasRetainedRolloverMarker(first.summary)
126
- ) {
136
+ ): ContextWithSystemEvent["messages"] {
137
+ const summaryIndex = messages.findIndex((message) => message.role !== "system");
138
+ const first = messages[summaryIndex];
139
+ if (first?.role === "compactionSummary" && hasRetainedRolloverMarker(first.summary)) {
127
140
  const count = countRetainedMessages(ctx, stale);
128
- if (count > 0 && 1 + count <= messages.length) {
129
- const retainedSlice = messages.slice(1, 1 + count);
130
- const afterSlice = messages.slice(1 + count);
131
- if (retainedSlice[0]?.role !== "assistant") {
132
- return [...retainedSlice, first, ...afterSlice];
141
+ const end = count > 0 ? retainedTailEnd(messages, summaryIndex + 1, count) : undefined;
142
+ if (end !== undefined) {
143
+ const prefix = messages.slice(0, summaryIndex);
144
+ const retainedSlice = messages.slice(summaryIndex + 1, end);
145
+ const afterSlice = messages.slice(end);
146
+ if (retainedSlice.find((message) => message.role !== "system")?.role !== "assistant") {
147
+ return [...prefix, ...retainedSlice, first, ...afterSlice];
133
148
  }
134
149
  return [
150
+ ...prefix,
135
151
  {
136
152
  role: "custom",
137
153
  customType: "posthorse-retained-tail",
@@ -152,7 +168,7 @@ function registerReminderFilter(
152
168
  policy: SnapshotReader,
153
169
  reminders: ReminderLookup,
154
170
  ): void {
155
- pi.on("context", (event, ctx) => {
171
+ pi.on("context_with_system", (event, ctx) => {
156
172
  const stale = staleReminderPredicate(event.messages, ctx, policy, reminders);
157
173
  const filtered = event.messages.some(stale)
158
174
  ? event.messages.filter((message) => !stale(message))
@@ -411,8 +427,8 @@ export function registerRollover(
411
427
  pi.on("session_tree", () => {
412
428
  reminders.reset();
413
429
  });
414
- registerGuidance(pi, policy);
415
430
  registerReminderFilter(pi, policy, reminders);
431
+ registerGuidance(pi, policy);
416
432
  registerAutomaticRollover(pi, policy, activeToolTokens, resources.notes);
417
433
  pi.on("turn_end", (event, ctx) => {
418
434
  const summary = resetRequests.take(event.toolResults);