pi-posthorse 0.10.7 → 0.10.9
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.
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/budget.ts +10 -9
- package/src/rollover.ts +6 -9
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ Give Pi your task. For example:
|
|
|
23
23
|
|
|
24
24
|
## How rollover works
|
|
25
25
|
|
|
26
|
-
Posthorse can
|
|
26
|
+
Posthorse can send a routine task-note reminder before rollover. The reminder tells the model to save current task state if needed, then immediately continue the prescribed work. The context window is not a task deadline. The reminder does not require `new_context` or wake an agent after its final answer. Large turns can reach rollover before the reminder. See [Reminder timing](docs/reminder-timing.md) for the trigger and its relationship to Pi's reserve and retention settings.
|
|
27
27
|
|
|
28
28
|
Automatic rollover retains a safe recent-message tail using Pi's `compaction.keepRecentTokens`, alongside a bounded recovery record for discarded inputs and tool evidence. It never calls a summarization model. The model must restore notes and check live state before it continues. Optional `new_context` deliberately retains no prior messages; manual `/compact` uses Pi's normal summarization.
|
|
29
29
|
|
package/package.json
CHANGED
package/src/budget.ts
CHANGED
|
@@ -13,8 +13,13 @@ import {
|
|
|
13
13
|
import { imagesOf, textOf } from "./message-text.ts";
|
|
14
14
|
|
|
15
15
|
const MIN_USABLE_TOKENS = Math.ceil(MAX_HANDOFF_CHARS / 4) * 2;
|
|
16
|
-
export const
|
|
17
|
-
|
|
16
|
+
export const CHECKPOINT_GUIDANCE = `Keep working on the assigned task; Pi handles context rollover automatically.
|
|
17
|
+
|
|
18
|
+
The current context window is not a deadline for finishing your task. Do not reduce scope, skip prescribed steps or verification, or issue a final progress summary because rollover is approaching.
|
|
19
|
+
|
|
20
|
+
Update the task's current-state note if needed: goal, progress, decisions, and next steps. Use available file-editing tools at its absolute path; use notes write only for creation, substantial restructuring, or when editing tools are unavailable. Leave an already-current note unchanged. Then immediately execute the next prescribed task step in this run. No new_context call, waiting for rollover, or user "continue" is needed.
|
|
21
|
+
|
|
22
|
+
Finish when the requested work and required verification are complete, or report a genuine blocker. Approaching context rollover is not a blocker.`;
|
|
18
23
|
export type Budget = {
|
|
19
24
|
readonly contextWindow: number;
|
|
20
25
|
readonly reserveTokens: number;
|
|
@@ -76,15 +81,11 @@ function automaticGuidance(budget: Budget | undefined, enabled: boolean): string
|
|
|
76
81
|
if (budget !== undefined && !budget.supported) {
|
|
77
82
|
return unsupportedMessage(budget);
|
|
78
83
|
}
|
|
79
|
-
const deadline =
|
|
80
|
-
budget === undefined
|
|
81
|
-
? "the configured Pi context limit"
|
|
82
|
-
: `${Math.max(1, Math.round((budget.rolloverAt / budget.contextWindow) * 100))}% used`;
|
|
83
84
|
const line =
|
|
84
85
|
budget === undefined
|
|
85
86
|
? ""
|
|
86
87
|
: ` The rollover line is ${budget.rolloverAt.toLocaleString("en-US")} tokens used under the available Pi settings.`;
|
|
87
|
-
return
|
|
88
|
+
return `${CHECKPOINT_GUIDANCE}\nAutomatic rollover follows Pi's compaction setting and retains a safe recent-message tail using compaction.keepRecentTokens, without model summarization.${line} At most one routine task-note reminder may arrive at the end of a working turn, never on a turn that ends the run. new_context is an optional deliberate clean reset, not a checkpoint requirement.`;
|
|
88
89
|
}
|
|
89
90
|
export function buildGuidance(ctx: PolicyContext): string {
|
|
90
91
|
const budget = budgetFor(ctx);
|
|
@@ -93,10 +94,10 @@ export function buildGuidance(ctx: PolicyContext): string {
|
|
|
93
94
|
budget === undefined
|
|
94
95
|
? "Configured context capacity is unknown."
|
|
95
96
|
: `Configured context capacity: ${budget.contextWindow.toLocaleString("en-US")} tokens. This is Pi's best available native limit, not remaining space or a measured provider boundary. Fresh windows use the active configuration; system instructions, tools, the handoff, retained recent messages, and new messages consume part of it.`;
|
|
96
|
-
return `##
|
|
97
|
+
return `## Automatic context management (Posthorse)
|
|
98
|
+
${automaticGuidance(budget, enabled)}
|
|
97
99
|
${capacity}
|
|
98
100
|
Do not guess context capacity or remaining space from response-token limits or reasoning budgets. Before reporting a remaining-token count or changing your work plan because of context limits, call get_context_remaining. If usage is unknown, report it as unknown. No routine budget checks are needed.
|
|
99
|
-
${automaticGuidance(budget, enabled)}
|
|
100
101
|
After a rollover, earlier conversation stays in history. Restore notes and todos, then verify live state before stateful or external work; automatic handoffs record inputs, not progress.
|
|
101
102
|
Keep one concise current-state note per task. Preserve decisions and safety constraints; link fuller evidence and history instead of copying them. Edit changed sections rather than resending unchanged content.
|
|
102
103
|
Write handoffs and notes as normal readable prose; notes and history search match literal text.`;
|
package/src/rollover.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type {
|
|
|
5
5
|
ExtensionContext,
|
|
6
6
|
TurnEndEvent,
|
|
7
7
|
} from "@earendil-works/pi-coding-agent";
|
|
8
|
-
import { budgetFor,
|
|
8
|
+
import { budgetFor, CHECKPOINT_GUIDANCE, freshPayloadChars, type Budget } from "./budget.ts";
|
|
9
9
|
import {
|
|
10
10
|
isRecord,
|
|
11
11
|
isReminderType,
|
|
@@ -83,9 +83,7 @@ function endsRun(
|
|
|
83
83
|
ctx.hasPendingMessages?.() !== true
|
|
84
84
|
);
|
|
85
85
|
}
|
|
86
|
-
function reminderBudget(
|
|
87
|
-
host: PolicyContext,
|
|
88
|
-
): { readonly budget: Budget; readonly tokens: number } | undefined {
|
|
86
|
+
function reminderBudget(host: PolicyContext): Budget | undefined {
|
|
89
87
|
const usage = host.getContextUsage();
|
|
90
88
|
if (usage === undefined || usage.tokens === null || usage.contextWindow <= 0) {
|
|
91
89
|
return undefined;
|
|
@@ -100,14 +98,13 @@ function reminderBudget(
|
|
|
100
98
|
return undefined;
|
|
101
99
|
}
|
|
102
100
|
const buffer = Math.min(REMINDER_BUFFER_TOKENS, Math.floor(budget.usable * 0.1));
|
|
103
|
-
return usage.tokens < budget.rolloverAt - buffer ? undefined :
|
|
101
|
+
return usage.tokens < budget.rolloverAt - buffer ? undefined : budget;
|
|
104
102
|
}
|
|
105
103
|
function sendReminder(
|
|
106
104
|
pi: ExtensionAPI,
|
|
107
105
|
ctx: ExtensionContext,
|
|
108
106
|
available: {
|
|
109
107
|
readonly budget: Budget;
|
|
110
|
-
readonly tokens: number;
|
|
111
108
|
readonly pendingMessages: readonly {
|
|
112
109
|
readonly role: string;
|
|
113
110
|
readonly customType?: string | undefined;
|
|
@@ -116,7 +113,7 @@ function sendReminder(
|
|
|
116
113
|
},
|
|
117
114
|
reminders: ReminderLookup,
|
|
118
115
|
): void {
|
|
119
|
-
const { budget
|
|
116
|
+
const { budget } = available;
|
|
120
117
|
const state = reminders.read(ctx);
|
|
121
118
|
const fingerprint: ReminderFingerprint = {
|
|
122
119
|
windowId: state.windowId,
|
|
@@ -137,7 +134,7 @@ function sendReminder(
|
|
|
137
134
|
pi.sendMessage(
|
|
138
135
|
{
|
|
139
136
|
customType: REMINDER_TYPE,
|
|
140
|
-
content: `[posthorse]
|
|
137
|
+
content: `[posthorse] Routine task-note update.\n${CHECKPOINT_GUIDANCE}`,
|
|
141
138
|
display: true,
|
|
142
139
|
details: fingerprint,
|
|
143
140
|
},
|
|
@@ -481,7 +478,7 @@ export function registerRollover(
|
|
|
481
478
|
sendReminder(
|
|
482
479
|
pi,
|
|
483
480
|
ctx,
|
|
484
|
-
{
|
|
481
|
+
{ budget: available, pendingMessages: event.context.pendingMessages },
|
|
485
482
|
reminders,
|
|
486
483
|
);
|
|
487
484
|
}
|