@8monkey/pi-context-history 0.1.0 → 0.2.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.
- package/README.md +7 -2
- package/package.json +1 -1
- package/src/index.ts +57 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# pi-context-history
|
|
2
2
|
|
|
3
|
-
A [Pi](https://github.com/earendil-works/pi-coding-agent) extension that manages conversation context end-to-end. It trims old history, strips stale tool chatter from earlier turns, keeps a rolling session summary,
|
|
3
|
+
A [Pi](https://github.com/earendil-works/pi-coding-agent) extension that manages conversation context end-to-end. It trims old history, strips stale tool chatter from earlier turns, keeps a rolling session summary, folds that summary back into the system prompt, and lets you append messages to the history by hand — so long-running conversations stay lean, focused, and continuous.
|
|
4
4
|
|
|
5
5
|
Each feature is independent and can be turned off individually, so you can run the whole pipeline or just the parts you want.
|
|
6
6
|
|
|
@@ -12,6 +12,7 @@ Each feature is independent and can be turned off individually, so you can run t
|
|
|
12
12
|
| **Strip tool history** | `context` | Removes tool calls and results from prior turns, keeping the current turn's tool interactions intact. |
|
|
13
13
|
| **Generate summary** | `session_start` | Regenerates a stale rolling summary in the background when a session resumes; also available on demand via `/summarize-session`. |
|
|
14
14
|
| **Inject summary** | `before_agent_start` | Folds the rolling summary into the system prompt so the model continues with prior context. |
|
|
15
|
+
| **Append message** | command | Adds a user or assistant message to the end of the history via `/add-user-message` and `/add-assistant-message`. |
|
|
15
16
|
|
|
16
17
|
The summary features are a producer/consumer pair: **Generate summary** writes `~/.pi/agent/summary.md`, and **Inject summary** reads it.
|
|
17
18
|
|
|
@@ -27,13 +28,16 @@ pi install npm:@8monkey/pi-context-history
|
|
|
27
28
|
- **Strip tool history.** Tool calls and results from earlier turns are removed; the current turn is left untouched. At the start of each agent loop the extension marks where the current turn begins (scanning back past the latest tool exchange) and holds that mark steady across the loop, so a running turn is never stripped mid-flight. Before the mark, tool results are dropped and assistant messages lose their tool-call blocks (if nothing else remains, the message goes too).
|
|
28
29
|
- **Generate summary.** When you resume a session whose summary has gone stale — older than `PI_SUMMARY_STALENESS_DAYS`, with a first message older than the window too — the extension rebuilds `~/.pi/agent/summary.md` by shelling out to `pi -p` (extensions, context files, and skills disabled). New and empty sessions are skipped. To override the built-in prompt, drop your own at `prompts/session-summary.md` (project `.pi/` wins over `~/.pi/`); it must contain the `{conversation_history}` placeholder.
|
|
29
30
|
- **Inject summary.** Before each agent run, when `~/.pi/agent/summary.md` exists, its contents are wrapped in a `<summary date="…">` block (the date is the file's modified time) followed by an `<additional_context>` note telling the model to maintain continuity and match the existing language and tone.
|
|
31
|
+
- **Append message.** `/add-user-message <text>` and `/add-assistant-message <text>` write a message with the matching role to the end of the session history. The entry is persisted immediately but enters the live context on the next rebuild (resume or branch), since Pi has no public way to inject into a running turn. Appending an assistant message requires a model to be selected, as the message records its identity.
|
|
30
32
|
|
|
31
33
|
Zero runtime dependencies. Pi loads the TypeScript directly, so there's no build step. Runs under Node or Bun.
|
|
32
34
|
|
|
33
|
-
##
|
|
35
|
+
## Commands
|
|
34
36
|
|
|
35
37
|
| Command | Description |
|
|
36
38
|
|---|---|
|
|
39
|
+
| `/add-assistant-message <text>` | Append an assistant message to the end of the history. Persisted immediately; enters context on the next rebuild. Available only when the **Append message** feature is enabled. |
|
|
40
|
+
| `/add-user-message <text>` | Append a user message to the end of the history. Persisted immediately; enters context on the next rebuild. Available only when the **Append message** feature is enabled. |
|
|
37
41
|
| `/summarize-session` | Regenerate the current session's summary on demand, ignoring the staleness window. Writes `~/.pi/agent/summary.md` and reports success, failure, or an empty session. Available only when the **Generate summary** feature is enabled. |
|
|
38
42
|
|
|
39
43
|
## Configuration
|
|
@@ -50,6 +54,7 @@ Every feature is **on by default** and switched off by setting its flag to `fals
|
|
|
50
54
|
| `PI_STRIP_TOOL_HISTORY` | on | Strip tool history |
|
|
51
55
|
| `PI_GENERATE_SUMMARY` | on | Generate summary |
|
|
52
56
|
| `PI_INJECT_SUMMARY` | on | Inject summary |
|
|
57
|
+
| `PI_APPEND_MESSAGE` | on | Append message |
|
|
53
58
|
|
|
54
59
|
### Settings
|
|
55
60
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@8monkey/pi-context-history",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Pi extension that manages conversation context: trims old history, strips stale tool calls, and keeps a rolling summary fed back into the system prompt. Each feature toggles independently.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { writeFileSync } from "node:fs";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
|
-
import type { ExtensionAPI,
|
|
4
|
+
import type { ExtensionAPI, SessionManager } from "@earendil-works/pi-coding-agent";
|
|
5
5
|
import { buildContextPrompt } from "./build-prompt.ts";
|
|
6
6
|
import { featureEnabled, HISTORY_DAYS, SUMMARY_STALENESS_DAYS } from "./config.ts";
|
|
7
7
|
import { filterByAge } from "./filter.ts";
|
|
@@ -17,6 +17,14 @@ import {
|
|
|
17
17
|
|
|
18
18
|
const HISTORY_MS = HISTORY_DAYS * 86_400_000;
|
|
19
19
|
const SUMMARY_PATH = join(homedir(), ".pi", "agent", "summary.md");
|
|
20
|
+
const ZERO_USAGE = {
|
|
21
|
+
input: 0,
|
|
22
|
+
output: 0,
|
|
23
|
+
cacheRead: 0,
|
|
24
|
+
cacheWrite: 0,
|
|
25
|
+
totalTokens: 0,
|
|
26
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
27
|
+
};
|
|
20
28
|
|
|
21
29
|
function registerTrimHistory(pi: ExtensionAPI) {
|
|
22
30
|
pi.on("context", (event) => {
|
|
@@ -76,7 +84,7 @@ function registerGenerateSummary(pi: ExtensionAPI) {
|
|
|
76
84
|
|
|
77
85
|
pi.registerCommand("summarize-session", {
|
|
78
86
|
description: "Regenerate the current session's summary now (ignores staleness)",
|
|
79
|
-
handler: async (_args, ctx
|
|
87
|
+
handler: async (_args, ctx) => {
|
|
80
88
|
const entries = ctx.sessionManager.getEntries() as TranscriptEntry[];
|
|
81
89
|
let result: string | "empty";
|
|
82
90
|
try {
|
|
@@ -106,9 +114,56 @@ function registerInjectSummary(pi: ExtensionAPI) {
|
|
|
106
114
|
});
|
|
107
115
|
}
|
|
108
116
|
|
|
117
|
+
function registerAppendMessage(pi: ExtensionAPI) {
|
|
118
|
+
pi.registerCommand("add-user-message", {
|
|
119
|
+
description: "Append a user message to the end of the conversation history",
|
|
120
|
+
handler: async (args, ctx) => {
|
|
121
|
+
const text = args.trim();
|
|
122
|
+
if (!text) {
|
|
123
|
+
if (ctx.hasUI) ctx.ui.notify("Usage: /add-user-message <text>", "warning");
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const session = ctx.sessionManager as SessionManager;
|
|
127
|
+
session.appendMessage({ role: "user", content: [{ type: "text", text }], timestamp: Date.now() });
|
|
128
|
+
if (ctx.hasUI) ctx.ui.notify("Appended a user message; it applies on the next session rebuild.", "info");
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
pi.registerCommand("add-assistant-message", {
|
|
133
|
+
description: "Append an assistant message to the end of the conversation history",
|
|
134
|
+
handler: async (args, ctx) => {
|
|
135
|
+
const text = args.trim();
|
|
136
|
+
if (!text) {
|
|
137
|
+
if (ctx.hasUI) ctx.ui.notify("Usage: /add-assistant-message <text>", "warning");
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (!ctx.model) {
|
|
141
|
+
if (ctx.hasUI) ctx.ui.notify("Cannot append an assistant message: no model selected.", "error");
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
const { api, provider, id } = ctx.model;
|
|
145
|
+
const session = ctx.sessionManager as SessionManager;
|
|
146
|
+
session.appendMessage({
|
|
147
|
+
role: "assistant",
|
|
148
|
+
content: [{ type: "text", text }],
|
|
149
|
+
api,
|
|
150
|
+
provider,
|
|
151
|
+
model: id,
|
|
152
|
+
usage: ZERO_USAGE,
|
|
153
|
+
stopReason: "stop",
|
|
154
|
+
timestamp: Date.now(),
|
|
155
|
+
});
|
|
156
|
+
if (ctx.hasUI) {
|
|
157
|
+
ctx.ui.notify("Appended an assistant message; it applies on the next session rebuild.", "info");
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
109
163
|
export default function (pi: ExtensionAPI) {
|
|
110
164
|
if (featureEnabled("PI_TRIM_HISTORY")) registerTrimHistory(pi);
|
|
111
165
|
if (featureEnabled("PI_STRIP_TOOL_HISTORY")) registerStripToolHistory(pi);
|
|
112
166
|
if (featureEnabled("PI_GENERATE_SUMMARY")) registerGenerateSummary(pi);
|
|
113
167
|
if (featureEnabled("PI_INJECT_SUMMARY")) registerInjectSummary(pi);
|
|
168
|
+
if (featureEnabled("PI_APPEND_MESSAGE")) registerAppendMessage(pi);
|
|
114
169
|
}
|