@ziggs-ai/api-client 0.9.0 → 0.9.2
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/dist/ConnectionManager.d.ts +23 -59
- package/dist/ConnectionManager.js +37 -166
- package/dist/capabilities/agreements.js +2 -2
- package/dist/capabilities/chat.js +13 -3
- package/dist/capabilities/connections.js +1 -1
- package/dist/capabilities/index.d.ts +1 -1
- package/dist/capabilities/index.js +1 -1
- package/dist/capabilities/links.d.ts +0 -8
- package/dist/capabilities/links.js +3 -25
- package/dist/capabilities/payments.js +5 -0
- package/dist/capabilities/types.js +3 -0
- package/dist/config.d.ts +33 -0
- package/dist/config.js +42 -0
- package/dist/http/AgentSearchClient.d.ts +0 -1
- package/dist/http/AgentSearchClient.js +0 -1
- package/dist/http/AgreementClient.d.ts +32 -1
- package/dist/http/AgreementClient.js +96 -23
- package/dist/http/ArtifactsClient.d.ts +0 -1
- package/dist/http/ArtifactsClient.js +0 -1
- package/dist/http/ChatClient.d.ts +6 -3
- package/dist/http/ChatClient.js +7 -6
- package/dist/http/ConnectionsClient.d.ts +0 -1
- package/dist/http/ConnectionsClient.js +4 -5
- package/dist/http/ContextDiscoveryClient.d.ts +0 -1
- package/dist/http/ContextDiscoveryClient.js +2 -2
- package/dist/http/ContextGrantsClient.d.ts +0 -1
- package/dist/http/ContextGrantsClient.js +0 -1
- package/dist/http/ContextReadClient.d.ts +0 -1
- package/dist/http/ContextReadClient.js +5 -17
- package/dist/http/GrantsClient.d.ts +0 -1
- package/dist/http/GrantsClient.js +2 -2
- package/dist/http/InboxClient.d.ts +1 -177
- package/dist/http/InboxClient.js +0 -40
- package/dist/http/MarketplaceClient.d.ts +0 -1
- package/dist/http/MarketplaceClient.js +5 -4
- package/dist/http/MessagesClient.d.ts +0 -1
- package/dist/http/MessagesClient.js +3 -6
- package/dist/http/OrgsClient.d.ts +0 -1
- package/dist/http/OrgsClient.js +3 -3
- package/dist/http/PaymentsClient.d.ts +4 -2
- package/dist/http/PaymentsClient.js +27 -7
- package/dist/http/TaskClient.d.ts +0 -1
- package/dist/http/TaskClient.js +0 -1
- package/dist/http/TelemetryClient.d.ts +0 -1
- package/dist/http/TelemetryClient.js +0 -1
- package/dist/http/agreementFlows.d.ts +13 -5
- package/dist/http/agreementFlows.js +18 -24
- package/dist/http/index.d.ts +0 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.js +5 -2
- package/dist/shared/apiError.d.ts +22 -1
- package/dist/shared/apiError.js +60 -3
- package/dist/shared/rateLimit.d.ts +12 -22
- package/dist/shared/rateLimit.js +18 -51
- package/dist/shared/runtimeLog.d.ts +0 -6
- package/dist/shared/runtimeLog.js +10 -7
- package/dist/types.d.ts +167 -1
- package/dist/types.js +20 -1
- package/dist/utils/urlUtils.js +3 -2
- package/package.json +1 -2
package/dist/shared/apiError.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ApiError } from '../types.js';
|
|
1
|
+
import { ApiError, RateLimitedError } from '../types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Read the message out of a Ziggs error response.
|
|
4
4
|
*
|
|
@@ -51,7 +51,64 @@ export function parseErrorMessage(responseBody, defaultMessage) {
|
|
|
51
51
|
(preferMessage ? message : (error ?? message)) ??
|
|
52
52
|
defaultMessage);
|
|
53
53
|
}
|
|
54
|
-
/**
|
|
54
|
+
/** Machine code from `{ error, code }` when the filter (or thrower) supplied one. */
|
|
55
|
+
export function parseErrorCode(responseBody) {
|
|
56
|
+
if (!responseBody)
|
|
57
|
+
return null;
|
|
58
|
+
try {
|
|
59
|
+
const parsed = JSON.parse(responseBody);
|
|
60
|
+
if (typeof parsed !== 'object' || parsed === null)
|
|
61
|
+
return null;
|
|
62
|
+
const code = parsed['code'];
|
|
63
|
+
return typeof code === 'string' && code ? code : null;
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const MAX_RETRY_AFTER_MS = 120_000;
|
|
70
|
+
/**
|
|
71
|
+
* Read the wait out of a 429 response. `Retry-After` wins (it is the explicit
|
|
72
|
+
* one) and is accepted in both forms — delta-seconds or an HTTP date;
|
|
73
|
+
* `RateLimit-Reset` is the standard-headers fallback, in seconds. Capped so a
|
|
74
|
+
* bad header cannot park a loop for an hour, floored at a second so a `0` does
|
|
75
|
+
* not reproduce the hot-retry it is meant to stop.
|
|
76
|
+
*
|
|
77
|
+
* Lives next to {@link throwApiError} so every client path (not only the poll
|
|
78
|
+
* surface) can honour the server's number (ZIG-1124).
|
|
79
|
+
*/
|
|
80
|
+
export function parseRetryAfterMs(headers) {
|
|
81
|
+
const explicit = headers.get('retry-after');
|
|
82
|
+
if (explicit) {
|
|
83
|
+
const seconds = Number(explicit);
|
|
84
|
+
if (Number.isFinite(seconds))
|
|
85
|
+
return clampRetryMs(seconds * 1000);
|
|
86
|
+
const at = Date.parse(explicit);
|
|
87
|
+
if (!Number.isNaN(at))
|
|
88
|
+
return clampRetryMs(at - Date.now());
|
|
89
|
+
}
|
|
90
|
+
const reset = headers.get('ratelimit-reset');
|
|
91
|
+
if (reset) {
|
|
92
|
+
const seconds = Number(reset);
|
|
93
|
+
if (Number.isFinite(seconds))
|
|
94
|
+
return clampRetryMs(seconds * 1000);
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
function clampRetryMs(ms) {
|
|
99
|
+
if (!Number.isFinite(ms))
|
|
100
|
+
return 1_000;
|
|
101
|
+
return Math.min(MAX_RETRY_AFTER_MS, Math.max(1_000, Math.round(ms)));
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Throw the parsed failure as an {@link ApiError} (or {@link RateLimitedError}
|
|
105
|
+
* for 429), preserving status, body, machine code, and Retry-After.
|
|
106
|
+
*/
|
|
55
107
|
export function throwApiError(response, responseBody, defaultMessage) {
|
|
56
|
-
|
|
108
|
+
const message = parseErrorMessage(responseBody, defaultMessage);
|
|
109
|
+
const code = parseErrorCode(responseBody);
|
|
110
|
+
if (response.status === 429) {
|
|
111
|
+
throw new RateLimitedError(message, response.headers ? parseRetryAfterMs(response.headers) : null, responseBody, code);
|
|
112
|
+
}
|
|
113
|
+
throw new ApiError(message, response.status, responseBody, code);
|
|
57
114
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ApiError, RateLimitedError } from '../types.js';
|
|
2
|
+
import { parseRetryAfterMs } from './apiError.js';
|
|
1
3
|
/**
|
|
2
4
|
* ZIG-1019 — a 429 is not a generic failure, it is an instruction with a
|
|
3
5
|
* deadline attached.
|
|
@@ -11,36 +13,24 @@
|
|
|
11
13
|
* The server already says exactly how long to wait — `Retry-After`, or
|
|
12
14
|
* `RateLimit-Reset` from the standard headers. These helpers carry that number
|
|
13
15
|
* to whoever is doing the backing off.
|
|
16
|
+
*
|
|
17
|
+
* ZIG-1124 — {@link RateLimitedError} extends {@link ApiError}; non-429 poll
|
|
18
|
+
* failures are ApiError too (same shape as {@link throwApiError}).
|
|
14
19
|
*/
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
readonly status = 429;
|
|
18
|
-
/** How long the server said to wait. Null when it said nothing. */
|
|
19
|
-
readonly retryAfterMs: number | null;
|
|
20
|
-
constructor(message: string, retryAfterMs: number | null);
|
|
21
|
-
}
|
|
22
|
-
/** True for the error above — survives structured clones and re-wraps. */
|
|
20
|
+
export { RateLimitedError, parseRetryAfterMs };
|
|
21
|
+
/** True for a 429 that carries a wait field — survives structured clones. */
|
|
23
22
|
export declare function isRateLimited(err: unknown): err is {
|
|
24
23
|
retryAfterMs: number | null;
|
|
24
|
+
status: number;
|
|
25
25
|
};
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
* bad header cannot park a loop for an hour, floored at a second so a `0` does
|
|
31
|
-
* not reproduce the hot-retry it is meant to stop.
|
|
32
|
-
*/
|
|
33
|
-
export declare function parseRetryAfterMs(headers: {
|
|
34
|
-
get(name: string): string | null;
|
|
35
|
-
}): number | null;
|
|
36
|
-
/**
|
|
37
|
-
* Build the error for a failed poll-surface response: 429s carry the server's
|
|
38
|
-
* wait, everything else stays an ordinary Error so existing handling is
|
|
39
|
-
* unchanged.
|
|
27
|
+
* Build the error for a failed poll-surface response. Same shape as
|
|
28
|
+
* {@link throwApiError}: ApiError with status/body/code, or RateLimitedError
|
|
29
|
+
* when the server said 429.
|
|
40
30
|
*/
|
|
41
31
|
export declare function pollSurfaceError(label: string, res: {
|
|
42
32
|
status: number;
|
|
43
33
|
headers: {
|
|
44
34
|
get(name: string): string | null;
|
|
45
35
|
};
|
|
46
|
-
}, body: string):
|
|
36
|
+
}, body: string): ApiError;
|
package/dist/shared/rateLimit.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { ApiError, RateLimitedError } from '../types.js';
|
|
2
|
+
import { parseErrorCode, parseErrorMessage, parseRetryAfterMs, } from './apiError.js';
|
|
1
3
|
/**
|
|
2
4
|
* ZIG-1019 — a 429 is not a generic failure, it is an instruction with a
|
|
3
5
|
* deadline attached.
|
|
@@ -11,63 +13,28 @@
|
|
|
11
13
|
* The server already says exactly how long to wait — `Retry-After`, or
|
|
12
14
|
* `RateLimit-Reset` from the standard headers. These helpers carry that number
|
|
13
15
|
* to whoever is doing the backing off.
|
|
16
|
+
*
|
|
17
|
+
* ZIG-1124 — {@link RateLimitedError} extends {@link ApiError}; non-429 poll
|
|
18
|
+
* failures are ApiError too (same shape as {@link throwApiError}).
|
|
14
19
|
*/
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
status = 429;
|
|
18
|
-
/** How long the server said to wait. Null when it said nothing. */
|
|
19
|
-
retryAfterMs;
|
|
20
|
-
constructor(message, retryAfterMs) {
|
|
21
|
-
super(message);
|
|
22
|
-
this.name = 'RateLimitedError';
|
|
23
|
-
this.retryAfterMs = retryAfterMs;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
/** True for the error above — survives structured clones and re-wraps. */
|
|
20
|
+
export { RateLimitedError, parseRetryAfterMs };
|
|
21
|
+
/** True for a 429 that carries a wait field — survives structured clones. */
|
|
27
22
|
export function isRateLimited(err) {
|
|
28
23
|
return (!!err &&
|
|
29
24
|
typeof err === 'object' &&
|
|
30
|
-
err.status === 429
|
|
31
|
-
|
|
32
|
-
const MAX_RETRY_AFTER_MS = 120_000;
|
|
33
|
-
/**
|
|
34
|
-
* Read the wait out of a 429 response. `Retry-After` wins (it is the explicit
|
|
35
|
-
* one) and is accepted in both forms — delta-seconds or an HTTP date;
|
|
36
|
-
* `RateLimit-Reset` is the standard-headers fallback, in seconds. Capped so a
|
|
37
|
-
* bad header cannot park a loop for an hour, floored at a second so a `0` does
|
|
38
|
-
* not reproduce the hot-retry it is meant to stop.
|
|
39
|
-
*/
|
|
40
|
-
export function parseRetryAfterMs(headers) {
|
|
41
|
-
const explicit = headers.get('retry-after');
|
|
42
|
-
if (explicit) {
|
|
43
|
-
const seconds = Number(explicit);
|
|
44
|
-
if (Number.isFinite(seconds))
|
|
45
|
-
return clampRetryMs(seconds * 1000);
|
|
46
|
-
const at = Date.parse(explicit);
|
|
47
|
-
if (!Number.isNaN(at))
|
|
48
|
-
return clampRetryMs(at - Date.now());
|
|
49
|
-
}
|
|
50
|
-
const reset = headers.get('ratelimit-reset');
|
|
51
|
-
if (reset) {
|
|
52
|
-
const seconds = Number(reset);
|
|
53
|
-
if (Number.isFinite(seconds))
|
|
54
|
-
return clampRetryMs(seconds * 1000);
|
|
55
|
-
}
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
function clampRetryMs(ms) {
|
|
59
|
-
if (!Number.isFinite(ms))
|
|
60
|
-
return 1_000;
|
|
61
|
-
return Math.min(MAX_RETRY_AFTER_MS, Math.max(1_000, Math.round(ms)));
|
|
25
|
+
err.status === 429 &&
|
|
26
|
+
'retryAfterMs' in err);
|
|
62
27
|
}
|
|
63
28
|
/**
|
|
64
|
-
* Build the error for a failed poll-surface response
|
|
65
|
-
*
|
|
66
|
-
*
|
|
29
|
+
* Build the error for a failed poll-surface response. Same shape as
|
|
30
|
+
* {@link throwApiError}: ApiError with status/body/code, or RateLimitedError
|
|
31
|
+
* when the server said 429.
|
|
67
32
|
*/
|
|
68
33
|
export function pollSurfaceError(label, res, body) {
|
|
69
|
-
const message = `${label} ${res.status}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
34
|
+
const message = parseErrorMessage(body, `${label} failed: ${res.status}`);
|
|
35
|
+
const code = parseErrorCode(body);
|
|
36
|
+
if (res.status === 429) {
|
|
37
|
+
return new RateLimitedError(message, parseRetryAfterMs(res.headers), body, code);
|
|
38
|
+
}
|
|
39
|
+
return new ApiError(message, res.status, body, code);
|
|
73
40
|
}
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Same semantics as `@ziggs-ai/agent-sdk` `shared/runtimeLog.ts` (duplicated
|
|
3
|
-
* here so this package stays dependency-free).
|
|
4
|
-
*
|
|
5
|
-
* @see agent-sdk/src/shared/runtimeLog.ts
|
|
6
|
-
*/
|
|
7
1
|
export type RuntimeLogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
8
2
|
export declare function resetRuntimeLogLevelCache(): void;
|
|
9
3
|
export declare const runtimeLog: {
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*
|
|
5
5
|
* @see agent-sdk/src/shared/runtimeLog.ts
|
|
6
6
|
*/
|
|
7
|
+
import { apiClientConfig, apiClientConfigVersion } from '../config.js';
|
|
7
8
|
const SEVERITY = {
|
|
8
9
|
debug: 0,
|
|
9
10
|
info: 1,
|
|
@@ -11,12 +12,7 @@ const SEVERITY = {
|
|
|
11
12
|
error: 3,
|
|
12
13
|
};
|
|
13
14
|
function parseThreshold() {
|
|
14
|
-
|
|
15
|
-
return SEVERITY.debug;
|
|
16
|
-
}
|
|
17
|
-
const raw = (process.env.LOG_LEVEL ||
|
|
18
|
-
process.env.AGENTPLUS_LOG_LEVEL ||
|
|
19
|
-
'info').toLowerCase();
|
|
15
|
+
const raw = (apiClientConfig().logLevel || 'info').toLowerCase();
|
|
20
16
|
if (raw === 'silent' || raw === 'none')
|
|
21
17
|
return SEVERITY.error;
|
|
22
18
|
if (raw === 'debug' || raw === 'trace')
|
|
@@ -28,13 +24,20 @@ function parseThreshold() {
|
|
|
28
24
|
return SEVERITY.info;
|
|
29
25
|
}
|
|
30
26
|
let cachedThreshold = null;
|
|
27
|
+
let cachedVersion = -1;
|
|
31
28
|
function threshold() {
|
|
32
|
-
|
|
29
|
+
// Recompute when the host reconfigures, so a `configureApiClient` call after
|
|
30
|
+
// the first log line still takes effect.
|
|
31
|
+
const v = apiClientConfigVersion();
|
|
32
|
+
if (cachedThreshold === null || cachedVersion !== v) {
|
|
33
33
|
cachedThreshold = parseThreshold();
|
|
34
|
+
cachedVersion = v;
|
|
35
|
+
}
|
|
34
36
|
return cachedThreshold;
|
|
35
37
|
}
|
|
36
38
|
export function resetRuntimeLogLevelCache() {
|
|
37
39
|
cachedThreshold = null;
|
|
40
|
+
cachedVersion = -1;
|
|
38
41
|
}
|
|
39
42
|
function shouldEmit(level) {
|
|
40
43
|
return SEVERITY[level] >= threshold();
|
package/dist/types.d.ts
CHANGED
|
@@ -1,7 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One failure shape for every HTTP client path (ZIG-1124).
|
|
3
|
+
*
|
|
4
|
+
* `status` and optional machine `code` come from the response; `body` is the
|
|
5
|
+
* raw text so callers can re-parse without scraping concatenated messages.
|
|
6
|
+
* A 429 is {@link RateLimitedError}, which adds the server's wait.
|
|
7
|
+
*/
|
|
1
8
|
export declare class ApiError extends Error {
|
|
2
9
|
readonly status: number;
|
|
3
10
|
readonly body?: string | undefined;
|
|
4
|
-
|
|
11
|
+
readonly code?: string | null | undefined;
|
|
12
|
+
constructor(message: string, status: number, body?: string | undefined, code?: string | null | undefined);
|
|
13
|
+
}
|
|
14
|
+
/** HTTP 429 — same fields as {@link ApiError}, plus the server's Retry-After. */
|
|
15
|
+
export declare class RateLimitedError extends ApiError {
|
|
16
|
+
/** How long the server said to wait. Null when it said nothing. */
|
|
17
|
+
readonly retryAfterMs: number | null;
|
|
18
|
+
constructor(message: string, retryAfterMs: number | null, body?: string, code?: string | null);
|
|
5
19
|
}
|
|
6
20
|
export interface Creds {
|
|
7
21
|
operatorKey: string;
|
|
@@ -255,3 +269,155 @@ export interface MessageMetadata {
|
|
|
255
269
|
sentTimestamp?: string;
|
|
256
270
|
}
|
|
257
271
|
export type MessageHandler = (text: string, metadata: MessageMetadata) => Promise<void>;
|
|
272
|
+
/**
|
|
273
|
+
* What a delivery can be about. A closed union, not a comment: a consumer that
|
|
274
|
+
* dispatches on `kind` (the MCP read plan) is only safe if the compiler can tell
|
|
275
|
+
* it a case is missing. The task-only deliverable that was acked unread got
|
|
276
|
+
* through precisely because this was `string`.
|
|
277
|
+
*
|
|
278
|
+
* A type and not a value list, unlike the backend's `RESOURCE_KINDS` — nothing
|
|
279
|
+
* on this side validates a delivery kind at runtime (the server does that on the
|
|
280
|
+
* way in), and exhaustiveness checking is purely type-level.
|
|
281
|
+
*/
|
|
282
|
+
export type InboxDeliveryKind = 'message' | 'artifact' | 'task-state' | 'agreement' | 'quest';
|
|
283
|
+
/**
|
|
284
|
+
* One thing addressed to this agent. A reference, never content — following it
|
|
285
|
+
* (a chat read, a task read) is where this agent's grants are enforced.
|
|
286
|
+
*/
|
|
287
|
+
export interface InboxDeliveryRef {
|
|
288
|
+
kind: InboxDeliveryKind;
|
|
289
|
+
resourceId: string;
|
|
290
|
+
chatId: string | null;
|
|
291
|
+
agreementId: string | null;
|
|
292
|
+
taskId: string | null;
|
|
293
|
+
/** Who wrote it. Never this agent — you are not woken by your own writes. */
|
|
294
|
+
actorId: string | null;
|
|
295
|
+
ts: string;
|
|
296
|
+
/**
|
|
297
|
+
* ZIG-703 — lifecycle hint when the server includes one (e.g.
|
|
298
|
+
* `connection_request_fulfilled`). Absent on ordinary doorbells / older servers.
|
|
299
|
+
*/
|
|
300
|
+
reason?: string | null;
|
|
301
|
+
/** ZIG-703 — MCP connection after a fulfilled first-hop request. */
|
|
302
|
+
connectionId?: string | null;
|
|
303
|
+
/** ZIG-703 — grant minted for this agent on fulfill. */
|
|
304
|
+
grantId?: string | null;
|
|
305
|
+
}
|
|
306
|
+
/** Message/artifact deliveries folded by chat, so you can open chats directly. */
|
|
307
|
+
export interface InboxChatNews {
|
|
308
|
+
chatId: string;
|
|
309
|
+
count: number;
|
|
310
|
+
latestAt: string;
|
|
311
|
+
}
|
|
312
|
+
export interface InboxProposalRef {
|
|
313
|
+
agreementId: string;
|
|
314
|
+
title: string;
|
|
315
|
+
proposedAt: string | null;
|
|
316
|
+
/**
|
|
317
|
+
* ZIG-1087 — party ids still owing a decision, and the named responder slot.
|
|
318
|
+
* The inbox lists proposals awaiting the agent OR its human, and only the
|
|
319
|
+
* agent's own slot is one it can submit; these say which is which.
|
|
320
|
+
*
|
|
321
|
+
* Optional because a backend deployed before ZIG-1087 omits them, and this
|
|
322
|
+
* client is installed independently of the server it talks to. Absent reads
|
|
323
|
+
* as "no slot of mine", which routes the decision to the human — the safe
|
|
324
|
+
* direction: it withholds a call, it never invents authority.
|
|
325
|
+
*/
|
|
326
|
+
pendingApprovalPartyIds?: string[];
|
|
327
|
+
proposedTo?: string | null;
|
|
328
|
+
}
|
|
329
|
+
export interface InboxConnectionRequestRef {
|
|
330
|
+
requestId: string;
|
|
331
|
+
/**
|
|
332
|
+
* Non-addressable persona reference for the requester (`psn_*`).
|
|
333
|
+
* Never use as an account id for lookup / wake / pay (ZIG-1137).
|
|
334
|
+
*/
|
|
335
|
+
requesterRef: string;
|
|
336
|
+
/** ZIG-1039 — human-readable name for consent cards. */
|
|
337
|
+
requesterDisplayName?: string | null;
|
|
338
|
+
/** ZIG-1039 — org label for consent cards. */
|
|
339
|
+
requesterOrgName?: string | null;
|
|
340
|
+
message: string | null;
|
|
341
|
+
requestedAt: string | null;
|
|
342
|
+
/** ZIG-1087 — see InboxProposalRef; a link request uses the same gate. */
|
|
343
|
+
pendingApprovalPartyIds?: string[];
|
|
344
|
+
proposedTo?: string | null;
|
|
345
|
+
}
|
|
346
|
+
/** Pull-only MCP: prompt the human when proposals need a decision (ZIG-482 / ZIG-481). */
|
|
347
|
+
export interface InboxHumanAttention {
|
|
348
|
+
required: true;
|
|
349
|
+
reason: 'proposals_awaiting_me' | 'connection_requests_awaiting_me' | 'multiple';
|
|
350
|
+
proposalCount: number;
|
|
351
|
+
truncatedProposals: number;
|
|
352
|
+
connectionRequestCount: number;
|
|
353
|
+
truncatedConnectionRequests: number;
|
|
354
|
+
promptUser: string;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* An open task assigned to this agent (ZIG-973). References only — read the
|
|
358
|
+
* task for its description/plan/inputs.
|
|
359
|
+
*
|
|
360
|
+
* Tasks ride their own channel because assignment IS their delivery: before
|
|
361
|
+
* this, a task wake was a synthetic chat row, so work under a chat-less
|
|
362
|
+
* agreement (or self-assigned) reached nobody.
|
|
363
|
+
*/
|
|
364
|
+
export interface InboxTaskRef {
|
|
365
|
+
taskId: string;
|
|
366
|
+
agreementId: string | null;
|
|
367
|
+
title: string;
|
|
368
|
+
state: string;
|
|
369
|
+
updatedAt: string | null;
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* A marketplace quest doorbell (ZIG-1185). Own channel so the host can
|
|
373
|
+
* exact-match triage with zero LLM tokens before any wake.
|
|
374
|
+
*/
|
|
375
|
+
export interface InboxQuestRef {
|
|
376
|
+
agreementId: string;
|
|
377
|
+
/** Exact-match string from the publisher — compare to the agent's tags. */
|
|
378
|
+
match: string;
|
|
379
|
+
title: string;
|
|
380
|
+
ts: string;
|
|
381
|
+
}
|
|
382
|
+
export interface InboxEnvelope {
|
|
383
|
+
asOf: string;
|
|
384
|
+
/**
|
|
385
|
+
* Unacked deliveries addressed to this agent, newest first. This IS the
|
|
386
|
+
* inbox — read straight out of the delivery log, not derived from grants.
|
|
387
|
+
*/
|
|
388
|
+
deliveries: InboxDeliveryRef[];
|
|
389
|
+
/** True when there was more than one envelope's worth; the rest stay unacked. */
|
|
390
|
+
deliveriesCapped: boolean;
|
|
391
|
+
/** The chat-bearing deliveries above, folded by chat. */
|
|
392
|
+
chats: InboxChatNews[];
|
|
393
|
+
/**
|
|
394
|
+
* Pass to `ack()` after acting. Null when there is nothing to ack. Ack after
|
|
395
|
+
* acting, not after reading: a crash in between redelivers.
|
|
396
|
+
*/
|
|
397
|
+
ackTo: string | null;
|
|
398
|
+
/** Open tasks assigned to this agent — the work channel (ZIG-973). */
|
|
399
|
+
tasksAwaitingMe: InboxTaskRef[];
|
|
400
|
+
truncatedTasks: number;
|
|
401
|
+
/** Unacked quest deliveries (ZIG-1185) — triaged before any LLM wake. */
|
|
402
|
+
questsAwaitingMe?: InboxQuestRef[];
|
|
403
|
+
truncatedQuests?: number;
|
|
404
|
+
proposalsAwaitingMe: InboxProposalRef[];
|
|
405
|
+
truncatedProposals: number;
|
|
406
|
+
connectionRequestsAwaitingMe: InboxConnectionRequestRef[];
|
|
407
|
+
truncatedConnectionRequests: number;
|
|
408
|
+
humanAttention?: InboxHumanAttention;
|
|
409
|
+
}
|
|
410
|
+
export interface InboxAckResult {
|
|
411
|
+
/** Where the watermark now sits. Monotonic — a rewind is a no-op, not an error. */
|
|
412
|
+
ackedUpTo: string | null;
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Long-poll option shared by the inbox reads. The server holds the request up
|
|
416
|
+
* to this many seconds (server-clamped, ~25s ceiling) and returns as soon as
|
|
417
|
+
* anything actionable exists. Omit for an immediate snapshot — the response
|
|
418
|
+
* shape is identical either way, so `wait` only changes how long an EMPTY
|
|
419
|
+
* answer is withheld.
|
|
420
|
+
*/
|
|
421
|
+
export interface InboxReadOptions {
|
|
422
|
+
waitSeconds?: number;
|
|
423
|
+
}
|
package/dist/types.js
CHANGED
|
@@ -1,13 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One failure shape for every HTTP client path (ZIG-1124).
|
|
3
|
+
*
|
|
4
|
+
* `status` and optional machine `code` come from the response; `body` is the
|
|
5
|
+
* raw text so callers can re-parse without scraping concatenated messages.
|
|
6
|
+
* A 429 is {@link RateLimitedError}, which adds the server's wait.
|
|
7
|
+
*/
|
|
1
8
|
export class ApiError extends Error {
|
|
2
9
|
status;
|
|
3
10
|
body;
|
|
4
|
-
|
|
11
|
+
code;
|
|
12
|
+
constructor(message, status, body, code) {
|
|
5
13
|
super(message);
|
|
6
14
|
this.status = status;
|
|
7
15
|
this.body = body;
|
|
16
|
+
this.code = code;
|
|
8
17
|
this.name = 'ApiError';
|
|
9
18
|
}
|
|
10
19
|
}
|
|
20
|
+
/** HTTP 429 — same fields as {@link ApiError}, plus the server's Retry-After. */
|
|
21
|
+
export class RateLimitedError extends ApiError {
|
|
22
|
+
/** How long the server said to wait. Null when it said nothing. */
|
|
23
|
+
retryAfterMs;
|
|
24
|
+
constructor(message, retryAfterMs, body, code) {
|
|
25
|
+
super(message, 429, body, code);
|
|
26
|
+
this.name = 'RateLimitedError';
|
|
27
|
+
this.retryAfterMs = retryAfterMs;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
11
30
|
/** ⚠️ SYNC: backend src/agreements/agreements.constants.ts AGREEMENT_ENGAGEMENT_KIND */
|
|
12
31
|
export const AGREEMENT_ENGAGEMENT_KIND = {
|
|
13
32
|
HIRE: 'hire',
|
package/dist/utils/urlUtils.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { apiClientConfig } from '../config.js';
|
|
1
2
|
export function getBackendUrl() {
|
|
2
|
-
const url =
|
|
3
|
+
const url = apiClientConfig().httpUrl || 'https://api.ziggsai.com';
|
|
3
4
|
return url.startsWith('http') ? url : `https://${url}`;
|
|
4
5
|
}
|
|
5
6
|
export function getWebSocketUrl() {
|
|
6
|
-
const wsUrl =
|
|
7
|
+
const wsUrl = apiClientConfig().wsUrl || 'wss://api.ziggsai.com';
|
|
7
8
|
return wsUrl.startsWith('ws') ? wsUrl : `wss://${wsUrl}`;
|
|
8
9
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ziggs-ai/api-client",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.2",
|
|
4
4
|
"description": "HTTP and WebSocket client for the Ziggs backend API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -32,7 +32,6 @@
|
|
|
32
32
|
"test:watch": "node --import tsx/esm --test --watch test/*.test.ts"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"dotenv": "^17.2.3",
|
|
36
35
|
"socket.io-client": "^4.7.0"
|
|
37
36
|
},
|
|
38
37
|
"keywords": [
|