@nemphi/sdk 0.1.0 → 0.2.4556

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/index.js CHANGED
@@ -1,17 +1,1350 @@
1
- import { NemphiClient } from "./client";
2
- import { CrmResource } from "./resources/crm";
3
- import { OrganizationResource } from "./resources/organization";
4
- import { UsageResource } from "./resources/usage";
5
- export class NemphiSdk {
6
- constructor(options) {
7
- this.client = new NemphiClient(options);
8
- this.usage = new UsageResource(this.client);
9
- this.organization = new OrganizationResource(this.client);
10
- this.crm = new CrmResource(this.client);
1
+ /**
2
+ * @nemphi/sdk — typed client for the nemphi API.
3
+ *
4
+ * Built to `dist/` (ESM + `.d.ts`) for npm. In the monorepo the web app
5
+ * depends on the built package via `workspace:*`.
6
+ *
7
+ * Auth: pass an API key (`nk_…`) or session token (`nse_…`) as `token`.
8
+ * User sessions also need `tenantId` for tenant-scoped calls; API keys are
9
+ * tenant-bound already.
10
+ */
11
+ export * from "./block-kit.js";
12
+ export * from "./block-kit-state.js";
13
+ export * from "./reactions.js";
14
+ /**
15
+ * Whether a parsed value is a JSON object. A response body and
16
+ * `JSON.parse` hand back `unknown`; this is where that becomes a value with
17
+ * members, so a caller branches on a checked shape instead of asserting one.
18
+ */
19
+ export const isJsonObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
20
+ /** Whether a socket frame is text: the hub's frames always are, and a binary one is not ours. */
21
+ const isTextFrame = (data) => typeof data === "string";
22
+ /** Whether a parsed frame is one of the hub's events, by the discriminant it carries. */
23
+ const isRealtimeEvent = (value) => isJsonObject(value) &&
24
+ (value.type === "action" ||
25
+ value.type === "notification" ||
26
+ value.type === "marketing" ||
27
+ value.type === "typing" ||
28
+ value.type === "presence" ||
29
+ value.type === "change" ||
30
+ value.type === "viewing");
31
+ /**
32
+ * One frame off `GET /v1/events/socket`. A binary frame, a truncated line
33
+ * or a kind this build does not know yet is dropped, since these lanes
34
+ * carry no cursor and the next read shows the current state anyway.
35
+ */
36
+ const realtimeFrame = (data) => {
37
+ if (!isTextFrame(data))
38
+ return undefined;
39
+ let parsed;
40
+ try {
41
+ parsed = JSON.parse(data);
11
42
  }
43
+ catch {
44
+ return undefined;
45
+ }
46
+ return isRealtimeEvent(parsed) ? parsed : undefined;
47
+ };
48
+ /** Whether a member of a parsed response carries text. */
49
+ const isJsonText = (value) => typeof value === "string";
50
+ /** Whether a member of a parsed response is an object. */
51
+ const isJsonMap = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
52
+ /** A response body, parsed; anything that is not JSON reads as `null`. */
53
+ const parsedBody = (res) => res.json().catch(() => null);
54
+ /** Every operator a condition may use, in the order a picker shows them. */
55
+ export const WorkflowConditionOperators = [
56
+ "eq",
57
+ "ne",
58
+ "gt",
59
+ "gte",
60
+ "lt",
61
+ "lte",
62
+ "contains",
63
+ "not_contains",
64
+ "starts_with",
65
+ "ends_with",
66
+ "is_empty",
67
+ "is_not_empty",
68
+ "is_true",
69
+ "is_false",
70
+ ];
71
+ /** The operators that read only the left side, so a form hides the right one. */
72
+ export const WorkflowUnaryOperators = [
73
+ "is_empty",
74
+ "is_not_empty",
75
+ "is_true",
76
+ "is_false",
77
+ ];
78
+ export class ApiError extends Error {
79
+ status;
80
+ /** Stable machine-readable code, e.g. "approval_required". */
81
+ code;
82
+ body;
83
+ /** The input the refusal is about, for a form to show it there. */
84
+ refusal;
85
+ constructor(status, code, message, body, refusal = null) {
86
+ super(message);
87
+ this.name = "ApiError";
88
+ this.status = status;
89
+ this.code = code;
90
+ this.body = body;
91
+ this.refusal = refusal;
92
+ }
93
+ }
94
+ /** The input an error envelope names, read where the envelope is parsed. */
95
+ function fieldRefusalOf(error) {
96
+ const { field, reason, params: given } = error;
97
+ if (!isJsonText(field) || !isJsonText(reason))
98
+ return null;
99
+ const params = {};
100
+ if (isJsonMap(given)) {
101
+ for (const [name, value] of Object.entries(given)) {
102
+ if (isJsonText(value))
103
+ params[name] = value;
104
+ }
105
+ }
106
+ return { field, reason, params };
107
+ }
108
+ /** A guest's seat in a standalone call: the base of the public room routes. */
109
+ const publicCallSeatPath = (token, participantId) => `/v1/public/calls/${encodeURIComponent(token)}/participants/${encodeURIComponent(participantId)}`;
110
+ export function createClient(options) {
111
+ const baseUrl = options.baseUrl.replace(/\/+$/, "");
112
+ const fetchFn = options.fetch ?? fetch;
113
+ function buildHeaders(init, isJson = true) {
114
+ const headers = { ...options.headers };
115
+ if (isJson)
116
+ headers["Content-Type"] = "application/json";
117
+ const extra = init?.headers;
118
+ if (extra) {
119
+ // SAFETY: SDK callers pass a string record, not a Headers instance.
120
+ Object.assign(headers, extra);
121
+ }
122
+ if (options.token)
123
+ headers["Authorization"] = `Bearer ${options.token}`;
124
+ if (options.tenantId)
125
+ headers["X-Tenant-Id"] = options.tenantId;
126
+ return headers;
127
+ }
128
+ async function request(path, init) {
129
+ // Let fetch set the multipart boundary itself for FormData bodies.
130
+ const isJson = !(init?.body instanceof FormData);
131
+ const res = await fetchFn(`${baseUrl}${path}`, {
132
+ ...init,
133
+ headers: buildHeaders(init, isJson),
134
+ });
135
+ const body = await parsedBody(res);
136
+ if (!res.ok) {
137
+ const error = isJsonObject(body) ? body : {};
138
+ throw new ApiError(res.status, isJsonText(error.code) ? error.code : "unknown", isJsonText(error.error) ? error.error : `request failed with status ${res.status}`, body, fieldRefusalOf(error));
139
+ }
140
+ // SAFETY: `T` is the response the API documents for `path`, and every
141
+ // caller below is one of this client's own methods passing the type from
142
+ // the same contract these interfaces mirror. A 2xx body is that shape or
143
+ // the server is broken; the SDK does not re-validate it.
144
+ return body;
145
+ }
146
+ /** `?from=…&to=…`, omitting whichever the caller left out. */
147
+ const bookingWindow = (window) => {
148
+ const params = new URLSearchParams();
149
+ if (window?.from)
150
+ params.set("from", window.from);
151
+ if (window?.to)
152
+ params.set("to", window.to);
153
+ const query = params.toString();
154
+ return query === "" ? "" : `?${query}`;
155
+ };
156
+ const post = (path, input, headers) => request(path, { method: "POST", body: JSON.stringify(input ?? {}), headers });
157
+ const invoke = async (tool, input, opts) => {
158
+ const headers = {};
159
+ if (opts?.idempotencyKey)
160
+ headers["Idempotency-Key"] = opts.idempotencyKey;
161
+ const res = await post(`/v1/tools/${encodeURIComponent(tool)}:invoke`, input, headers);
162
+ return res.output;
163
+ };
164
+ /**
165
+ * Decodes an SSE body into `{ event, data }` frames. Comment lines
166
+ * (keepalives) and frames without a data payload are skipped.
167
+ */
168
+ async function* sseFrames(body) {
169
+ const reader = body.getReader();
170
+ const decoder = new TextDecoder();
171
+ let buf = "";
172
+ try {
173
+ for (;;) {
174
+ const { done, value } = await reader.read();
175
+ if (done)
176
+ break;
177
+ buf += decoder.decode(value, { stream: true });
178
+ // SSE frames are separated by a blank line.
179
+ for (let idx = buf.indexOf("\n\n"); idx !== -1; idx = buf.indexOf("\n\n")) {
180
+ const frame = buf.slice(0, idx);
181
+ buf = buf.slice(idx + 2);
182
+ const lines = frame.split("\n");
183
+ const event = lines
184
+ .find((line) => line.startsWith("event:"))
185
+ ?.slice(6)
186
+ .trim() ?? "";
187
+ const data = lines
188
+ .filter((line) => line.startsWith("data:"))
189
+ .map((line) => line.slice(5).trimStart())
190
+ .join("\n");
191
+ if (data)
192
+ yield { event, data };
193
+ }
194
+ }
195
+ }
196
+ finally {
197
+ reader.releaseLock();
198
+ }
199
+ }
200
+ /** Turns a non-2xx (or bodyless) stream response into an ApiError. */
201
+ async function streamError(res) {
202
+ const body = await parsedBody(res);
203
+ const error = isJsonObject(body) ? body : {};
204
+ throw new ApiError(res.status, isJsonText(error.code) ? error.code : "unknown", isJsonText(error.error) ? error.error : `stream failed with status ${res.status}`, body, fieldRefusalOf(error));
205
+ }
206
+ async function* streamEvents(opts) {
207
+ const params = new URLSearchParams();
208
+ if (opts?.cursor !== undefined)
209
+ params.set("cursor", String(opts.cursor));
210
+ const qs = params.toString();
211
+ const res = await fetchFn(`${baseUrl}/v1/events/stream${qs ? `?${qs}` : ""}`, {
212
+ headers: buildHeaders(undefined, false),
213
+ signal: opts?.signal,
214
+ });
215
+ if (!res.ok || !res.body)
216
+ await streamError(res);
217
+ for await (const frame of sseFrames(res.body)) {
218
+ const action = JSON.parse(frame.data);
219
+ yield action;
220
+ }
221
+ }
222
+ const openRealtimeSocket = (options) => {
223
+ const url = `${baseUrl.replace(/^http/, "ws")}/v1/events/socket`;
224
+ const headers = buildHeaders(undefined, false);
225
+ // SAFETY: React Native's WebSocket accepts `{ headers }` as a third
226
+ // argument; the standard constructor ignores extra arguments, so the
227
+ // wider signature holds for both.
228
+ const Headered = WebSocket;
229
+ const open = options.webSocket ?? ((target, extra) => new Headered(target, undefined, { headers: extra }));
230
+ let closed = false;
231
+ let socket;
232
+ let attempt = 0;
233
+ let timer;
234
+ const connect = () => {
235
+ if (closed)
236
+ return;
237
+ const ws = open(url, headers);
238
+ socket = ws;
239
+ ws.onopen = () => {
240
+ attempt = 0;
241
+ options.onOpen?.();
242
+ };
243
+ ws.onmessage = (message) => {
244
+ const event = realtimeFrame(message.data);
245
+ if (event !== undefined)
246
+ options.onEvent(event);
247
+ };
248
+ ws.onclose = () => {
249
+ if (socket !== ws)
250
+ return;
251
+ socket = undefined;
252
+ options.onClose?.();
253
+ if (closed)
254
+ return;
255
+ // Back off to half a minute; a workspace switch or sign-out closes for good.
256
+ const delay = Math.min(30_000, 1_000 * 2 ** Math.min(attempt, 5));
257
+ attempt += 1;
258
+ timer = setTimeout(connect, delay);
259
+ };
260
+ ws.onerror = () => {
261
+ // `onclose` follows and schedules the retry.
262
+ };
263
+ };
264
+ connect();
265
+ return {
266
+ close: () => {
267
+ closed = true;
268
+ if (timer !== undefined)
269
+ clearTimeout(timer);
270
+ const ws = socket;
271
+ socket = undefined;
272
+ ws?.close(1000, "closed by client");
273
+ },
274
+ };
275
+ };
276
+ const sendTyping = (input) => post("/v1/events/typing", input);
277
+ const sendViewing = (input) => post("/v1/events/viewing", input);
278
+ async function* overviewChatStream(input, opts) {
279
+ const res = await fetchFn(`${baseUrl}/v1/overview/chat/stream`, {
280
+ method: "POST",
281
+ body: JSON.stringify(input),
282
+ headers: { ...buildHeaders(), Accept: "text/event-stream" },
283
+ signal: opts?.signal,
284
+ });
285
+ if (!res.ok || !res.body)
286
+ await streamError(res);
287
+ for await (const frame of sseFrames(res.body)) {
288
+ const data = JSON.parse(frame.data);
289
+ switch (frame.event) {
290
+ case "turn":
291
+ yield { type: "turn", n: data.n };
292
+ break;
293
+ case "delta":
294
+ yield { type: "delta", text: data.text };
295
+ break;
296
+ case "tool":
297
+ yield { type: "tool", name: data.name, phase: data.phase };
298
+ break;
299
+ case "done":
300
+ yield { type: "done", response: data };
301
+ return;
302
+ case "error":
303
+ yield { type: "error", error: data.error, code: data.code };
304
+ return;
305
+ // An event this build doesn't know yet is not a reason to stop.
306
+ }
307
+ }
308
+ }
309
+ return {
310
+ health: () => request("/healthz"),
311
+ joinWaitlist: async (input) => {
312
+ await post("/v1/waitlist", input);
313
+ },
314
+ signup: (input) => post("/v1/auth/signup", input),
315
+ login: (input) => post("/v1/auth/login", input),
316
+ logout: async () => {
317
+ await post("/v1/auth/logout");
318
+ },
319
+ verifyMfa: (input) => post("/v1/auth/mfa/verify", input),
320
+ requestMagicLink: async (email) => {
321
+ await post("/v1/auth/magic-link", { email });
322
+ },
323
+ redeemMagicLink: (token) => post("/v1/auth/magic-link/redeem", { token }),
324
+ beginPasskeyLogin: () => post("/v1/auth/passkeys/login/begin"),
325
+ finishPasskeyLogin: (input) => post("/v1/auth/passkeys/login/finish", input),
326
+ lookupSso: (email) => post("/v1/auth/sso/lookup", { email }),
327
+ startSso: (input) => post("/v1/auth/sso/start", input),
328
+ createNativeHandoff: (input) => post("/v1/auth/native/handoff", input),
329
+ redeemNativeHandoff: (input) => post("/v1/auth/native/handoff/redeem", input),
330
+ completeSso: (input) => post("/v1/auth/sso/callback", input),
331
+ completeSaml: ({ connection_id, ...body }) => post(`/v1/auth/saml/${encodeURIComponent(connection_id)}/acs`, body),
332
+ verifyEmail: async (token) => {
333
+ await post("/v1/auth/verify-email", { token });
334
+ },
335
+ resendVerificationEmail: async () => {
336
+ await post("/v1/auth/resend-verification-email");
337
+ },
338
+ requestPasswordReset: async (email) => {
339
+ await post("/v1/auth/request-password-reset", { email });
340
+ },
341
+ resetPassword: async (input) => {
342
+ await post("/v1/auth/reset-password", input);
343
+ },
344
+ me: () => request("/v1/me"),
345
+ setMyLocale: (locale) => request("/v1/me/locale", {
346
+ method: "PUT",
347
+ body: JSON.stringify({ locale }),
348
+ }),
349
+ updateMyMembership: (input) => request("/v1/me/membership", {
350
+ method: "PUT",
351
+ body: JSON.stringify(input),
352
+ }),
353
+ updateMe: (input) => request("/v1/me", { method: "PATCH", body: JSON.stringify(input) }),
354
+ uploadMyAvatar: (file, opts) => {
355
+ const form = new FormData();
356
+ if (opts?.filename)
357
+ form.append("file", file, opts.filename);
358
+ else
359
+ form.append("file", file);
360
+ return request("/v1/me/avatar", {
361
+ method: "POST",
362
+ body: form,
363
+ });
364
+ },
365
+ chooseMyAvatar: (identityId) => request("/v1/me/avatar", {
366
+ method: "PUT",
367
+ body: JSON.stringify({ identity_id: identityId }),
368
+ }),
369
+ clearMyAvatar: () => request("/v1/me/avatar", { method: "DELETE" }),
370
+ getMyAvatar: () => request("/v1/me/avatar"),
371
+ getUserAvatar: (userId) => request(`/v1/users/${encodeURIComponent(userId)}/avatar`),
372
+ getIdentityPhoto: (identityId) => request(`/v1/me/identities/${encodeURIComponent(identityId)}/photo`),
373
+ getAgentAvatar: (agentId) => request(`/v1/agents/${encodeURIComponent(agentId)}/avatar`),
374
+ getDefinitionAvatar: (slug) => request(`/v1/agents/definition/${encodeURIComponent(slug)}/avatar`),
375
+ uploadAgentAvatar: (agentId, file, opts) => {
376
+ const form = new FormData();
377
+ if (opts?.filename)
378
+ form.append("file", file, opts.filename);
379
+ else
380
+ form.append("file", file);
381
+ return request(`/v1/agents/${encodeURIComponent(agentId)}/avatar`, {
382
+ method: "POST",
383
+ body: form,
384
+ });
385
+ },
386
+ clearAgentAvatar: (agentId) => request(`/v1/agents/${encodeURIComponent(agentId)}/avatar`, {
387
+ method: "DELETE",
388
+ }),
389
+ changeMyPassword: async (input) => {
390
+ await request("/v1/me/password", { method: "PUT", body: JSON.stringify(input) });
391
+ },
392
+ getMfa: () => request("/v1/me/mfa"),
393
+ startTotpEnrollment: () => post("/v1/me/mfa/totp"),
394
+ confirmTotpEnrollment: (code) => post("/v1/me/mfa/totp/confirm", { code }),
395
+ disableTotp: async (code) => {
396
+ await post("/v1/me/mfa/totp/disable", { code });
397
+ },
398
+ regenerateRecoveryCodes: (code) => post("/v1/me/mfa/recovery-codes", { code }),
399
+ listPasskeys: async () => {
400
+ const res = await request("/v1/me/passkeys");
401
+ return res.passkeys ?? [];
402
+ },
403
+ beginPasskeyRegistration: () => post("/v1/me/passkeys/begin"),
404
+ finishPasskeyRegistration: (input) => post("/v1/me/passkeys/finish", input),
405
+ renamePasskey: async (id, name) => {
406
+ await request(`/v1/me/passkeys/${encodeURIComponent(id)}`, {
407
+ method: "PATCH",
408
+ body: JSON.stringify({ name }),
409
+ });
410
+ },
411
+ deletePasskey: async (id) => {
412
+ await request(`/v1/me/passkeys/${encodeURIComponent(id)}`, { method: "DELETE" });
413
+ },
414
+ listIdentities: async () => {
415
+ const res = await request("/v1/me/identities");
416
+ return res.identities ?? [];
417
+ },
418
+ startIdentityLink: (input) => post("/v1/me/identities/start", input),
419
+ unlinkIdentity: async (id) => {
420
+ await request(`/v1/me/identities/${encodeURIComponent(id)}`, { method: "DELETE" });
421
+ },
422
+ listMySessions: async () => {
423
+ const res = await request("/v1/me/sessions");
424
+ return res.sessions ?? [];
425
+ },
426
+ revokeMySession: (id) => request(`/v1/me/sessions/${encodeURIComponent(id)}`, {
427
+ method: "DELETE",
428
+ }),
429
+ revokeMyOtherSessions: () => request("/v1/me/sessions", { method: "DELETE" }),
430
+ listMyOAuthApps: async () => {
431
+ const res = await request("/v1/me/oauth-apps");
432
+ return res.apps ?? [];
433
+ },
434
+ revokeMyOAuthApp: (id) => request(`/v1/me/oauth-apps/${encodeURIComponent(id)}`, {
435
+ method: "DELETE",
436
+ }),
437
+ onboardingState: () => invoke("onboarding.state", {}),
438
+ answerOnboarding: (answers) => invoke("onboarding.answer", { answers }),
439
+ completeOnboarding: (answers) => invoke("onboarding.complete", answers ? { answers } : {}),
440
+ listCalendarConnections: () => invoke("calendar.list_connections", {}),
441
+ listConnectedCalendarEvents: (input) => invoke("calendar.list_connected_events", input),
442
+ connectCalendarAccount: (input) => invoke("calendar.connect_account", input),
443
+ listEmailAccounts: async () => {
444
+ const res = await invoke("email.list_accounts", {});
445
+ return res.accounts ?? [];
446
+ },
447
+ connectEmailAccount: (input) => invoke("email.connect_account", input),
448
+ syncEmailAccount: (accountId) => invoke("email.sync_now", {
449
+ account_id: accountId,
450
+ }),
451
+ disconnectEmailAccount: (accountId) => invoke("email.disconnect_account", { account_id: accountId }),
452
+ configureEmailAccount: (input) => invoke("email.configure_account", input),
453
+ crmSettings: () => invoke("crm.settings", {}),
454
+ configureCRM: (input) => invoke("crm.configure", input),
455
+ crmProspecting: () => invoke("crm.prospecting", {}),
456
+ saveProspectingProfile: async (input) => {
457
+ const res = await invoke("crm.save_prospecting_profile", input);
458
+ return res.profile;
459
+ },
460
+ findProspects: async () => {
461
+ const res = await invoke("crm.find_prospects", {});
462
+ return res.run;
463
+ },
464
+ crmGrid: (query) => invoke("crm.grid", query),
465
+ listCRMFields: async (entity) => {
466
+ const res = await invoke("crm.list_fields", entity ? { entity } : {});
467
+ return res.fields ?? [];
468
+ },
469
+ listWorkflows: async () => {
470
+ const res = await invoke("workflows.list", {});
471
+ return res.workflows ?? [];
472
+ },
473
+ getWorkflow: (key) => invoke("workflows.get", { key }),
474
+ saveWorkflow: (input, opts) => invoke("workflows.save", input, opts),
475
+ setWorkflowLive: (key, live) => invoke("workflows.set_live", { key, live }),
476
+ triggerWorkflow: (key, input) => invoke("workflows.trigger", input ? { key, input } : { key }),
477
+ deleteWorkflow: (key) => invoke("workflows.delete", { key }),
478
+ listWorkflowRuns: async (key, limit) => {
479
+ const res = await invoke("workflows.runs", limit ? { key, limit } : { key });
480
+ return res.runs ?? [];
481
+ },
482
+ cancelWorkflowRun: (runId) => invoke("workflows.cancel_run", { run_id: runId }),
483
+ listMarketingChannels: async () => {
484
+ const res = await invoke("marketing.list_channels", {});
485
+ return res.channels ?? [];
486
+ },
487
+ connectWhatsApp: (input) => invoke("marketing.connect_whatsapp", input),
488
+ completeWhatsApp: (input) => request("/oauth/whatsapp/complete", {
489
+ method: "POST",
490
+ body: JSON.stringify(input),
491
+ }),
492
+ connectInstagram: (input) => invoke("marketing.connect_instagram", input ?? {}),
493
+ connectFacebook: (input) => invoke("marketing.connect_facebook", input ?? {}),
494
+ connectLinkedIn: (input) => invoke("marketing.connect_linkedin", input ?? {}),
495
+ connectTikTok: (input) => invoke("marketing.connect_tiktok", input ?? {}),
496
+ syncMarketingChannel: (channelId) => invoke("marketing.sync_metrics", {
497
+ channel_id: channelId,
498
+ }),
499
+ disconnectMarketingChannel: (channelId) => invoke("marketing.disconnect_channel", { channel_id: channelId }),
500
+ connectGoogleAds: () => invoke("marketing.connect_google_ads", {}),
501
+ listMarketingAdAccounts: () => invoke("marketing.list_ad_accounts", {}),
502
+ compareMarketingAccounts: (input) => invoke("marketing.compare_accounts", input ?? {}),
503
+ marketingChannelTrend: (input) => invoke("marketing.channel_trend", input),
504
+ marketingAdTrend: (input) => invoke("marketing.ad_trend", input ?? {}),
505
+ marketingTopPosts: (input) => invoke("marketing.top_posts", input ?? {}),
506
+ emailMarketingStatus: () => invoke("marketing.email_status", {}),
507
+ emailReputation: () => invoke("marketing.email_reputation", {}),
508
+ enableEmailMarketing: (input) => invoke("marketing.enable_email", input ?? {}),
509
+ updateEmailMarketingSettings: (input) => invoke("marketing.update_email_settings", input),
510
+ checkEmailSpam: (input) => invoke("marketing.check_email_spam", input),
511
+ suggestEmailFixes: (input) => invoke("marketing.suggest_email_fixes", input),
512
+ saveEmailTemplate: (input) => invoke("marketing.save_email_template", input),
513
+ listEmailTemplates: async (input) => {
514
+ const res = await invoke("marketing.list_email_templates", input ?? {});
515
+ return res.templates ?? [];
516
+ },
517
+ getEmailTemplate: (templateId) => invoke("marketing.get_email_template", {
518
+ template_id: templateId,
519
+ }),
520
+ deleteEmailTemplate: (templateId) => invoke("marketing.delete_email_template", {
521
+ template_id: templateId,
522
+ }),
523
+ listEmailRows: async () => {
524
+ const res = await invoke("marketing.list_email_rows", {});
525
+ return res.rows ?? [];
526
+ },
527
+ saveEmailRow: (input) => invoke("marketing.save_email_row", input),
528
+ deleteEmailRow: (rowId) => invoke("marketing.delete_email_row", { row_id: rowId }),
529
+ listEmailTemplateRevisions: async (input) => {
530
+ const res = await invoke("marketing.list_email_template_revisions", input);
531
+ return { revisions: res.revisions ?? [], before_version: res.before_version ?? null };
532
+ },
533
+ getEmailTemplateRevision: (input) => invoke("marketing.get_email_template_revision", input),
534
+ restoreEmailTemplateRevision: (input) => invoke("marketing.restore_email_template_revision", input),
535
+ sendEmailTest: (input) => invoke("marketing.send_email_test", input),
536
+ createEmailCampaign: (input) => invoke("marketing.create_email_campaign", input),
537
+ updateEmailCampaign: (input) => invoke("marketing.update_email_campaign", input),
538
+ sendEmailCampaign: (input) => invoke("marketing.send_email_campaign", input),
539
+ cancelEmailCampaign: (campaignId) => invoke("marketing.cancel_email_campaign", {
540
+ campaign_id: campaignId,
541
+ }),
542
+ listEmailCampaigns: (input) => invoke("marketing.list_email_campaigns", input ?? {}),
543
+ getEmailCampaign: (campaignId, recipientsLimit) => {
544
+ const input = { campaign_id: campaignId };
545
+ if (recipientsLimit !== undefined)
546
+ input.recipients_limit = recipientsLimit;
547
+ return invoke("marketing.get_email_campaign", input);
548
+ },
549
+ listEmailUnsubscribes: async (input) => {
550
+ const res = await invoke("marketing.list_email_unsubscribes", input ?? {});
551
+ return res.unsubscribes ?? [];
552
+ },
553
+ unsubscribeEmail: (email) => invoke("marketing.unsubscribe_email", { email }),
554
+ enableMarketingAdAccount: (adAccountId) => invoke("marketing.enable_ad_account", { ad_account_id: adAccountId }),
555
+ disconnectMarketingAdAccount: (adAccountId) => invoke("marketing.disconnect_ad_account", {
556
+ ad_account_id: adAccountId,
557
+ }),
558
+ getMarketingAdInsights: (adAccountId, observedOn) => invoke("marketing.list_ad_insights", {
559
+ ad_account_id: adAccountId,
560
+ observed_on: observedOn,
561
+ }),
562
+ listMarketingMetrics: async (input) => {
563
+ const res = await invoke("marketing.list_metrics", input ?? {});
564
+ return res.snapshots ?? [];
565
+ },
566
+ createMarketingPost: (input) => invoke("marketing.create_post", input),
567
+ getTikTokCreatorInfo: (channelId) => invoke("marketing.tiktok_creator_info", { channel_id: channelId }),
568
+ listMarketingPostRevisions: (input) => invoke("marketing.list_post_revisions", input),
569
+ listMarketingHistory: (input) => invoke("marketing.list_history", input),
570
+ listMarketingMedia: (input) => invoke("marketing.list_media", input ?? {}),
571
+ listMarketingPostBoard: (input) => invoke("marketing.list_posts", input ?? {}),
572
+ listMarketingPosts: async (input) => {
573
+ const res = await invoke("marketing.list_posts", input ?? {});
574
+ return res.posts ?? [];
575
+ },
576
+ saveMarketingPostDraft: (input) => invoke("marketing.save_post_draft", input),
577
+ submitMarketingPost: (postId) => invoke("marketing.submit_post", { post_id: postId }),
578
+ reviewMarketingPost: (input) => invoke("marketing.review_post", input),
579
+ scheduleMarketingPost: (input) => invoke("marketing.schedule_post", input),
580
+ getMarketingPost: (postId) => invoke("marketing.get_post", { post_id: postId }),
581
+ cancelMarketingPost: (postId) => invoke("marketing.cancel_post", { post_id: postId }),
582
+ uploadMarketingMedia: (file, opts) => {
583
+ const form = new FormData();
584
+ if (opts?.filename)
585
+ form.append("file", file, opts.filename);
586
+ else
587
+ form.append("file", file);
588
+ return request("/v1/marketing/media", { method: "POST", body: form });
589
+ },
590
+ listMarketingConversations: async (input) => {
591
+ const res = await invoke("marketing.list_conversations", input ?? {});
592
+ return res.conversations ?? [];
593
+ },
594
+ listMarketingInboxTopics: async () => {
595
+ const res = await invoke("marketing.list_inbox_topics", {});
596
+ return res.topics ?? [];
597
+ },
598
+ saveMarketingInboxTopic: (input) => invoke("marketing.save_inbox_topic", input),
599
+ deleteMarketingInboxTopic: (topicId) => invoke("marketing.delete_inbox_topic", {
600
+ topic_id: topicId,
601
+ }),
602
+ createMarketingConversationDeal: (conversationId) => invoke("marketing.create_conversation_deal", { conversation_id: conversationId }),
603
+ resumeMarketingResponder: (conversationId) => invoke("marketing.resume_responder", {
604
+ conversation_id: conversationId,
605
+ }),
606
+ getMarketingConversation: (conversationId, input) => invoke("marketing.get_conversation", input ? { conversation_id: conversationId, ...input } : { conversation_id: conversationId }),
607
+ markMarketingConversationRead: (conversationId) => invoke("marketing.mark_conversation_read", {
608
+ conversation_id: conversationId,
609
+ }),
610
+ sendWhatsAppReply: async (input) => {
611
+ const res = await invoke("marketing.send_whatsapp", input);
612
+ return res.message;
613
+ },
614
+ sendDirectMessage: async (input) => {
615
+ const res = await invoke("marketing.send_direct_message", input);
616
+ return res.message;
617
+ },
618
+ linkMarketingConversationParty: (input) => invoke("marketing.link_conversation_party", input),
619
+ listMarketingCalls: async (input) => {
620
+ const res = await invoke("marketing.list_calls", input ?? {});
621
+ return res.calls ?? [];
622
+ },
623
+ getMarketingCall: (callId) => invoke("marketing.get_call", { call_id: callId }),
624
+ rejectMarketingCall: (callId) => invoke("marketing.reject_call", {
625
+ call_id: callId,
626
+ }),
627
+ terminateMarketingCall: (callId) => invoke("marketing.terminate_call", {
628
+ call_id: callId,
629
+ }),
630
+ answerMarketingCall: (input) => invoke("marketing.answer_call", input),
631
+ placeMarketingCall: (input) => invoke("marketing.place_call", input),
632
+ requestMarketingCallPermission: (input) => invoke("marketing.request_call_permission", input),
633
+ callCenterDesk: () => invoke("callcenter.desk", {}),
634
+ answerCallCenterWebCall: (callId) => invoke("callcenter.answer_web_call", {
635
+ call_id: callId,
636
+ }),
637
+ linkCallCenterContact: (callId, partyId) => invoke("callcenter.link_contact", {
638
+ call_id: callId,
639
+ party_id: partyId,
640
+ }),
641
+ callCenterBoard: () => invoke("callcenter.board", {}),
642
+ listCallCenterQueues: async () => {
643
+ const res = await invoke("callcenter.list_queues", {});
644
+ return res.queues ?? [];
645
+ },
646
+ saveCallCenterQueue: (input) => invoke("callcenter.save_queue", input),
647
+ deleteCallCenterQueue: (queueId) => invoke("callcenter.delete_queue", { queue_id: queueId }),
648
+ setCallCenterStatus: (status) => invoke("callcenter.set_status", { status }),
649
+ callCenterTranscript: async (callId) => {
650
+ const res = await invoke("callcenter.transcript", {
651
+ call_id: callId,
652
+ });
653
+ return res.lines ?? [];
654
+ },
655
+ callCenterCallLog: async (callId) => {
656
+ const res = await invoke("callcenter.transcript", {
657
+ call_id: callId,
658
+ });
659
+ return {
660
+ lines: res.lines ?? [],
661
+ recordings: res.recordings ?? [],
662
+ tool_calls: res.tool_calls ?? [],
663
+ };
664
+ },
665
+ addCallCenterTranscript: (input) => invoke("callcenter.add_transcript", input),
666
+ uploadCallCenterRecording: (callId, audio, timing) => {
667
+ const query = new URLSearchParams({
668
+ started_at: timing.started_at,
669
+ duration_ms: String(Math.max(0, Math.round(timing.duration_ms))),
670
+ });
671
+ return request(`/v1/callcenter/calls/${encodeURIComponent(callId)}/recordings?${query}`, {
672
+ method: "POST",
673
+ headers: { "Content-Type": audio.type || "audio/webm" },
674
+ body: audio,
675
+ });
676
+ },
677
+ downloadCallCenterRecording: async (recordingId, range) => {
678
+ const response = await fetchFn(`${baseUrl}/v1/callcenter/recordings/${encodeURIComponent(recordingId)}`, {
679
+ headers: buildHeaders(range ? { headers: { Range: range } } : undefined, false),
680
+ });
681
+ if (!response.ok && response.status !== 416)
682
+ return streamError(response);
683
+ return response;
684
+ },
685
+ listWhatsAppTemplates: async (channelId) => {
686
+ const res = await invoke("marketing.list_templates", {
687
+ channel_id: channelId,
688
+ });
689
+ return res.templates ?? [];
690
+ },
691
+ sendWhatsAppTemplate: (input) => invoke("marketing.send_template", input),
692
+ listMarketingCampaigns: async (input) => {
693
+ const res = await invoke("marketing.list_campaigns", input ?? {});
694
+ return res.campaigns ?? [];
695
+ },
696
+ getMarketingCampaign: (campaignId) => invoke("marketing.get_campaign", { campaign_id: campaignId }),
697
+ listCRMPartyTags: async (input) => {
698
+ const res = await invoke("crm.list_party_tags", input ?? {});
699
+ return res.tags ?? [];
700
+ },
701
+ saveCRMPartyTag: (input) => invoke("crm.save_party_tag", input),
702
+ deleteCRMPartyTag: (tagId) => invoke("crm.delete_party_tag", { tag_id: tagId }),
703
+ setPartyTags: (partyId, tagIds) => invoke("crm.set_party_tags", {
704
+ party_id: partyId,
705
+ tag_ids: tagIds,
706
+ }),
707
+ listPartiesByTag: async (input) => {
708
+ const res = await invoke("crm.list_parties_by_tag", input);
709
+ return res.parties ?? [];
710
+ },
711
+ listCRMInteractions: (input) => invoke("crm.list_interactions", input ?? {}),
712
+ listProjects: async (input) => {
713
+ const res = await invoke("projects.list", input ?? {});
714
+ return res.projects ?? [];
715
+ },
716
+ projectBoard: (input) => invoke("projects.board", input ?? {}),
717
+ projectTimeline: (input) => invoke("projects.timeline", input ?? {}),
718
+ projectTask: (input) => invoke("projects.get_task", input),
719
+ myWork: (input) => invoke("projects.my_work", input ?? {}),
720
+ listEmailMessages: (input) => invoke("email.list_messages", input ?? {}),
721
+ listEmailTags: async () => {
722
+ const res = await invoke("email.list_tags", {});
723
+ return res.tags ?? [];
724
+ },
725
+ saveEmailTag: (input) => invoke("email.save_tag", input),
726
+ deleteEmailTag: (tagId) => invoke("email.delete_tag", { tag_id: tagId }),
727
+ setEmailMessageTag: (messageId, tagId) => invoke("email.set_tag", {
728
+ message_id: messageId,
729
+ tag_id: tagId || undefined,
730
+ }),
731
+ readEmailMessage: (messageId) => invoke("email.read_message", { message_id: messageId }),
732
+ markEmailMessagesRead: (input) => invoke("email.mark_read", input),
733
+ createTenant: (input) => post("/v1/tenants", input),
734
+ createApiKey: (tenantId, input) => post(`/v1/tenants/${encodeURIComponent(tenantId)}/api-keys`, input),
735
+ listApiKeys: async (tenantId) => {
736
+ const res = await request(`/v1/tenants/${encodeURIComponent(tenantId)}/api-keys`);
737
+ return res.keys ?? [];
738
+ },
739
+ revokeApiKey: (tenantId, keyId) => request(`/v1/tenants/${encodeURIComponent(tenantId)}/api-keys/${encodeURIComponent(keyId)}`, { method: "DELETE" }),
740
+ apiKeyUsage: (tenantId, keyId, opts) => request(`/v1/tenants/${encodeURIComponent(tenantId)}/api-keys/${encodeURIComponent(keyId)}/usage${opts?.days ? `?days=${opts.days}` : ""}`),
741
+ getOAuthConsent: (requestId) => request(`/oauth/consent?request_id=${encodeURIComponent(requestId)}`),
742
+ decideOAuthConsent: (input) => post("/oauth/consent", input),
743
+ listTools: async (opts) => {
744
+ const names = (opts?.names ?? []).filter(Boolean);
745
+ const query = names.length > 0 ? `?names=${encodeURIComponent(names.join(","))}` : "";
746
+ const res = await request(`/v1/tools${query}`);
747
+ return res.tools ?? [];
748
+ },
749
+ invoke,
750
+ startRun: (input) => post("/v1/runs", input),
751
+ cancelRun: (id) => post(`/v1/runs/${encodeURIComponent(id)}/cancel`),
752
+ listRuns: async () => {
753
+ const res = await request("/v1/runs");
754
+ return res.runs ?? [];
755
+ },
756
+ getRun: (id) => request(`/v1/runs/${encodeURIComponent(id)}`),
757
+ getRunTrace: (id) => request(`/v1/runs/${encodeURIComponent(id)}/trace`),
758
+ approveRun: (id, input) => post(`/v1/runs/${encodeURIComponent(id)}/approve`, input),
759
+ denyRun: (id) => post(`/v1/runs/${encodeURIComponent(id)}/deny`),
760
+ answerRun: (id, answers) => post(`/v1/runs/${encodeURIComponent(id)}/answer`, { answers }),
761
+ listRoutines: async (input) => {
762
+ const res = await invoke("routines.list", input ?? {});
763
+ return res.routines ?? [];
764
+ },
765
+ getRoutine: (id) => invoke("routines.get", { routine: id }),
766
+ saveRoutine: (input) => invoke("routines.save", input),
767
+ runRoutineNow: (id) => invoke("routines.run_now", {
768
+ routine: id,
769
+ }),
770
+ rotateRoutineKey: (id, key) => invoke("routines.rotate_key", {
771
+ routine: id,
772
+ key,
773
+ }),
774
+ deleteRoutine: (id) => invoke("routines.delete", { routine: id }),
775
+ getInbox: () => request("/v1/inbox"),
776
+ markNotificationRead: (id) => post(`/v1/inbox/notifications/${encodeURIComponent(id)}/read`),
777
+ markAllNotificationsRead: () => post("/v1/inbox/read-all"),
778
+ getNotificationPrefs: () => request("/v1/inbox/preferences"),
779
+ updateNotificationPrefs: (input) => request("/v1/inbox/preferences", {
780
+ method: "PUT",
781
+ body: JSON.stringify(input),
782
+ }),
783
+ getNotificationSettings: () => request("/v1/inbox/notification-settings"),
784
+ updateNotificationSettings: (input) => request("/v1/inbox/notification-settings", {
785
+ method: "PUT",
786
+ body: JSON.stringify(input),
787
+ }),
788
+ startPhoneVerification: () => request("/v1/me/phone/verification", {
789
+ method: "POST",
790
+ body: "{}",
791
+ }),
792
+ confirmPhoneVerification: (code) => request("/v1/me/phone/verification/confirm", {
793
+ method: "POST",
794
+ body: JSON.stringify({ code }),
795
+ }),
796
+ previewAction: (token) => request(`/v1/inbox/act?token=${encodeURIComponent(token)}`),
797
+ actOnToken: (token) => post("/v1/inbox/act", { token }),
798
+ dismissPolicySuggestion: (key) => post(`/v1/inbox/suggestions/${encodeURIComponent(key)}/dismiss`),
799
+ listPolicies: () => invoke("policies.list"),
800
+ createInvite: (input) => post("/v1/members/invites", input),
801
+ listInvites: async () => {
802
+ const res = await request("/v1/members/invites");
803
+ return res.invitations ?? [];
804
+ },
805
+ deleteInvite: (id) => request(`/v1/members/invites/${encodeURIComponent(id)}`, {
806
+ method: "DELETE",
807
+ }),
808
+ previewInvite: (token) => request(`/v1/invites/${encodeURIComponent(token)}`),
809
+ acceptInvite: (token) => post(`/v1/invites/${encodeURIComponent(token)}/accept`),
810
+ setMemberRole: (userId, role, roleId) => request(`/v1/members/${encodeURIComponent(userId)}`, {
811
+ method: "PUT",
812
+ body: JSON.stringify({ role, role_id: roleId }),
813
+ }),
814
+ removeMember: (userId) => request(`/v1/members/${encodeURIComponent(userId)}`, {
815
+ method: "DELETE",
816
+ }),
817
+ listRoles: () => invoke("roles.list"),
818
+ createRole: (input) => invoke("roles.create", input),
819
+ updateRole: (input) => invoke("roles.update", input),
820
+ deleteRole: (roleId) => invoke("roles.delete", { role_id: roleId }),
821
+ listRecurringDocuments: async () => {
822
+ const res = await invoke("recurring.list");
823
+ return res.recurring ?? [];
824
+ },
825
+ listBankTransactions: (input) => invoke("bank.transactions", input ?? {}),
826
+ importStatementText: (input) => invoke("bank.import_statement_text", input),
827
+ getParty: (partyId) => invoke("parties.get", { party_id: partyId }),
828
+ updateParty: (input) => invoke("parties.update", input),
829
+ setPartyBankDetails: (input, opts) => invoke("parties.set_bank_details", input, opts),
830
+ listBanks: async () => {
831
+ const res = await invoke("banks.list");
832
+ return res.banks ?? [];
833
+ },
834
+ listPaymentFormats: () => invoke("bank.payment_formats"),
835
+ listPaymentRuns: async (input) => {
836
+ const res = await invoke("bank.payment_runs", input ?? {});
837
+ return res.runs ?? [];
838
+ },
839
+ getPaymentRun: (runId) => invoke("bank.payment_run", { run_id: runId }),
840
+ createPaymentRun: (input, opts) => invoke("bank.create_payment_run", input, opts),
841
+ exportPaymentRun: (input, opts) => invoke("bank.export_payment_run", input, opts),
842
+ settlePaymentRun: (input, opts) => invoke("bank.settle_payment_run", input, opts),
843
+ cancelPaymentRun: (runId, opts) => invoke("bank.cancel_payment_run", { run_id: runId }, opts),
844
+ createFixedAsset: async (input) => {
845
+ const res = await invoke("assets.create", input);
846
+ return res.asset;
847
+ },
848
+ updateFixedAsset: async (input) => {
849
+ const res = await invoke("assets.update", input);
850
+ return res.asset;
851
+ },
852
+ listFixedAssets: async (input) => {
853
+ const res = await invoke("assets.list", input ?? {});
854
+ return res.assets ?? [];
855
+ },
856
+ getFixedAsset: (assetId) => invoke("assets.get", {
857
+ asset_id: assetId,
858
+ }),
859
+ getFixedAssetSchedule: (assetId) => invoke("assets.schedule", { asset_id: assetId }),
860
+ fixedAssetSummary: (asOf) => invoke("assets.summary", asOf ? { as_of: asOf } : {}),
861
+ capitalizeFixedAsset: (input, opts) => invoke("assets.capitalize", input, opts),
862
+ depreciateFixedAssets: (input, opts) => invoke("assets.depreciate", input, opts),
863
+ disposeFixedAsset: (input, opts) => invoke("assets.dispose", input, opts),
864
+ listEmployees: async (input) => {
865
+ const res = await invoke("employees.list", input ?? {});
866
+ return res.employees ?? [];
867
+ },
868
+ getEmployee: (employeeId) => invoke("employees.get", { employee_id: employeeId }),
869
+ createEmployee: (input, opts) => invoke("employees.create", input, opts),
870
+ updateEmployee: (input, opts) => invoke("employees.update", input, opts),
871
+ terminateEmployee: (input, opts) => invoke("employees.terminate", input, opts),
872
+ payrollParameters: (year) => invoke("payroll.parameters", year ? { year } : {}),
873
+ setPayrollParameters: (input, opts) => invoke("payroll.set_parameters", input, opts),
874
+ addPayrollNovelty: (input, opts) => invoke("payroll.add_novelty", input, opts),
875
+ listPayrollNovelties: async (input) => {
876
+ const res = await invoke("payroll.novelties", input ?? {});
877
+ return res.novelties ?? [];
878
+ },
879
+ deletePayrollNovelty: (noveltyId, opts) => invoke("payroll.delete_novelty", { novelty_id: noveltyId }, opts),
880
+ calculatePayroll: (input, opts) => invoke("payroll.calculate", input, opts),
881
+ payrollRun: (runId) => invoke("payroll.run", { run_id: runId }),
882
+ listPayrollRuns: async (input) => {
883
+ const res = await invoke("payroll.runs", input ?? {});
884
+ return res.runs ?? [];
885
+ },
886
+ postPayrollRun: (input, opts) => invoke("payroll.post", input, opts),
887
+ payPayroll: (input, opts) => invoke("payroll.pay", input, opts),
888
+ liquidateEmployee: (input, opts) => invoke("payroll.liquidate", input, opts),
889
+ pilaSummary: (period) => invoke("payroll.pila_summary", { period }),
890
+ listPayrollSubmissions: async (input) => {
891
+ const res = await invoke("payroll.submissions", input ?? {});
892
+ return res.submissions ?? [];
893
+ },
894
+ uploadDocument: (file, opts) => {
895
+ const form = new FormData();
896
+ if (opts?.filename)
897
+ form.append("file", file, opts.filename);
898
+ else
899
+ form.append("file", file);
900
+ if (opts?.kind)
901
+ form.append("kind", opts.kind);
902
+ if (opts?.partyId)
903
+ form.append("party_id", opts.partyId);
904
+ return request("/v1/documents", { method: "POST", body: form });
905
+ },
906
+ uploadCompanyLogo: (file, opts) => {
907
+ const form = new FormData();
908
+ if (opts?.filename)
909
+ form.append("file", file, opts.filename);
910
+ else
911
+ form.append("file", file);
912
+ return request("/v1/company/logo", { method: "POST", body: form });
913
+ },
914
+ getCompanyLogo: () => request("/v1/company/logo"),
915
+ clearCompanyLogo: () => request("/v1/company/logo", { method: "DELETE" }),
916
+ lookupCompanyDirectory: (input) => invoke("parties.lookup_directory", input),
917
+ findPartyMatches: (input) => invoke("parties.find_matches", input),
918
+ listDocuments: async () => {
919
+ const res = await request("/v1/documents");
920
+ return res.documents ?? [];
921
+ },
922
+ getDocument: (id) => request(`/v1/documents/${encodeURIComponent(id)}`),
923
+ listLiveDocuments: async (filter = {}) => {
924
+ const res = await invoke("knowledge.list_docs", { ...filter });
925
+ return res.docs ?? [];
926
+ },
927
+ createLiveDocument: (title, kind = "doc", place = {}) => invoke("knowledge.create_doc", { title, kind, ...place }),
928
+ moveLiveDocument: (id, place) => invoke("knowledge.move_doc", { live_document_id: id, ...place }),
929
+ listLiveDocumentShares: (id) => invoke("knowledge.list_doc_shares", { live_document_id: id }),
930
+ shareLiveDocument: (id, userId) => invoke("knowledge.share_doc", {
931
+ live_document_id: id,
932
+ user_id: userId,
933
+ }),
934
+ unshareLiveDocument: (id, userId) => invoke("knowledge.unshare_doc", {
935
+ live_document_id: id,
936
+ user_id: userId,
937
+ }),
938
+ listLiveDocumentFolders: async (space) => {
939
+ const res = await invoke("knowledge.list_doc_folders", {
940
+ space,
941
+ });
942
+ return res.folders ?? [];
943
+ },
944
+ createLiveDocumentFolder: (name, space, parentId) => invoke("knowledge.create_doc_folder", parentId ? { name, space, parent_id: parentId } : { name, space }),
945
+ renameLiveDocumentFolder: (id, name) => invoke("knowledge.rename_doc_folder", { folder_id: id, name }),
946
+ deleteLiveDocumentFolder: (id) => invoke("knowledge.delete_doc_folder", { folder_id: id }),
947
+ listLiveDocumentTags: async () => {
948
+ const res = await invoke("knowledge.list_doc_tags", {});
949
+ return res.tags ?? [];
950
+ },
951
+ tagLiveDocument: (id, tag) => invoke("knowledge.tag_doc", { live_document_id: id, tag }),
952
+ untagLiveDocument: (id, tag) => invoke("knowledge.untag_doc", { live_document_id: id, tag }),
953
+ readLiveDocument: (id) => invoke("knowledge.read_doc", {
954
+ live_document_id: id,
955
+ }),
956
+ openLiveDocument: (id) => request(`/v1/live-documents/${encodeURIComponent(id)}`),
957
+ pushLiveDocumentUpdate: (id, update) => request(`/v1/live-documents/${encodeURIComponent(id)}/updates`, {
958
+ method: "POST",
959
+ body: JSON.stringify({ update }),
960
+ }),
961
+ downloadDocument: async (id) => {
962
+ const response = await fetchFn(`${baseUrl}/v1/documents/${encodeURIComponent(id)}/content`, {
963
+ headers: buildHeaders(undefined, false),
964
+ });
965
+ if (!response.ok)
966
+ return streamError(response);
967
+ return response;
968
+ },
969
+ listActions: (opts) => {
970
+ const params = new URLSearchParams();
971
+ if (opts?.before !== undefined)
972
+ params.set("before", String(opts.before));
973
+ else if (opts?.after !== undefined)
974
+ params.set("after", String(opts.after));
975
+ if (opts?.limit !== undefined)
976
+ params.set("limit", String(opts.limit));
977
+ if (opts?.actor_id)
978
+ params.set("actor_id", opts.actor_id);
979
+ const qs = params.toString();
980
+ return request(`/v1/actions${qs ? `?${qs}` : ""}`);
981
+ },
982
+ streamEvents,
983
+ openRealtimeSocket,
984
+ sendTyping,
985
+ sendViewing,
986
+ ping: () => invoke("system.ping"),
987
+ sendEmail: (input, opts) => invoke("email.send", input, opts),
988
+ searchKnowledge: (input) => invoke("knowledge.search", input),
989
+ createBillDraft: (input) => invoke("bills.create_draft", input),
990
+ updateBillDraft: (input) => invoke("bills.update_draft", input),
991
+ deleteBillDraft: (billId) => invoke("bills.delete_draft", { bill_id: billId }),
992
+ postBill: (billId, opts) => {
993
+ const { tags, ...invokeOpts } = opts ?? {};
994
+ return invoke("bills.post", { bill_id: billId, tags }, invokeOpts);
995
+ },
996
+ listBills: async (input) => {
997
+ const res = await invoke("bills.list", input ?? {});
998
+ return res.bills ?? [];
999
+ },
1000
+ getBill: (billId) => invoke("bills.get", { bill_id: billId }),
1001
+ createBillCreditNote: (input) => invoke("bills.create_credit_note", input),
1002
+ createBillDebitNote: (input) => invoke("bills.create_debit_note", input),
1003
+ createItem: (input) => invoke("items.create", input),
1004
+ updateItem: (input) => invoke("items.update", input),
1005
+ listItems: async (input) => {
1006
+ const res = await invoke("items.list", input ?? {});
1007
+ return res.items ?? [];
1008
+ },
1009
+ getItem: (input) => invoke("items.get", input),
1010
+ createWarehouse: async (input) => {
1011
+ const res = await invoke("warehouses.create", input);
1012
+ return res.warehouse;
1013
+ },
1014
+ updateWarehouse: async (input) => {
1015
+ const res = await invoke("warehouses.update", input);
1016
+ return res.warehouse;
1017
+ },
1018
+ listWarehouses: async (input) => {
1019
+ const res = await invoke("warehouses.list", input ?? {});
1020
+ return res.warehouses ?? [];
1021
+ },
1022
+ stockLevels: (input) => invoke("inventory.levels", input ?? {}),
1023
+ stockMovements: (input) => invoke("inventory.movements", input ?? {}),
1024
+ inventoryValuation: (input) => invoke("inventory.valuation", input ?? {}),
1025
+ reorderSuggestions: async (input) => {
1026
+ const res = await invoke("inventory.reorder_suggestions", input ?? {});
1027
+ return res.suggestions ?? [];
1028
+ },
1029
+ adjustStock: (input, opts) => invoke("inventory.adjust", input, opts),
1030
+ transferStock: (input, opts) => invoke("inventory.transfer", input, opts),
1031
+ inventoryOpeningBalance: (input, opts) => invoke("inventory.opening_balance", input, opts),
1032
+ startInventoryCount: (input) => invoke("inventory.count_start", input ?? {}),
1033
+ recordInventoryCount: (input) => invoke("inventory.count_record", input),
1034
+ postInventoryCount: (input, opts) => invoke("inventory.count_post", input, opts),
1035
+ listInventoryCounts: async (input) => {
1036
+ const res = await invoke("inventory.count_list", input ?? {});
1037
+ return res.counts ?? [];
1038
+ },
1039
+ getInventoryCount: (countId) => invoke("inventory.count_get", { count_id: countId }),
1040
+ inventorySettings: () => invoke("inventory.settings"),
1041
+ configureInventory: (input) => invoke("inventory.configure", input),
1042
+ createParty: (input) => invoke("parties.create", input),
1043
+ listParties: async () => {
1044
+ const res = await invoke("parties.list");
1045
+ return res.parties ?? [];
1046
+ },
1047
+ listAccounts: async () => {
1048
+ const res = await invoke("ledger.accounts");
1049
+ return res.accounts ?? [];
1050
+ },
1051
+ postEntry: (input, opts) => invoke("ledger.post_entry", input, opts),
1052
+ reverseEntry: (input, opts) => invoke("ledger.reverse_entry", input, opts),
1053
+ trialBalance: () => invoke("ledger.trial_balance"),
1054
+ balanceSheet: (input) => invoke("ledger.balance_sheet", input ?? {}),
1055
+ incomeStatement: (input) => invoke("ledger.income_statement", input ?? {}),
1056
+ accountStatement: (input) => invoke("ledger.account_statement", input),
1057
+ arAging: (input) => invoke("ar.aging", input ?? {}),
1058
+ apAging: (input) => invoke("ap.aging", input ?? {}),
1059
+ partyStatement: (input) => invoke("parties.statement", input),
1060
+ listPeriods: (input) => invoke("periods.list", input ?? {}),
1061
+ closePeriod: (input, opts) => invoke("periods.close", input, opts),
1062
+ reopenPeriod: (input, opts) => invoke("periods.reopen", input, opts),
1063
+ listEntries: async () => {
1064
+ const res = await invoke("ledger.entries");
1065
+ return res.entries ?? [];
1066
+ },
1067
+ getEntry: (entryId) => invoke("ledger.entry", { entry_id: entryId }),
1068
+ taxProfile: (input) => invoke("tax.profile", input ?? {}),
1069
+ setTaxProfile: (input, opts) => invoke("tax.set_profile", input, opts),
1070
+ partyTaxProfile: (partyId) => invoke("tax.party_profile", { party_id: partyId }),
1071
+ listPartyTaxProfiles: async () => {
1072
+ const res = await invoke("tax.party_profile", {});
1073
+ return res.profiles ?? [];
1074
+ },
1075
+ setPartyTaxProfile: (input, opts) => invoke("tax.set_party_profile", input, opts),
1076
+ suggestWithholding: (input) => invoke("tax.withholding_suggest", input),
1077
+ ivaReport: (input) => invoke("tax.iva_report", input ?? {}),
1078
+ withholdingReport: (input) => invoke("tax.withholding_report", input ?? {}),
1079
+ withholdingCertificates: (input) => invoke("tax.withholding_certificates", input ?? {}),
1080
+ icaReport: (input) => invoke("tax.ica_report", input ?? {}),
1081
+ exogena: (input) => invoke("tax.exogena", input),
1082
+ taxCalendar: (input) => invoke("tax.calendar", input ?? {}),
1083
+ agenda: (input) => invoke("calendar.agenda", input ?? {}),
1084
+ listCalendarEvents: (input) => invoke("calendar.list", input ?? {}),
1085
+ createCalendarEvent: (input) => invoke("calendar.create", input),
1086
+ updateCalendarEvent: (input) => invoke("calendar.update", input),
1087
+ completeCalendarEvent: (input) => invoke("calendar.complete", input),
1088
+ deleteCalendarEvent: (input) => invoke("calendar.delete", input),
1089
+ createTagDimension: (input) => invoke("tags.create_dimension", input),
1090
+ createTag: (input) => invoke("tags.create", input),
1091
+ setTagActive: (input) => invoke("tags.set_active", input),
1092
+ listTags: async (input) => {
1093
+ const res = await invoke("tags.list", input);
1094
+ return res.dimensions ?? [];
1095
+ },
1096
+ profitability: (input) => invoke("ledger.profitability", input),
1097
+ createNumberingRange: (input) => invoke("numbering.create_range", input),
1098
+ listNumberingRanges: async () => {
1099
+ const res = await invoke("numbering.list_ranges");
1100
+ return res.ranges ?? [];
1101
+ },
1102
+ createInvoiceDraft: (input) => invoke("invoices.create_draft", input),
1103
+ updateInvoiceDraft: (input) => invoke("invoices.update_draft", input),
1104
+ deleteInvoiceDraft: (invoiceId) => invoke("invoices.delete_draft", { invoice_id: invoiceId }),
1105
+ postInvoice: (invoiceId, opts) => {
1106
+ const { tags, ...invokeOpts } = opts ?? {};
1107
+ return invoke("invoices.post", { invoice_id: invoiceId, tags }, invokeOpts);
1108
+ },
1109
+ listInvoices: async (input) => {
1110
+ const res = await invoke("invoices.list", input ?? {});
1111
+ return res.invoices ?? [];
1112
+ },
1113
+ getInvoice: (invoiceId) => invoke("invoices.get", { invoice_id: invoiceId }),
1114
+ createInvoiceCreditNote: (input) => invoke("invoices.create_credit_note", input),
1115
+ createInvoiceDebitNote: (input) => invoke("invoices.create_debit_note", input),
1116
+ recordClearance: (input) => invoke("einvoice.record_clearance", input),
1117
+ recordPayment: (input, opts) => invoke("payments.record", input, opts),
1118
+ setFxRate: (input) => invoke("fx.set_rate", input),
1119
+ fxRates: (input) => invoke("fx.rates", input ?? {}),
1120
+ fxConvert: (input) => invoke("fx.convert", input),
1121
+ overviewChat: (input) => post("/v1/overview/chat", input),
1122
+ overviewChatStream,
1123
+ overviewSuggestions: () => request("/v1/overview/suggestions"),
1124
+ voiceSession: () => post("/v1/voice/session", {}),
1125
+ listConversations: async () => {
1126
+ const res = await request("/v1/overview/conversations");
1127
+ return res.conversations ?? [];
1128
+ },
1129
+ getConversation: async (id) => {
1130
+ const res = await request(`/v1/overview/conversations/${encodeURIComponent(id)}`);
1131
+ return res.conversation;
1132
+ },
1133
+ saveConversation: async (input) => {
1134
+ const res = await post("/v1/overview/conversations", input);
1135
+ return res.conversation;
1136
+ },
1137
+ deleteConversation: async (id) => {
1138
+ await request(`/v1/overview/conversations/${encodeURIComponent(id)}`, { method: "DELETE" });
1139
+ },
1140
+ overviewThread: async () => {
1141
+ const res = await request("/v1/overview/thread");
1142
+ return res.thread ?? [];
1143
+ },
1144
+ mirrorOverviewThread: (turns) => post("/v1/overview/thread", { turns }),
1145
+ decideChatApproval: (id, approve) => post(`/v1/overview/approvals/${encodeURIComponent(id)}/decide`, { approve }),
1146
+ listDashboards: async () => {
1147
+ const res = await request("/v1/dashboards");
1148
+ return res.dashboards ?? [];
1149
+ },
1150
+ getDashboard: async (slug, range) => {
1151
+ const query = range ? `?${new URLSearchParams({ from: range.from, to: range.to })}` : "";
1152
+ const res = await request(`/v1/dashboards/${encodeURIComponent(slug)}${query}`);
1153
+ return res.dashboard;
1154
+ },
1155
+ saveDashboard: (input, opts) => invoke("dashboards.save", input, opts),
1156
+ appendDashboard: (slug, blocks, opts) => invoke("dashboards.append", { slug, blocks }, opts),
1157
+ deleteDashboard: (slug, opts) => invoke("dashboards.delete", { slug }, opts),
1158
+ listMembers: async (opts) => {
1159
+ const params = new URLSearchParams();
1160
+ const q = opts?.q?.trim();
1161
+ if (q)
1162
+ params.set("q", q);
1163
+ if (opts?.limit != null)
1164
+ params.set("limit", String(opts.limit));
1165
+ const qs = params.toString();
1166
+ const res = await request(`/v1/members${qs ? `?${qs}` : ""}`);
1167
+ return res.members ?? [];
1168
+ },
1169
+ listDashboardShares: async (slug) => {
1170
+ const res = await request(`/v1/dashboards/${encodeURIComponent(slug)}/shares`);
1171
+ return res.shares ?? [];
1172
+ },
1173
+ shareDashboard: async (slug, userId) => {
1174
+ await post(`/v1/dashboards/${encodeURIComponent(slug)}/shares`, { user_id: userId });
1175
+ },
1176
+ unshareDashboard: async (slug, userId) => {
1177
+ await request(`/v1/dashboards/${encodeURIComponent(slug)}/shares/${encodeURIComponent(userId)}`, { method: "DELETE" });
1178
+ },
1179
+ publishDashboardSnapshot: async (slug, range) => {
1180
+ const res = await post(`/v1/dashboards/${encodeURIComponent(slug)}/snapshots`, range ?? {});
1181
+ return res.snapshot;
1182
+ },
1183
+ listDashboardSnapshots: async (slug) => {
1184
+ const res = await request(`/v1/dashboards/${encodeURIComponent(slug)}/snapshots`);
1185
+ return res.snapshots ?? [];
1186
+ },
1187
+ revokeDashboardSnapshot: async (slug, snapshotId) => {
1188
+ await request(`/v1/dashboards/${encodeURIComponent(slug)}/snapshots/${encodeURIComponent(snapshotId)}`, { method: "DELETE" });
1189
+ },
1190
+ getPublicSnapshot: async (token) => {
1191
+ const res = await request(`/v1/public/snapshots/${encodeURIComponent(token)}`);
1192
+ return res.snapshot;
1193
+ },
1194
+ startCall: (input, opts) => invoke("calls.start", input, opts),
1195
+ scheduleCall: (input, opts) => invoke("calls.schedule", input, opts),
1196
+ renameCall: (input, opts) => invoke("calls.rename", input, opts),
1197
+ storageUsage: () => invoke("usage.storage"),
1198
+ listCallRecordings: (callId) => invoke("calls.recordings", { call_id: callId }),
1199
+ downloadCallRecording: async (recordingId, range) => {
1200
+ const response = await fetchFn(`${baseUrl}/v1/call-recordings/${encodeURIComponent(recordingId)}`, {
1201
+ headers: buildHeaders(range ? { headers: { Range: range } } : undefined, false),
1202
+ });
1203
+ if (!response.ok && response.status !== 416)
1204
+ return streamError(response);
1205
+ return response;
1206
+ },
1207
+ listCalls: async () => {
1208
+ const res = await invoke("calls.list");
1209
+ return res.calls ?? [];
1210
+ },
1211
+ getCall: async (callId) => (await invoke("calls.get", { call_id: callId })).call,
1212
+ joinCall: (callId, opts) => invoke("calls.join", { call_id: callId }, opts),
1213
+ listCallParticipants: async (callId) => (await invoke("calls.list_participants", {
1214
+ call_id: callId,
1215
+ })).participants ?? [],
1216
+ inviteToCall: (input, opts) => invoke("calls.invite", input, opts),
1217
+ setCallPresenters: (input, opts) => invoke("calls.set_presenters", input, opts),
1218
+ endCall: (callId, opts) => invoke("calls.end", { call_id: callId }, opts),
1219
+ summarizeCall: (callId, opts) => invoke("calls.summarize", { call_id: callId }, opts),
1220
+ createCallTasks: (input, opts) => invoke("calls.create_tasks", input, opts),
1221
+ dismissCallActionItem: (input, opts) => invoke("calls.dismiss_action_item", input, opts),
1222
+ listBookingTypes: (input) => invoke("bookings.list_types", input ?? {}),
1223
+ createBookingType: (input, opts) => invoke("bookings.create_type", input, opts),
1224
+ updateBookingType: (input, opts) => invoke("bookings.update_type", input, opts),
1225
+ setBookingRanges: (input, opts) => invoke("bookings.set_ranges", input, opts),
1226
+ clearBookingRanges: (input, opts) => invoke("bookings.clear_ranges", input, opts),
1227
+ bookingSlots: (input) => invoke("bookings.slots", input),
1228
+ book: (input, opts) => invoke("bookings.book", input, opts),
1229
+ listBookings: (input) => invoke("bookings.list", input ?? {}),
1230
+ cancelBooking: (input, opts) => invoke("bookings.cancel", input, opts),
1231
+ getPublicBookingType: async (slug) => (await request(`/v1/public/bookings/${encodeURIComponent(slug)}`)).booking_type,
1232
+ getPublicBookingSlots: (slug, window) => request(`/v1/public/bookings/${encodeURIComponent(slug)}/slots${bookingWindow(window)}`),
1233
+ takePublicBookingSlot: (slug, input) => post(`/v1/public/bookings/${encodeURIComponent(slug)}`, input),
1234
+ getManagedBooking: (token) => request(`/v1/public/bookings/manage/${encodeURIComponent(token)}`),
1235
+ cancelManagedBooking: (token, reason) => post(`/v1/public/bookings/manage/${encodeURIComponent(token)}/cancel`, {
1236
+ reason: reason ?? "",
1237
+ }),
1238
+ getPublicCall: async (token) => (await request(`/v1/public/calls/${encodeURIComponent(token)}`)).call,
1239
+ getPublicCallCenterQueue: async (key) => (await request(`/v1/public/callcenter/${encodeURIComponent(key)}`)).queue,
1240
+ ringPublicCallCenter: async (key, input) => (await post(`/v1/public/callcenter/${encodeURIComponent(key)}/calls`, input)).call,
1241
+ getPublicCallCenterCall: async (key, callId, callerKey) => (await request(`/v1/public/callcenter/${encodeURIComponent(key)}/calls/${encodeURIComponent(callId)}?key=${encodeURIComponent(callerKey)}`)).call,
1242
+ hangUpPublicCallCenterCall: async (key, callId, callerKey) => (await post(`/v1/public/callcenter/${encodeURIComponent(key)}/calls/${encodeURIComponent(callId)}/hang-up`, { key: callerKey })).call,
1243
+ joinPublicCall: (token, name) => post(`/v1/public/calls/${encodeURIComponent(token)}/join`, { name }),
1244
+ getPublicCallParticipant: async (token, participantId, secret) => (await request(`/v1/public/calls/${encodeURIComponent(token)}/participants/${encodeURIComponent(participantId)}?secret=${encodeURIComponent(secret)}`)).participant,
1245
+ touchPublicCallParticipant: async (token, participantId, secret) => (await post(`/v1/public/calls/${encodeURIComponent(token)}/participants/${encodeURIComponent(participantId)}/presence`, { secret })).participant,
1246
+ leavePublicCallParticipant: async (token, participantId, secret) => {
1247
+ await post(`/v1/public/calls/${encodeURIComponent(token)}/participants/${encodeURIComponent(participantId)}/leave`, { secret });
1248
+ },
1249
+ postCallMessage: (input, opts) => invoke("calls.post_message", input, opts),
1250
+ listCallMessages: async (callId, after) => {
1251
+ const input = { call_id: callId };
1252
+ if (after)
1253
+ input.after = after;
1254
+ const res = await invoke("calls.list_messages", input);
1255
+ return res.messages ?? [];
1256
+ },
1257
+ recordCallTranscript: (input, opts) => invoke("calls.record_transcript", input, opts),
1258
+ listCallTranscript: async (callId, after) => {
1259
+ const input = { call_id: callId };
1260
+ if (after)
1261
+ input.after = after;
1262
+ const res = await invoke("calls.list_transcript", input);
1263
+ return res.segments ?? [];
1264
+ },
1265
+ listPublicCallMessages: async (token, participantId, secret, after) => (await request(`${publicCallSeatPath(token, participantId)}/messages?secret=${encodeURIComponent(secret)}${after ? `&after=${encodeURIComponent(after)}` : ""}`)).messages ?? [],
1266
+ postPublicCallMessage: (token, participantId, secret, body) => post(`${publicCallSeatPath(token, participantId)}/messages`, {
1267
+ secret,
1268
+ body,
1269
+ }),
1270
+ listPublicCallTranscript: async (token, participantId, secret, after) => (await request(`${publicCallSeatPath(token, participantId)}/transcript?secret=${encodeURIComponent(secret)}${after ? `&after=${encodeURIComponent(after)}` : ""}`)).segments ?? [],
1271
+ recordPublicCallTranscript: (token, participantId, secret, segments) => post(`${publicCallSeatPath(token, participantId)}/transcript`, {
1272
+ secret,
1273
+ segments,
1274
+ }),
1275
+ queryRecords: (input) => invoke("records.query", input),
1276
+ queryMetric: (input) => invoke("metrics.query", input),
1277
+ queryResult: (tool, values) => invoke("dashboards.result", { tool, values }),
1278
+ queryMetricsBatch: (queries) => invoke("metrics.batch", { queries }),
1279
+ queryAnalytics: (input) => invoke("analytics.query", input),
1280
+ analyticsCatalog: () => invoke("analytics.catalog"),
1281
+ createConnection: (input, opts) => invoke("connections.create", input, opts),
1282
+ createEinvoiceConnection: (input, opts) => invoke("connections.create", { provider: "factus", ...input }, opts),
1283
+ listConnections: async () => {
1284
+ const res = await invoke("connections.list");
1285
+ return res.connections ?? [];
1286
+ },
1287
+ deleteConnection: (connectionId, opts) => invoke("connections.delete", { connection_id: connectionId }, opts),
1288
+ listEinvoiceSubmissions: async (input) => {
1289
+ const res = await invoke("einvoice.submissions", input ?? {});
1290
+ return { submissions: res.submissions ?? [], counts: res.counts ?? {} };
1291
+ },
1292
+ retryEinvoice: (input, opts) => invoke("einvoice.retry", input, opts),
1293
+ einvoiceStatus: (input) => invoke("einvoice.status", input),
1294
+ einvoiceDownload: (input) => invoke("einvoice.download", input),
1295
+ syncEinvoiceNumberingRanges: (opts) => invoke("einvoice.sync_numbering_ranges", {}, opts),
1296
+ setBillSupportDocument: (input, opts) => invoke("bills.set_support_document", input, opts),
1297
+ featureUsage: async (input) => {
1298
+ const res = await invoke("usage.features", input ?? {});
1299
+ return {
1300
+ window_days: res.window_days ?? 30,
1301
+ totals: res.totals ?? {},
1302
+ surfaces: res.surfaces ?? [],
1303
+ features: res.features ?? [],
1304
+ };
1305
+ },
1306
+ llmUsage: async () => {
1307
+ const res = await invoke("usage.llm");
1308
+ return {
1309
+ usage: res.usage ?? [],
1310
+ by_user: res.by_user ?? [],
1311
+ currency: res.currency ?? "USD",
1312
+ };
1313
+ },
1314
+ listQuotes: async (input) => {
1315
+ const res = await invoke("quotes.list", input ?? {});
1316
+ return res.quotes ?? [];
1317
+ },
1318
+ getQuote: (quoteId) => invoke("quotes.get", { quote_id: quoteId }),
1319
+ createQuote: (input, opts) => invoke("quotes.create", input, opts),
1320
+ updateQuote: (input, opts) => invoke("quotes.update", input, opts),
1321
+ sendQuote: (quoteId, opts) => invoke("quotes.send", { quote_id: quoteId }, opts),
1322
+ acceptQuote: (input, opts) => invoke("quotes.accept", input, opts),
1323
+ rejectQuote: (input, opts) => invoke("quotes.reject", input, opts),
1324
+ convertQuote: (input, opts) => invoke("quotes.convert", input, opts),
1325
+ listSalesOrders: async (input) => {
1326
+ const res = await invoke("sales_orders.list", input ?? {});
1327
+ return res.sales_orders ?? [];
1328
+ },
1329
+ getSalesOrder: (salesOrderId) => invoke("sales_orders.get", { sales_order_id: salesOrderId }),
1330
+ createSalesOrder: (input, opts) => invoke("sales_orders.create", input, opts),
1331
+ updateSalesOrder: (input, opts) => invoke("sales_orders.update", input, opts),
1332
+ confirmSalesOrder: (salesOrderId, opts) => invoke("sales_orders.confirm", { sales_order_id: salesOrderId }, opts),
1333
+ cancelSalesOrder: (salesOrderId, opts) => invoke("sales_orders.cancel", { sales_order_id: salesOrderId }, opts),
1334
+ invoiceSalesOrder: (input, opts) => invoke("sales_orders.invoice", input, opts),
1335
+ listPurchaseOrders: async (input) => {
1336
+ const res = await invoke("purchase_orders.list", input ?? {});
1337
+ return res.purchase_orders ?? [];
1338
+ },
1339
+ getPurchaseOrder: (purchaseOrderId) => invoke("purchase_orders.get", { purchase_order_id: purchaseOrderId }),
1340
+ createPurchaseOrder: (input, opts) => invoke("purchase_orders.create", input, opts),
1341
+ updatePurchaseOrder: (input, opts) => invoke("purchase_orders.update", input, opts),
1342
+ sendPurchaseOrder: (purchaseOrderId, opts) => invoke("purchase_orders.send", { purchase_order_id: purchaseOrderId }, opts),
1343
+ confirmPurchaseOrder: (purchaseOrderId, opts) => invoke("purchase_orders.confirm", { purchase_order_id: purchaseOrderId }, opts),
1344
+ cancelPurchaseOrder: (purchaseOrderId, opts) => invoke("purchase_orders.cancel", { purchase_order_id: purchaseOrderId }, opts),
1345
+ receivePurchaseOrder: (input, opts) => invoke("purchase_orders.receive", input, opts),
1346
+ billPurchaseOrder: (input, opts) => invoke("purchase_orders.bill", input, opts),
1347
+ matchPurchaseOrder: (input) => invoke("purchase_orders.match", input),
1348
+ };
12
1349
  }
13
- export { NemphiClient } from "./client";
14
- export { NemphiApiError } from "./errors";
15
- export { CrmResource } from "./resources/crm";
16
- export { OrganizationResource } from "./resources/organization";
17
- export { UsageResource } from "./resources/usage";
1350
+ //# sourceMappingURL=index.js.map