@yuliaedomskikh/agentflow-client 1.1.0 → 1.2.0

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 ADDED
@@ -0,0 +1,29 @@
1
+ # Changelog
2
+
3
+ This SDK follows semantic versioning.
4
+
5
+ SemVer rules:
6
+ - `MAJOR`: breaking changes such as removed methods or incompatible parameter changes
7
+ - `MINOR`: new methods, optional parameters, or additive model fields
8
+ - `PATCH`: bug fixes and internal changes with no public API break
9
+
10
+ Deprecation policy:
11
+ - A method or field is deprecated with a warning for one full major version before removal
12
+ - The warning states what is deprecated, what to use instead, and in which version removal happens
13
+
14
+ ## [Unreleased]
15
+
16
+ ### Added
17
+ - `RetryPolicy` with exponential backoff, jitter, and `Retry-After` support for transient SDK failures
18
+ - `CircuitBreaker`, `CircuitState`, and `CircuitOpenError` exports for repeated backend failure protection
19
+
20
+ ### Changed
21
+ - `AgentFlowClient` now accepts optional `retryPolicy` and `circuitBreaker` options
22
+ - Idempotent SDK requests now retry on `429`, `502`, `503`, `504`, and transport failures before surfacing the final error
23
+ - Added resilience-focused Vitest coverage for retry/backoff and circuit-breaker behavior
24
+
25
+ ## [1.0.0] - 2026-04-11
26
+
27
+ ### Added
28
+ - Stable TypeScript SDK for entity, metric, batch, query, health, and SSE APIs
29
+ - Root package exports for the client, public exception types, and response model types
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { AgentFlowClient } from "./src/client.js";
2
2
  export { CircuitBreaker, CircuitOpenError, CircuitState, } from "./src/circuitBreaker.js";
3
- export { AgentFlowError, AuthError, DataFreshnessError, EntityNotFoundError, RateLimitError, } from "./src/exceptions.js";
3
+ export { AgentFlowError, AuthError, DataFreshnessError, EntityNotFoundError, PermissionDeniedError, RateLimitError, } from "./src/exceptions.js";
4
4
  export { RetryPolicy } from "./src/retry.js";
5
5
  export type { BatchItem, BatchResponse, CatalogResponse, ClientOptions, EventFilters, HealthStatus, MetricName, MetricResult, OrderEntity, PipelineEvent, ProductEntity, QueryResult, SessionEntity, TimeWindow, UserEntity, } from "./src/models.js";
6
6
  export type { CircuitBreakerOptions } from "./src/circuitBreaker.js";
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  export { AgentFlowClient } from "./src/client.js";
2
2
  export { CircuitBreaker, CircuitOpenError, CircuitState, } from "./src/circuitBreaker.js";
3
- export { AgentFlowError, AuthError, DataFreshnessError, EntityNotFoundError, RateLimitError, } from "./src/exceptions.js";
3
+ export { AgentFlowError, AuthError, DataFreshnessError, EntityNotFoundError, PermissionDeniedError, RateLimitError, } from "./src/exceptions.js";
4
4
  export { RetryPolicy } from "./src/retry.js";
@@ -1,4 +1,4 @@
1
- import type { BatchItem, BatchResponse, CatalogResponse, EventFilters, FetchLike, HealthStatus, MetricName, MetricResult, OrderEntity, PipelineEvent, ProductEntity, QueryResult, SessionEntity, TimeWindow, UserEntity } from "./models.js";
1
+ import type { BatchItem, BatchResponse, CatalogResponse, ClientOptions, EventFilters, HealthStatus, MetricName, MetricResult, OrderEntity, PipelineEvent, ProductEntity, QueryResult, SessionEntity, TimeWindow, UserEntity } from "./models.js";
2
2
  import { CircuitBreaker } from "./circuitBreaker.js";
3
3
  import { RetryPolicy } from "./retry.js";
4
4
  export declare class AgentFlowClient {
@@ -11,12 +11,7 @@ export declare class AgentFlowClient {
11
11
  private readonly contractCache;
12
12
  retryPolicy: RetryPolicy;
13
13
  circuitBreaker: CircuitBreaker;
14
- constructor(baseUrl: string, apiKey: string, options?: {
15
- fetch?: FetchLike;
16
- timeoutMs?: number;
17
- headers?: HeadersInit;
18
- contractVersion?: string;
19
- });
14
+ constructor(baseUrl: string, apiKey: string, options?: ClientOptions);
20
15
  configureResilience(options: {
21
16
  retryPolicy?: RetryPolicy;
22
17
  circuitBreaker?: CircuitBreaker;
@@ -1,4 +1,4 @@
1
- import { AgentFlowError, AuthError, DataFreshnessError, EntityNotFoundError, RateLimitError, } from "./exceptions.js";
1
+ import { AgentFlowError, AuthError, DataFreshnessError, EntityNotFoundError, PermissionDeniedError, RateLimitError, } from "./exceptions.js";
2
2
  import { CircuitBreaker } from "./circuitBreaker.js";
3
3
  import { RETRYABLE_STATUS, RetryPolicy, isRetryableMethod, } from "./retry.js";
4
4
  import { streamSseJson } from "./stream.js";
@@ -19,15 +19,14 @@ export class AgentFlowClient {
19
19
  retryPolicy;
20
20
  circuitBreaker;
21
21
  constructor(baseUrl, apiKey, options = {}) {
22
- const legacyOptions = options;
23
22
  this.baseUrl = baseUrl.replace(/\/+$/, "");
24
23
  this.apiKey = apiKey;
25
24
  this.fetchImpl = options.fetch ?? this.resolveFetch();
26
25
  this.timeoutMs = options.timeoutMs ?? 10_000;
27
26
  this.headers = options.headers;
28
27
  this.contractVersions = this.parseContractVersions(options.contractVersion);
29
- this.retryPolicy = legacyOptions.retryPolicy ?? new RetryPolicy();
30
- this.circuitBreaker = legacyOptions.circuitBreaker ?? new CircuitBreaker();
28
+ this.retryPolicy = options.retryPolicy ?? new RetryPolicy();
29
+ this.circuitBreaker = options.circuitBreaker ?? new CircuitBreaker();
31
30
  }
32
31
  configureResilience(options) {
33
32
  if (options.retryPolicy) {
@@ -243,7 +242,8 @@ export class AgentFlowClient {
243
242
  if (error instanceof AgentFlowError
244
243
  || error instanceof AuthError
245
244
  || error instanceof RateLimitError
246
- || error instanceof EntityNotFoundError) {
245
+ || error instanceof EntityNotFoundError
246
+ || error instanceof PermissionDeniedError) {
247
247
  throw error;
248
248
  }
249
249
  const timedOut = controller.signal.aborted && !options.signal?.aborted;
@@ -278,6 +278,9 @@ export class AgentFlowClient {
278
278
  if (response.status === 401) {
279
279
  throw new AuthError(detail ?? "Unauthorized");
280
280
  }
281
+ if (response.status === 403) {
282
+ throw new PermissionDeniedError(detail ?? "Forbidden");
283
+ }
281
284
  if (response.status === 429) {
282
285
  const retryAfterHeader = response.headers.get("retry-after");
283
286
  const retryAfter = retryAfterHeader ? Number(retryAfterHeader) : 0;
@@ -5,6 +5,9 @@ export declare class AgentFlowError extends Error {
5
5
  export declare class AuthError extends AgentFlowError {
6
6
  constructor(message?: string);
7
7
  }
8
+ export declare class PermissionDeniedError extends AgentFlowError {
9
+ constructor(message?: string);
10
+ }
8
11
  export declare class RateLimitError extends AgentFlowError {
9
12
  readonly retryAfter: number;
10
13
  constructor(message?: string, retryAfter?: number);
@@ -12,6 +12,12 @@ export class AuthError extends AgentFlowError {
12
12
  this.name = "AuthError";
13
13
  }
14
14
  }
15
+ export class PermissionDeniedError extends AgentFlowError {
16
+ constructor(message = "Forbidden") {
17
+ super(message, 403);
18
+ this.name = "PermissionDeniedError";
19
+ }
20
+ }
15
21
  export class RateLimitError extends AgentFlowError {
16
22
  retryAfter;
17
23
  constructor(message = "Rate limit exceeded", retryAfter = 0) {
@@ -35,8 +35,9 @@ export async function* streamSseJson(response, signal) {
35
35
  }
36
36
  }
37
37
  buffer += decoder.decode().replace(/\r\n/g, "\n");
38
- if (buffer.trim().startsWith("data:")) {
39
- const data = buffer
38
+ const finalFrame = buffer.trim();
39
+ if (finalFrame) {
40
+ const data = finalFrame
40
41
  .split("\n")
41
42
  .filter((line) => line.startsWith("data:"))
42
43
  .map((line) => line.slice(5).trimStart())
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuliaedomskikh/agentflow-client",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "TypeScript SDK for the AgentFlow API",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -16,14 +16,15 @@
16
16
  },
17
17
  "files": [
18
18
  "dist",
19
- "README.md"
19
+ "README.md",
20
+ "CHANGELOG.md"
20
21
  ],
21
22
  "sideEffects": false,
22
23
  "scripts": {
23
24
  "build": "tsc -p tsconfig.json",
24
25
  "typecheck": "tsc --noEmit",
25
- "test:unit": "vitest run --root .. --exclude=mutants/** tests/client.test.ts sdk-ts/tests/retry.test.ts sdk-ts/tests/circuitBreaker.test.ts sdk-ts/tests/resilience-integration.test.ts",
26
- "test": "vitest run --root .. --exclude=mutants/** tests/client.test.ts sdk-ts/tests/retry.test.ts sdk-ts/tests/circuitBreaker.test.ts sdk-ts/tests/resilience-integration.test.ts"
26
+ "test:unit": "vitest run --root .. --exclude=mutants/** tests/client.test.ts sdk-ts/tests",
27
+ "test": "vitest run --root .. --exclude=mutants/** tests/client.test.ts sdk-ts/tests"
27
28
  },
28
29
  "keywords": [
29
30
  "agentflow",