@hyperdrive.bot/fleet-client 0.3.160 → 0.3.162

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.
@@ -131,6 +131,21 @@ export interface DaemonClientConfig {
131
131
  */
132
132
  defaultSendQueueTimeoutMs?: number;
133
133
  capabilities?: Partial<Record<ClientCapability, unknown>>;
134
+ /**
135
+ * Called once per request/response round trip that goes through the shared
136
+ * correlation path, with its wall time and outcome. Must not throw and must not
137
+ * forward the payloads anywhere: they carry prompts and paths. The app uses it
138
+ * to sample RPC latency into telemetry, reading only allowlisted fields.
139
+ */
140
+ onRequestComplete?: (event: DaemonRequestCompletion) => void;
141
+ }
142
+ export interface DaemonRequestCompletion {
143
+ requestType: SessionInboundMessage["type"];
144
+ durationMs: number;
145
+ outcome: "ok" | "error" | "timeout";
146
+ request: SessionInboundMessage;
147
+ /** The selected response value on `ok`, otherwise undefined. */
148
+ response?: unknown;
134
149
  }
135
150
  export interface SendMessageOptions {
136
151
  messageId?: string;
@@ -851,6 +866,7 @@ export declare class DaemonClient {
851
866
  skipQueue?: boolean;
852
867
  };
853
868
  }): Promise<T>;
869
+ private reportRequestCompletion;
854
870
  private sendCorrelatedRequest;
855
871
  private sendCorrelatedSessionRequest;
856
872
  private sendNamespacedCorrelatedSessionRequest;
@@ -719,6 +719,7 @@ export class DaemonClient {
719
719
  }
720
720
  return { kind: "ok", value };
721
721
  }, timeout, params.options);
722
+ const startedAt = Date.now();
722
723
  try {
723
724
  await this.sendSessionMessageOrThrow(params.message);
724
725
  }
@@ -726,14 +727,43 @@ export class DaemonClient {
726
727
  const err = error instanceof Error ? error : new Error(String(error));
727
728
  cancel(err);
728
729
  void promise.catch(() => undefined);
730
+ this.reportRequestCompletion(params.message, startedAt, "error");
729
731
  throw err;
730
732
  }
731
- const result = await promise;
733
+ let result;
734
+ try {
735
+ result = await promise;
736
+ }
737
+ catch (error) {
738
+ const outcome = isWaiterTimeoutError(error) ? "timeout" : "error";
739
+ this.reportRequestCompletion(params.message, startedAt, outcome);
740
+ throw error;
741
+ }
732
742
  if (result.kind === "error") {
743
+ this.reportRequestCompletion(params.message, startedAt, "error");
733
744
  throw result.error;
734
745
  }
746
+ this.reportRequestCompletion(params.message, startedAt, "ok", result.value);
735
747
  return result.value;
736
748
  }
749
+ reportRequestCompletion(request, startedAt, outcome, response) {
750
+ const hook = this.config.onRequestComplete;
751
+ if (!hook)
752
+ return;
753
+ try {
754
+ hook({
755
+ requestType: request.type,
756
+ durationMs: Date.now() - startedAt,
757
+ outcome,
758
+ request,
759
+ ...(outcome === "ok" ? { response } : {}),
760
+ });
761
+ }
762
+ catch (error) {
763
+ // Telemetry must never fail a request, but a silent give-up is invisible.
764
+ this.logger.warn({ err: error }, "onRequestComplete hook threw");
765
+ }
766
+ }
737
767
  async sendCorrelatedRequest(params) {
738
768
  return this.sendRequest({
739
769
  requestId: params.requestId,
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import { DaemonClient } from "./daemon-client.js";
3
3
  import type { FetchAgentTimelineCursor, FetchAgentTimelineDirection, FetchAgentTimelinePayload, FetchAgentTimelineProjection } from "./daemon-client.js";
4
4
  export { DaemonClient };
5
5
  export { UploadCancelledError, UploadCapExceededError, UploadFailedError, } from "./daemon-client.js";
6
- export type { DaemonClientConfig, DaemonEvent, BrowserAutomationExecuteRequestMessage, BrowserAutomationExecuteResponseMessage, WebSocketFactory, WebSocketLike, } from "./daemon-client.js";
6
+ export type { DaemonClientConfig, DaemonEvent, DaemonRequestCompletion, BrowserAutomationExecuteRequestMessage, BrowserAutomationExecuteResponseMessage, WebSocketFactory, WebSocketLike, } from "./daemon-client.js";
7
7
  export type ConnectionState = {
8
8
  status: "idle";
9
9
  } | {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hyperdrive.bot/fleet-client",
3
- "version": "0.3.160",
3
+ "version": "0.3.162",
4
4
  "description": "Paseo client SDK package",
5
5
  "license": "Apache-2.0",
6
6
  "files": [
@@ -36,8 +36,8 @@
36
36
  "test": "vitest run"
37
37
  },
38
38
  "dependencies": {
39
- "@hyperdrive.bot/fleet-protocol": "0.3.160",
40
- "@hyperdrive.bot/fleet-relay": "0.3.160",
39
+ "@hyperdrive.bot/fleet-protocol": "0.3.162",
40
+ "@hyperdrive.bot/fleet-relay": "0.3.162",
41
41
  "zod": "^4.4.3"
42
42
  },
43
43
  "devDependencies": {