@zhushanwen/pi-unified-hooks 0.0.1

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 ADDED
@@ -0,0 +1,55 @@
1
+ # unified-hooks — Unified Hooks Extension
2
+
3
+ Collect scattered hooks in one place for easy maintenance. Each hook is a self-contained module that can be enabled/disabled independently.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ ln -s /path/to/xyz-pi-extensions/unified-hooks ~/.pi/agent/extensions/unified-hooks
9
+ ```
10
+
11
+ ## Available Hooks
12
+
13
+ ### edit-whitespace-autofix
14
+
15
+ When edit tool fails due to whitespace mismatch, injects a steering message that tells the AI to fix whitespace and retry.
16
+
17
+ **Trigger patterns:**
18
+ - `Could not find the exact text`
19
+ - `oldText must match exactly`
20
+ - `Could not find edits[`
21
+
22
+ **Behavior:**
23
+ 1. Detect whitespace mismatch error from edit tool
24
+ 2. Extract the file path from tool args
25
+ 3. Inject steer message with `fix_whitespace.py --fix <file>` command
26
+ 4. AI automatically fixes whitespace and retries the edit
27
+
28
+ ### tool-error-handler
29
+
30
+ Logs all tool execution errors to console for debugging.
31
+
32
+ ## Adding New Hooks
33
+
34
+ 1. Create `src/hooks/my-hook.ts`:
35
+ ```typescript
36
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
37
+
38
+ export function setupMyHook(pi: ExtensionAPI): void {
39
+ pi.on("tool_execution_end", async (event) => {
40
+ if (event.toolName === "edit" && event.isError) {
41
+ // Your logic
42
+ }
43
+ });
44
+ }
45
+ ```
46
+
47
+ 2. Register in `src/index.ts` hookModules array
48
+
49
+ 3. Type check: `npx tsc --noEmit`
50
+
51
+ ## Important API Notes
52
+
53
+ - Use `pi.sendUserMessage()` in event handlers, **not** `ctx.sendUserMessage()` (only available in command context)
54
+ - `tool_execution_end` event has `{ toolCallId, toolName, args, result, isError }`
55
+ - Inject direct instructions in steer messages, don't try to invoke `/skill-name` via text
package/index.ts ADDED
@@ -0,0 +1 @@
1
+ export { default } from "./src/index.ts";
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@zhushanwen/pi-unified-hooks",
3
+ "version": "0.0.1",
4
+ "description": "Unified hooks extension - collect scattered hooks in one place for easy maintenance",
5
+ "main": "index.js",
6
+ "type": "module",
7
+ "keywords": [
8
+ "pi",
9
+ "extension",
10
+ "hooks"
11
+ ],
12
+ "license": "MIT",
13
+ "peerDependencies": {
14
+ "typebox": "*",
15
+ "@mariozechner/pi-coding-agent": "*"
16
+ },
17
+ "files": [
18
+ "src/",
19
+ "index.ts"
20
+ ],
21
+ "scripts": {
22
+ "typecheck": "npx tsc --noEmit"
23
+ }
24
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Tool Error Handler Hook
3
+ *
4
+ * Logs tool execution errors for debugging. Can be extended to handle
5
+ * specific error patterns with contextual recovery.
6
+ */
7
+
8
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
9
+
10
+ export function setupToolErrorHandler(pi: ExtensionAPI): void {
11
+ pi.on("tool_execution_end", async (event) => {
12
+ if (!event.isError) return;
13
+ console.log(`[unified-hooks] ${event.toolName} error (callId=${event.toolCallId})`);
14
+ });
15
+ }
package/src/index.ts ADDED
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Unified Hooks Extension
3
+ *
4
+ * Collects scattered hooks in one place for easy maintenance.
5
+ * Each hook is a self-contained module that can be enabled/disabled independently.
6
+ */
7
+
8
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
9
+
10
+ // Re-export hook modules for easy access
11
+ export { setupToolErrorHandler } from "./hooks/tool-error-handler";
12
+
13
+ import { setupToolErrorHandler } from "./hooks/tool-error-handler";
14
+
15
+ /**
16
+ * Extension factory - registers all unified hooks
17
+ */
18
+ export default function unifiedHooksExtension(pi: ExtensionAPI): void {
19
+ // Initialize hook registry
20
+ const hooks: Array<{ name: string; enabled: boolean }> = [];
21
+
22
+ // edit-stale-content-guard removed: pi-hashline-edit replaces built-in edit
23
+ // with hash-anchor mode, making oldText-based guard unreachable
24
+ const hookModules = [
25
+ { name: "tool-error-handler", setup: setupToolErrorHandler },
26
+ ];
27
+
28
+ for (const hook of hookModules) {
29
+ try {
30
+ hook.setup(pi);
31
+ hooks.push({ name: hook.name, enabled: true });
32
+ } catch (err) {
33
+ console.error(`[unified-hooks] Failed to setup ${hook.name}:`, err);
34
+ hooks.push({ name: hook.name, enabled: false });
35
+ }
36
+ }
37
+
38
+ // Log hook status on session start for debugging
39
+ pi.on("session_start", () => {
40
+ const enabled = hooks.filter((h) => h.enabled).map((h) => h.name);
41
+ const disabled = hooks.filter((h) => !h.enabled).map((h) => h.name);
42
+ console.log(
43
+ `[unified-hooks] Loaded: ${enabled.join(", ") || "(none)"}${
44
+ disabled.length ? ` | Failed: ${disabled.join(", ")}` : ""
45
+ }`
46
+ );
47
+ });
48
+ }