@oh-my-pi/pi-utils 16.4.5 → 16.4.6

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 CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [16.4.6] - 2026-07-12
6
+
7
+ ### Added
8
+
9
+ - Added `AsyncDrain`, the deferred write-batching helper previously private to the coding-agent's prompt-history storage; now shared with model-perf recording.
10
+
5
11
  ## [16.4.2] - 2026-07-10
6
12
 
7
13
  ### Added
@@ -4,3 +4,17 @@
4
4
  * Cleans up all listeners on settlement.
5
5
  */
6
6
  export declare function withTimeout<T>(promise: Promise<T>, ms: number, message: string, signal?: AbortSignal): Promise<T>;
7
+ /**
8
+ * Coalesces rapid-fire writes into one deferred batch. `push` queues a value
9
+ * and returns a promise for the batch flush; the first push of a batch arms a
10
+ * timer (`delayMs`, or a microtask at 0), and every push before it fires joins
11
+ * the same batch and shares the same promise. Used to keep hot paths off
12
+ * synchronous storage (prompt history, model perf).
13
+ */
14
+ export declare class AsyncDrain<T> {
15
+ #private;
16
+ readonly delayMs: number;
17
+ constructor(delayMs?: number);
18
+ /** Queue `value`; `hnd` receives the whole batch when the window closes. */
19
+ push(value: T, hnd: (values: T[]) => Promise<void> | void): Promise<void>;
20
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-utils",
4
- "version": "16.4.5",
4
+ "version": "16.4.6",
5
5
  "description": "Shared utilities for pi packages",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": "Can Boluk",
@@ -31,7 +31,7 @@
31
31
  "fmt": "biome format --write ."
32
32
  },
33
33
  "dependencies": {
34
- "@oh-my-pi/pi-natives": "16.4.5",
34
+ "@oh-my-pi/pi-natives": "16.4.6",
35
35
  "handlebars": "^4.7.9",
36
36
  "winston": "^3.19.0",
37
37
  "winston-daily-rotate-file": "^5.0.0"
package/src/async.ts CHANGED
@@ -48,3 +48,44 @@ export function withTimeout<T>(promise: Promise<T>, ms: number, message: string,
48
48
 
49
49
  return wrapped;
50
50
  }
51
+
52
+ /**
53
+ * Coalesces rapid-fire writes into one deferred batch. `push` queues a value
54
+ * and returns a promise for the batch flush; the first push of a batch arms a
55
+ * timer (`delayMs`, or a microtask at 0), and every push before it fires joins
56
+ * the same batch and shares the same promise. Used to keep hot paths off
57
+ * synchronous storage (prompt history, model perf).
58
+ */
59
+ export class AsyncDrain<T> {
60
+ #queue?: T[];
61
+ #promise = Promise.resolve();
62
+
63
+ constructor(readonly delayMs: number = 0) {}
64
+
65
+ /** Queue `value`; `hnd` receives the whole batch when the window closes. */
66
+ push(value: T, hnd: (values: T[]) => Promise<void> | void): Promise<void> {
67
+ let queue = this.#queue;
68
+ if (!queue) {
69
+ this.#queue = queue = [];
70
+ const { promise, resolve, reject } = Promise.withResolvers<void>();
71
+ const exec = (): void => {
72
+ try {
73
+ if (this.#queue === queue) {
74
+ this.#queue = undefined;
75
+ }
76
+ resolve(hnd(queue!));
77
+ } catch (error) {
78
+ reject(error);
79
+ }
80
+ };
81
+ if (this.delayMs > 0) {
82
+ setTimeout(exec, this.delayMs);
83
+ } else {
84
+ queueMicrotask(exec);
85
+ }
86
+ this.#promise = promise;
87
+ }
88
+ queue.push(value);
89
+ return this.#promise;
90
+ }
91
+ }