@ziggs-ai/api-client 0.33.1 → 0.34.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.
|
@@ -105,6 +105,8 @@ export declare class ContextReadClient {
|
|
|
105
105
|
* intended. Send it on every read made while acting on a wake.
|
|
106
106
|
*/
|
|
107
107
|
constructor(operatorKey: string, agentId?: string, baseUrl?: string, laneId?: string);
|
|
108
|
+
/** The same reader acting on one wake's lane. */
|
|
109
|
+
withLane(laneId: string | undefined): ContextReadClient;
|
|
108
110
|
read<T = unknown>(type: ContextReadType, query: ContextReadQuery): Promise<ContextReadEnvelope<T>>;
|
|
109
111
|
/**
|
|
110
112
|
* Aggregated chat snapshot — `GET /context/snapshot?via=chat:<id>`. The
|
|
@@ -74,6 +74,12 @@ export class ContextReadClient {
|
|
|
74
74
|
this.baseUrl = baseUrl || getBackendUrl();
|
|
75
75
|
this.laneId = laneId;
|
|
76
76
|
}
|
|
77
|
+
/** The same reader acting on one wake's lane. */
|
|
78
|
+
withLane(laneId) {
|
|
79
|
+
if (!laneId || laneId === this.laneId)
|
|
80
|
+
return this;
|
|
81
|
+
return new ContextReadClient(this.operatorKey, this.agentId, this.baseUrl, laneId);
|
|
82
|
+
}
|
|
77
83
|
async read(type, query) {
|
|
78
84
|
if (!query.via?.trim()) {
|
|
79
85
|
throw new Error('ContextReadClient.read: via is required');
|
|
@@ -31,9 +31,11 @@ export declare function parseErrorCode(responseBody: string): string | null;
|
|
|
31
31
|
export declare function parseRetryAfterMs(headers: {
|
|
32
32
|
get(name: string): string | null;
|
|
33
33
|
}): number | null;
|
|
34
|
+
export declare function isCoverageRefusal(code: string | null | undefined): boolean;
|
|
34
35
|
/**
|
|
35
36
|
* Throw the parsed failure as an {@link ApiError} (or {@link RateLimitedError}
|
|
36
|
-
* for 429), preserving status, body, machine
|
|
37
|
+
* for a 429 that is not a coverage refusal), preserving status, body, machine
|
|
38
|
+
* code, and Retry-After.
|
|
37
39
|
*/
|
|
38
40
|
export declare function throwApiError(response: {
|
|
39
41
|
status: number;
|
package/dist/shared/apiError.js
CHANGED
|
@@ -100,14 +100,34 @@ function clampRetryMs(ms) {
|
|
|
100
100
|
return 1_000;
|
|
101
101
|
return Math.min(MAX_RETRY_AFTER_MS, Math.max(1_000, Math.round(ms)));
|
|
102
102
|
}
|
|
103
|
+
/**
|
|
104
|
+
* Coverage refusals name themselves. A 429 with one of these codes is not a
|
|
105
|
+
* wait-and-retry: the writer has to hire, or someone has to set the agreement
|
|
106
|
+
* up. The backend answers them as 403; this keeps a stale 429 from becoming a
|
|
107
|
+
* rate limit too.
|
|
108
|
+
*/
|
|
109
|
+
const COVERAGE_REFUSALS = new Set([
|
|
110
|
+
'CONVERSATION_ALLOWANCE_EXHAUSTED',
|
|
111
|
+
'CONTACT_POLICY_REFUSED',
|
|
112
|
+
'LISTING_PAUSED',
|
|
113
|
+
'CONVERSATION_COVERAGE_REQUIRED',
|
|
114
|
+
'CONVERSATION_COVERAGE_ENDED',
|
|
115
|
+
'CONVERSATION_NOT_FUNDED',
|
|
116
|
+
'CONVERSATION_SPONSORSHIP_REQUIRED',
|
|
117
|
+
'TASK_ONLY_AGENT',
|
|
118
|
+
]);
|
|
119
|
+
export function isCoverageRefusal(code) {
|
|
120
|
+
return !!code && COVERAGE_REFUSALS.has(code);
|
|
121
|
+
}
|
|
103
122
|
/**
|
|
104
123
|
* Throw the parsed failure as an {@link ApiError} (or {@link RateLimitedError}
|
|
105
|
-
* for 429), preserving status, body, machine
|
|
124
|
+
* for a 429 that is not a coverage refusal), preserving status, body, machine
|
|
125
|
+
* code, and Retry-After.
|
|
106
126
|
*/
|
|
107
127
|
export function throwApiError(response, responseBody, defaultMessage) {
|
|
108
128
|
const message = parseErrorMessage(responseBody, defaultMessage);
|
|
109
129
|
const code = parseErrorCode(responseBody);
|
|
110
|
-
if (response.status === 429) {
|
|
130
|
+
if (response.status === 429 && !isCoverageRefusal(code)) {
|
|
111
131
|
throw new RateLimitedError(message, response.headers ? parseRetryAfterMs(response.headers) : null, responseBody, code);
|
|
112
132
|
}
|
|
113
133
|
throw new ApiError(message, response.status, responseBody, code);
|
package/dist/shared/rateLimit.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ApiError, RateLimitedError } from '../types.js';
|
|
2
|
-
import { parseErrorCode, parseErrorMessage, parseRetryAfterMs, } from './apiError.js';
|
|
2
|
+
import { isCoverageRefusal, parseErrorCode, parseErrorMessage, parseRetryAfterMs, } from './apiError.js';
|
|
3
3
|
/**
|
|
4
4
|
* a 429 is not a generic failure, it is an instruction with a
|
|
5
5
|
* deadline attached.
|
|
@@ -33,7 +33,7 @@ export function isRateLimited(err) {
|
|
|
33
33
|
export function pollSurfaceError(label, res, body) {
|
|
34
34
|
const message = parseErrorMessage(body, `${label} failed: ${res.status}`);
|
|
35
35
|
const code = parseErrorCode(body);
|
|
36
|
-
if (res.status === 429) {
|
|
36
|
+
if (res.status === 429 && !isCoverageRefusal(code)) {
|
|
37
37
|
return new RateLimitedError(message, parseRetryAfterMs(res.headers), body, code);
|
|
38
38
|
}
|
|
39
39
|
return new ApiError(message, res.status, body, code);
|