bermudis-pi-goodies 0.29.0 → 0.30.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 +6 -6
- package/copy-trajectory.ts +71 -38
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,18 +6,18 @@ extensions. One entry point, thirteen independent features.
|
|
|
6
6
|
| Feature | Command / hook | What it does |
|
|
7
7
|
| ------------------- | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
8
8
|
| `copy-with-model` | `/copy-with-model` | Copy last assistant message to the clipboard in a code fence tagged with the model name. |
|
|
9
|
-
| `copy-trajectory` | `/copy-trajectory [thinking]` | Copy the whole conversation (user + assistant text, tool calls stripped) to the clipboard; `thinking` also includes assistant thinking blocks.
|
|
9
|
+
| `copy-trajectory` | `/copy-trajectory [thinking]` | Copy the whole conversation (user + assistant text, plus injected context later turns may answer — displayed custom messages such as side-consultation handoffs and external-change diffs, plus branch summaries; tool calls stripped) to the clipboard; `thinking` also includes assistant thinking blocks. Compaction summaries are omitted because the raw originals stay on the copied branch. |
|
|
10
10
|
| `name-with-ai` | `/name-with-ai [name]` | Generate a short session name from the first user message (or set one manually). |
|
|
11
|
-
| `prefer-tools` | hook (no command) | Blocks legacy tools: `rm` → `trash <path>` (and `trash-rm`/`trash-empty`, which delete permanently), `python`/`pip`/`pytest`/`mypy` are not blocked (removed 2026-10-24 — steering to `uv` is AGENTS.md's job, not the hook's). Bash `rg` is allowed, except the replace flag: `-r` (including clusters like `-rn`) is blocked because it is `--replace` and silently replaces matched text — use `--replace` explicitly if you mean it. The built-in grep tool still works.
|
|
11
|
+
| `prefer-tools` | hook (no command) | Blocks legacy tools: `rm` → `trash <path>` (and `trash-rm`/`trash-empty`, which delete permanently), `python`/`pip`/`pytest`/`mypy` are not blocked (removed 2026-10-24 — steering to `uv` is AGENTS.md's job, not the hook's). Bash `rg` is allowed, except the replace flag: `-r` (including clusters like `-rn`) is blocked because it is `--replace` and silently replaces matched text — use `--replace` explicitly if you mean it. The built-in grep tool still works. |
|
|
12
12
|
| `keep-model-on-new` | hook (no command) | Keep the active model when `/new` starts a fresh session instead of reverting to pi's saved default model. |
|
|
13
13
|
| `model-thinking` | `/model-thinking` | Per-model default thinking levels: save the current level as this model's default and get it back on every switch to that model, instead of pi's global default. |
|
|
14
14
|
| `clean-tui` | tool overrides (no command) | Collapse built-in tool output for a cleaner TUI: back-to-back same-tool calls share one block (e.g. `read ×2`) until a boundary — visible text (assistant prose or a typed user message) or a thinking block (even an empty one, as OpenAI emits between tool calls) — so reasoning-per-call models render one block per call. Images stay visible without expanding, expand a row with ctrl+o to see the full command and results/diffs. Long bash commands get an AI-generated summary once you pick a model with `/goodies summary-model <provider/model>` (see "Smart summaries" below) — expanding a row swaps the summary back out for the raw command. While enabled, also flips `@bermudi/pi-codex`'s `apply_patch`/`web_search` into the same burst style. Long thinking runs can show a live plain-English line above the editor (`/goodies thinking-summaries on`) instead of a static `Thinking...` — see "Smart summaries". |
|
|
15
|
-
| `review` | `/review`, `/end-review` | Code review workflow: review uncommitted changes, a branch, a commit, a commit range (`A..B`/`A...B`), a GitHub PR, or folders. Prioritized findings with actionable follow-ups. Targets tab-complete. Works in the terminal and in RPC hosts like T3 Code (plain selectors replace the search-as-you-type ones outside the TUI).
|
|
15
|
+
| `review` | `/review`, `/end-review` | Code review workflow: review uncommitted changes, a branch, a commit, a commit range (`A..B`/`A...B`), a GitHub PR, or folders. Prioritized findings with actionable follow-ups. Targets tab-complete. Works in the terminal and in RPC hosts like T3 Code (plain selectors replace the search-as-you-type ones outside the TUI). |
|
|
16
16
|
| `kilo` | provider | Access Kilo Gateway models via `/login kilo` or `KILO_API_KEY`. |
|
|
17
|
-
| `provider-balance` | footer (no command) | Show remaining Kilo, OpenRouter, or CommandCode credits, z.ai token-plan quota, Anthropic Pro/Max subscription usage (including `claude-code`), or OpenAI Codex quota on the right side of the working-directory footer line.
|
|
17
|
+
| `provider-balance` | footer (no command) | Show remaining Kilo, OpenRouter, or CommandCode credits, z.ai token-plan quota, Anthropic Pro/Max subscription usage (including `claude-code`), or OpenAI Codex quota on the right side of the working-directory footer line. |
|
|
18
18
|
| `tps` | hook (no command) | Notify tokens/sec and in/out/cache token usage at the end of each agent turn. |
|
|
19
19
|
| `vision` | `vision` tool, `/vision` | Ask a vision model targeted questions about an image file and get a text answer — for models that can't see images. Follow-ups via `followUp: true`. Self-hides when the active model has image input. |
|
|
20
|
-
| `side` | `/side`, `/end-side-session`
|
|
20
|
+
| `side` | `/side`, `/end-side-session` | Consult a second model alongside the session. `/side [provider/model-id]` parks the main agent (branch tip + model recorded in a marker entry) and opens a side conversation on its own tree limb; the side model sees the main conversation as one attributed quote — “a transcript of a session you were not part of”, untrusted evidence, not its own history — via a per-request context lens. `/end-side-session [trajectory\|summary\|nothing]` picks the handoff at exit: full transcript quote, a summary written by the side model, or nothing; the main branch stays clean either way. Arguments tab-complete. |
|
|
21
21
|
| `goodies` | `/goodies` | Toggle individual features on/off without losing the rest. Also supports `/goodies summary-model [provider/model]` to pick the model used for AI bash-command summaries, and `/goodies thinking-summaries <on\|off>` for live thinking summaries. State persists to `~/.pi/agent/goodies.json`. Arguments tab-complete. |
|
|
22
22
|
|
|
23
23
|
## Install
|
|
@@ -25,7 +25,7 @@ extensions. One entry point, thirteen independent features.
|
|
|
25
25
|
First install, pinned to a published version:
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
pi install npm:bermudis-pi-goodies@0.
|
|
28
|
+
pi install npm:bermudis-pi-goodies@0.30.0
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
Picking up a new release on an existing install (`pi install` is not the
|
package/copy-trajectory.ts
CHANGED
|
@@ -2,10 +2,19 @@
|
|
|
2
2
|
* copy-trajectory — /copy-trajectory
|
|
3
3
|
*
|
|
4
4
|
* Copies the current session's trajectory to the system clipboard as plain
|
|
5
|
-
* text, keeping only the
|
|
6
|
-
* assistant text
|
|
5
|
+
* text, keeping only what the conversation actually ran on: user and
|
|
6
|
+
* assistant text, plus injected context that later turns may answer —
|
|
7
|
+
* displayed custom_message entries (side-consultation handoffs,
|
|
8
|
+
* external-change diffs, ketamine summaries) and branch summaries (pi-native,
|
|
9
|
+
* the only record of an abandoned limb). Without those, turns replying to
|
|
10
|
+
* injected material ("the consultant's other points…") dangle without
|
|
11
|
+
* their referent.
|
|
12
|
+
* Tool calls, tool results, and session metadata are stripped. Compaction
|
|
13
|
+
* summaries are skipped on purpose: getBranch() is the raw parent chain, so
|
|
14
|
+
* the pre-compaction originals are still on the branch and the summary
|
|
15
|
+
* would only duplicate them.
|
|
7
16
|
*
|
|
8
|
-
* /copy-trajectory copy user + assistant text
|
|
17
|
+
* /copy-trajectory copy user + assistant text + injected context
|
|
9
18
|
* /copy-trajectory thinking also include assistant thinking blocks
|
|
10
19
|
*
|
|
11
20
|
* Uses ctx.sessionManager.getBranch() for the active branch (the raw parent
|
|
@@ -38,10 +47,13 @@ const extractThinkingParts = (content: unknown): string[] => {
|
|
|
38
47
|
};
|
|
39
48
|
|
|
40
49
|
type Turn = {
|
|
41
|
-
role: "User" | "Assistant";
|
|
50
|
+
role: "User" | "Assistant" | "Context";
|
|
42
51
|
/** For assistant turns: the model that actually served the reply (or the
|
|
43
52
|
* requested model when the provider doesn't report the resolved one). */
|
|
44
53
|
model?: string;
|
|
54
|
+
/** For context turns: what injected the content (customType, or a fixed
|
|
55
|
+
* label for pi-native entries like branch summaries). */
|
|
56
|
+
source?: string;
|
|
45
57
|
body: string;
|
|
46
58
|
};
|
|
47
59
|
|
|
@@ -53,39 +65,58 @@ export function buildTrajectory(
|
|
|
53
65
|
const turns: Turn[] = [];
|
|
54
66
|
|
|
55
67
|
for (const entry of entries) {
|
|
56
|
-
// getBranch() returns the full SessionEntry union;
|
|
57
|
-
//
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
68
|
+
// getBranch() returns the full SessionEntry union; `message` entries are
|
|
69
|
+
// the conversation itself, custom_message/branch_summary entries are
|
|
70
|
+
// injected context the model saw and later turns may lean on.
|
|
71
|
+
if (entry.type === "message") {
|
|
72
|
+
const message = entry.message;
|
|
73
|
+
if (message.role !== "user" && message.role !== "assistant") continue;
|
|
74
|
+
|
|
75
|
+
const chunks: string[] = [...extractTextParts(message.content)];
|
|
76
|
+
|
|
77
|
+
let model: string | undefined;
|
|
78
|
+
if (message.role === "assistant") {
|
|
79
|
+
// AssistantMessage carries both the requested `model` and, when the
|
|
80
|
+
// provider echoes it back, `responseModel` (the model that actually ran).
|
|
81
|
+
model = message.responseModel ?? message.model;
|
|
82
|
+
if (includeThinking) {
|
|
83
|
+
for (const t of extractThinkingParts(message.content)) {
|
|
84
|
+
chunks.push(
|
|
85
|
+
t
|
|
86
|
+
.split("\n")
|
|
87
|
+
.map((line) => `> ${line}`)
|
|
88
|
+
.join("\n"),
|
|
89
|
+
);
|
|
90
|
+
}
|
|
77
91
|
}
|
|
78
92
|
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
const body = chunks.join("\n").trim();
|
|
82
|
-
if (!body) continue; // skip empty / tool-only turns
|
|
83
93
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
94
|
+
const body = chunks.join("\n").trim();
|
|
95
|
+
if (!body) continue; // skip empty / tool-only turns
|
|
96
|
+
|
|
97
|
+
turns.push({
|
|
98
|
+
role: message.role === "user" ? "User" : "Assistant",
|
|
99
|
+
model,
|
|
100
|
+
body,
|
|
101
|
+
});
|
|
102
|
+
} else if (entry.type === "custom_message") {
|
|
103
|
+
// Displayed injections (side handoffs, external-change diffs, ketamine
|
|
104
|
+
// summaries, …) are part of what the model answered; hidden ones
|
|
105
|
+
// (display: false) are machinery the reader never saw. The content is
|
|
106
|
+
// self-describing — side handoffs embed their own model/turn header —
|
|
107
|
+
// so no per-producer knowledge is needed here.
|
|
108
|
+
if (!entry.display) continue;
|
|
109
|
+
const body = extractTextParts(entry.content).join("\n").trim();
|
|
110
|
+
if (!body) continue; // image-only injections carry no text
|
|
111
|
+
turns.push({ role: "Context", source: entry.customType, body });
|
|
112
|
+
} else if (entry.type === "branch_summary") {
|
|
113
|
+
// The summarized limb's entries are not on this branch — the summary
|
|
114
|
+
// is the only record of them.
|
|
115
|
+
const body = entry.summary.trim();
|
|
116
|
+
if (body) turns.push({ role: "Context", source: "branch summary", body });
|
|
117
|
+
}
|
|
118
|
+
// compaction: deliberately skipped — see file header. Everything else
|
|
119
|
+
// (markers, model_change, usage, …) is machinery.
|
|
89
120
|
}
|
|
90
121
|
|
|
91
122
|
return turns;
|
|
@@ -95,9 +126,11 @@ export const renderTrajectory = (turns: readonly Turn[]): string =>
|
|
|
95
126
|
turns
|
|
96
127
|
.map((t) => {
|
|
97
128
|
const header =
|
|
98
|
-
t.role === "
|
|
99
|
-
? `##
|
|
100
|
-
:
|
|
129
|
+
t.role === "Context"
|
|
130
|
+
? `## Injected context${t.source ? ` (${t.source})` : ""}`
|
|
131
|
+
: t.role === "Assistant" && t.model
|
|
132
|
+
? `## Assistant (${t.model})`
|
|
133
|
+
: `## ${t.role}`;
|
|
101
134
|
return `${header}\n\n${t.body}`;
|
|
102
135
|
})
|
|
103
136
|
.join("\n\n");
|
|
@@ -105,7 +138,7 @@ export const renderTrajectory = (turns: readonly Turn[]): string =>
|
|
|
105
138
|
export default function (pi: ExtensionAPI) {
|
|
106
139
|
pi.registerCommand("copy-trajectory", {
|
|
107
140
|
description:
|
|
108
|
-
"Copy the conversation (user + assistant text, no tool calls) to the clipboard",
|
|
141
|
+
"Copy the conversation (user + assistant text + injected context, no tool calls) to the clipboard",
|
|
109
142
|
getArgumentCompletions: (prefix) => {
|
|
110
143
|
const opts = ["thinking"].filter((o) => o.startsWith(prefix));
|
|
111
144
|
return opts.length > 0 ? opts.map((o) => ({ value: o, label: o })) : null;
|