@ziggs-ai/api-client 0.33.0 → 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.
|
@@ -171,7 +171,7 @@ export const agreementBuyCapability = {
|
|
|
171
171
|
chatId: CHAT_PARAM,
|
|
172
172
|
...TERMS_PARAMS,
|
|
173
173
|
mandateAgreementId: MANDATE_PARAM,
|
|
174
|
-
parentAgreementId: { type: 'string', description: '
|
|
174
|
+
parentAgreementId: { type: 'string', description: 'The job this work is part of; ending that job ends this work. Never a link: a link is who can reach whom, so paid work cannot be placed under one. This placement does not grant spending consent.' },
|
|
175
175
|
},
|
|
176
176
|
needsAgentId: true,
|
|
177
177
|
handler: async (args, env) => {
|
|
@@ -203,7 +203,7 @@ export const agreementBidCapability = {
|
|
|
203
203
|
chatId: CHAT_PARAM,
|
|
204
204
|
...TERMS_PARAMS,
|
|
205
205
|
mandateAgreementId: MANDATE_PARAM,
|
|
206
|
-
parentAgreementId: { type: 'string', description: '
|
|
206
|
+
parentAgreementId: { type: 'string', description: 'The job this work is part of; ending that job ends this work. Never a link: a link is who can reach whom, so paid work cannot be placed under one. This placement does not grant spending consent.' },
|
|
207
207
|
},
|
|
208
208
|
needsAgentId: true,
|
|
209
209
|
handler: async (args, env) => {
|
|
@@ -243,7 +243,7 @@ export const agreementBrokerCapability = {
|
|
|
243
243
|
chatId: CHAT_PARAM,
|
|
244
244
|
...TERMS_PARAMS,
|
|
245
245
|
mandateAgreementId: MANDATE_PARAM,
|
|
246
|
-
parentAgreementId: { type: 'string', description: '
|
|
246
|
+
parentAgreementId: { type: 'string', description: 'The job this work is part of; ending that job ends this work. Never a link: a link is who can reach whom, so paid work cannot be placed under one. This placement does not grant spending consent.' },
|
|
247
247
|
},
|
|
248
248
|
needsAgentId: true,
|
|
249
249
|
handler: async (args, env) => {
|
|
@@ -274,7 +274,7 @@ export const agreementRequestCapability = {
|
|
|
274
274
|
...TERMS_PARAMS,
|
|
275
275
|
match: MATCH_PARAM,
|
|
276
276
|
mandateAgreementId: MANDATE_PARAM,
|
|
277
|
-
parentAgreementId: { type: 'string', description: '
|
|
277
|
+
parentAgreementId: { type: 'string', description: 'The job this work is part of; ending that job ends this work. Never a link: a link is who can reach whom, so paid work cannot be placed under one. This placement does not grant spending consent.' },
|
|
278
278
|
},
|
|
279
279
|
needsAgentId: true,
|
|
280
280
|
handler: async (args, env) => {
|
|
@@ -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);
|