@hyperdrive.bot/fleet-client 0.3.161 → 0.3.163

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;
@@ -516,6 +531,9 @@ export type FetchAgentsOptions = Omit<FetchAgentsRequest, "type" | "requestId">
516
531
  timeout?: number;
517
532
  };
518
533
  export type FetchAgentsEntry = FetchAgentsPayload["entries"][number];
534
+ export type GetAgentsByIdsPayload = Extract<SessionOutboundMessage, {
535
+ type: "get_agents_by_ids_response";
536
+ }>["payload"];
519
537
  export type FetchAgentsPageInfo = FetchAgentsPayload["pageInfo"];
520
538
  type FetchAgentHistoryPayload = Extract<SessionOutboundMessage, {
521
539
  type: "fetch_agent_history_response";
@@ -851,6 +869,7 @@ export declare class DaemonClient {
851
869
  skipQueue?: boolean;
852
870
  };
853
871
  }): Promise<T>;
872
+ private reportRequestCompletion;
854
873
  private sendCorrelatedRequest;
855
874
  private sendCorrelatedSessionRequest;
856
875
  private sendNamespacedCorrelatedSessionRequest;
@@ -893,6 +912,16 @@ export declare class DaemonClient {
893
912
  private stopLivenessHeartbeat;
894
913
  private scheduleNextLivenessHeartbeat;
895
914
  fetchAgents(options?: FetchAgentsOptions): Promise<FetchAgentsPayload>;
915
+ /**
916
+ * Resolve up to 200 agents by id without a list load. Requires
917
+ * server_info.features.agentDirectoryDelta.
918
+ */
919
+ getAgentsByIds(ids: string[], options?: {
920
+ requestId?: string;
921
+ timeout?: number;
922
+ fields?: FetchAgentsOptions["fields"];
923
+ scope?: "active";
924
+ }): Promise<GetAgentsByIdsPayload>;
896
925
  fetchAgentHistory(options?: FetchAgentHistoryOptions): Promise<FetchAgentHistoryPayload>;
897
926
  fetchRecentProviderSessions(options?: FetchRecentProviderSessionsOptions): Promise<FetchRecentProviderSessionsPayload>;
898
927
  fetchWorkspaces(options?: FetchWorkspacesOptions): Promise<FetchWorkspacesPayload>;
@@ -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,
@@ -998,6 +1028,9 @@ export class DaemonClient {
998
1028
  ...(options?.sort ? { sort: options.sort } : {}),
999
1029
  ...(options?.page ? { page: options.page } : {}),
1000
1030
  ...(options?.subscribe ? { subscribe: options.subscribe } : {}),
1031
+ ...(options?.sinceCursor ? { sinceCursor: options.sinceCursor } : {}),
1032
+ ...(options?.fields ? { fields: options.fields } : {}),
1033
+ ...(options?.query ? { query: options.query } : {}),
1001
1034
  });
1002
1035
  return this.sendRequest({
1003
1036
  requestId: resolvedRequestId,
@@ -1015,6 +1048,35 @@ export class DaemonClient {
1015
1048
  },
1016
1049
  });
1017
1050
  }
1051
+ /**
1052
+ * Resolve up to 200 agents by id without a list load. Requires
1053
+ * server_info.features.agentDirectoryDelta.
1054
+ */
1055
+ async getAgentsByIds(ids, options) {
1056
+ const resolvedRequestId = this.createRequestId(options?.requestId);
1057
+ const message = SessionInboundMessageSchema.parse({
1058
+ type: "get_agents_by_ids_request",
1059
+ requestId: resolvedRequestId,
1060
+ ids,
1061
+ ...(options?.fields ? { fields: options.fields } : {}),
1062
+ ...(options?.scope ? { scope: options.scope } : {}),
1063
+ });
1064
+ return this.sendRequest({
1065
+ requestId: resolvedRequestId,
1066
+ message,
1067
+ timeout: options?.timeout,
1068
+ options: { skipQueue: true },
1069
+ select: (msg) => {
1070
+ if (msg.type !== "get_agents_by_ids_response") {
1071
+ return null;
1072
+ }
1073
+ if (msg.payload.requestId !== resolvedRequestId) {
1074
+ return null;
1075
+ }
1076
+ return msg.payload;
1077
+ },
1078
+ });
1079
+ }
1018
1080
  async fetchAgentHistory(options) {
1019
1081
  const resolvedRequestId = this.createRequestId(options?.requestId);
1020
1082
  const message = SessionInboundMessageSchema.parse({
@@ -4705,6 +4767,7 @@ export class DaemonClient {
4705
4767
  [CLIENT_CAPS.customModeIcons]: true,
4706
4768
  [CLIENT_CAPS.reasoningMergeEnum]: true,
4707
4769
  [CLIENT_CAPS.terminalReflowableSnapshot]: true,
4770
+ [CLIENT_CAPS.agentDirectoryDelta]: true,
4708
4771
  ...this.config.capabilities,
4709
4772
  },
4710
4773
  ...(this.config.appVersion ? { appVersion: this.config.appVersion } : {}),
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.161",
3
+ "version": "0.3.163",
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.161",
40
- "@hyperdrive.bot/fleet-relay": "0.3.161",
39
+ "@hyperdrive.bot/fleet-protocol": "0.3.163",
40
+ "@hyperdrive.bot/fleet-relay": "0.3.163",
41
41
  "zod": "^4.4.3"
42
42
  },
43
43
  "devDependencies": {