@fyeeme/pi-hooks 1.0.0 → 1.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/CHANGELOG.md +7 -0
- package/index.ts +23 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.0.1] - 2025-07-15
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Process hang when hook command ignores SIGTERM: added SIGKILL escalation after 5s grace window
|
|
15
|
+
- Race condition between `close` and `error` events: added `finish()` guard to prevent double-resolve
|
|
16
|
+
|
|
10
17
|
## [1.0.0] - 2025-05-31
|
|
11
18
|
|
|
12
19
|
### Added
|
package/index.ts
CHANGED
|
@@ -110,27 +110,44 @@ async function runCommand(command: string, cwd: string, stdinJson: unknown): Pro
|
|
|
110
110
|
});
|
|
111
111
|
|
|
112
112
|
let stdout = "";
|
|
113
|
+
let settled = false;
|
|
114
|
+
const finish = (result: HookOutput | null) => {
|
|
115
|
+
if (settled) return;
|
|
116
|
+
settled = true;
|
|
117
|
+
clearTimeout(sigtermTimer);
|
|
118
|
+
clearTimeout(sigkillTimer);
|
|
119
|
+
resolve(result);
|
|
120
|
+
};
|
|
121
|
+
|
|
113
122
|
proc.stdout?.on("data", (chunk: Buffer) => {
|
|
114
123
|
stdout += chunk.toString();
|
|
115
124
|
});
|
|
116
125
|
|
|
117
|
-
|
|
126
|
+
let sigkillTimer: NodeJS.Timeout | undefined;
|
|
127
|
+
|
|
128
|
+
const sigtermTimer = setTimeout(() => {
|
|
129
|
+
try { proc.kill("SIGTERM"); } catch { /* already dead */ }
|
|
130
|
+
// escalate to SIGKILL after a 5s grace window
|
|
131
|
+
sigkillTimer = setTimeout(() => {
|
|
132
|
+
try { proc.kill("SIGKILL"); } catch { /* already dead */ }
|
|
133
|
+
// force-resolve: a process that survives SIGKILL is unrecoverable
|
|
134
|
+
finish(null);
|
|
135
|
+
}, 5_000);
|
|
136
|
+
}, 10_000);
|
|
118
137
|
|
|
119
138
|
proc.on("close", (code) => {
|
|
120
|
-
clearTimeout(timer);
|
|
121
139
|
if (code !== 0) console.error(`[hooks] exited ${code}: ${command}`);
|
|
122
140
|
try {
|
|
123
141
|
const trimmed = stdout.trim();
|
|
124
|
-
|
|
142
|
+
finish(trimmed ? (JSON.parse(trimmed) as HookOutput) : null);
|
|
125
143
|
} catch {
|
|
126
|
-
|
|
144
|
+
finish(null);
|
|
127
145
|
}
|
|
128
146
|
});
|
|
129
147
|
|
|
130
148
|
proc.on("error", (err) => {
|
|
131
|
-
clearTimeout(timer);
|
|
132
149
|
console.error(`[hooks] spawn error: ${command}: ${err}`);
|
|
133
|
-
|
|
150
|
+
finish(null);
|
|
134
151
|
});
|
|
135
152
|
|
|
136
153
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fyeeme/pi-hooks",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Claude Code-compatible hooks runner for pi. Reads .pi/hooks.json and maps SessionStart, PreToolUse, and Stop events to pi lifecycle events.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|