@ziggs-ai/api-client 0.38.0 → 0.39.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.
Files changed (75) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +14 -36
  3. package/dist/capabilities/agreementVerbs.js +13 -21
  4. package/dist/capabilities/agreements.d.ts +2 -3
  5. package/dist/capabilities/agreements.js +8 -43
  6. package/dist/capabilities/artifacts.d.ts +6 -0
  7. package/dist/capabilities/artifacts.js +84 -43
  8. package/dist/capabilities/connections.js +10 -7
  9. package/dist/capabilities/context.d.ts +1 -1
  10. package/dist/capabilities/context.js +52 -45
  11. package/dist/capabilities/discovery.js +5 -5
  12. package/dist/capabilities/everyday.d.ts +1 -1
  13. package/dist/capabilities/everyday.js +1 -2
  14. package/dist/capabilities/index.d.ts +3 -4
  15. package/dist/capabilities/index.js +3 -4
  16. package/dist/capabilities/introductions.d.ts +1 -0
  17. package/dist/capabilities/introductions.js +64 -17
  18. package/dist/capabilities/links.d.ts +1 -9
  19. package/dist/capabilities/links.js +40 -39
  20. package/dist/capabilities/mcpBriefs.js +41 -34
  21. package/dist/capabilities/messaging.d.ts +9 -0
  22. package/dist/capabilities/messaging.js +11 -0
  23. package/dist/capabilities/nextCall.js +8 -17
  24. package/dist/capabilities/sources.d.ts +2 -3
  25. package/dist/capabilities/sources.js +1 -2
  26. package/dist/capabilities/tasks.d.ts +1 -0
  27. package/dist/capabilities/tasks.js +43 -2
  28. package/dist/capabilities/toolLane.js +2 -2
  29. package/dist/engagementGuide.d.ts +2 -2
  30. package/dist/engagementGuide.js +6 -6
  31. package/dist/handles.d.ts +1 -1
  32. package/dist/handles.js +2 -2
  33. package/dist/http/AgreementClient.d.ts +25 -63
  34. package/dist/http/AgreementClient.js +14 -65
  35. package/dist/http/ArtifactsClient.d.ts +31 -19
  36. package/dist/http/ArtifactsClient.js +43 -62
  37. package/dist/http/ConnectionsClient.d.ts +6 -7
  38. package/dist/http/ConnectionsClient.js +5 -3
  39. package/dist/http/ContextDiscoveryClient.d.ts +2 -2
  40. package/dist/http/ContextGrantsClient.d.ts +9 -15
  41. package/dist/http/ContextGrantsClient.js +3 -5
  42. package/dist/http/ContextOpenClient.d.ts +5 -6
  43. package/dist/http/ContextOpenClient.js +11 -4
  44. package/dist/http/ContextReadClient.d.ts +23 -27
  45. package/dist/http/ContextReadClient.js +24 -23
  46. package/dist/http/ExecutionContextClient.d.ts +5 -1
  47. package/dist/http/ExecutionContextClient.js +48 -1
  48. package/dist/http/IntroductionsClient.d.ts +33 -4
  49. package/dist/http/IntroductionsClient.js +6 -2
  50. package/dist/http/MessageRecordsClient.d.ts +36 -0
  51. package/dist/http/MessageRecordsClient.js +30 -0
  52. package/dist/http/SessionsClient.d.ts +5 -5
  53. package/dist/http/SessionsClient.js +6 -6
  54. package/dist/http/TaskClient.d.ts +35 -6
  55. package/dist/http/TaskClient.js +38 -36
  56. package/dist/http/agreementFlows.d.ts +2 -3
  57. package/dist/http/agreementFlows.js +5 -5
  58. package/dist/http/index.d.ts +3 -5
  59. package/dist/http/index.js +3 -4
  60. package/dist/http/operatorHeaders.d.ts +3 -0
  61. package/dist/http/operatorHeaders.js +14 -5
  62. package/dist/inboxAck.d.ts +2 -2
  63. package/dist/inboxAck.js +2 -2
  64. package/dist/index.d.ts +4 -4
  65. package/dist/index.js +2 -2
  66. package/dist/types.d.ts +25 -55
  67. package/package.json +2 -2
  68. package/dist/capabilities/chat.d.ts +0 -43
  69. package/dist/capabilities/chat.js +0 -196
  70. package/dist/capabilities/chatListFields.d.ts +0 -14
  71. package/dist/capabilities/chatListFields.js +0 -61
  72. package/dist/http/ChatClient.d.ts +0 -187
  73. package/dist/http/ChatClient.js +0 -219
  74. package/dist/http/MessagesClient.d.ts +0 -40
  75. package/dist/http/MessagesClient.js +0 -81
@@ -1,219 +0,0 @@
1
- import { decodeOperatorKeyClaims } from '../shared/operatorKey.js';
2
- import { runtimeLog } from '../shared/runtimeLog.js';
3
- import { getBackendUrl } from '../utils/urlUtils.js';
4
- import { throwApiError } from '../shared/apiError.js';
5
- import { buildCredsHeaders } from './operatorHeaders.js';
6
- // Auth, agent and the wake's lane, from the one helper — see operatorHeaders.
7
- const buildHeaders = buildCredsHeaders;
8
- function assertCreds(creds, op) {
9
- if (!creds?.operatorKey)
10
- throw new Error(`operatorKey is required for ${op}`);
11
- if (!creds?.agentId && !decodeOperatorKeyClaims(creds.operatorKey)?.connectionClientId)
12
- throw new Error(`agentId is required for ${op}`);
13
- }
14
- export async function openConversation(participant, creds, { newChat = false, agreementId, createIfMissing } = {}) {
15
- const input = typeof participant === 'string'
16
- ? { participantId: participant, ...(newChat ? { newChat } : {}), ...(agreementId ? { agreementId } : {}), ...(createIfMissing !== undefined ? { createIfMissing } : {}) }
17
- : participant;
18
- const resumeHire = !!input?.chatId && !!input.agreementId;
19
- if (resumeHire && (input.participantId || input.participantIds || input.newChat !== undefined || input.name !== undefined || input.idempotencyKey !== undefined || input.createIfMissing !== undefined)) {
20
- throw new Error('To resume hire admission, pass only chatId and agreementId');
21
- }
22
- if (!input || (!resumeHire && !input.participantId && !input.participantIds?.length)) {
23
- throw new Error('participantId is required, or use participantIds to invite people');
24
- }
25
- assertCreds(creds, 'open conversation');
26
- const route = resumeHire
27
- ? `/chats/${encodeURIComponent(input.chatId)}/hires/${encodeURIComponent(input.agreementId)}/admission`
28
- : '/chats';
29
- const res = await fetch(`${getBackendUrl()}${route}`, {
30
- method: 'POST',
31
- headers: buildHeaders(creds),
32
- // Only sent when asked for: an older backend ignores the field, so a
33
- // caller that never wants a separate room behaves identically either way.
34
- body: JSON.stringify(resumeHire ? {} : input),
35
- });
36
- if (!res.ok) {
37
- const body = await res.text().catch(() => '');
38
- throwApiError(res, body, `openConversation failed: ${res.status} ${res.statusText}`);
39
- }
40
- const data = await res.json().catch(() => null);
41
- if (!data?.['chatId'] || typeof data['chatId'] !== 'string') {
42
- throw new Error('Invalid response: expected { chatId } from POST /chats');
43
- }
44
- // left UNDEFINED rather than defaulted when the backend does not
45
- // send it. A backend from before this field cannot be assumed to have created
46
- // the room — defaulting to false would report a reused conversation as fresh,
47
- // which is worse than saying nothing.
48
- if (resumeHire && (data.chatId !== input.chatId || data.agreementId !== input.agreementId || !['ready', 'admission_failed'].includes(String(data.status)))) {
49
- throw new Error('Invalid hire-admission response: expected the selected chat, hire and admission status');
50
- }
51
- const reused = data['reused'];
52
- const name = data['name'];
53
- const invited = Array.isArray(data['invited'])
54
- ? data['invited']
55
- : undefined;
56
- return {
57
- chatId: data['chatId'],
58
- ...(resumeHire ? {
59
- agreementId: input.agreementId,
60
- status: data.status,
61
- ...(typeof data.reason === 'string' ? { reason: data.reason } : {}),
62
- } : {}),
63
- ...(typeof reused === 'boolean' ? { reused } : {}),
64
- ...(typeof name === 'string' && name ? { name } : {}),
65
- ...(invited ? { invited } : {}),
66
- };
67
- }
68
- function coverageFrom(value) {
69
- if (!value || typeof value !== 'object')
70
- return null;
71
- const row = value;
72
- return typeof row['agreementId'] === 'string' &&
73
- typeof row['message'] === 'string' &&
74
- typeof row['messagesUsed'] === 'number' &&
75
- (row['messageLimit'] === null || typeof row['messageLimit'] === 'number')
76
- ? {
77
- agreementId: row['agreementId'],
78
- messagesUsed: row['messagesUsed'],
79
- messageLimit: row['messageLimit'],
80
- message: row['message'],
81
- }
82
- : null;
83
- }
84
- /**
85
- * POST /chats/:chatId/members — add user/agent; agent-invite may return pending admission.
86
- */
87
- export async function addChatMember(input, creds) {
88
- assertCreds(creds, 'add chat member');
89
- const res = await fetch(`${getBackendUrl()}/chats/${encodeURIComponent(input.chatId)}/members`, {
90
- method: 'POST',
91
- headers: buildHeaders(creds),
92
- body: JSON.stringify({
93
- chatId: input.chatId,
94
- memberId: input.memberId,
95
- memberType: input.memberType,
96
- temporal: input.temporal,
97
- }),
98
- });
99
- const body = await res.text().catch(() => '');
100
- if (!res.ok) {
101
- throwApiError(res, body, `addChatMember failed: ${res.status} ${res.statusText}`);
102
- }
103
- const data = JSON.parse(body);
104
- if (data['status'] === 'pending' && data['pendingAdmission']) {
105
- return {
106
- status: 'pending',
107
- pendingAdmission: data['pendingAdmission'],
108
- };
109
- }
110
- if (data['status'] === 'approved') {
111
- return { status: 'approved', chat: data['chat'] };
112
- }
113
- return { chat: data['chat'] };
114
- }
115
- /**
116
- * POST /chats/:chatId/messages, or POST /chats/messages when `to` names
117
- * an existing participant and `chatId` is omitted.
118
- */
119
- export async function sendChatMessage(input, creds) {
120
- assertCreds(creds, 'send chat message');
121
- const chatId = typeof input.chatId === 'string' ? input.chatId.trim() : '';
122
- const to = typeof input.to === 'string' ? input.to.trim() : '';
123
- if (!chatId && !to) {
124
- throw new Error('chatId or to is required for send chat message');
125
- }
126
- const entryType = input.entryType ?? 'message';
127
- const contentType = input.contentType ?? 'text';
128
- const personSend = !chatId && Boolean(to);
129
- const url = personSend
130
- ? `${getBackendUrl()}/chats/messages`
131
- : `${getBackendUrl()}/chats/${encodeURIComponent(chatId)}/messages`;
132
- const res = await fetch(url, {
133
- method: 'POST',
134
- headers: buildHeaders(creds),
135
- body: JSON.stringify({
136
- ...(personSend ? { to } : { chatId }),
137
- messageId: input.messageId,
138
- text: input.text,
139
- entryType,
140
- contentType,
141
- // Canonical wire shape is `{ id, type? }`; bare strings are still
142
- // accepted by the backend after edge normalize, but first-party
143
- // clients send the object.
144
- receiver: input.receiverId ? { id: input.receiverId } : undefined,
145
- underAgreementId: input.underAgreementId,
146
- conversationAgreementId: input.conversationAgreementId,
147
- taskId: input.taskId,
148
- ...(input.sources ? { sources: input.sources } : {}),
149
- }),
150
- });
151
- if (!res.ok) {
152
- const body = await res.text().catch(() => '');
153
- throwApiError(res, body, `sendChatMessage failed: ${res.status} ${res.statusText}`);
154
- }
155
- const data = (await res.json().catch(() => null));
156
- const delivery = data?.['delivery'];
157
- const coverage = coverageFrom(data?.['coverage']);
158
- return {
159
- success: Boolean(data?.['success']),
160
- message: String(data?.['message'] ?? 'ok'),
161
- messageId: String(data?.['messageId'] ?? input.messageId),
162
- chatId: String(data?.['chatId'] ?? chatId),
163
- // Passed through as the server reported it, or absent. Never reconstructed
164
- // from the request: the whole point is that the destination may not be the
165
- // one the caller named.
166
- ...(delivery && typeof delivery === 'object'
167
- ? { delivery: delivery }
168
- : {}),
169
- ...(coverage ? { coverage } : {}),
170
- };
171
- }
172
- export async function listMyChats(creds, filters = {}) {
173
- assertCreds(creds, 'list my chats');
174
- const query = new URLSearchParams();
175
- if (filters.participantId)
176
- query.set('participantId', filters.participantId);
177
- if (filters.readable !== undefined)
178
- query.set('readable', String(filters.readable));
179
- const qs = query.toString();
180
- // empty array only for a genuine empty 200; any failure (non-2xx /
181
- // network) throws so ziggs_chat_list reports a real error instead of "you
182
- // have no chats". HTTP failures are ApiError (status/body/code).
183
- let res;
184
- try {
185
- res = await fetch(`${getBackendUrl()}/chats/mine${qs ? `?${qs}` : ''}`, {
186
- method: 'GET',
187
- headers: buildHeaders(creds),
188
- });
189
- }
190
- catch (e) {
191
- runtimeLog.warn('ChatClient', `⚠️ listMyChats failed: ${e.message}`);
192
- throw new Error(`GET /chats/mine network error: ${e.message}`);
193
- }
194
- if (!res.ok) {
195
- const body = await res.text().catch(() => '');
196
- runtimeLog.warn('ChatClient', `⚠️ listMyChats failed: ${res.status} ${res.statusText} ${body?.slice(0, 200)}`);
197
- throwApiError(res, body, `GET /chats/mine failed: ${res.status}`);
198
- }
199
- const data = await res.json().catch(() => null);
200
- return Array.isArray(data?.['chats']) ? data['chats'] : [];
201
- }
202
- export class ChatClient {
203
- creds;
204
- /**
205
- * @param operatorKey Agent-scoped or fleet operator key.
206
- * @param agentId Required for fleet keys (sent as X-Agent-Id). Omit for agent-scoped keys.
207
- */
208
- constructor(operatorKey, agentId) {
209
- if (!operatorKey)
210
- throw new Error('ChatClient: operatorKey is required');
211
- // agentId may be absent for agent-scoped keys; the Creds-based
212
- // standalone functions still assert it per call.
213
- this.creds = { operatorKey, agentId };
214
- }
215
- open(participant, opts) { return openConversation(participant, this.creds, opts); }
216
- addMember(input) { return addChatMember(input, this.creds); }
217
- sendMessage(input) { return sendChatMessage(input, this.creds); }
218
- listMine() { return listMyChats(this.creds); }
219
- }
@@ -1,40 +0,0 @@
1
- export interface ListMessagesOptions {
2
- /** ISO timestamp; only entries with `timestamp > after` are returned. */
3
- after?: string;
4
- /** Page size, default 100, hard cap 1000. */
5
- limit?: number;
6
- }
7
- /**
8
- * The chat message URL.
9
- *
10
- * `after` is a forward delta: the server returns that page only when both
11
- * `after` and `direction=forward` are set. Omitting both is the newest page,
12
- * which is how a person asks what just happened without already knowing a time.
13
- */
14
- export declare function messagesListUrl(base: string, chatId: string, opts?: ListMessagesOptions): string;
15
- export interface ListMessagesResult {
16
- messages: unknown[];
17
- latestSequence: string | null;
18
- }
19
- /**
20
- * Read-side client for forward-delta message reads.
21
- *
22
- * Hits the canonical `GET /chats/:chatId/messages?after=&direction=forward&limit=`
23
- * endpoint and returns a `{ messages, latestSequence }` envelope
24
- * (`chat-messaging.controller.listMessagesForward` →
25
- * `MessagesService.listForChat`).
26
- */
27
- export declare class MessagesClient {
28
- private readonly operatorKey;
29
- private readonly agentId;
30
- constructor(operatorKey: string, agentId: string);
31
- list(chatId: string, opts?: ListMessagesOptions): Promise<ListMessagesResult>;
32
- /**
33
- * Newest page. No `after`, so the server walks backward from now.
34
- * `list` is the forward delta and cannot answer "what just happened".
35
- */
36
- listLatest(chatId: string, opts?: {
37
- limit?: number;
38
- }): Promise<ListMessagesResult>;
39
- private _headers;
40
- }
@@ -1,81 +0,0 @@
1
- import { decodeOperatorKeyClaims } from '../shared/operatorKey.js';
2
- import { buildOperatorHeaders } from './operatorHeaders.js';
3
- import { getBackendUrl } from '../utils/urlUtils.js';
4
- import { throwApiError } from '../shared/apiError.js';
5
- /**
6
- * The chat message URL.
7
- *
8
- * `after` is a forward delta: the server returns that page only when both
9
- * `after` and `direction=forward` are set. Omitting both is the newest page,
10
- * which is how a person asks what just happened without already knowing a time.
11
- */
12
- export function messagesListUrl(base, chatId, opts = {}) {
13
- const url = new URL(`${base}/chats/${encodeURIComponent(chatId)}/messages`);
14
- if (opts.after) {
15
- url.searchParams.set('direction', 'forward');
16
- url.searchParams.set('after', opts.after);
17
- }
18
- if (opts.limit != null)
19
- url.searchParams.set('limit', String(opts.limit));
20
- return url.toString();
21
- }
22
- /**
23
- * Read-side client for forward-delta message reads.
24
- *
25
- * Hits the canonical `GET /chats/:chatId/messages?after=&direction=forward&limit=`
26
- * endpoint and returns a `{ messages, latestSequence }` envelope
27
- * (`chat-messaging.controller.listMessagesForward` →
28
- * `MessagesService.listForChat`).
29
- */
30
- export class MessagesClient {
31
- operatorKey;
32
- agentId;
33
- constructor(operatorKey, agentId) {
34
- if (!operatorKey)
35
- throw new Error('MessagesClient: operatorKey is required');
36
- if (!agentId && !decodeOperatorKeyClaims(operatorKey)?.connectionClientId)
37
- throw new Error('MessagesClient: agentId is required (operator-token impersonation)');
38
- this.operatorKey = operatorKey;
39
- this.agentId = agentId;
40
- }
41
- async list(chatId, opts = {}) {
42
- if (!chatId)
43
- return { messages: [], latestSequence: null };
44
- // Forward-delta read mode. Backend routes to `listMessagesForward`
45
- // only when BOTH `after` and `direction=forward` are present; without
46
- // `after` the same handler falls into backward pagination and returns
47
- // a different envelope. Default `after` to the unix epoch so the
48
- // forward branch always wins when callers want "from the beginning".
49
- const url = messagesListUrl(getBackendUrl(), chatId, {
50
- after: opts.after || '1970-01-01T00:00:00.000Z',
51
- limit: opts.limit,
52
- });
53
- const res = await fetch(url, { headers: this._headers() });
54
- if (!res.ok) {
55
- const body = await res.text().catch(() => '');
56
- // Callers branch on ApiError.status (404 = chat deleted/not visible).
57
- throwApiError(res, body, `MessagesClient.list failed: ${res.status}`);
58
- }
59
- return (await res.json());
60
- }
61
- /**
62
- * Newest page. No `after`, so the server walks backward from now.
63
- * `list` is the forward delta and cannot answer "what just happened".
64
- */
65
- async listLatest(chatId, opts = {}) {
66
- if (!chatId)
67
- return { messages: [], latestSequence: null };
68
- const res = await fetch(messagesListUrl(getBackendUrl(), chatId, { limit: opts.limit }), { headers: this._headers() });
69
- if (!res.ok) {
70
- const body = await res.text().catch(() => '');
71
- throwApiError(res, body, `MessagesClient.listLatest failed: ${res.status}`);
72
- }
73
- return (await res.json());
74
- }
75
- _headers() {
76
- return {
77
- 'content-type': 'application/json',
78
- ...buildOperatorHeaders(this.operatorKey, this.agentId),
79
- };
80
- }
81
- }