@oh-my-pi/pi-agent-core 15.5.7 → 15.5.8

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.
@@ -1,6 +1,3 @@
1
- /** Agent class that uses the agent-loop directly.
2
- * No transport abstraction - calls streamSimple via the loop.
3
- */
4
1
  import { type AssistantMessage, type AssistantMessageEvent, type CursorExecHandlers, type CursorToolResultHandler, type Effort, type ImageContent, type Message, type Model, type ProviderSessionState, type ServiceTier, type SimpleStreamOptions, type ThinkingBudgets, type ToolChoice } from "@oh-my-pi/pi-ai";
5
2
  import type { AppendOnlyContextManager } from "./append-only-context";
6
3
  import type { HarmonyAuditEvent } from "./harmony-leak";
@@ -24,22 +24,10 @@
24
24
  * sleep loops) are retained for the agent-loop hot-path where Promises
25
25
  * resolve frequently and the keepalive alone is insufficient.
26
26
  */
27
- /**
28
- * Await a Promise with an event-loop keepalive active.
29
- *
30
- * This is the primary fix for Bun's busy-wait on unresolved Promises.
31
- * Use it wherever you `await` a Promise that may remain unresolved for
32
- * an extended period (user input, long-running subprocess, etc.).
33
- *
34
- * ```ts
35
- * // Before (100% CPU while waiting):
36
- * const input = await mode.getUserInput();
37
- *
38
- * // After (proper epoll_wait sleep):
39
- * const input = await keepaliveWhile(mode.getUserInput());
40
- * ```
41
- */
42
- export declare function keepaliveWhile<T>(promise: Promise<T>): Promise<T>;
27
+ export declare class EventLoopKeepalive {
28
+ #private;
29
+ [Symbol.dispose](): void;
30
+ }
43
31
  /**
44
32
  * Yield to the Bun event loop, sleeping for at least 20 ms — but at most
45
33
  * once every {@link YIELD_INTERVAL_MS}. Callers in hot paths can invoke
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-agent-core",
4
- "version": "15.5.7",
4
+ "version": "15.5.8",
5
5
  "description": "General-purpose agent with transport abstraction, state management, and attachment support",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": "Can Boluk",
@@ -35,9 +35,9 @@
35
35
  "fmt": "biome format --write ."
36
36
  },
37
37
  "dependencies": {
38
- "@oh-my-pi/pi-ai": "15.5.7",
39
- "@oh-my-pi/pi-natives": "15.5.7",
40
- "@oh-my-pi/pi-utils": "15.5.7",
38
+ "@oh-my-pi/pi-ai": "15.5.8",
39
+ "@oh-my-pi/pi-natives": "15.5.8",
40
+ "@oh-my-pi/pi-utils": "15.5.8",
41
41
  "@opentelemetry/api": "^1.9.0"
42
42
  },
43
43
  "devDependencies": {
package/src/agent.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  /** Agent class that uses the agent-loop directly.
2
2
  * No transport abstraction - calls streamSimple via the loop.
3
3
  */
4
-
5
4
  import { isPromise } from "node:util/types";
6
5
  import {
7
6
  type AssistantMessage,
@@ -36,6 +35,7 @@ import type {
36
35
  StreamFn,
37
36
  ToolCallContext,
38
37
  } from "./types";
38
+ import { EventLoopKeepalive } from "./utils/yield";
39
39
 
40
40
  /**
41
41
  * Default convertToLlm: Keep only LLM-compatible messages, convert attachments.
@@ -859,7 +859,7 @@ export class Agent {
859
859
  if (!model) throw new Error("No model configured");
860
860
 
861
861
  let skipInitialSteeringPoll = options?.skipInitialSteeringPoll === true;
862
-
862
+ using _ = new EventLoopKeepalive();
863
863
  const { promise, resolve } = Promise.withResolvers<void>();
864
864
  this.#runningPrompt = promise;
865
865
  this.#resolveRunningPrompt = resolve;
@@ -31,30 +31,10 @@ import { scheduler } from "node:timers/promises";
31
31
  // EventLoopKeepalive — the primary fix for idle-state busy-wait
32
32
  // ---------------------------------------------------------------------------
33
33
 
34
- const KEEPALIVE_INTERVAL_MS = 86_400_000; // 24 hours — re-armed each interval
35
-
36
- /**
37
- * Await a Promise with an event-loop keepalive active.
38
- *
39
- * This is the primary fix for Bun's busy-wait on unresolved Promises.
40
- * Use it wherever you `await` a Promise that may remain unresolved for
41
- * an extended period (user input, long-running subprocess, etc.).
42
- *
43
- * ```ts
44
- * // Before (100% CPU while waiting):
45
- * const input = await mode.getUserInput();
46
- *
47
- * // After (proper epoll_wait sleep):
48
- * const input = await keepaliveWhile(mode.getUserInput());
49
- * ```
50
- */
51
- export async function keepaliveWhile<T>(promise: Promise<T>): Promise<T> {
52
- const ka = setInterval(() => {}, KEEPALIVE_INTERVAL_MS);
53
- try {
54
- ka.unref();
55
- return await promise;
56
- } finally {
57
- clearInterval(ka);
34
+ export class EventLoopKeepalive {
35
+ #tmr = setInterval(() => {}, 86_400_000).unref();
36
+ [Symbol.dispose](): void {
37
+ clearInterval(this.#tmr);
58
38
  }
59
39
  }
60
40