@cadraos/sdk 0.3.5 → 0.3.7

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.
@@ -44,6 +44,8 @@ interface HttpClientConfig {
44
44
  retry: RetryConfig;
45
45
  /** Custom headers */
46
46
  headers?: Record<string, string>;
47
+ /** Optional fetch implementation — inject `expo/fetch` for React Native streaming. Defaults to global fetch. */
48
+ fetch?: typeof fetch;
47
49
  }
48
50
  /**
49
51
  * Request options
@@ -965,6 +967,8 @@ interface RemoteAgentCreateInput {
965
967
  name: string;
966
968
  description?: string;
967
969
  adapterType: string;
970
+ /** Bind the agent to a specific runner (e.g. a Cadra Desktop install). */
971
+ defaultRunnerId?: number | null;
968
972
  executionTargetKind?: RemoteAgentExecutionTargetKind;
969
973
  adapterConfig?: Record<string, unknown>;
970
974
  inputSchema?: Record<string, unknown>;
@@ -975,6 +979,8 @@ interface RemoteAgentUpdateInput {
975
979
  name?: string;
976
980
  description?: string;
977
981
  adapterType?: string;
982
+ /** Re-bind the agent to a specific runner. */
983
+ defaultRunnerId?: number | null;
978
984
  executionTargetKind?: RemoteAgentExecutionTargetKind;
979
985
  adapterConfig?: Record<string, unknown>;
980
986
  inputSchema?: Record<string, unknown>;
@@ -1744,6 +1750,8 @@ interface StreamConfig {
1744
1750
  token?: string;
1745
1751
  tokenProvider?: () => Promise<string>;
1746
1752
  orgId: number;
1753
+ /** Optional fetch implementation — inject `expo/fetch` for React Native streaming. Defaults to global fetch. */
1754
+ fetch?: typeof fetch;
1747
1755
  }
1748
1756
 
1749
1757
  /**
@@ -3071,6 +3079,8 @@ interface CadraClientOptionsApiKey {
3071
3079
  maxRetries?: number;
3072
3080
  /** Custom headers to include in all requests */
3073
3081
  headers?: Record<string, string>;
3082
+ /** Optional fetch implementation — inject `expo/fetch` for React Native streaming. Defaults to global fetch. */
3083
+ fetch?: typeof fetch;
3074
3084
  }
3075
3085
  /**
3076
3086
  * Client options for OAuth token authentication
@@ -3088,6 +3098,8 @@ interface CadraClientOptionsToken {
3088
3098
  maxRetries?: number;
3089
3099
  /** Custom headers to include in all requests */
3090
3100
  headers?: Record<string, string>;
3101
+ /** Optional fetch implementation — inject `expo/fetch` for React Native streaming. Defaults to global fetch. */
3102
+ fetch?: typeof fetch;
3091
3103
  }
3092
3104
  /**
3093
3105
  * Client options for token provider authentication
@@ -3105,6 +3117,8 @@ interface CadraClientOptionsTokenProvider {
3105
3117
  maxRetries?: number;
3106
3118
  /** Custom headers to include in all requests */
3107
3119
  headers?: Record<string, string>;
3120
+ /** Optional fetch implementation — inject `expo/fetch` for React Native streaming. Defaults to global fetch. */
3121
+ fetch?: typeof fetch;
3108
3122
  }
3109
3123
  /**
3110
3124
  * All client options
@@ -44,6 +44,8 @@ interface HttpClientConfig {
44
44
  retry: RetryConfig;
45
45
  /** Custom headers */
46
46
  headers?: Record<string, string>;
47
+ /** Optional fetch implementation — inject `expo/fetch` for React Native streaming. Defaults to global fetch. */
48
+ fetch?: typeof fetch;
47
49
  }
48
50
  /**
49
51
  * Request options
@@ -965,6 +967,8 @@ interface RemoteAgentCreateInput {
965
967
  name: string;
966
968
  description?: string;
967
969
  adapterType: string;
970
+ /** Bind the agent to a specific runner (e.g. a Cadra Desktop install). */
971
+ defaultRunnerId?: number | null;
968
972
  executionTargetKind?: RemoteAgentExecutionTargetKind;
969
973
  adapterConfig?: Record<string, unknown>;
970
974
  inputSchema?: Record<string, unknown>;
@@ -975,6 +979,8 @@ interface RemoteAgentUpdateInput {
975
979
  name?: string;
976
980
  description?: string;
977
981
  adapterType?: string;
982
+ /** Re-bind the agent to a specific runner. */
983
+ defaultRunnerId?: number | null;
978
984
  executionTargetKind?: RemoteAgentExecutionTargetKind;
979
985
  adapterConfig?: Record<string, unknown>;
980
986
  inputSchema?: Record<string, unknown>;
@@ -1744,6 +1750,8 @@ interface StreamConfig {
1744
1750
  token?: string;
1745
1751
  tokenProvider?: () => Promise<string>;
1746
1752
  orgId: number;
1753
+ /** Optional fetch implementation — inject `expo/fetch` for React Native streaming. Defaults to global fetch. */
1754
+ fetch?: typeof fetch;
1747
1755
  }
1748
1756
 
1749
1757
  /**
@@ -3071,6 +3079,8 @@ interface CadraClientOptionsApiKey {
3071
3079
  maxRetries?: number;
3072
3080
  /** Custom headers to include in all requests */
3073
3081
  headers?: Record<string, string>;
3082
+ /** Optional fetch implementation — inject `expo/fetch` for React Native streaming. Defaults to global fetch. */
3083
+ fetch?: typeof fetch;
3074
3084
  }
3075
3085
  /**
3076
3086
  * Client options for OAuth token authentication
@@ -3088,6 +3098,8 @@ interface CadraClientOptionsToken {
3088
3098
  maxRetries?: number;
3089
3099
  /** Custom headers to include in all requests */
3090
3100
  headers?: Record<string, string>;
3101
+ /** Optional fetch implementation — inject `expo/fetch` for React Native streaming. Defaults to global fetch. */
3102
+ fetch?: typeof fetch;
3091
3103
  }
3092
3104
  /**
3093
3105
  * Client options for token provider authentication
@@ -3105,6 +3117,8 @@ interface CadraClientOptionsTokenProvider {
3105
3117
  maxRetries?: number;
3106
3118
  /** Custom headers to include in all requests */
3107
3119
  headers?: Record<string, string>;
3120
+ /** Optional fetch implementation — inject `expo/fetch` for React Native streaming. Defaults to global fetch. */
3121
+ fetch?: typeof fetch;
3108
3122
  }
3109
3123
  /**
3110
3124
  * All client options
@@ -297,7 +297,8 @@ var HttpClient = class {
297
297
  const controller = new AbortController();
298
298
  const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
299
299
  try {
300
- const response = await fetch(url, {
300
+ const doFetch = this.config.fetch ?? fetch;
301
+ const response = await doFetch(url, {
301
302
  method: options.method,
302
303
  headers,
303
304
  body: options.body !== void 0 ? JSON.stringify(options.body) : void 0,
@@ -429,7 +430,8 @@ var SSEClient = class {
429
430
  console.log("[SDK:SSE] Auth header:", this.config.authHeader ? `${this.config.authHeader.substring(0, 30)}...` : "MISSING");
430
431
  console.log("[SDK:SSE] Org ID:", this.config.orgId);
431
432
  try {
432
- const response = await fetch(this.config.url, {
433
+ const doFetch = this.config.fetch ?? fetch;
434
+ const response = await doFetch(this.config.url, {
433
435
  method: "GET",
434
436
  headers: {
435
437
  "Authorization": this.config.authHeader,
@@ -667,6 +669,15 @@ var ExecutionStreamControllerImpl = class {
667
669
  sseClient = null;
668
670
  status = "connecting";
669
671
  reconnectAttempts = 0;
672
+ // CAD-39 / webchat dual-plane create-connect race. `hasConnected` flips true on
673
+ // the first successful SSE open; `notFoundRetries` bounds retries of a 404
674
+ // encountered BEFORE we ever connect (the run row is persisted slightly AFTER
675
+ // the client opens the stream — the norm on the webchat path where msg-api owns
676
+ // the executionId and cadra persists the agent_executions row via an async
677
+ // worker callback). See handleConnectionError.
678
+ hasConnected = false;
679
+ notFoundRetries = 0;
680
+ maxConnectRaceRetries = 3;
670
681
  seenEventIds = /* @__PURE__ */ new Set();
671
682
  _lastEventId = null;
672
683
  activityTimeoutId = null;
@@ -795,6 +806,7 @@ var ExecutionStreamControllerImpl = class {
795
806
  url,
796
807
  authHeader: `Bearer ${authToken}`,
797
808
  orgId: this.options.orgId,
809
+ fetch: this.options.fetch,
798
810
  onEvent: (event) => this.handleEvent(event),
799
811
  onError: (error) => {
800
812
  console.error("[SDK:StreamController] SSE error:", error);
@@ -805,6 +817,8 @@ var ExecutionStreamControllerImpl = class {
805
817
  if (connected) {
806
818
  this.status = "connected";
807
819
  this.reconnectAttempts = 0;
820
+ this.hasConnected = true;
821
+ this.notFoundRetries = 0;
808
822
  this.resetActivityTimeout();
809
823
  }
810
824
  this.emit("connectionChange", { connected, usingFallback: false });
@@ -1094,6 +1108,38 @@ var ExecutionStreamControllerImpl = class {
1094
1108
  return;
1095
1109
  }
1096
1110
  const msg = error instanceof Error ? error.message : String(error);
1111
+ const isNotFound = /\b404\b/.test(msg);
1112
+ const isAuthFailure = /\b40[13]\b/.test(msg) || /INVALID_API_KEY|INVALID_REQUEST/.test(msg);
1113
+ if (isNotFound && !isAuthFailure && !this.hasConnected) {
1114
+ if (this.notFoundRetries < this.maxConnectRaceRetries) {
1115
+ this.notFoundRetries++;
1116
+ this.status = "reconnecting";
1117
+ const delay = Math.min(
1118
+ this.config.reconnectBaseDelayMs * this.notFoundRetries,
1119
+ this.config.reconnectMaxDelayMs
1120
+ );
1121
+ await new Promise((resolve) => setTimeout(resolve, delay));
1122
+ if (this.status === "closed") {
1123
+ return;
1124
+ }
1125
+ try {
1126
+ await this.connectSSE();
1127
+ } catch (retryError) {
1128
+ await this.handleConnectionError(retryError);
1129
+ }
1130
+ return;
1131
+ }
1132
+ if (this.pollingEnabled) {
1133
+ if (this.sseClient) {
1134
+ this.sseClient.disconnect();
1135
+ this.sseClient = null;
1136
+ }
1137
+ this.status = "fallback_polling";
1138
+ this.emit("connectionChange", { connected: false, usingFallback: true });
1139
+ this.startPolling();
1140
+ return;
1141
+ }
1142
+ }
1097
1143
  if (/\b4\d\d\b/.test(msg) || /INVALID_API_KEY|INVALID_REQUEST/.test(msg)) {
1098
1144
  if (this.sseClient) {
1099
1145
  this.sseClient.disconnect();
@@ -1472,6 +1518,7 @@ var AgentsAPI = class extends BaseResourceAPI {
1472
1518
  apiKey: config.apiKey,
1473
1519
  tokenProvider: config.tokenProvider,
1474
1520
  orgId: config.orgId,
1521
+ fetch: config.fetch,
1475
1522
  getExecution: (id) => this.getExecution(id)
1476
1523
  });
1477
1524
  console.log("[SDK:Agents] Stream controller created - caller must call connect() after registering listeners");
@@ -1518,6 +1565,7 @@ var AgentsAPI = class extends BaseResourceAPI {
1518
1565
  apiKey: config.apiKey,
1519
1566
  tokenProvider: config.tokenProvider,
1520
1567
  orgId: config.orgId,
1568
+ fetch: config.fetch,
1521
1569
  getExecution: (id) => this.getExecution(id)
1522
1570
  });
1523
1571
  console.log("[SDK:Agents] Stream controller created for existing execution - caller must call connect() after registering listeners");
@@ -2366,6 +2414,7 @@ var SessionsAPI = class extends BaseResourceAPI {
2366
2414
  baseUrl: config.baseUrl,
2367
2415
  apiKey: config.apiKey,
2368
2416
  orgId: config.orgId,
2417
+ fetch: config.fetch,
2369
2418
  getExecution: (id) => this.getExecution(id)
2370
2419
  });
2371
2420
  await controller.connect();
@@ -3020,7 +3069,8 @@ var CadraClient = class {
3020
3069
  baseUrl: options.baseUrl ?? DEFAULT_BASE_URL,
3021
3070
  orgId: options.orgId,
3022
3071
  timeout: options.timeout ?? DEFAULT_TIMEOUT,
3023
- headers: options.headers
3072
+ headers: options.headers,
3073
+ fetch: options.fetch
3024
3074
  };
3025
3075
  if ("apiKey" in options) {
3026
3076
  this.config.apiKey = options.apiKey;
@@ -3041,7 +3091,8 @@ var CadraClient = class {
3041
3091
  orgId: this.config.orgId,
3042
3092
  timeout: this.config.timeout,
3043
3093
  retry: retryConfig,
3044
- headers: this.config.headers
3094
+ headers: this.config.headers,
3095
+ fetch: this.config.fetch
3045
3096
  };
3046
3097
  this.httpClient = new HttpClient(httpConfig);
3047
3098
  const getStreamConfig = () => ({
@@ -3049,7 +3100,8 @@ var CadraClient = class {
3049
3100
  apiKey: this.config.apiKey,
3050
3101
  token: this.config.token,
3051
3102
  tokenProvider: this.config.tokenProvider,
3052
- orgId: this.config.orgId
3103
+ orgId: this.config.orgId,
3104
+ fetch: this.config.fetch
3053
3105
  });
3054
3106
  this.agents = new AgentsAPI(this.httpClient, getStreamConfig);
3055
3107
  this.skills = new SkillsAPI(this.httpClient);