@coval/sdk 0.4.0 → 0.4.1
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/README.md +42 -0
- package/dist/CovalClient.d.ts +12 -0
- package/dist/CovalClient.d.ts.map +1 -1
- package/dist/CovalClient.js +13 -1
- package/dist/CovalClient.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/retry.d.ts +5 -0
- package/dist/retry.d.ts.map +1 -1
- package/dist/retry.js +20 -0
- package/dist/retry.js.map +1 -1
- package/dist/stats.d.ts +13 -0
- package/dist/stats.d.ts.map +1 -0
- package/dist/stats.js +13 -0
- package/dist/stats.js.map +1 -0
- package/package.json +1 -1
- package/src/CovalClient.ts +20 -1
- package/src/index.ts +2 -0
- package/src/retry.ts +24 -0
- package/src/stats.ts +25 -0
package/README.md
CHANGED
|
@@ -108,6 +108,48 @@ const all = await collectAll({
|
|
|
108
108
|
});
|
|
109
109
|
```
|
|
110
110
|
|
|
111
|
+
### Diagnosing intermittent failures
|
|
112
|
+
|
|
113
|
+
A request that dies in transit never reaches the API, so there is no
|
|
114
|
+
server-side trace of it. The client keeps live counters:
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
coval.stats;
|
|
118
|
+
// { calls: 12, requests: 14, retries: 2, networkErrors: 1 }
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
`calls` is logical API calls, `requests` counts every `fetch` including
|
|
122
|
+
retries, and `networkErrors` counts failures where no response came back at
|
|
123
|
+
all. Include these when reporting sporadic timeouts. For a line per retry and
|
|
124
|
+
per in-transit failure:
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
const coval = new CovalClient({ apiKey, onDebug: console.debug });
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Connection reuse
|
|
131
|
+
|
|
132
|
+
On Node the client uses the global `fetch` (undici), which expires idle
|
|
133
|
+
keep-alive connections after roughly 4 seconds. That bound matters: some
|
|
134
|
+
network paths silently drop an idle connection without closing it, and reusing
|
|
135
|
+
one stalls the request until your timeout, because it never reaches the server.
|
|
136
|
+
|
|
137
|
+
Requests made within that window can still reuse a pooled connection. If you
|
|
138
|
+
submit infrequently, or you have seen unexplained timeouts, pass an explicit
|
|
139
|
+
dispatcher:
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
import { Agent, fetch as undiciFetch } from 'undici';
|
|
143
|
+
|
|
144
|
+
const coval = new CovalClient({
|
|
145
|
+
apiKey,
|
|
146
|
+
fetch: ((input, init) =>
|
|
147
|
+
undiciFetch(input as never, { ...init, dispatcher: new Agent({ keepAliveTimeout: 1_000 }) })) as typeof fetch,
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The Python SDK exposes the same bound directly as `max_idle_seconds`.
|
|
152
|
+
|
|
111
153
|
## Customization
|
|
112
154
|
|
|
113
155
|
### Override base URL (staging, self-host)
|
package/dist/CovalClient.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type RetryOptions } from './retry.js';
|
|
2
|
+
import { type CovalTransportStats } from './stats.js';
|
|
2
3
|
import { AgentsApi, APIKeysApi, AudioApi, Configuration, ConversationsApi, DashboardsApi, type FetchAPI, IntegrationsApi, type Middleware, MetricOutputsApi, MetricsApi, MonitorEventsApi, MonitorsApi, MutationsApi, OrganizationConversationsConfigApi, PersonasApi, ReportsApi, ReviewAnnotationsApi, ReviewProjectsApi, RunsApi, RunTemplatesApi, ScheduledRunsApi, SimulationsApi, TagsApi, TestCasesApi, TestSetsApi, TracesApi, WebhooksApi, WidgetsApi } from './generated/index.js';
|
|
3
4
|
export interface CovalClientOptions {
|
|
4
5
|
/** Coval API key. Required. Sent as `x-api-key` (lowercase). */
|
|
@@ -11,6 +12,11 @@ export interface CovalClientOptions {
|
|
|
11
12
|
middleware?: Middleware[];
|
|
12
13
|
/** Override the global fetch (e.g., for tests, undici-with-keepalive, etc). */
|
|
13
14
|
fetch?: FetchAPI;
|
|
15
|
+
/**
|
|
16
|
+
* Called with a diagnostic line on each retry and each in-transit failure.
|
|
17
|
+
* Pass `console.debug` when investigating intermittent timeouts.
|
|
18
|
+
*/
|
|
19
|
+
onDebug?: (message: string) => void;
|
|
14
20
|
}
|
|
15
21
|
export declare class CovalClient {
|
|
16
22
|
readonly agents: AgentsApi;
|
|
@@ -40,6 +46,12 @@ export declare class CovalClient {
|
|
|
40
46
|
readonly webhooks: WebhooksApi;
|
|
41
47
|
readonly widgets: WidgetsApi;
|
|
42
48
|
readonly configuration: Configuration;
|
|
49
|
+
/**
|
|
50
|
+
* Live transport counters. A request that dies in transit leaves no
|
|
51
|
+
* server-side trace, so these are often the only evidence when diagnosing
|
|
52
|
+
* intermittent failures. Include them when reporting one.
|
|
53
|
+
*/
|
|
54
|
+
readonly stats: CovalTransportStats;
|
|
43
55
|
constructor(options: CovalClientOptions);
|
|
44
56
|
}
|
|
45
57
|
//# sourceMappingURL=CovalClient.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CovalClient.d.ts","sourceRoot":"","sources":["../src/CovalClient.ts"],"names":[],"mappings":"AAcA,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,EACL,SAAS,EACT,UAAU,EACV,QAAQ,EACR,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,KAAK,QAAQ,EACb,eAAe,EACf,KAAK,UAAU,EACf,gBAAgB,EAChB,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,kCAAkC,EAClC,WAAW,EACX,UAAU,EACV,oBAAoB,EACpB,iBAAiB,EACjB,OAAO,EACP,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,OAAO,EACP,YAAY,EACZ,WAAW,EACX,SAAS,EACT,WAAW,EACX,UAAU,EACX,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,kBAAkB;IACjC,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,KAAK,CAAC,EAAE,YAAY,GAAG,KAAK,CAAC;IAC7B,yDAAyD;IACzD,UAAU,CAAC,EAAE,UAAU,EAAE,CAAC;IAC1B,+EAA+E;IAC/E,KAAK,CAAC,EAAE,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"CovalClient.d.ts","sourceRoot":"","sources":["../src/CovalClient.ts"],"names":[],"mappings":"AAcA,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,EAAwB,KAAK,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAC5E,OAAO,EACL,SAAS,EACT,UAAU,EACV,QAAQ,EACR,aAAa,EACb,gBAAgB,EAChB,aAAa,EACb,KAAK,QAAQ,EACb,eAAe,EACf,KAAK,UAAU,EACf,gBAAgB,EAChB,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,kCAAkC,EAClC,WAAW,EACX,UAAU,EACV,oBAAoB,EACpB,iBAAiB,EACjB,OAAO,EACP,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,OAAO,EACP,YAAY,EACZ,WAAW,EACX,SAAS,EACT,WAAW,EACX,UAAU,EACX,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,kBAAkB;IACjC,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,KAAK,CAAC,EAAE,YAAY,GAAG,KAAK,CAAC;IAC7B,yDAAyD;IACzD,UAAU,CAAC,EAAE,UAAU,EAAE,CAAC;IAC1B,+EAA+E;IAC/E,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAID,qBAAa,WAAW;IACtB,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,aAAa,EAAE,gBAAgB,CAAC;IACzC,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC;IACnC,QAAQ,CAAC,YAAY,EAAE,eAAe,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,aAAa,EAAE,gBAAgB,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,gBAAgB,CAAC;IACzC,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IACjC,QAAQ,CAAC,+BAA+B,EAAE,kCAAkC,CAAC;IAC7E,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,iBAAiB,EAAE,oBAAoB,CAAC;IACjD,QAAQ,CAAC,cAAc,EAAE,iBAAiB,CAAC;IAC3C,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,eAAe,CAAC;IACvC,QAAQ,CAAC,aAAa,EAAE,gBAAgB,CAAC;IACzC,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC;IACrC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAE7B,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IAEtC;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAC;gBAExB,OAAO,EAAE,kBAAkB;CAwDxC"}
|
package/dist/CovalClient.js
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
import { apiKeyAuthMiddleware } from './auth.js';
|
|
13
13
|
import { CovalApiError, parseErrorResponse } from './errors.js';
|
|
14
14
|
import { createRetryingFetch } from './retry.js';
|
|
15
|
+
import { createTransportStats } from './stats.js';
|
|
15
16
|
import { AgentsApi, APIKeysApi, AudioApi, Configuration, ConversationsApi, DashboardsApi, IntegrationsApi, MetricOutputsApi, MetricsApi, MonitorEventsApi, MonitorsApi, MutationsApi, OrganizationConversationsConfigApi, PersonasApi, ReportsApi, ReviewAnnotationsApi, ReviewProjectsApi, RunsApi, RunTemplatesApi, ScheduledRunsApi, SimulationsApi, TagsApi, TestCasesApi, TestSetsApi, TracesApi, WebhooksApi, WidgetsApi, } from './generated/index.js';
|
|
16
17
|
const DEFAULT_BASE_URL = 'https://api.coval.dev/v1';
|
|
17
18
|
export class CovalClient {
|
|
@@ -42,14 +43,25 @@ export class CovalClient {
|
|
|
42
43
|
webhooks;
|
|
43
44
|
widgets;
|
|
44
45
|
configuration;
|
|
46
|
+
/**
|
|
47
|
+
* Live transport counters. A request that dies in transit leaves no
|
|
48
|
+
* server-side trace, so these are often the only evidence when diagnosing
|
|
49
|
+
* intermittent failures. Include them when reporting one.
|
|
50
|
+
*/
|
|
51
|
+
stats;
|
|
45
52
|
constructor(options) {
|
|
46
53
|
if (!options.apiKey) {
|
|
47
54
|
throw new Error('CovalClient: apiKey is required');
|
|
48
55
|
}
|
|
56
|
+
this.stats = createTransportStats();
|
|
49
57
|
const innerFetch = options.fetch ?? globalThis.fetch;
|
|
50
58
|
const fetchApi = options.retry === false
|
|
51
59
|
? innerFetch
|
|
52
|
-
: createRetryingFetch(options.retry ?? {}, {
|
|
60
|
+
: createRetryingFetch(options.retry ?? {}, {
|
|
61
|
+
fetch: innerFetch,
|
|
62
|
+
stats: this.stats,
|
|
63
|
+
onDebug: options.onDebug,
|
|
64
|
+
});
|
|
53
65
|
const middleware = [
|
|
54
66
|
apiKeyAuthMiddleware({ apiKey: options.apiKey }),
|
|
55
67
|
errorMiddleware(),
|
package/dist/CovalClient.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CovalClient.js","sourceRoot":"","sources":["../src/CovalClient.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,EAAE;AACF,iDAAiD;AACjD,oEAAoE;AACpE,qEAAqE;AACrE,yEAAyE;AACzE,2EAA2E;AAC3E,EAAE;AACF,2EAA2E;AAC3E,yEAAyE;AACzE,iDAAiD;AAEjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAqB,MAAM,YAAY,CAAC;AACpE,OAAO,EACL,SAAS,EACT,UAAU,EACV,QAAQ,EACR,aAAa,EACb,gBAAgB,EAChB,aAAa,EAEb,eAAe,EAEf,gBAAgB,EAChB,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,YAAY,EACZ,kCAAkC,EAClC,WAAW,EACX,UAAU,EACV,oBAAoB,EACpB,iBAAiB,EACjB,OAAO,EACP,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,OAAO,EACP,YAAY,EACZ,WAAW,EACX,SAAS,EACT,WAAW,EACX,UAAU,GACX,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"CovalClient.js","sourceRoot":"","sources":["../src/CovalClient.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,5 +7,7 @@ export type { PaginateOptions } from './pagination.js';
|
|
|
7
7
|
export { apiKeyAuthMiddleware } from './auth.js';
|
|
8
8
|
export { createRetryingFetch } from './retry.js';
|
|
9
9
|
export type { RetryOptions } from './retry.js';
|
|
10
|
+
export { createTransportStats, formatTransportStats } from './stats.js';
|
|
11
|
+
export type { CovalTransportStats } from './stats.js';
|
|
10
12
|
export * from './generated/index.js';
|
|
11
13
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC/D,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACvD,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAC/D,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACvD,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACxE,YAAY,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAKtD,cAAc,sBAAsB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ export { CovalApiError, CovalNetworkError } from './errors.js';
|
|
|
4
4
|
export { paginate, collectAll } from './pagination.js';
|
|
5
5
|
export { apiKeyAuthMiddleware } from './auth.js';
|
|
6
6
|
export { createRetryingFetch } from './retry.js';
|
|
7
|
+
export { createTransportStats, formatTransportStats } from './stats.js';
|
|
7
8
|
// Re-export the entire generated surface so callers can reach for request
|
|
8
9
|
// types, model types, and individual API classes if they want to bypass the
|
|
9
10
|
// CovalClient wrapper.
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qCAAqC;AAErC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAE/D,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qCAAqC;AAErC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAE/D,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEjD,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAGxE,0EAA0E;AAC1E,4EAA4E;AAC5E,uBAAuB;AACvB,cAAc,sBAAsB,CAAC"}
|
package/dist/retry.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { FetchAPI } from './generated/runtime.js';
|
|
2
|
+
import type { CovalTransportStats } from './stats.js';
|
|
2
3
|
export interface RetryOptions {
|
|
3
4
|
/** Max total attempts including the first. Default 3. */
|
|
4
5
|
maxAttempts?: number;
|
|
@@ -16,6 +17,10 @@ export interface RetryOptions {
|
|
|
16
17
|
export interface RetryDeps {
|
|
17
18
|
fetch?: FetchAPI;
|
|
18
19
|
sleep?: (ms: number) => Promise<void>;
|
|
20
|
+
/** Counters mutated in place so the client can expose a live view. */
|
|
21
|
+
stats?: CovalTransportStats;
|
|
22
|
+
/** Called with a human-readable line on each retry or network error. */
|
|
23
|
+
onDebug?: (message: string) => void;
|
|
19
24
|
}
|
|
20
25
|
export declare function createRetryingFetch(options?: RetryOptions, deps?: RetryDeps): FetchAPI;
|
|
21
26
|
//# sourceMappingURL=retry.d.ts.map
|
package/dist/retry.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAKtD,MAAM,WAAW,YAAY;IAC3B,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wFAAwF;IACxF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;IACtB,4EAA4E;IAC5E,iBAAiB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAChC,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,sEAAsE;IACtE,KAAK,CAAC,EAAE,mBAAmB,CAAC;IAC5B,wEAAwE;IACxE,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC;AAED,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,YAAiB,EAAE,IAAI,GAAE,SAAc,GAAG,QAAQ,CAgF9F"}
|
package/dist/retry.js
CHANGED
|
@@ -17,15 +17,24 @@ export function createRetryingFetch(options = {}, deps = {}) {
|
|
|
17
17
|
const retryableMethods = options.retryableMethods ?? RETRYABLE_METHODS;
|
|
18
18
|
const innerFetch = deps.fetch ?? globalThis.fetch;
|
|
19
19
|
const sleep = deps.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
20
|
+
const stats = deps.stats;
|
|
21
|
+
const debug = deps.onDebug;
|
|
20
22
|
return async function retryingFetch(input, init) {
|
|
21
23
|
let lastError;
|
|
22
24
|
const method = (init?.method ?? 'GET').toUpperCase();
|
|
23
25
|
const url = typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url;
|
|
26
|
+
if (stats)
|
|
27
|
+
stats.calls += 1;
|
|
24
28
|
if (!retryableMethods.has(method)) {
|
|
25
29
|
try {
|
|
30
|
+
if (stats)
|
|
31
|
+
stats.requests += 1;
|
|
26
32
|
return await innerFetch(input, init);
|
|
27
33
|
}
|
|
28
34
|
catch (err) {
|
|
35
|
+
if (stats)
|
|
36
|
+
stats.networkErrors += 1;
|
|
37
|
+
debug?.(`coval-sdk: ${method} ${url} failed in transit (not retried): ${stringifyError(err)}`);
|
|
29
38
|
throw new CovalNetworkError({
|
|
30
39
|
message: `Coval API request failed: ${stringifyError(err)}`,
|
|
31
40
|
url,
|
|
@@ -37,16 +46,24 @@ export function createRetryingFetch(options = {}, deps = {}) {
|
|
|
37
46
|
}
|
|
38
47
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
39
48
|
try {
|
|
49
|
+
if (stats)
|
|
50
|
+
stats.requests += 1;
|
|
40
51
|
const response = await innerFetch(input, init);
|
|
41
52
|
if (!retryable.has(response.status) || attempt === maxAttempts) {
|
|
42
53
|
return response;
|
|
43
54
|
}
|
|
44
55
|
const wait = computeDelay({ attempt, baseDelay, maxDelay, jitter, response });
|
|
56
|
+
if (stats)
|
|
57
|
+
stats.retries += 1;
|
|
58
|
+
debug?.(`coval-sdk: ${method} ${url} returned ${response.status}, retrying in ${wait}ms (attempt ${attempt}/${maxAttempts})`);
|
|
45
59
|
await sleep(wait);
|
|
46
60
|
}
|
|
47
61
|
catch (err) {
|
|
48
62
|
lastError = err;
|
|
63
|
+
if (stats)
|
|
64
|
+
stats.networkErrors += 1;
|
|
49
65
|
if (attempt === maxAttempts) {
|
|
66
|
+
debug?.(`coval-sdk: ${method} ${url} failed in transit after ${attempt} attempts: ${stringifyError(err)}`);
|
|
50
67
|
throw new CovalNetworkError({
|
|
51
68
|
message: `Coval API request failed after ${attempt} attempt${attempt > 1 ? 's' : ''}: ${stringifyError(err)}`,
|
|
52
69
|
url,
|
|
@@ -56,6 +73,9 @@ export function createRetryingFetch(options = {}, deps = {}) {
|
|
|
56
73
|
});
|
|
57
74
|
}
|
|
58
75
|
const wait = computeDelay({ attempt, baseDelay, maxDelay, jitter });
|
|
76
|
+
if (stats)
|
|
77
|
+
stats.retries += 1;
|
|
78
|
+
debug?.(`coval-sdk: ${method} ${url} failed in transit (${stringifyError(err)}), retrying in ${wait}ms (attempt ${attempt}/${maxAttempts})`);
|
|
59
79
|
await sleep(wait);
|
|
60
80
|
}
|
|
61
81
|
}
|
package/dist/retry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,EAAE;AACF,8EAA8E;AAC9E,6EAA6E;AAC7E,2EAA2E;AAC3E,2EAA2E;AAC3E,kCAAkC;AAElC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,EAAE;AACF,8EAA8E;AAC9E,6EAA6E;AAC7E,2EAA2E;AAC3E,2EAA2E;AAC3E,kCAAkC;AAElC,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIhD,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AACnE,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;AA0B9D,MAAM,UAAU,mBAAmB,CAAC,UAAwB,EAAE,EAAE,OAAkB,EAAE;IAClF,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,CAAC,CAAC;IAC7C,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,IAAI,GAAG,CAAC;IAC7C,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,IAAI,KAAK,CAAC;IAC7C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC;IAC7C,MAAM,SAAS,GAAG,OAAO,CAAC,iBAAiB,IAAI,kBAAkB,CAAC;IAClE,MAAM,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,IAAI,iBAAiB,CAAC;IACvE,MAAM,UAAU,GAAa,IAAI,CAAC,KAAK,IAAK,UAAU,CAAC,KAAkB,CAAC;IAC1E,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,EAAU,EAAE,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAChG,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IACzB,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC;IAE3B,OAAO,KAAK,UAAU,aAAa,CAAC,KAAK,EAAE,IAAI;QAC7C,IAAI,SAAkB,CAAC;QACvB,MAAM,MAAM,GAAG,CAAC,IAAI,EAAE,MAAM,IAAI,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;QACrD,MAAM,GAAG,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,YAAY,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;QACpG,IAAI,KAAK;YAAE,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;QAE5B,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YAClC,IAAI,CAAC;gBACH,IAAI,KAAK;oBAAE,KAAK,CAAC,QAAQ,IAAI,CAAC,CAAC;gBAC/B,OAAO,MAAM,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YACvC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,KAAK;oBAAE,KAAK,CAAC,aAAa,IAAI,CAAC,CAAC;gBACpC,KAAK,EAAE,CAAC,cAAc,MAAM,IAAI,GAAG,qCAAqC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBAC/F,MAAM,IAAI,iBAAiB,CAAC;oBAC1B,OAAO,EAAE,6BAA6B,cAAc,CAAC,GAAG,CAAC,EAAE;oBAC3D,GAAG;oBACH,MAAM;oBACN,QAAQ,EAAE,CAAC;oBACX,KAAK,EAAE,GAAG;iBACX,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;YACxD,IAAI,CAAC;gBACH,IAAI,KAAK;oBAAE,KAAK,CAAC,QAAQ,IAAI,CAAC,CAAC;gBAC/B,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;gBAC/C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;oBAC/D,OAAO,QAAQ,CAAC;gBAClB,CAAC;gBACD,MAAM,IAAI,GAAG,YAAY,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;gBAC9E,IAAI,KAAK;oBAAE,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;gBAC9B,KAAK,EAAE,CACL,cAAc,MAAM,IAAI,GAAG,aAAa,QAAQ,CAAC,MAAM,iBAAiB,IAAI,eAAe,OAAO,IAAI,WAAW,GAAG,CACrH,CAAC;gBACF,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;YACpB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,SAAS,GAAG,GAAG,CAAC;gBAChB,IAAI,KAAK;oBAAE,KAAK,CAAC,aAAa,IAAI,CAAC,CAAC;gBACpC,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;oBAC5B,KAAK,EAAE,CACL,cAAc,MAAM,IAAI,GAAG,4BAA4B,OAAO,cAAc,cAAc,CAAC,GAAG,CAAC,EAAE,CAClG,CAAC;oBACF,MAAM,IAAI,iBAAiB,CAAC;wBAC1B,OAAO,EAAE,kCAAkC,OAAO,WAAW,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,cAAc,CAAC,GAAG,CAAC,EAAE;wBAC7G,GAAG;wBACH,MAAM;wBACN,QAAQ,EAAE,OAAO;wBACjB,KAAK,EAAE,GAAG;qBACX,CAAC,CAAC;gBACL,CAAC;gBACD,MAAM,IAAI,GAAG,YAAY,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;gBACpE,IAAI,KAAK;oBAAE,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;gBAC9B,KAAK,EAAE,CACL,cAAc,MAAM,IAAI,GAAG,uBAAuB,cAAc,CAAC,GAAG,CAAC,kBAAkB,IAAI,eAAe,OAAO,IAAI,WAAW,GAAG,CACpI,CAAC;gBACF,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;YACpB,CAAC;QACH,CAAC;QAED,MAAM,IAAI,iBAAiB,CAAC;YAC1B,OAAO,EAAE,8CAA8C,cAAc,CAAC,SAAS,CAAC,EAAE;YAClF,GAAG;YACH,MAAM;YACN,QAAQ,EAAE,WAAW;YACrB,KAAK,EAAE,SAAS;SACjB,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,IAMrB;IACC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAChE,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QACvD,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;YACnC,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,CAAC,EAAE,CAAC;gBAC7C,OAAO,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC,CAAC;YAC5C,CAAC;YACD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YACpC,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC1B,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;IACH,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,GAAG,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;IAC/D,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,cAAc,CAAC,GAAY;IAClC,IAAI,GAAG,YAAY,KAAK;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC;IAC7C,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC;AACrB,CAAC"}
|
package/dist/stats.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface CovalTransportStats {
|
|
2
|
+
/** Logical API calls started. */
|
|
3
|
+
calls: number;
|
|
4
|
+
/** fetch invocations, including retries — exceeds `calls` when retries fire. */
|
|
5
|
+
requests: number;
|
|
6
|
+
/** Retry attempts beyond the initial request. */
|
|
7
|
+
retries: number;
|
|
8
|
+
/** fetch rejections: DNS failure, reset, abort, or a stranded pooled socket. */
|
|
9
|
+
networkErrors: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function createTransportStats(): CovalTransportStats;
|
|
12
|
+
export declare function formatTransportStats(stats: CovalTransportStats): string;
|
|
13
|
+
//# sourceMappingURL=stats.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../src/stats.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,mBAAmB;IAClC,iCAAiC;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,gFAAgF;IAChF,QAAQ,EAAE,MAAM,CAAC;IACjB,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,gFAAgF;IAChF,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,oBAAoB,IAAI,mBAAmB,CAE1D;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,mBAAmB,GAAG,MAAM,CAEvE"}
|
package/dist/stats.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Transport counters for diagnosing intermittent failures.
|
|
2
|
+
//
|
|
3
|
+
// A request that dies in transit never reaches the API, so there is no
|
|
4
|
+
// server-side trace of it. These counters are often the only evidence available
|
|
5
|
+
// when a caller reports sporadic timeouts. Mirrors `connection_stats` in the
|
|
6
|
+
// Python SDK.
|
|
7
|
+
export function createTransportStats() {
|
|
8
|
+
return { calls: 0, requests: 0, retries: 0, networkErrors: 0 };
|
|
9
|
+
}
|
|
10
|
+
export function formatTransportStats(stats) {
|
|
11
|
+
return `CovalTransportStats(calls=${stats.calls}, requests=${stats.requests}, retries=${stats.retries}, networkErrors=${stats.networkErrors})`;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=stats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stats.js","sourceRoot":"","sources":["../src/stats.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,EAAE;AACF,uEAAuE;AACvE,gFAAgF;AAChF,6EAA6E;AAC7E,cAAc;AAad,MAAM,UAAU,oBAAoB;IAClC,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAA0B;IAC7D,OAAO,6BAA6B,KAAK,CAAC,KAAK,cAAc,KAAK,CAAC,QAAQ,aAAa,KAAK,CAAC,OAAO,mBAAmB,KAAK,CAAC,aAAa,GAAG,CAAC;AACjJ,CAAC"}
|
package/package.json
CHANGED
package/src/CovalClient.ts
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import { apiKeyAuthMiddleware } from './auth.js';
|
|
14
14
|
import { CovalApiError, parseErrorResponse } from './errors.js';
|
|
15
15
|
import { createRetryingFetch, type RetryOptions } from './retry.js';
|
|
16
|
+
import { createTransportStats, type CovalTransportStats } from './stats.js';
|
|
16
17
|
import {
|
|
17
18
|
AgentsApi,
|
|
18
19
|
APIKeysApi,
|
|
@@ -56,6 +57,11 @@ export interface CovalClientOptions {
|
|
|
56
57
|
middleware?: Middleware[];
|
|
57
58
|
/** Override the global fetch (e.g., for tests, undici-with-keepalive, etc). */
|
|
58
59
|
fetch?: FetchAPI;
|
|
60
|
+
/**
|
|
61
|
+
* Called with a diagnostic line on each retry and each in-transit failure.
|
|
62
|
+
* Pass `console.debug` when investigating intermittent timeouts.
|
|
63
|
+
*/
|
|
64
|
+
onDebug?: (message: string) => void;
|
|
59
65
|
}
|
|
60
66
|
|
|
61
67
|
const DEFAULT_BASE_URL = 'https://api.coval.dev/v1';
|
|
@@ -90,16 +96,29 @@ export class CovalClient {
|
|
|
90
96
|
|
|
91
97
|
readonly configuration: Configuration;
|
|
92
98
|
|
|
99
|
+
/**
|
|
100
|
+
* Live transport counters. A request that dies in transit leaves no
|
|
101
|
+
* server-side trace, so these are often the only evidence when diagnosing
|
|
102
|
+
* intermittent failures. Include them when reporting one.
|
|
103
|
+
*/
|
|
104
|
+
readonly stats: CovalTransportStats;
|
|
105
|
+
|
|
93
106
|
constructor(options: CovalClientOptions) {
|
|
94
107
|
if (!options.apiKey) {
|
|
95
108
|
throw new Error('CovalClient: apiKey is required');
|
|
96
109
|
}
|
|
97
110
|
|
|
111
|
+
this.stats = createTransportStats();
|
|
112
|
+
|
|
98
113
|
const innerFetch: FetchAPI = options.fetch ?? (globalThis.fetch as FetchAPI);
|
|
99
114
|
const fetchApi: FetchAPI =
|
|
100
115
|
options.retry === false
|
|
101
116
|
? innerFetch
|
|
102
|
-
: createRetryingFetch(options.retry ?? {}, {
|
|
117
|
+
: createRetryingFetch(options.retry ?? {}, {
|
|
118
|
+
fetch: innerFetch,
|
|
119
|
+
stats: this.stats,
|
|
120
|
+
onDebug: options.onDebug,
|
|
121
|
+
});
|
|
103
122
|
|
|
104
123
|
const middleware: Middleware[] = [
|
|
105
124
|
apiKeyAuthMiddleware({ apiKey: options.apiKey }),
|
package/src/index.ts
CHANGED
|
@@ -9,6 +9,8 @@ export type { PaginateOptions } from './pagination.js';
|
|
|
9
9
|
export { apiKeyAuthMiddleware } from './auth.js';
|
|
10
10
|
export { createRetryingFetch } from './retry.js';
|
|
11
11
|
export type { RetryOptions } from './retry.js';
|
|
12
|
+
export { createTransportStats, formatTransportStats } from './stats.js';
|
|
13
|
+
export type { CovalTransportStats } from './stats.js';
|
|
12
14
|
|
|
13
15
|
// Re-export the entire generated surface so callers can reach for request
|
|
14
16
|
// types, model types, and individual API classes if they want to bypass the
|
package/src/retry.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import { CovalNetworkError } from './errors.js';
|
|
10
10
|
import type { FetchAPI } from './generated/runtime.js';
|
|
11
|
+
import type { CovalTransportStats } from './stats.js';
|
|
11
12
|
|
|
12
13
|
const RETRYABLE_STATUSES = new Set([408, 429, 500, 502, 503, 504]);
|
|
13
14
|
const RETRYABLE_METHODS = new Set(['GET', 'HEAD', 'OPTIONS']);
|
|
@@ -30,6 +31,10 @@ export interface RetryOptions {
|
|
|
30
31
|
export interface RetryDeps {
|
|
31
32
|
fetch?: FetchAPI;
|
|
32
33
|
sleep?: (ms: number) => Promise<void>;
|
|
34
|
+
/** Counters mutated in place so the client can expose a live view. */
|
|
35
|
+
stats?: CovalTransportStats;
|
|
36
|
+
/** Called with a human-readable line on each retry or network error. */
|
|
37
|
+
onDebug?: (message: string) => void;
|
|
33
38
|
}
|
|
34
39
|
|
|
35
40
|
export function createRetryingFetch(options: RetryOptions = {}, deps: RetryDeps = {}): FetchAPI {
|
|
@@ -41,16 +46,22 @@ export function createRetryingFetch(options: RetryOptions = {}, deps: RetryDeps
|
|
|
41
46
|
const retryableMethods = options.retryableMethods ?? RETRYABLE_METHODS;
|
|
42
47
|
const innerFetch: FetchAPI = deps.fetch ?? (globalThis.fetch as FetchAPI);
|
|
43
48
|
const sleep = deps.sleep ?? ((ms: number) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
49
|
+
const stats = deps.stats;
|
|
50
|
+
const debug = deps.onDebug;
|
|
44
51
|
|
|
45
52
|
return async function retryingFetch(input, init) {
|
|
46
53
|
let lastError: unknown;
|
|
47
54
|
const method = (init?.method ?? 'GET').toUpperCase();
|
|
48
55
|
const url = typeof input === 'string' ? input : input instanceof URL ? input.toString() : input.url;
|
|
56
|
+
if (stats) stats.calls += 1;
|
|
49
57
|
|
|
50
58
|
if (!retryableMethods.has(method)) {
|
|
51
59
|
try {
|
|
60
|
+
if (stats) stats.requests += 1;
|
|
52
61
|
return await innerFetch(input, init);
|
|
53
62
|
} catch (err) {
|
|
63
|
+
if (stats) stats.networkErrors += 1;
|
|
64
|
+
debug?.(`coval-sdk: ${method} ${url} failed in transit (not retried): ${stringifyError(err)}`);
|
|
54
65
|
throw new CovalNetworkError({
|
|
55
66
|
message: `Coval API request failed: ${stringifyError(err)}`,
|
|
56
67
|
url,
|
|
@@ -63,15 +74,24 @@ export function createRetryingFetch(options: RetryOptions = {}, deps: RetryDeps
|
|
|
63
74
|
|
|
64
75
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
65
76
|
try {
|
|
77
|
+
if (stats) stats.requests += 1;
|
|
66
78
|
const response = await innerFetch(input, init);
|
|
67
79
|
if (!retryable.has(response.status) || attempt === maxAttempts) {
|
|
68
80
|
return response;
|
|
69
81
|
}
|
|
70
82
|
const wait = computeDelay({ attempt, baseDelay, maxDelay, jitter, response });
|
|
83
|
+
if (stats) stats.retries += 1;
|
|
84
|
+
debug?.(
|
|
85
|
+
`coval-sdk: ${method} ${url} returned ${response.status}, retrying in ${wait}ms (attempt ${attempt}/${maxAttempts})`,
|
|
86
|
+
);
|
|
71
87
|
await sleep(wait);
|
|
72
88
|
} catch (err) {
|
|
73
89
|
lastError = err;
|
|
90
|
+
if (stats) stats.networkErrors += 1;
|
|
74
91
|
if (attempt === maxAttempts) {
|
|
92
|
+
debug?.(
|
|
93
|
+
`coval-sdk: ${method} ${url} failed in transit after ${attempt} attempts: ${stringifyError(err)}`,
|
|
94
|
+
);
|
|
75
95
|
throw new CovalNetworkError({
|
|
76
96
|
message: `Coval API request failed after ${attempt} attempt${attempt > 1 ? 's' : ''}: ${stringifyError(err)}`,
|
|
77
97
|
url,
|
|
@@ -81,6 +101,10 @@ export function createRetryingFetch(options: RetryOptions = {}, deps: RetryDeps
|
|
|
81
101
|
});
|
|
82
102
|
}
|
|
83
103
|
const wait = computeDelay({ attempt, baseDelay, maxDelay, jitter });
|
|
104
|
+
if (stats) stats.retries += 1;
|
|
105
|
+
debug?.(
|
|
106
|
+
`coval-sdk: ${method} ${url} failed in transit (${stringifyError(err)}), retrying in ${wait}ms (attempt ${attempt}/${maxAttempts})`,
|
|
107
|
+
);
|
|
84
108
|
await sleep(wait);
|
|
85
109
|
}
|
|
86
110
|
}
|
package/src/stats.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Transport counters for diagnosing intermittent failures.
|
|
2
|
+
//
|
|
3
|
+
// A request that dies in transit never reaches the API, so there is no
|
|
4
|
+
// server-side trace of it. These counters are often the only evidence available
|
|
5
|
+
// when a caller reports sporadic timeouts. Mirrors `connection_stats` in the
|
|
6
|
+
// Python SDK.
|
|
7
|
+
|
|
8
|
+
export interface CovalTransportStats {
|
|
9
|
+
/** Logical API calls started. */
|
|
10
|
+
calls: number;
|
|
11
|
+
/** fetch invocations, including retries — exceeds `calls` when retries fire. */
|
|
12
|
+
requests: number;
|
|
13
|
+
/** Retry attempts beyond the initial request. */
|
|
14
|
+
retries: number;
|
|
15
|
+
/** fetch rejections: DNS failure, reset, abort, or a stranded pooled socket. */
|
|
16
|
+
networkErrors: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function createTransportStats(): CovalTransportStats {
|
|
20
|
+
return { calls: 0, requests: 0, retries: 0, networkErrors: 0 };
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function formatTransportStats(stats: CovalTransportStats): string {
|
|
24
|
+
return `CovalTransportStats(calls=${stats.calls}, requests=${stats.requests}, retries=${stats.retries}, networkErrors=${stats.networkErrors})`;
|
|
25
|
+
}
|