perf(hooks): fire-and-forget telemetry hooks (#573) - #688
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
🚧 Files skipped from review as they are similar to previous changes (5)
📝 WalkthroughWalkthroughHook and CLI scripts were changed to send telemetry as non-blocking fire-and-forget fetch calls (errors suppressed via .catch) and to schedule short unref'd process exits, with AGENTS.md updated to document context-injecting vs telemetry-only hook patterns. ChangesFire-and-forget telemetry hook patterns
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint skipped: no ESLint configuration detected in root package.json. To enable, add Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
42a9df9 to
a1ca8d6
Compare
Telemetry hooks (notification, post-tool-failure, post-tool-use,
prompt-submit, stop, session-end, subagent-start, subagent-stop,
task-completed) previously `await fetch(..., AbortSignal.timeout(N))`
inside a try/catch. The await kept the hook process alive until the
response arrived — up to N ms per request — which blocks Claude Code's
next-prompt boundary on every assistant turn.
Switch to fire-and-forget:
fetch(url, { signal: AbortSignal.timeout(N) }).catch(() => {});
setTimeout(() => process.exit(0), 500).unref();
The unawaited fetch dispatches the request; the unref'd setTimeout
force-exits the process after the request has been flushed to the
local daemon's socket buffer (~500ms is enough). Without the
setTimeout Node keeps the event loop alive waiting for any in-flight
fetch to settle, which means the hook still blocks Claude Code's
next-prompt boundary for up to the AbortSignal duration.
Context-injecting hooks (pre-tool-use, pre-compact, session-start)
still use `await fetch` because Claude Code reads their stdout for
context injection — left untouched.
AGENTS.md updated with the two-pattern guidance.
a1ca8d6 to
0dea5b6
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@plugin/scripts/stop.mjs`:
- Around line 26-38: The exit delay is too short for the multi-request hook:
update the setTimeout that calls process.exit(0) (the call paired with the two
fetches to `${REST_URL}/agentmemory/summarize` and
`${REST_URL}/agentmemory/session/end`) to use 1500 ms instead of 500 ms so both
fetch requests have time to be initiated; keep the .unref() call to allow clean
shutdown but extend the timeout to 1500 to match the PR guidance for
multi-request session-end hooks.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: d0ba3b3b-ed8a-4fdf-afc4-eaaf3c4d2364
📒 Files selected for processing (19)
AGENTS.mdplugin/scripts/notification.mjsplugin/scripts/post-tool-failure.mjsplugin/scripts/post-tool-use.mjsplugin/scripts/prompt-submit.mjsplugin/scripts/session-end.mjsplugin/scripts/stop.mjsplugin/scripts/subagent-start.mjsplugin/scripts/subagent-stop.mjsplugin/scripts/task-completed.mjssrc/hooks/notification.tssrc/hooks/post-tool-failure.tssrc/hooks/post-tool-use.tssrc/hooks/prompt-submit.tssrc/hooks/session-end.tssrc/hooks/stop.tssrc/hooks/subagent-start.tssrc/hooks/subagent-stop.tssrc/hooks/task-completed.ts
Multi-request hooks (stop fires 2, session-end up to 4) need more than 500ms to initiate all fetches when AGENTMEMORY_URL points to a remote daemon — DNS + TCP + TLS handshakes can eat the budget before the second/third fetch is even dispatched. Bump to 1500ms on those two hooks only; single-request hooks keep 500ms. AGENTS.md updated with the multi-request exception.
Bumps version across 9 files + adds CHANGELOG entry summarizing the 18 commits since v0.9.22. Highlights: - GitHub Copilot CLI first-class support (#534) — plugin + hooks + MCP with LSP-style Content-Length framing on the standalone stdio transport. - Five new MCP adapters: Warp, Cline, Continue, Zed, Droid (#677); ADAPTERS count 11 → 17. - Three silent DX bugs fixed: graph extraction never fired on session end (#666 / #698), status reported zero memories (#666), consolidation defaulted off even with an LLM provider configured (#612 / #696). - Nine telemetry hooks switched to fire-and-forget so they don't block Claude Code's next-prompt boundary (#573 / #688). - Hook project field now sends repo basename instead of full filesystem path so auto-injected context isn't silently filtered out (#474 / #687). - Local-LLM docs: Ollama / LM Studio / vLLM section added (#671 / #697). Version-bump files: package.json, plugin/.claude-plugin/plugin.json, plugin/plugin.json, plugin/.codex-plugin/plugin.json, packages/mcp/package.json, src/version.ts, src/types.ts, src/functions/export-import.ts, test/export-import.test.ts.
* chore(release): v0.9.23 Bumps version across 9 files + adds CHANGELOG entry summarizing the 18 commits since v0.9.22. Highlights: - GitHub Copilot CLI first-class support (#534) — plugin + hooks + MCP with LSP-style Content-Length framing on the standalone stdio transport. - Five new MCP adapters: Warp, Cline, Continue, Zed, Droid (#677); ADAPTERS count 11 → 17. - Three silent DX bugs fixed: graph extraction never fired on session end (#666 / #698), status reported zero memories (#666), consolidation defaulted off even with an LLM provider configured (#612 / #696). - Nine telemetry hooks switched to fire-and-forget so they don't block Claude Code's next-prompt boundary (#573 / #688). - Hook project field now sends repo basename instead of full filesystem path so auto-injected context isn't silently filtered out (#474 / #687). - Local-LLM docs: Ollama / LM Studio / vLLM section added (#671 / #697). Version-bump files: package.json, plugin/.claude-plugin/plugin.json, plugin/plugin.json, plugin/.codex-plugin/plugin.json, packages/mcp/package.json, src/version.ts, src/types.ts, src/functions/export-import.ts, test/export-import.test.ts. * chore(release): add #701 + #709 to v0.9.23 CHANGELOG
…#688) * perf(hooks): fire-and-forget telemetry hooks (closes rohitg00#573) Telemetry hooks (notification, post-tool-failure, post-tool-use, prompt-submit, stop, session-end, subagent-start, subagent-stop, task-completed) previously `await fetch(..., AbortSignal.timeout(N))` inside a try/catch. The await kept the hook process alive until the response arrived — up to N ms per request — which blocks Claude Code's next-prompt boundary on every assistant turn. Switch to fire-and-forget: fetch(url, { signal: AbortSignal.timeout(N) }).catch(() => {}); setTimeout(() => process.exit(0), 500).unref(); The unawaited fetch dispatches the request; the unref'd setTimeout force-exits the process after the request has been flushed to the local daemon's socket buffer (~500ms is enough). Without the setTimeout Node keeps the event loop alive waiting for any in-flight fetch to settle, which means the hook still blocks Claude Code's next-prompt boundary for up to the AbortSignal duration. Context-injecting hooks (pre-tool-use, pre-compact, session-start) still use `await fetch` because Claude Code reads their stdout for context injection — left untouched. AGENTS.md updated with the two-pattern guidance. * chore(hooks): drop verbose comments on fire-and-forget hooks * fix(hooks): bump stop+session-end exit delay to 1500ms Multi-request hooks (stop fires 2, session-end up to 4) need more than 500ms to initiate all fetches when AGENTMEMORY_URL points to a remote daemon — DNS + TCP + TLS handshakes can eat the budget before the second/third fetch is even dispatched. Bump to 1500ms on those two hooks only; single-request hooks keep 500ms. AGENTS.md updated with the multi-request exception.
* chore(release): v0.9.23 Bumps version across 9 files + adds CHANGELOG entry summarizing the 18 commits since v0.9.22. Highlights: - GitHub Copilot CLI first-class support (rohitg00#534) — plugin + hooks + MCP with LSP-style Content-Length framing on the standalone stdio transport. - Five new MCP adapters: Warp, Cline, Continue, Zed, Droid (rohitg00#677); ADAPTERS count 11 → 17. - Three silent DX bugs fixed: graph extraction never fired on session end (rohitg00#666 / rohitg00#698), status reported zero memories (rohitg00#666), consolidation defaulted off even with an LLM provider configured (rohitg00#612 / rohitg00#696). - Nine telemetry hooks switched to fire-and-forget so they don't block Claude Code's next-prompt boundary (rohitg00#573 / rohitg00#688). - Hook project field now sends repo basename instead of full filesystem path so auto-injected context isn't silently filtered out (rohitg00#474 / rohitg00#687). - Local-LLM docs: Ollama / LM Studio / vLLM section added (rohitg00#671 / rohitg00#697). Version-bump files: package.json, plugin/.claude-plugin/plugin.json, plugin/plugin.json, plugin/.codex-plugin/plugin.json, packages/mcp/package.json, src/version.ts, src/types.ts, src/functions/export-import.ts, test/export-import.test.ts. * chore(release): add rohitg00#701 + rohitg00#709 to v0.9.23 CHANGELOG
Summary
Telemetry hooks block Claude Code's next-prompt boundary on every assistant turn because they
await fetch(...)inside a try/catch — the hook process stays alive until the response arrives, up to theAbortSignal.timeoutduration per request. On a slow daemon or local hang this stacks visibly into the UX.Switch the 9 telemetry-only hooks to fire-and-forget:
The unawaited fetch dispatches the request; the unref'd
setTimeoutforce-exits the process after the request has been flushed to the local daemon's socket buffer (~500ms is enough). Without thesetTimeoutNode keeps the event loop alive waiting for any in-flight fetch to settle, which means the hook still blocks Claude Code's next-prompt boundary for up to the AbortSignal duration — exactly the bug fire-and-forget is meant to fix.Changes
Telemetry hooks switched to fire-and-forget (9 files):
notification,post-tool-failure,post-tool-use,prompt-submitsubagent-start,subagent-stop,task-completedstop,session-end(multi-fetch branches all converted)Context-injecting hooks left untouched — they read the response to write context to stdout, so they must
await fetch:pre-tool-use,pre-compact,session-startAGENTS.mdupdated with the two-pattern guidance (context-injecting vs telemetry-only) so the convention is discoverable for future hooks.Test plan
npx vitest run— 1238 pass, 1 integration file skipped (server not running, pre-existing)grep setTimeout plugin/scripts/notification.mjsconfirmssetTimeout(() => process.exit(0), 500).unref();lands in the bundleawaitleft in telemetry hook bundles —grep -E 'await fetch' plugin/scripts/{notification,post-tool-use,post-tool-failure,prompt-submit,subagent-start,subagent-stop,task-completed,stop,session-end}.mjsreturns empty_project*.mjschunks (per-entry tsdown config from fix(hooks): send repo basename as project, not full path (#474) #687 holds)Stacked on top of #687 (the
fix/474reimplementation) since both PRs heavily touch the same hook files. GitHub will auto-reconcile base tomainonce #687 lands.Closes #573.
Summary by CodeRabbit