orchajs 0.23.8 → 0.23.9

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.
@@ -7,6 +7,8 @@ export declare class AmarsiaTelemetryClient {
7
7
  endpoint?: string;
8
8
  });
9
9
  enqueue(fact: AmarsiaRunFact): void;
10
+ /** @internal Tracks telemetry projection work that must settle before drain completes. */
11
+ trackProjection(projection: Promise<void>): void;
10
12
  drain(options?: {
11
13
  timeoutMs?: number;
12
14
  }): Promise<void>;
@@ -15,6 +15,7 @@ export class AmarsiaTelemetryClient {
15
15
  #baseUrl;
16
16
  #queue = new Map();
17
17
  #activeRuns = new Map();
18
+ #pendingProjections = new Set();
18
19
  #timer;
19
20
  #heartbeatTimer;
20
21
  #attempt = 0;
@@ -56,6 +57,13 @@ export class AmarsiaTelemetryClient {
56
57
  const timer = this.#timer;
57
58
  timer.unref?.();
58
59
  }
60
+ /** @internal Tracks telemetry projection work that must settle before drain completes. */
61
+ trackProjection(projection) {
62
+ this.#pendingProjections.add(projection);
63
+ void projection.finally(() => {
64
+ this.#pendingProjections.delete(projection);
65
+ });
66
+ }
59
67
  #scheduleTerminal() {
60
68
  if (this.#timer)
61
69
  clearTimeout(this.#timer);
@@ -81,14 +89,23 @@ export class AmarsiaTelemetryClient {
81
89
  async drain(options = {}) {
82
90
  const timeoutMs = Math.max(0, options.timeoutMs ?? 2_000);
83
91
  const deadline = Date.now() + timeoutMs;
84
- if (this.#timer) {
85
- clearTimeout(this.#timer);
86
- this.#timer = undefined;
87
- }
88
- while (this.#queue.size > 0 || this.#flushPromise) {
92
+ while (this.#pendingProjections.size > 0 ||
93
+ this.#queue.size > 0 ||
94
+ this.#flushPromise) {
89
95
  const remaining = deadline - Date.now();
90
96
  if (remaining <= 0)
91
97
  return;
98
+ if (this.#pendingProjections.size > 0) {
99
+ await Promise.race([
100
+ Promise.allSettled([...this.#pendingProjections]).then(() => undefined),
101
+ new Promise((resolve) => setTimeout(resolve, remaining)),
102
+ ]);
103
+ continue;
104
+ }
105
+ if (this.#timer) {
106
+ clearTimeout(this.#timer);
107
+ this.#timer = undefined;
108
+ }
92
109
  await Promise.race([
93
110
  this.#flush(),
94
111
  new Promise((resolve) => setTimeout(resolve, remaining)),
@@ -102,6 +119,11 @@ export class AmarsiaTelemetryClient {
102
119
  }
103
120
  this.#activeRuns.clear();
104
121
  await this.drain(options);
122
+ if (this.#heartbeatTimer) {
123
+ clearTimeout(this.#heartbeatTimer);
124
+ this.#heartbeatTimer = undefined;
125
+ }
126
+ this.#activeRuns.clear();
105
127
  }
106
128
  async #flush() {
107
129
  if (this.#flushPromise)
@@ -206,11 +228,17 @@ export function withAmarsiaTelemetry(options) {
206
228
  })
207
229
  .catch(() => undefined);
208
230
  pending.set(sessionId, processing);
231
+ client.trackProjection(processing);
209
232
  void processing.finally(() => {
210
233
  if (pending.get(sessionId) === processing) {
211
234
  pending.delete(sessionId);
212
235
  }
213
236
  });
237
+ if (events.some((event) => event.type === "run.completed" ||
238
+ event.type === "run.failed" ||
239
+ event.type === "run.paused")) {
240
+ await processing;
241
+ }
214
242
  },
215
243
  };
216
244
  }
@@ -40,6 +40,7 @@ class AmarsiaTelemetryClient {
40
40
  #baseUrl;
41
41
  #queue = /* @__PURE__ */ new Map();
42
42
  #activeRuns = /* @__PURE__ */ new Map();
43
+ #pendingProjections = /* @__PURE__ */ new Set();
43
44
  #timer;
44
45
  #heartbeatTimer;
45
46
  #attempt = 0;
@@ -79,6 +80,13 @@ class AmarsiaTelemetryClient {
79
80
  const timer = this.#timer;
80
81
  timer.unref?.();
81
82
  }
83
+ /** @internal Tracks telemetry projection work that must settle before drain completes. */
84
+ trackProjection(projection) {
85
+ this.#pendingProjections.add(projection);
86
+ void projection.finally(() => {
87
+ this.#pendingProjections.delete(projection);
88
+ });
89
+ }
82
90
  #scheduleTerminal() {
83
91
  if (this.#timer) clearTimeout(this.#timer);
84
92
  this.#timer = setTimeout(() => {
@@ -102,13 +110,20 @@ class AmarsiaTelemetryClient {
102
110
  async drain(options = {}) {
103
111
  const timeoutMs = Math.max(0, options.timeoutMs ?? 2e3);
104
112
  const deadline = Date.now() + timeoutMs;
105
- if (this.#timer) {
106
- clearTimeout(this.#timer);
107
- this.#timer = void 0;
108
- }
109
- while (this.#queue.size > 0 || this.#flushPromise) {
113
+ while (this.#pendingProjections.size > 0 || this.#queue.size > 0 || this.#flushPromise) {
110
114
  const remaining = deadline - Date.now();
111
115
  if (remaining <= 0) return;
116
+ if (this.#pendingProjections.size > 0) {
117
+ await Promise.race([
118
+ Promise.allSettled([...this.#pendingProjections]).then(() => void 0),
119
+ new Promise((resolve) => setTimeout(resolve, remaining))
120
+ ]);
121
+ continue;
122
+ }
123
+ if (this.#timer) {
124
+ clearTimeout(this.#timer);
125
+ this.#timer = void 0;
126
+ }
112
127
  await Promise.race([
113
128
  this.#flush(),
114
129
  new Promise((resolve) => setTimeout(resolve, remaining))
@@ -122,6 +137,11 @@ class AmarsiaTelemetryClient {
122
137
  }
123
138
  this.#activeRuns.clear();
124
139
  await this.drain(options);
140
+ if (this.#heartbeatTimer) {
141
+ clearTimeout(this.#heartbeatTimer);
142
+ this.#heartbeatTimer = void 0;
143
+ }
144
+ this.#activeRuns.clear();
125
145
  }
126
146
  async #flush() {
127
147
  if (this.#flushPromise) return this.#flushPromise;
@@ -223,11 +243,17 @@ function withAmarsiaTelemetry(options) {
223
243
  }
224
244
  }).catch(() => void 0);
225
245
  pending.set(sessionId, processing);
246
+ client.trackProjection(processing);
226
247
  void processing.finally(() => {
227
248
  if (pending.get(sessionId) === processing) {
228
249
  pending.delete(sessionId);
229
250
  }
230
251
  });
252
+ if (events.some(
253
+ (event) => event.type === "run.completed" || event.type === "run.failed" || event.type === "run.paused"
254
+ )) {
255
+ await processing;
256
+ }
231
257
  }
232
258
  };
233
259
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orchajs",
3
- "version": "0.23.8",
3
+ "version": "0.23.9",
4
4
  "description": "A filesystem-convention, stateful agent framework for JavaScript.",
5
5
  "license": "MIT",
6
6
  "repository": {