@ziggs-ai/api-client 0.37.17 → 0.37.18
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 +6 -0
- package/dist/capabilities/mcpBriefs.js +6 -0
- package/dist/capabilities/nextCall.js +2 -0
- package/dist/http/AssistantConnectionClient.d.ts +34 -2
- package/dist/http/AssistantConnectionClient.js +14 -1
- package/dist/http/InboxClient.d.ts +4 -1
- package/dist/http/InboxClient.js +12 -0
- package/dist/index.d.ts +1 -1
- package/dist/shared/operationError.d.ts +2 -0
- package/dist/shared/operationError.js +10 -0
- package/dist/types.d.ts +14 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.37.18
|
|
6
|
+
|
|
7
|
+
- Inspect notification health through a read-only assistant-connection status tool: explicit workspace, expiry, callback acceptance, retry timing and categorized failures, without callback URLs or signing secrets. Receipt is not proof of a host response. Preserve backend errors when observing through a connection.
|
|
8
|
+
|
|
9
|
+
- Read small inbox deltas with an observation cursor that renews on use, independent of work acknowledgements. Preserve the recovery cursor when the stream limit is reached. Reuse it to wait for new arrivals despite older unhandled mail; available through both HTTP connection modes and MCP.
|
|
10
|
+
|
|
5
11
|
## 0.37.17
|
|
6
12
|
|
|
7
13
|
- Clarify the shared hiring instructions: a mandate governs the work; agent-initiated hires need a covering grant or approval on the existing agreement.
|
|
@@ -13,6 +13,12 @@ const BRIEFS = {
|
|
|
13
13
|
does: 'Sets this assistant up in each workspace its owner has enabled.',
|
|
14
14
|
changes: 'may create hires, grants and assistant identities; a retry reuses them',
|
|
15
15
|
},
|
|
16
|
+
ziggs_notification_status: {
|
|
17
|
+
does: 'Reads this connection’s notification state, expiry and failures in one workspace. Callback receipt is not a host response; null means unknown.',
|
|
18
|
+
},
|
|
19
|
+
ziggs_inbox_changes: {
|
|
20
|
+
does: 'Reads 25 new inbox references per page; reuse the observation cursor to wait. No claim or ack.',
|
|
21
|
+
},
|
|
16
22
|
ziggs_inbox_peek: {
|
|
17
23
|
does: 'Says whether mail arrived since your last ack (count is 1 or 0, not a total) and names who you represent. Does not return deliveries, claim the inbox or ack.',
|
|
18
24
|
next: 'ziggs_inbox to read it',
|
|
@@ -63,6 +63,8 @@ const HTTP_BINDINGS = {
|
|
|
63
63
|
open: { method: 'POST', path: '/context/open' },
|
|
64
64
|
access_explain: { method: 'POST', path: '/context/access/explain' },
|
|
65
65
|
inbox_peek: { method: 'GET', path: '/inbox/peek' },
|
|
66
|
+
inbox_changes: { method: 'GET', path: '/inbox/changes' },
|
|
67
|
+
notification_status: { method: 'GET', path: '/oauth/events/status' },
|
|
66
68
|
task_get: { method: 'GET', path: '/tasks/:taskId' },
|
|
67
69
|
task_list: { method: 'GET', path: '/tasks' },
|
|
68
70
|
link_list: { method: 'GET', path: '/agreements?engagementKind=link' },
|
|
@@ -1,9 +1,38 @@
|
|
|
1
|
-
import { type Creds } from '../types.js';
|
|
1
|
+
import { type Creds, type InboxChangesOptions, type InboxChangesResult } from '../types.js';
|
|
2
2
|
export interface AssistantWorkspace {
|
|
3
3
|
orgId: string;
|
|
4
4
|
name: string;
|
|
5
5
|
agentId: string;
|
|
6
6
|
}
|
|
7
|
+
export interface McpEventStatus {
|
|
8
|
+
asOf: string;
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
orgId: string;
|
|
11
|
+
event: 'ziggs.inbox.updated';
|
|
12
|
+
receiptMeaning: string;
|
|
13
|
+
truncated: boolean;
|
|
14
|
+
subscriptions: Array<{
|
|
15
|
+
id: string;
|
|
16
|
+
state: 'active' | 'expired' | 'stopped';
|
|
17
|
+
expiresAt: string;
|
|
18
|
+
lastVerifiedAt: string | null;
|
|
19
|
+
lastCheckedAt: string | null;
|
|
20
|
+
lastWorkerErrorAt: string | null;
|
|
21
|
+
lastAcceptedAt: string | null;
|
|
22
|
+
lastAttempt: {
|
|
23
|
+
at: string;
|
|
24
|
+
httpStatus: number | null;
|
|
25
|
+
outcome: 'accepted' | 'retrying' | 'failed' | null;
|
|
26
|
+
} | null;
|
|
27
|
+
lastFailure: {
|
|
28
|
+
at: string;
|
|
29
|
+
reason: 'network' | 'http' | 'attempts_exhausted' | null;
|
|
30
|
+
httpStatus: number | null;
|
|
31
|
+
} | null;
|
|
32
|
+
nextAttemptAt: string | null;
|
|
33
|
+
stoppedReason: 'unsubscribed' | 'access_revoked' | 'connection_changed' | 'receiver_gone' | null;
|
|
34
|
+
}>;
|
|
35
|
+
}
|
|
7
36
|
/**
|
|
8
37
|
* The reads a connection makes about itself: which workspaces it works in,
|
|
9
38
|
* and its one inbox across all of them. It never remembers a
|
|
@@ -14,7 +43,7 @@ export declare class AssistantConnectionClient {
|
|
|
14
43
|
private readonly creds;
|
|
15
44
|
private readonly baseUrl;
|
|
16
45
|
constructor(creds: Creds, baseUrl?: string);
|
|
17
|
-
request<T>(path: string, body?: unknown): Promise<T>;
|
|
46
|
+
request<T>(path: string, body?: unknown, signal?: AbortSignal): Promise<T>;
|
|
18
47
|
/** Read existing enabled assistant hires. Provisioning is an explicit sync action. */
|
|
19
48
|
workspaces(): Promise<AssistantWorkspace[]>;
|
|
20
49
|
/** Which of the connection's assistants is on an existing thing. */
|
|
@@ -23,6 +52,9 @@ export declare class AssistantConnectionClient {
|
|
|
23
52
|
choices: AssistantWorkspace[];
|
|
24
53
|
}>;
|
|
25
54
|
inbox(waitSeconds?: number, snapshot?: boolean): Promise<Record<string, unknown>>;
|
|
55
|
+
getChanges(options?: InboxChangesOptions): Promise<InboxChangesResult>;
|
|
56
|
+
/** Receipt diagnostics only: this does not subscribe, renew or wake a host. */
|
|
57
|
+
eventStatus(orgId: string, signal?: AbortSignal): Promise<McpEventStatus>;
|
|
26
58
|
ack(upTo: string, handledResourceIds?: string[]): Promise<unknown>;
|
|
27
59
|
park(agreementId: string): Promise<{
|
|
28
60
|
agreementId: string;
|
|
@@ -15,9 +15,10 @@ export class AssistantConnectionClient {
|
|
|
15
15
|
this.creds = creds;
|
|
16
16
|
this.baseUrl = baseUrl;
|
|
17
17
|
}
|
|
18
|
-
async request(path, body) {
|
|
18
|
+
async request(path, body, signal) {
|
|
19
19
|
const response = await fetch(`${this.baseUrl}/oauth/${path}`, {
|
|
20
20
|
method: body === undefined ? 'GET' : 'POST',
|
|
21
|
+
signal,
|
|
21
22
|
headers: {
|
|
22
23
|
Authorization: `Bearer ${this.creds.operatorKey}`,
|
|
23
24
|
'Content-Type': 'application/json',
|
|
@@ -47,6 +48,18 @@ export class AssistantConnectionClient {
|
|
|
47
48
|
inbox(waitSeconds = 0, snapshot = false) {
|
|
48
49
|
return this.request(`inbox${snapshot ? "/snapshot" : ""}?wait=${waitSeconds}`);
|
|
49
50
|
}
|
|
51
|
+
getChanges(options = {}) {
|
|
52
|
+
const query = new URLSearchParams();
|
|
53
|
+
if (options.cursor !== undefined)
|
|
54
|
+
query.set('cursor', options.cursor);
|
|
55
|
+
if (options.waitSeconds !== undefined)
|
|
56
|
+
query.set('wait', String(options.waitSeconds));
|
|
57
|
+
return this.request(`inbox/changes?${query}`, undefined, options.signal);
|
|
58
|
+
}
|
|
59
|
+
/** Receipt diagnostics only: this does not subscribe, renew or wake a host. */
|
|
60
|
+
eventStatus(orgId, signal) {
|
|
61
|
+
return this.request(`events/status?${new URLSearchParams({ orgId })}`, undefined, signal);
|
|
62
|
+
}
|
|
50
63
|
ack(upTo, handledResourceIds = []) {
|
|
51
64
|
return this.request('inbox/ack', { upTo, handledResourceIds });
|
|
52
65
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { InboxAckResult, InboxEnvelope, InboxPeek, InboxReadOptions } from '../types.js';
|
|
1
|
+
import type { InboxAckResult, InboxEnvelope, InboxPeek, InboxReadOptions, InboxChangesOptions, InboxChangesResult } from '../types.js';
|
|
2
2
|
/**
|
|
3
3
|
* The doorbell, not the door: references addressed to this agent
|
|
4
4
|
* since its last ack — never content. Flow: inbox → read → act → ack
|
|
@@ -26,6 +26,9 @@ export declare class InboxClient {
|
|
|
26
26
|
});
|
|
27
27
|
private headers;
|
|
28
28
|
private inboxUrl;
|
|
29
|
+
/** At most 25 retained references per page. Keep cursor for subsequent waits;
|
|
30
|
+
* observation never claims work or acknowledges it. Expired cursors return 410. */
|
|
31
|
+
getChanges(opts?: InboxChangesOptions): Promise<InboxChangesResult>;
|
|
29
32
|
/** Read without acquiring worker ownership or recording receipts. */
|
|
30
33
|
getSnapshot(opts?: InboxReadOptions & {
|
|
31
34
|
signal?: AbortSignal;
|
package/dist/http/InboxClient.js
CHANGED
|
@@ -57,6 +57,18 @@ export class InboxClient {
|
|
|
57
57
|
}
|
|
58
58
|
return url.toString();
|
|
59
59
|
}
|
|
60
|
+
/** At most 25 retained references per page. Keep cursor for subsequent waits;
|
|
61
|
+
* observation never claims work or acknowledges it. Expired cursors return 410. */
|
|
62
|
+
async getChanges(opts = {}) {
|
|
63
|
+
const url = new URL(this.inboxUrl('/inbox/changes', opts));
|
|
64
|
+
if (opts.cursor !== undefined)
|
|
65
|
+
url.searchParams.set('cursor', opts.cursor);
|
|
66
|
+
const res = await fetch(url.toString(), { headers: this.headers(), signal: opts.signal });
|
|
67
|
+
const body = await res.text().catch(() => '');
|
|
68
|
+
if (!res.ok)
|
|
69
|
+
throw pollSurfaceError('InboxClient.getChanges', res, body);
|
|
70
|
+
return JSON.parse(body);
|
|
71
|
+
}
|
|
60
72
|
/** Read without acquiring worker ownership or recording receipts. */
|
|
61
73
|
async getSnapshot(opts = {}) {
|
|
62
74
|
const res = await fetch(this.inboxUrl('/inbox/snapshot', opts), {
|
package/dist/index.d.ts
CHANGED
|
@@ -30,7 +30,7 @@ export type { ContinuationKind, InboxAckDriver, InboxHandling, RepresentedPerson
|
|
|
30
30
|
export { inboxEngagement, isEchoOrDuplicate, isHireWorkOrder, contactPath, formationGuide, marketplaceFormation, liveHireChangedTerms, liveHireConflictFromStatus, withdrawHeldGraph, reminderHonesty, graphReleaseHonesty, hintsFromTasks, } from './engagementGuide.js';
|
|
31
31
|
export type { EngagementGuide, EngagementGuideKind, EngagementOutcome, EngagementTaskHint, ContactPathInput, FormationInput, GraphHonesty, HireTermsHonesty, WaitingOn, } from './engagementGuide.js';
|
|
32
32
|
export { isContextAccessRequest } from './shared/contextAccessRequest.js';
|
|
33
|
-
export { AssistantConnectionClient, type AssistantWorkspace, } from './http/AssistantConnectionClient.js';
|
|
33
|
+
export { AssistantConnectionClient, type AssistantWorkspace, type McpEventStatus, } from './http/AssistantConnectionClient.js';
|
|
34
34
|
export { withAssistantRequest, assistantRequestHeaders } from './http/operatorHeaders.js';
|
|
35
35
|
export { HANDLE_ALPHABET, findHandles, looksLikeHandle, parseHandle, parseRef, type HandleKind } from './handles.js';
|
|
36
36
|
export { describeOperationError, type OperationError } from './shared/operationError.js';
|
|
@@ -22,6 +22,8 @@ export interface OperationError {
|
|
|
22
22
|
* the same shape an open's action recovery has.
|
|
23
23
|
*/
|
|
24
24
|
recovery?: Record<string, unknown>;
|
|
25
|
+
/** Scoped restart position returned when too many observation streams exist. */
|
|
26
|
+
recoveryCursor?: string;
|
|
25
27
|
/** hidden | unreadable, the same outcome open and access_explain give. */
|
|
26
28
|
outcome?: string;
|
|
27
29
|
/** The resource the outcome is about. */
|
|
@@ -104,8 +104,18 @@ export function describeOperationError(input, surface = 'sdk') {
|
|
|
104
104
|
const recovery = typeof input === 'object' && input !== null
|
|
105
105
|
? recoveryIn(input.body)
|
|
106
106
|
: null;
|
|
107
|
+
let recoveryCursor;
|
|
108
|
+
if (shape.code === 'INBOX_OBSERVATION_LIMIT' && input && typeof input === 'object') {
|
|
109
|
+
try {
|
|
110
|
+
const body = JSON.parse(input.body ?? '{}');
|
|
111
|
+
if (typeof body.recoveryCursor === 'string' && /^ibxo1_[0-9a-f-]{36}$/.test(body.recoveryCursor))
|
|
112
|
+
recoveryCursor = body.recoveryCursor;
|
|
113
|
+
}
|
|
114
|
+
catch { /* Malformed recovery metadata does not hide the original refusal. */ }
|
|
115
|
+
}
|
|
107
116
|
const result = {
|
|
108
117
|
...shape,
|
|
118
|
+
...(recoveryCursor ? { recoveryCursor } : {}),
|
|
109
119
|
...(choices ? { choices } : {}),
|
|
110
120
|
...(recovery ? { recovery: typeof recovery.tool === 'string'
|
|
111
121
|
? { ...presentResourceCall(recovery, surface) }
|
package/dist/types.d.ts
CHANGED
|
@@ -526,3 +526,17 @@ export interface InboxPeek {
|
|
|
526
526
|
asOf: string;
|
|
527
527
|
count: number;
|
|
528
528
|
}
|
|
529
|
+
/** Private observation position, renewed on read for 24 idle hours; never pass to ack(). */
|
|
530
|
+
export interface InboxChangesOptions extends InboxReadOptions {
|
|
531
|
+
cursor?: string;
|
|
532
|
+
signal?: AbortSignal;
|
|
533
|
+
}
|
|
534
|
+
export interface InboxChangesResult {
|
|
535
|
+
asOf: string;
|
|
536
|
+
cursor: string;
|
|
537
|
+
expiresAt: string;
|
|
538
|
+
hasMore: boolean;
|
|
539
|
+
deliveries: Array<Pick<InboxDeliveryRef, 'eventId' | 'kind' | 'resourceId' | 'chatId' | 'taskId' | 'agreementId' | 'assigneeId' | 'needsHuman' | 'ts'> & {
|
|
540
|
+
orgId?: string | null;
|
|
541
|
+
}>;
|
|
542
|
+
}
|