pi-posthorse 0.6.0 → 0.8.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 +39 -37
- package/index.ts +397 -314
- package/package.json +6 -6
- package/ui.ts +8 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-posthorse",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
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": ["pi-package", "pi-extension", "context", "posthorse", "rollover"],
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"engines": {
|
|
14
14
|
"node": ">=24.12.0"
|
|
15
15
|
},
|
|
16
|
-
"packageManager": "npm@12.
|
|
16
|
+
"packageManager": "npm@12.2.0",
|
|
17
17
|
"pi": {
|
|
18
18
|
"extensions": ["./index.ts"],
|
|
19
19
|
"image": "https://raw.githubusercontent.com/fitchmultz/pi-posthorse/main/diagram.png"
|
|
@@ -42,11 +42,11 @@
|
|
|
42
42
|
}
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@earendil-works/pi-ai": "0.
|
|
46
|
-
"@earendil-works/pi-coding-agent": "0.
|
|
47
|
-
"@earendil-works/pi-tui": "0.
|
|
45
|
+
"@earendil-works/pi-ai": "1.0.0",
|
|
46
|
+
"@earendil-works/pi-coding-agent": "1.0.0",
|
|
47
|
+
"@earendil-works/pi-tui": "1.0.0",
|
|
48
48
|
"@types/node": "24.19.0",
|
|
49
|
-
"typebox": "1.3.
|
|
49
|
+
"typebox": "1.3.27",
|
|
50
50
|
"typescript": "7.0.2"
|
|
51
51
|
}
|
|
52
52
|
}
|
package/ui.ts
CHANGED
|
@@ -4,10 +4,10 @@ import { Box, MouseRegion, Text, stripTerminalSequences, truncateToWidth, type C
|
|
|
4
4
|
/** Display-only facts and offsets into content, never a second copy of a note or history page. */
|
|
5
5
|
export type PosthorseDisplay =
|
|
6
6
|
| { kind: "context"; usage?: { tokens: number | null; contextWindow: number; percent: number | null }; rollover?: "enabled" | "disabled" | "unsupported"; rolloverAt?: number }
|
|
7
|
-
| { kind: "notes-list" | "notes-search"; count: number; page?: { offset: number; end: number; total: number } }
|
|
8
|
-
| { kind: "note-read"; offset: number; end: number; total: number }
|
|
7
|
+
| { kind: "notes-list" | "notes-search"; count: number; headerLength?: number; page?: { offset: number; end: number; total: number } }
|
|
8
|
+
| { kind: "note-read"; headerLength?: number; offset: number; end: number; total: number }
|
|
9
9
|
| { kind: "note-write" | "note-append" | "new-context" }
|
|
10
|
-
| { kind: "history-search"; entries: Array<{ headerLength: number; length: number }>; footerLength?: number }
|
|
10
|
+
| { kind: "history-search"; entries: Array<{ headerLength: number; length: number }>; footerLength?: number; more?: boolean; skipped?: number }
|
|
11
11
|
| { kind: "history-read"; headerLength: number; offset: number; end: number; total: number; imageOffset?: number; imageEnd?: number; imageTotal?: number };
|
|
12
12
|
|
|
13
13
|
type ToolName = "notes" | "history" | "get_context_remaining" | "new_context";
|
|
@@ -62,7 +62,7 @@ export function toolCards(name: ToolName): Pick<ToolDefinition, "renderCall" | "
|
|
|
62
62
|
const args = argsOf(rawArgs);
|
|
63
63
|
const action = name === "notes" || name === "history" ? ` · ${argument(args.op, "op")}` : name === "new_context" ? " · request" : "";
|
|
64
64
|
const status = context.isError ? " · error" : context.isPartial ? context.executionStarted ? " · running" : " · preparing" : "";
|
|
65
|
-
const target = args.op === "search" ? ` · “${argument(args.query, "query")}”` : name === "notes" && args.op !== "list" ? ` · ${argument(args.path, "path")}` : name === "history" && args.op === "read" ? ` · ${argument(args.id, "id")}` : "";
|
|
65
|
+
const target = args.op === "search" ? ` · “${argument(args.query, "query")}”` : name === "notes" && (args.op !== "list" || args.path !== undefined) ? ` · ${argument(args.path, "path")}` : name === "history" && args.op === "read" ? ` · ${argument(args.id, "id")}` : "";
|
|
66
66
|
const label = `${context.isPartial ? "…" : context.expanded ? "▾" : "▸"} ${titles[name]}${action}${status}${target}`;
|
|
67
67
|
return {
|
|
68
68
|
invalidate() {},
|
|
@@ -103,7 +103,7 @@ export function toolCards(name: ToolName): Pick<ToolDefinition, "renderCall" | "
|
|
|
103
103
|
case "note-read": summary = pageSummary(display); break;
|
|
104
104
|
case "note-write": summary = args.content === "" ? "Cleared note" : "Saved note"; break;
|
|
105
105
|
case "note-append": summary = "Appended to note"; break;
|
|
106
|
-
case "history-search": if (Array.isArray(display.entries) && (!display.entries.length || sections)) summary = `${display.entries.length ? `${n(display.entries.length)} matches` : "No matches"} · ${args.all === true ? "all sessions" : "current branch"}${display.footerLength ? "\nMore results; continue with cursor" : ""}`; break;
|
|
106
|
+
case "history-search": if (Array.isArray(display.entries) && (!display.entries.length || sections)) summary = `${display.entries.length ? `${n(display.entries.length)} matches` : "No matches"} · ${args.all === true ? "all sessions" : "current branch"}${display.skipped ? ` · ${n(display.skipped)} in context skipped` : ""}${(display.more ?? display.footerLength) ? "\nMore results; continue with cursor" : ""}`; break;
|
|
107
107
|
case "history-read":
|
|
108
108
|
summary = pageSummary(display);
|
|
109
109
|
if (display.imageTotal && display.imageEnd !== undefined) {
|
|
@@ -127,7 +127,8 @@ export function toolCards(name: ToolName): Pick<ToolDefinition, "renderCall" | "
|
|
|
127
127
|
const submittedText = textBlock(submitted, theme);
|
|
128
128
|
const attachmentText = textBlock(attachment, theme, "muted");
|
|
129
129
|
// Old results have no spans. Only the preview sheds the known history prefix.
|
|
130
|
-
const
|
|
130
|
+
const noteHeaderLength = !context.isError && (display?.kind === "note-read" || display?.kind === "notes-list") ? display.headerLength ?? 0 : 0;
|
|
131
|
+
const preview = sections ? sections.map(({ body }) => body).join("\n") : noteHeaderLength ? body.slice(noteHeaderLength) : name === "history" && !context.isError ? body.replace(/^[^\n]*?\[window [^\]\n]+\] \[[^\]\n]+\](?: \[chars \d+-\d+ of \d+\])? /gm, "") : body;
|
|
131
132
|
const previewText = textBlock(preview, theme, color);
|
|
132
133
|
const searchPreviews = sections && display?.kind === "history-search" ? sections.slice(0, 3).map(({ body }) => theme.fg("toolOutput", clean(body).replace(/\s+/g, " "))) : undefined;
|
|
133
134
|
const summaryOnly = display?.kind === "context" || display?.kind === "new-context" || display?.kind === "note-write" || display?.kind === "note-append" || ((display?.kind === "notes-list" || display?.kind === "notes-search") && display.count === 0) || (display?.kind === "note-read" && display.total === 0) || (display?.kind === "history-search" && Array.isArray(display.entries) && display.entries.length === 0);
|
|
@@ -142,7 +143,7 @@ export function toolCards(name: ToolName): Pick<ToolDefinition, "renderCall" | "
|
|
|
142
143
|
? searchPreviews.map((line) => truncateToWidth(line, width))
|
|
143
144
|
: previewText.render(width);
|
|
144
145
|
const shown = previewRows.slice(0, Math.max(0, Math.min(3, 5 - summaryRows.length - (attachment ? 1 : 0))));
|
|
145
|
-
const hidden = summaryOnly || previewRows.length > shown.length || Boolean(sections || submitted);
|
|
146
|
+
const hidden = summaryOnly || previewRows.length > shown.length || Boolean(sections || submitted || noteHeaderLength);
|
|
146
147
|
return [...summaryRows, ...shown, ...(attachment ? [truncateToWidth(theme.fg("muted", attachment), width)] : []), ...(hidden ? [hint(theme, width)] : [])];
|
|
147
148
|
},
|
|
148
149
|
};
|