← Back to PRs

#9947: fix: preserve agent-events as standalone entry point for hook consumers

by therealkaiharper-wq open 2026-02-05 22:32 View on GitHub →
## Summary The tsdown migration in [`a03d852`](https://github.com/openclaw/openclaw/commit/a03d852d6526eee7d60c9499828b93b0ebc6a272) ("Migrate to tsdown, speed up JS bundling by ~10x") inadvertently broke internal hook handlers that subscribe to agent lifecycle events via `onAgentEvent`. This PR adds `src/infra/agent-events.ts` as an explicit tsdown entry point, restoring `dist/infra/agent-events.js` as a standalone importable file. ## What changed and when **Before `a03d852` (v2026.1.29 and earlier):** The build used plain `tsc`, which compiled each source file individually: ``` src/infra/agent-events.ts → dist/infra/agent-events.js (standalone, ~3 KB) ``` Hook handlers could safely `import("dist/infra/agent-events.js")` and Node's ESM loader would return the **same cached module instance** the gateway had already loaded — sharing the same `listeners` Set. Events emitted by the gateway via `emitAgentEvent()` reached hook listeners correctly. **After `a03d852` (v2026.2.x):** The build uses tsdown, which bundles non-entry modules into shared chunks: ``` src/infra/agent-events.ts → inlined into dist/loader-BAZoAqqR.js (2.2 MB shared chunk, ~190 modules) ``` `dist/infra/agent-events.js` no longer exists. When a hook handler imports the shared chunk: 1. **Gateway crash:** The chunk contains ~190 other modules with module-level side effects (subsystem initialization, timers, state setup). Re-executing these crashes the gateway process within ~10 seconds. 2. **Separate module instance:** Even if the import didn't crash, Node creates a separate module instance with its own `listeners` Set. The hook's `onAgentEvent` listener never receives events from the gateway's `emitAgentEvent` calls. ## What this PR does Adds a single entry to `tsdown.config.ts`: ```typescript { entry: "src/infra/agent-events.ts", outDir: "dist/infra", env, fixedExtension: false, platform: "node", }, ``` This restores `dist/infra/agent-events.js` as a standalone file that hook handlers can safely import, sharing the gateway's module instance via ESM caching. ## Who this affects Any third-party internal hook that subscribes to agent lifecycle events (start/end/error), tool events, or assistant events via `onAgentEvent`. For example, [openclaw-mission-control](https://github.com/openclaw/openclaw-mission-control) uses this to sync agent activity to a dashboard. The commit message for `a03d852` noted: *"This might break some existing users, but if it does, it's because they were using 'private' APIs."* — This PR makes `agent-events` an officially supported entry point rather than leaving it as an internal that hooks must reach into unsafely. ## Test plan - [ ] Build with `pnpm build` and verify `dist/infra/agent-events.js` exists as a standalone file - [ ] Verify gateway starts normally with a hook that imports `dist/infra/agent-events.js` - [ ] Verify `onAgentEvent` listener receives lifecycle events from the gateway - [ ] Verify existing entry points (`index.ts`, `entry.ts`, `plugin-sdk`, `extensionAPI`) are unaffected <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> This PR updates the `tsdown` build configuration to treat `src/infra/agent-events.ts` as an explicit standalone entry point. That restores a dedicated `dist/infra/agent-events.js` artifact for hook consumers, instead of having `agent-events` inlined into a shared bundle chunk. The goal is to preserve stable ESM module caching behavior so hook handlers importing `dist/infra/agent-events.js` share the same module instance as the gateway and avoid re-executing unrelated bundled modules with side effects. <h3>Confidence Score: 5/5</h3> - This PR is safe to merge with minimal risk. - Change is limited to adding a tsdown entry configuration; no runtime code paths are modified. The configuration is consistent with existing entries and should restore a standalone build artifact without affecting existing entry points. - tsdown.config.ts <!-- greptile_other_comments_section --> <sub>(2/5) Greptile learns from your feedback when you react with thumbs up/down!</sub> <!-- /greptile_comment -->

Most Similar PRs