Commit Graph
8 Commits
Author SHA1 Message Date
can1357 1052af5fa6 refactor(agent): restructured yield logic to support deterministic testing
- Extracted yield logic into a configurable YieldGate class to avoid process-global state.
- Injected time and sleep dependencies to support deterministic testing.
- Handled potential negative time progression by forcing a re-anchor instead of gating indefinitely.
- Maintained existing behavior for the public yieldIfDue export via a shared instance.
2026-06-24 15:30:29 +02:00
can1357 c1fa0e9f50 refactor(agent): replaced keepalive utility with disposable EventLoopKeepalive
- Replaced the `keepaliveWhile` Promise wrapper with a new `EventLoopKeepalive` class that registers and disposes an interval timer through `Symbol.dispose`.
- Updated `Agent` to instantiate `EventLoopKeepalive` via `using` during prompt execution instead of manually managing an interval.
- Wrapped interactive mode's await path with the new helper and removed redundant `keepaliveWhile` usage from the CLI entrypoint.
2026-05-28 09:51:57 +02:00
can1357 0e9137a703 refactor(agent/utils): simplified keepaliveWhile implementation using unrefed interval
- Removed the EventLoopKeepalive class and replaced it with a direct setInterval call.
- Added an unref call to the interval timer to prevent blocking the process exit.
2026-05-27 13:01:49 +02:00
hezhiyang2000 1126934300 fix: replace ReturnType<typeof setInterval> with NodeJS.Timeout
Project convention (AGENTS.md) prohibits ReturnType<> — use the
concrete type name instead. NodeJS.Timeout matches the existing
pattern used throughout the codebase (e.g. interactive-mode.ts).
2026-05-27 14:59:08 +08:00
hezhiyang2000 2159f56386 fix: add EventLoopKeepalive to eliminate idle busy-wait
Root cause: Bun 1.3.x (JavaScriptCore) busy-waits when the only
pending work is an unresolved Promise. A setInterval keepalive
keeps the event loop in epoll_wait instead of userspace spinning.

- EventLoopKeepalive: setInterval-based keepalive (re-arms after each
  firing, addressing the bot review concern about setTimeout expiry)
- keepaliveWhile(): wrapper to await a Promise with keepalive active
- Applied to getUserInput() in main.ts
- Retains yieldIfDue() and ExponentialYield from #1396

Idle CPU drops from ~100% to ~0% (wchan=do_epoll_wait).
2026-05-27 14:57:46 +08:00
can1357 3078d31a4c chore: reformat 2026-05-26 20:44:09 +02:00
can1357 1d8ee5a891 refactor(yield): migrated to scheduler.wait with abort support and gate
- Replaced Bun.sleep with scheduler.wait for Node-compatible cancellable sleeps.
- Added module-level timestamp gate to skip yields within 50ms of the last one.
- Threaded AbortSignal through ExponentialYield.sleep to cancel losing timers in race.
- Added tests covering gate behaviour and stray-timer cancellation.
2026-05-26 20:37:39 +02:00
hezhiyang2000 afe574b351 fix: prevent busy-wait in agent loop and bash executor
- yieldIfDue() uses compensated sleep (sleepAtLeast): retries Bun.sleep()
  until the requested wall-clock duration has elapsed. This is necessary
  because napi callbacks (uv_async_send) can wake the event loop
  prematurely, causing Bun.sleep(N) to return after only ~1-2ms.
- ExponentialYield for bash-executor: starts at 20ms, doubles to 10s.

Closes #1384
2026-05-26 17:35:00 +08:00