@normful/picadillo 3.0.0 → 4.0.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/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ ## [4.0.0] - 2026-02-17
2
+
3
+ ### 🚀 Features
4
+
5
+ - *(extension)* Add overstory extension boilerplate and logic
6
+
7
+ ### 📚 Documentation
8
+
9
+ - Add overstory extension to README
10
+
11
+ ### ⚙️ Miscellaneous Tasks
12
+
13
+ - Shorten package.json description, fix overstory repo URL
1
14
  ## [3.0.0] - 2026-02-17
2
15
 
3
16
  ### 🚀 Features
@@ -12,6 +25,10 @@
12
25
  ### 📚 Documentation
13
26
 
14
27
  - Update README with reorganized skills and extensions sections
28
+
29
+ ### ⚙️ Miscellaneous Tasks
30
+
31
+ - Release 3.0.0
15
32
  ## [2.0.3] - 2026-02-16
16
33
 
17
34
  ### 📚 Documentation
package/README.md CHANGED
@@ -67,6 +67,12 @@ Hooks to automatically run `gt prime` and `gt mail` from [gastown](https://githu
67
67
  Hooks to automatically run [mulch](https://github.com/jayminwest/mulch) for
68
68
  recording and retrieving structured project learnings.
69
69
 
70
+ ### overstory
71
+
72
+ Hooks to automatically run `overstory prime` and `overstory mail check` from
73
+ [overstory](https://github.com/jayminwest/overstory/), along with logging tool
74
+ start/end, session end events, and integration with mulch for learning.
75
+
70
76
  ## Parrot Extension Demo
71
77
 
72
78
  [![asciicast](https://asciinema.org/a/788693.svg)](https://asciinema.org/a/788693)
@@ -0,0 +1,207 @@
1
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
2
+ import type { ExecResult } from "@mariozechner/pi-coding-agent";
3
+
4
+ export type { ExecResult };
5
+ export const OVERSTORY_MESSAGE_TYPE = "overstory";
6
+
7
+ export async function overstoryPrime(
8
+ execFn: ExtensionAPI["exec"],
9
+ forCompact = false,
10
+ ): Promise<string> {
11
+ let primeText = "";
12
+ try {
13
+ const { stdout } = await execFn("overstory", [
14
+ "prime",
15
+ "--agent",
16
+ "orchestrator",
17
+ ...(forCompact ? ["--compact"] : []),
18
+ ]);
19
+ primeText = stdout;
20
+ } catch (e) {
21
+ console.error("overstory prime failed:", e);
22
+ }
23
+ return primeText;
24
+ }
25
+
26
+ export async function overstoryMailCheck(
27
+ execFn: ExtensionAPI["exec"],
28
+ ): Promise<string> {
29
+ let mailText = "";
30
+ try {
31
+ const { stdout } = await execFn("overstory", [
32
+ "mail",
33
+ "check",
34
+ "--inject",
35
+ "--agent",
36
+ "orchestrator",
37
+ ]);
38
+ mailText = stdout;
39
+ } catch (e) {
40
+ console.error("overstory mail check failed:", e);
41
+ }
42
+ return mailText;
43
+ }
44
+
45
+ export async function logToolStart(
46
+ execFn: ExtensionAPI["exec"],
47
+ toolName: string,
48
+ ): Promise<void> {
49
+ try {
50
+ await execFn("overstory", [
51
+ "log",
52
+ "tool-start",
53
+ "--agent",
54
+ "orchestrator",
55
+ "--tool-name",
56
+ toolName,
57
+ ]);
58
+ } catch (e) {
59
+ console.error("overstory log tool-start failed:", e);
60
+ }
61
+ }
62
+
63
+ export async function logToolEnd(
64
+ execFn: ExtensionAPI["exec"],
65
+ toolName: string,
66
+ ): Promise<void> {
67
+ try {
68
+ await execFn("overstory", [
69
+ "log",
70
+ "tool-end",
71
+ "--agent",
72
+ "orchestrator",
73
+ "--tool-name",
74
+ toolName,
75
+ ]);
76
+ } catch (e) {
77
+ console.error("overstory log tool-end failed:", e);
78
+ }
79
+ }
80
+
81
+ export async function logSessionEnd(
82
+ execFn: ExtensionAPI["exec"],
83
+ ): Promise<void> {
84
+ try {
85
+ await execFn("overstory", [
86
+ "log",
87
+ "session-end",
88
+ "--agent",
89
+ "orchestrator",
90
+ ]);
91
+ } catch (e) {
92
+ console.error("overstory log session-end failed:", e);
93
+ }
94
+ }
95
+
96
+ export async function mulchLearn(
97
+ execFn: ExtensionAPI["exec"],
98
+ ): Promise<string> {
99
+ let primeText = "";
100
+ try {
101
+ const { stdout } = await execFn("mulch", ["learn"]);
102
+ primeText = stdout;
103
+ } catch (e) {
104
+ console.error("mulch learn failed:", e);
105
+ }
106
+ return primeText;
107
+ }
108
+
109
+ export async function handleSessionStart(
110
+ execFn: ExtensionAPI["exec"],
111
+ sendMessage: ExtensionAPI["sendMessage"],
112
+ ): Promise<void> {
113
+ const primeText = await overstoryPrime(execFn);
114
+ if (!primeText) return;
115
+
116
+ const mailText = await overstoryMailCheck(execFn);
117
+ sendMessage(
118
+ {
119
+ customType: OVERSTORY_MESSAGE_TYPE,
120
+ content: primeText + "\n\n" + mailText,
121
+ display: true,
122
+ },
123
+ {
124
+ deliverAs: "followUp",
125
+ triggerTurn: true,
126
+ },
127
+ );
128
+ }
129
+
130
+ export function handleBeforeAgentStart(mailText: string) {
131
+ return {
132
+ message: {
133
+ customType: OVERSTORY_MESSAGE_TYPE,
134
+ content: mailText,
135
+ display: true,
136
+ },
137
+ };
138
+ }
139
+
140
+ export async function handleToolExecutionEnd(
141
+ execFn: ExtensionAPI["exec"],
142
+ event: { toolName: string },
143
+ ): Promise<void> {
144
+ logToolEnd(execFn, event.toolName);
145
+ }
146
+
147
+ export async function handleToolExecutionStart(
148
+ execFn: ExtensionAPI["exec"],
149
+ event: { toolName: string },
150
+ ): Promise<void> {
151
+ logToolStart(execFn, event.toolName);
152
+ }
153
+
154
+ export async function handleSessionCompact(
155
+ execFn: ExtensionAPI["exec"],
156
+ sendMessage: ExtensionAPI["sendMessage"],
157
+ ): Promise<void> {
158
+ const primeText = await overstoryPrime(execFn, true);
159
+ if (!primeText) return;
160
+
161
+ sendMessage(
162
+ {
163
+ customType: OVERSTORY_MESSAGE_TYPE,
164
+ content: primeText,
165
+ display: true,
166
+ },
167
+ {
168
+ deliverAs: "followUp",
169
+ triggerTurn: true,
170
+ },
171
+ );
172
+ }
173
+
174
+ export async function handleSessionShutdown(
175
+ execFn: ExtensionAPI["exec"],
176
+ ): Promise<void> {
177
+ await Promise.all([logSessionEnd(execFn), mulchLearn(execFn)]);
178
+ }
179
+
180
+ export default function (pi: ExtensionAPI) {
181
+ pi.on("session_start", async (_event, _ctx) => {
182
+ await handleSessionStart(pi.exec, pi.sendMessage);
183
+ });
184
+
185
+ pi.on("before_agent_start", async (_event, _ctx) => {
186
+ const mailText = await overstoryMailCheck(pi.exec);
187
+ return handleBeforeAgentStart(mailText);
188
+ });
189
+
190
+ pi.on("tool_execution_end", async (event, _ctx) => {
191
+ // Fire-and-forget: don't await, let it run in background
192
+ void handleToolExecutionEnd(pi.exec, event);
193
+ });
194
+
195
+ pi.on("tool_execution_start", async (event, _ctx) => {
196
+ // Fire-and-forget: don't await, let it run in background
197
+ void handleToolExecutionStart(pi.exec, event);
198
+ });
199
+
200
+ pi.on("session_compact", async (_event, _ctx) => {
201
+ await handleSessionCompact(pi.exec, pi.sendMessage);
202
+ });
203
+
204
+ pi.on("session_shutdown", async (_event, _ctx) => {
205
+ await handleSessionShutdown(pi.exec);
206
+ });
207
+ }
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@normful/picadillo",
3
- "version": "3.0.0",
3
+ "version": "4.0.0",
4
4
  "private": false,
5
- "description": "pi agent skills/extensions: run-in-tmux, parrot (send AI message with edited version of AI message)",
5
+ "description": "pi agent skills & extensions: run-in-tmux, parrot, mulch, overstory",
6
6
  "keywords": [
7
7
  "pi",
8
8
  "pi-coding-agent",