@verentis/sdk 0.2.6 → 1.0.1
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/README.md +42 -9
- package/dist/index.cjs +527 -145
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +591 -124
- package/dist/index.d.ts +591 -124
- package/dist/index.js +521 -145
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -259,6 +259,7 @@ var ContextModule = class {
|
|
|
259
259
|
};
|
|
260
260
|
|
|
261
261
|
// src/modules/executions.ts
|
|
262
|
+
var SCRIPT_ARGUMENTS_SCHEMA = "verentis.io/script-arguments/v1";
|
|
262
263
|
var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
263
264
|
"Completed",
|
|
264
265
|
"Failed",
|
|
@@ -289,7 +290,8 @@ var ExecutionsModule = class {
|
|
|
289
290
|
tool: options?.tool,
|
|
290
291
|
mode: options?.mode,
|
|
291
292
|
arguments: options?.arguments ?? [],
|
|
292
|
-
parameters: serializeParameters(options?.parameters)
|
|
293
|
+
parameters: serializeParameters(options?.parameters),
|
|
294
|
+
...options?.invocationKey ? { invocationKey: options.invocationKey } : {}
|
|
293
295
|
}),
|
|
294
296
|
headers: { "Content-Type": "application/json" }
|
|
295
297
|
});
|
|
@@ -314,10 +316,30 @@ var ExecutionsModule = class {
|
|
|
314
316
|
headers: { "Content-Type": "application/json" }
|
|
315
317
|
});
|
|
316
318
|
}
|
|
319
|
+
/**
|
|
320
|
+
* Read the arguments a script declares (its exported `<script>.arguments.json`), e.g. to build a form
|
|
321
|
+
* before {@link run}. Returns `null` for scripts that declare none. Reading never runs the script.
|
|
322
|
+
*/
|
|
323
|
+
async getArguments(filePath, options) {
|
|
324
|
+
const path = `${filePath}.arguments.json`.replace(/\/+/g, "/").replace(/^\//, "");
|
|
325
|
+
const response = await this.http.requestRaw("GET", `/files/raw/${path}`, {
|
|
326
|
+
params: { branch: options?.branch ?? "main" },
|
|
327
|
+
headers: { ...this.workspaceId ? { "X-Workspace-Id": this.workspaceId } : {}, Accept: "application/json" }
|
|
328
|
+
});
|
|
329
|
+
if (response.status === 404) return null;
|
|
330
|
+
if (!response.ok) {
|
|
331
|
+
throw new Error(`Failed to read script arguments: ${response.status} ${response.statusText}`);
|
|
332
|
+
}
|
|
333
|
+
const descriptor = await response.json();
|
|
334
|
+
if (descriptor?.schema !== SCRIPT_ARGUMENTS_SCHEMA || !Array.isArray(descriptor.arguments)) {
|
|
335
|
+
throw new Error(`Unsupported script argument descriptor for ${filePath}`);
|
|
336
|
+
}
|
|
337
|
+
return descriptor;
|
|
338
|
+
}
|
|
317
339
|
/** Get an execution by id. */
|
|
318
|
-
async get(
|
|
340
|
+
async get(id2, options) {
|
|
319
341
|
const workspaceId = this.requireWorkspaceId(options?.workspaceId);
|
|
320
|
-
return this.http.request("GET", `/executions/${encodeURIComponent(
|
|
342
|
+
return this.http.request("GET", `/executions/${encodeURIComponent(id2)}`, {
|
|
321
343
|
params: { workspaceId }
|
|
322
344
|
});
|
|
323
345
|
}
|
|
@@ -342,17 +364,17 @@ var ExecutionsModule = class {
|
|
|
342
364
|
});
|
|
343
365
|
}
|
|
344
366
|
/** Get the captured stdout/stderr of an execution. */
|
|
345
|
-
async logs(
|
|
367
|
+
async logs(id2, options) {
|
|
346
368
|
const workspaceId = this.requireWorkspaceId(options?.workspaceId);
|
|
347
|
-
return this.http.request("GET", `/executions/${encodeURIComponent(
|
|
369
|
+
return this.http.request("GET", `/executions/${encodeURIComponent(id2)}/logs`, {
|
|
348
370
|
params: { workspaceId }
|
|
349
371
|
});
|
|
350
372
|
}
|
|
351
373
|
/** Cancel a pending or running execution. */
|
|
352
|
-
async cancel(
|
|
374
|
+
async cancel(id2, options) {
|
|
353
375
|
const workspaceId = this.requireWorkspaceId(options?.workspaceId);
|
|
354
|
-
return this.http.request("POST", `/executions/${encodeURIComponent(
|
|
355
|
-
body: JSON.stringify({ id, workspaceId }),
|
|
376
|
+
return this.http.request("POST", `/executions/${encodeURIComponent(id2)}/cancel`, {
|
|
377
|
+
body: JSON.stringify({ id: id2, workspaceId }),
|
|
356
378
|
headers: { "Content-Type": "application/json" }
|
|
357
379
|
});
|
|
358
380
|
}
|
|
@@ -360,16 +382,16 @@ var ExecutionsModule = class {
|
|
|
360
382
|
* Poll an execution until it reaches a terminal status. Returns immediately if it is already
|
|
361
383
|
* terminal. Throws if `timeoutMs` elapses or the supplied signal aborts.
|
|
362
384
|
*/
|
|
363
|
-
async wait(
|
|
385
|
+
async wait(id2, options) {
|
|
364
386
|
const interval = options?.intervalMs ?? 1e3;
|
|
365
387
|
const deadline = options?.timeoutMs ? Date.now() + options.timeoutMs : void 0;
|
|
366
388
|
for (; ; ) {
|
|
367
|
-
const execution = await this.get(
|
|
389
|
+
const execution = await this.get(id2, { workspaceId: options?.workspaceId });
|
|
368
390
|
if (isTerminalStatus(execution.status)) {
|
|
369
391
|
return execution;
|
|
370
392
|
}
|
|
371
393
|
if (deadline !== void 0 && Date.now() >= deadline) {
|
|
372
|
-
throw new Error(`Timed out waiting for execution '${
|
|
394
|
+
throw new Error(`Timed out waiting for execution '${id2}' to complete`);
|
|
373
395
|
}
|
|
374
396
|
await delay(interval, options?.signal);
|
|
375
397
|
}
|
|
@@ -386,11 +408,11 @@ var ExecutionsModule = class {
|
|
|
386
408
|
return this.wait(execution.id, options);
|
|
387
409
|
}
|
|
388
410
|
requireWorkspaceId(override) {
|
|
389
|
-
const
|
|
390
|
-
if (!
|
|
411
|
+
const id2 = override ?? this.workspaceId;
|
|
412
|
+
if (!id2) {
|
|
391
413
|
throw new Error("workspaceId is required: provide it in options or when creating the client");
|
|
392
414
|
}
|
|
393
|
-
return
|
|
415
|
+
return id2;
|
|
394
416
|
}
|
|
395
417
|
};
|
|
396
418
|
function serializeParameters(parameters) {
|
|
@@ -431,8 +453,8 @@ var EnginesModule = class {
|
|
|
431
453
|
}
|
|
432
454
|
});
|
|
433
455
|
}
|
|
434
|
-
async get(
|
|
435
|
-
return this.http.request("GET", `/engines/${encodeURIComponent(
|
|
456
|
+
async get(id2, options) {
|
|
457
|
+
return this.http.request("GET", `/engines/${encodeURIComponent(id2)}`, {
|
|
436
458
|
params: { workspaceId: this.requireWorkspaceId(options?.workspaceId) }
|
|
437
459
|
});
|
|
438
460
|
}
|
|
@@ -653,11 +675,11 @@ var FilesModule = class {
|
|
|
653
675
|
});
|
|
654
676
|
}
|
|
655
677
|
workspaceHeaders() {
|
|
656
|
-
const
|
|
678
|
+
const headers2 = {};
|
|
657
679
|
if (this.workspaceId) {
|
|
658
|
-
|
|
680
|
+
headers2["X-Workspace-Id"] = this.workspaceId;
|
|
659
681
|
}
|
|
660
|
-
return
|
|
682
|
+
return headers2;
|
|
661
683
|
}
|
|
662
684
|
};
|
|
663
685
|
function requireNonBlank(value, name) {
|
|
@@ -749,14 +771,14 @@ var InstallationsModule = class {
|
|
|
749
771
|
}
|
|
750
772
|
});
|
|
751
773
|
}
|
|
752
|
-
async update(
|
|
774
|
+
async update(id2, options) {
|
|
753
775
|
const workspaceId = this.requireWorkspaceId(options?.workspaceId);
|
|
754
776
|
return this.http.request(
|
|
755
777
|
"PUT",
|
|
756
|
-
`/installations/${encodeURIComponent(
|
|
778
|
+
`/installations/${encodeURIComponent(id2)}`,
|
|
757
779
|
{
|
|
758
780
|
body: JSON.stringify({
|
|
759
|
-
id,
|
|
781
|
+
id: id2,
|
|
760
782
|
workspaceId,
|
|
761
783
|
packageVersion: options?.packageVersion,
|
|
762
784
|
installMode: options?.installMode
|
|
@@ -765,8 +787,8 @@ var InstallationsModule = class {
|
|
|
765
787
|
}
|
|
766
788
|
);
|
|
767
789
|
}
|
|
768
|
-
async uninstall(
|
|
769
|
-
await this.http.request("DELETE", `/installations/${encodeURIComponent(
|
|
790
|
+
async uninstall(id2, options) {
|
|
791
|
+
await this.http.request("DELETE", `/installations/${encodeURIComponent(id2)}`, {
|
|
770
792
|
params: { workspaceId: this.requireWorkspaceId(options?.workspaceId) }
|
|
771
793
|
});
|
|
772
794
|
}
|
|
@@ -792,10 +814,10 @@ var ResourcesModule = class {
|
|
|
792
814
|
params: { workspaceId: this.requireWorkspaceId(options?.workspaceId) }
|
|
793
815
|
});
|
|
794
816
|
}
|
|
795
|
-
async get(
|
|
817
|
+
async get(id2, options) {
|
|
796
818
|
return this.http.request(
|
|
797
819
|
"GET",
|
|
798
|
-
`/resources/${encodeURIComponent(
|
|
820
|
+
`/resources/${encodeURIComponent(id2)}`,
|
|
799
821
|
{ params: { workspaceId: this.requireWorkspaceId(options?.workspaceId) } }
|
|
800
822
|
);
|
|
801
823
|
}
|
|
@@ -847,7 +869,7 @@ var SettingsModule = class {
|
|
|
847
869
|
}
|
|
848
870
|
});
|
|
849
871
|
}
|
|
850
|
-
/** Upsert a setting value by its full key. Requires the `
|
|
872
|
+
/** Upsert a setting value by its full key. Requires the `setting.write` scope. */
|
|
851
873
|
async set(key, value, options) {
|
|
852
874
|
await this.http.request("PUT", `/settings/${encodeURIComponent(key)}`, {
|
|
853
875
|
params: {
|
|
@@ -858,7 +880,7 @@ var SettingsModule = class {
|
|
|
858
880
|
headers: { "Content-Type": "application/json" }
|
|
859
881
|
});
|
|
860
882
|
}
|
|
861
|
-
/** Delete a stored value (reverting to the definition default). Requires `
|
|
883
|
+
/** Delete a stored value (reverting to the definition default). Requires `setting.delete`. */
|
|
862
884
|
async reset(key, options) {
|
|
863
885
|
await this.http.request("DELETE", `/settings/${encodeURIComponent(key)}`, {
|
|
864
886
|
params: {
|
|
@@ -905,104 +927,78 @@ var SettingsModule = class {
|
|
|
905
927
|
}
|
|
906
928
|
};
|
|
907
929
|
|
|
908
|
-
// src/
|
|
909
|
-
var
|
|
930
|
+
// src/types.ts
|
|
931
|
+
var ApiError = class extends Error {
|
|
932
|
+
constructor(status, detail, title, code, retryAfterMs) {
|
|
933
|
+
super(title ?? `API error ${status}: ${detail}`);
|
|
934
|
+
this.status = status;
|
|
935
|
+
this.detail = detail;
|
|
936
|
+
this.title = title;
|
|
937
|
+
this.code = code;
|
|
938
|
+
this.retryAfterMs = retryAfterMs;
|
|
939
|
+
this.name = "ApiError";
|
|
940
|
+
}
|
|
941
|
+
status;
|
|
942
|
+
detail;
|
|
943
|
+
title;
|
|
944
|
+
code;
|
|
945
|
+
retryAfterMs;
|
|
946
|
+
};
|
|
947
|
+
|
|
948
|
+
// src/modules/notifications.ts
|
|
949
|
+
var NotificationsModule = class {
|
|
910
950
|
constructor(http, workspaceId) {
|
|
911
951
|
this.http = http;
|
|
912
952
|
this.workspaceId = workspaceId;
|
|
913
953
|
}
|
|
914
954
|
http;
|
|
915
955
|
workspaceId;
|
|
916
|
-
async
|
|
917
|
-
|
|
918
|
-
params: { workspaceId: this.workspace(options) }
|
|
919
|
-
});
|
|
920
|
-
}
|
|
921
|
-
async consents(options) {
|
|
922
|
-
return this.http.request("GET", "/email/consents", { params: { workspaceId: this.workspace(options) } });
|
|
923
|
-
}
|
|
924
|
-
/** Approve exactly the reviewed signed candidate; tracking stays off unless explicitly opted in. */
|
|
925
|
-
async consent(preview, approval, options) {
|
|
926
|
-
if (approval !== true) throw new Error("Explicit email consent is required");
|
|
927
|
-
if (!options?.senderGrants?.length) throw new Error("Explicit purpose/sender grants are required");
|
|
928
|
-
return this.http.request("PUT", `/email/consents/${encodeURIComponent(preview.installationId)}`, {
|
|
929
|
-
params: { workspaceId: preview.workspaceId },
|
|
956
|
+
async send(options) {
|
|
957
|
+
const request = {
|
|
930
958
|
body: JSON.stringify({
|
|
931
|
-
|
|
932
|
-
enabled: true,
|
|
933
|
-
allowOpenTracking: options?.allowOpenTracking ?? false,
|
|
934
|
-
allowClickTracking: options?.allowClickTracking ?? false,
|
|
935
|
-
senderGrants: options.senderGrants.map((grant) => ({ purpose: grant.purpose, senderId: grant.senderId }))
|
|
936
|
-
}),
|
|
937
|
-
headers: { "Content-Type": "application/json" }
|
|
938
|
-
});
|
|
939
|
-
}
|
|
940
|
-
async revoke(consent, options) {
|
|
941
|
-
return this.http.request("PUT", `/email/consents/${encodeURIComponent(consent.installationId)}`, {
|
|
942
|
-
params: { workspaceId: this.workspace(options) },
|
|
943
|
-
body: JSON.stringify({ candidateDigest: consent.candidateDigest, enabled: false, allowOpenTracking: false, allowClickTracking: false }),
|
|
944
|
-
headers: { "Content-Type": "application/json" }
|
|
945
|
-
});
|
|
946
|
-
}
|
|
947
|
-
async senders(options) {
|
|
948
|
-
return this.http.request("GET", "/email/senders", { params: { workspaceId: this.workspace(options) } });
|
|
949
|
-
}
|
|
950
|
-
async invoicePdf(recordId, installationId, options) {
|
|
951
|
-
this.mainBranch(options);
|
|
952
|
-
return this.http.request("POST", "/email/artifacts/invoice", {
|
|
953
|
-
body: JSON.stringify({ workspaceId: this.workspace(options), recordId, installationId }),
|
|
954
|
-
headers: { "Content-Type": "application/json" }
|
|
955
|
-
});
|
|
956
|
-
}
|
|
957
|
-
/** Authenticated immutable bytes; no public URL. The caller owns any local object URL it creates. */
|
|
958
|
-
async artifactContent(artifactId, options) {
|
|
959
|
-
this.mainBranch(options);
|
|
960
|
-
return this.http.request("GET", `/email/artifacts/${encodeURIComponent(artifactId)}/content`, {
|
|
961
|
-
params: { workspaceId: this.workspace(options), branch: "main" }
|
|
962
|
-
});
|
|
963
|
-
}
|
|
964
|
-
/** A stable key binds this exact request. After a lost response inspect status; never automatically resend. */
|
|
965
|
-
async dispatch(options) {
|
|
966
|
-
this.mainBranch(options);
|
|
967
|
-
return this.http.request("POST", "/email/dispatches", {
|
|
968
|
-
body: JSON.stringify({
|
|
969
|
-
workspaceId: this.workspace(options),
|
|
959
|
+
workspaceId: this.requireWorkspaceId(options.workspaceId),
|
|
970
960
|
installationId: options.installationId,
|
|
971
|
-
|
|
972
|
-
purpose: options.purpose,
|
|
973
|
-
templateId: options.templateId,
|
|
974
|
-
senderId: options.senderId,
|
|
975
|
-
recipients: options.recipients,
|
|
976
|
-
artifactIds: options.artifactIds,
|
|
961
|
+
typeKey: options.typeKey,
|
|
977
962
|
idempotencyKey: options.idempotencyKey,
|
|
978
|
-
|
|
963
|
+
userIds: options.userIds,
|
|
964
|
+
audienceScope: options.audienceScope,
|
|
965
|
+
emailAddresses: options.emailAddresses,
|
|
966
|
+
parameters: options.parameters
|
|
979
967
|
}),
|
|
980
968
|
headers: { "Content-Type": "application/json" }
|
|
981
|
-
}
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
async status(id, options) {
|
|
996
|
-
return this.outcome(id, options);
|
|
969
|
+
};
|
|
970
|
+
const deadline = Date.now() + 1e4;
|
|
971
|
+
for (; ; ) {
|
|
972
|
+
try {
|
|
973
|
+
return await this.http.request("POST", "/notifications/send", request);
|
|
974
|
+
} catch (error) {
|
|
975
|
+
if (!(error instanceof ApiError) || error.status !== 409 || error.code !== "execution_not_ready") {
|
|
976
|
+
throw error;
|
|
977
|
+
}
|
|
978
|
+
const delay2 = Math.max(250, error.retryAfterMs ?? 1e3);
|
|
979
|
+
if (Date.now() + delay2 > deadline) throw error;
|
|
980
|
+
await new Promise((resolve) => setTimeout(resolve, delay2));
|
|
981
|
+
}
|
|
982
|
+
}
|
|
997
983
|
}
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
984
|
+
async request(id2, options) {
|
|
985
|
+
return this.http.request(
|
|
986
|
+
"GET",
|
|
987
|
+
`/notifications/requests/${encodeURIComponent(id2)}`,
|
|
988
|
+
{
|
|
989
|
+
params: {
|
|
990
|
+
workspaceId: this.requireWorkspaceId(options?.workspaceId),
|
|
991
|
+
installationId: options?.installationId
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
);
|
|
1002
995
|
}
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
996
|
+
requireWorkspaceId(override) {
|
|
997
|
+
const workspaceId = override ?? this.workspaceId;
|
|
998
|
+
if (!workspaceId) {
|
|
999
|
+
throw new Error("workspaceId is required: provide it in options or when creating the client");
|
|
1000
|
+
}
|
|
1001
|
+
return workspaceId;
|
|
1006
1002
|
}
|
|
1007
1003
|
};
|
|
1008
1004
|
|
|
@@ -1032,8 +1028,8 @@ var BusinessModule = class _BusinessModule {
|
|
|
1032
1028
|
body: JSON.stringify(command)
|
|
1033
1029
|
});
|
|
1034
1030
|
}
|
|
1035
|
-
async read(
|
|
1036
|
-
return this.http.request("GET", `/business/records/${encodeURIComponent(
|
|
1031
|
+
async read(id2) {
|
|
1032
|
+
return this.http.request("GET", `/business/records/${encodeURIComponent(id2)}`, { headers: this.headers() });
|
|
1037
1033
|
}
|
|
1038
1034
|
async list(kind) {
|
|
1039
1035
|
return this.http.request("GET", "/business/records", {
|
|
@@ -1075,6 +1071,201 @@ var BusinessModule = class _BusinessModule {
|
|
|
1075
1071
|
}
|
|
1076
1072
|
};
|
|
1077
1073
|
|
|
1074
|
+
// src/modules/chat.ts
|
|
1075
|
+
var JSON_HEADERS = { "Content-Type": "application/json" };
|
|
1076
|
+
var ChatModule = class {
|
|
1077
|
+
constructor(http, bridge = null, executions) {
|
|
1078
|
+
this.http = http;
|
|
1079
|
+
this.bridge = bridge;
|
|
1080
|
+
this.executions = executions;
|
|
1081
|
+
}
|
|
1082
|
+
http;
|
|
1083
|
+
bridge;
|
|
1084
|
+
executions;
|
|
1085
|
+
// ── Conversations ─────────────────────────────────────────────────
|
|
1086
|
+
listConversations(options) {
|
|
1087
|
+
return this.http.request("GET", "/chat/conversations", { params: page(options) });
|
|
1088
|
+
}
|
|
1089
|
+
createConversation(options) {
|
|
1090
|
+
const { idempotencyKey, ...body } = options;
|
|
1091
|
+
return this.http.request("POST", "/chat/conversations", { body: JSON.stringify(body), headers: headers(idempotencyKey) });
|
|
1092
|
+
}
|
|
1093
|
+
/** Opens (or returns the existing) direct conversation with one participant. */
|
|
1094
|
+
openDirect(participant) {
|
|
1095
|
+
return this.createConversation({ kind: "direct", participants: [participant] });
|
|
1096
|
+
}
|
|
1097
|
+
getConversation(conversationId) {
|
|
1098
|
+
return this.http.request("GET", `/chat/conversations/${id(conversationId)}`);
|
|
1099
|
+
}
|
|
1100
|
+
updateConversation(conversationId, changes) {
|
|
1101
|
+
return this.http.request("PATCH", `/chat/conversations/${id(conversationId)}`, { body: JSON.stringify(changes), headers: JSON_HEADERS });
|
|
1102
|
+
}
|
|
1103
|
+
join(conversationId) {
|
|
1104
|
+
return this.http.request("POST", `/chat/conversations/${id(conversationId)}/join`, { body: "{}", headers: JSON_HEADERS });
|
|
1105
|
+
}
|
|
1106
|
+
listPublicChannels(options) {
|
|
1107
|
+
return this.http.request("GET", "/chat/channels", { params: { ...page(options), query: options?.query } });
|
|
1108
|
+
}
|
|
1109
|
+
// ── Members ───────────────────────────────────────────────────────
|
|
1110
|
+
listMembers(conversationId) {
|
|
1111
|
+
return this.http.request("GET", `/chat/conversations/${id(conversationId)}/members`);
|
|
1112
|
+
}
|
|
1113
|
+
addMembers(conversationId, participants, role) {
|
|
1114
|
+
return this.http.request("POST", `/chat/conversations/${id(conversationId)}/members`, {
|
|
1115
|
+
body: JSON.stringify({ participants, role }),
|
|
1116
|
+
headers: JSON_HEADERS
|
|
1117
|
+
});
|
|
1118
|
+
}
|
|
1119
|
+
/** Removes a member; pass yourself to leave. */
|
|
1120
|
+
async removeMember(conversationId, participant) {
|
|
1121
|
+
await this.http.request("DELETE", `/chat/conversations/${id(conversationId)}/members/${participant.kind}/${id(participant.id)}`);
|
|
1122
|
+
}
|
|
1123
|
+
changeRole(conversationId, participant, role) {
|
|
1124
|
+
return this.http.request("PUT", `/chat/conversations/${id(conversationId)}/members/${participant.kind}/${id(participant.id)}/role`, {
|
|
1125
|
+
body: JSON.stringify({ role }),
|
|
1126
|
+
headers: JSON_HEADERS
|
|
1127
|
+
});
|
|
1128
|
+
}
|
|
1129
|
+
// ── Messages ──────────────────────────────────────────────────────
|
|
1130
|
+
listMessages(conversationId, options) {
|
|
1131
|
+
return this.http.request("GET", `/chat/conversations/${id(conversationId)}/messages`, {
|
|
1132
|
+
params: { before: options?.before, limit: options?.limit }
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
getMessage(conversationId, messageId) {
|
|
1136
|
+
return this.http.request("GET", `/chat/conversations/${id(conversationId)}/messages/${id(messageId)}`);
|
|
1137
|
+
}
|
|
1138
|
+
send(conversationId, parts, options) {
|
|
1139
|
+
return this.http.request("POST", `/chat/conversations/${id(conversationId)}/messages`, {
|
|
1140
|
+
body: JSON.stringify({ parts, replyTo: options?.replyTo }),
|
|
1141
|
+
headers: headers(options?.idempotencyKey)
|
|
1142
|
+
});
|
|
1143
|
+
}
|
|
1144
|
+
/** Sends Markdown text (rendered without raw HTML by every reader). */
|
|
1145
|
+
sendText(conversationId, markdown, options) {
|
|
1146
|
+
return this.send(conversationId, [{ type: "text", data: { markdown } }], options);
|
|
1147
|
+
}
|
|
1148
|
+
/** Edits your own message; pass the revision you saw to reject a concurrent edit. */
|
|
1149
|
+
edit(conversationId, messageId, parts, options) {
|
|
1150
|
+
return this.http.request("PATCH", `/chat/conversations/${id(conversationId)}/messages/${id(messageId)}`, {
|
|
1151
|
+
body: JSON.stringify({ parts }),
|
|
1152
|
+
headers: { ...JSON_HEADERS, ...options?.revision ? { "If-Match": `"${options.revision}"` } : {} }
|
|
1153
|
+
});
|
|
1154
|
+
}
|
|
1155
|
+
delete(conversationId, messageId) {
|
|
1156
|
+
return this.http.request("DELETE", `/chat/conversations/${id(conversationId)}/messages/${id(messageId)}`);
|
|
1157
|
+
}
|
|
1158
|
+
/**
|
|
1159
|
+
* Durable changes after a position: `afterSeq` is a snapshot's `highWatermark` (or the last sequence you applied);
|
|
1160
|
+
* `after` is the `next` cursor of a previous page.
|
|
1161
|
+
*/
|
|
1162
|
+
events(conversationId, options) {
|
|
1163
|
+
return this.http.request("GET", `/chat/conversations/${id(conversationId)}/events`, {
|
|
1164
|
+
params: { after: options?.after, afterSeq: options?.afterSeq, limit: options?.limit }
|
|
1165
|
+
});
|
|
1166
|
+
}
|
|
1167
|
+
// ── Read state and preferences ────────────────────────────────────
|
|
1168
|
+
/** Marks messages read through a sequence; never moves back and never past what the server has. */
|
|
1169
|
+
markRead(conversationId, readThroughSeq) {
|
|
1170
|
+
return this.http.request("PUT", `/chat/conversations/${id(conversationId)}/read-state`, {
|
|
1171
|
+
body: JSON.stringify({ readThroughSeq }),
|
|
1172
|
+
headers: JSON_HEADERS
|
|
1173
|
+
});
|
|
1174
|
+
}
|
|
1175
|
+
setPreferences(conversationId, preferences) {
|
|
1176
|
+
return this.http.request("PUT", `/chat/conversations/${id(conversationId)}/preferences`, {
|
|
1177
|
+
body: JSON.stringify(preferences),
|
|
1178
|
+
headers: JSON_HEADERS
|
|
1179
|
+
});
|
|
1180
|
+
}
|
|
1181
|
+
// ── People, bots and commands ─────────────────────────────────────
|
|
1182
|
+
/** People in your workspace (name and avatar only). */
|
|
1183
|
+
searchPeople(options) {
|
|
1184
|
+
return this.http.request("GET", "/chat/people", { params: { ...page(options), query: options?.query } });
|
|
1185
|
+
}
|
|
1186
|
+
listBots() {
|
|
1187
|
+
return this.http.request("GET", "/chat/bots");
|
|
1188
|
+
}
|
|
1189
|
+
/** Workspace managers (`chat.manage`) decide whether a bot may message people directly. */
|
|
1190
|
+
updateBotSettings(botId, settings) {
|
|
1191
|
+
return this.http.request("PUT", `/chat/bots/${id(botId)}/settings`, { body: JSON.stringify(settings), headers: JSON_HEADERS });
|
|
1192
|
+
}
|
|
1193
|
+
listCommands() {
|
|
1194
|
+
return this.http.request("GET", "/chat/commands");
|
|
1195
|
+
}
|
|
1196
|
+
/** Validates and records a command invocation, returning the Execution request to run as you. */
|
|
1197
|
+
invokeCommand(conversationId, command, args, options) {
|
|
1198
|
+
return this.http.request("POST", `/chat/conversations/${id(conversationId)}/commands`, {
|
|
1199
|
+
body: JSON.stringify({ command, arguments: args ?? {} }),
|
|
1200
|
+
headers: headers(options?.idempotencyKey)
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
1203
|
+
/**
|
|
1204
|
+
* Invokes an installed app's command and runs its script with your own authorisation. Retrying with the same
|
|
1205
|
+
* idempotency key reuses the invocation key, so Execution never runs it twice.
|
|
1206
|
+
*/
|
|
1207
|
+
async runCommand(conversationId, command, args, options) {
|
|
1208
|
+
if (!this.executions) throw new Error("Running commands needs the executions module.");
|
|
1209
|
+
const invocation = await this.invokeCommand(conversationId, command, args, options);
|
|
1210
|
+
const execution = await this.executions.run(invocation.filePath, {
|
|
1211
|
+
workspaceId: invocation.workspaceId,
|
|
1212
|
+
branch: invocation.branch,
|
|
1213
|
+
parameters: JSON.parse(invocation.parameters),
|
|
1214
|
+
invocationKey: invocation.invocationKey
|
|
1215
|
+
});
|
|
1216
|
+
return { invocation, execution };
|
|
1217
|
+
}
|
|
1218
|
+
/**
|
|
1219
|
+
* Posts as the installed app's bot from a running script. The bot is derived from the script's execution; the
|
|
1220
|
+
* conversation must have added the bot (or, for `userId`, the workspace must allow it to message people).
|
|
1221
|
+
* Retries briefly while Execution's start event is still on its way.
|
|
1222
|
+
*/
|
|
1223
|
+
async postAsBot(options) {
|
|
1224
|
+
const { idempotencyKey, ...body } = options;
|
|
1225
|
+
const request = { body: JSON.stringify(body), headers: headers(idempotencyKey ?? globalThis.crypto?.randomUUID?.()) };
|
|
1226
|
+
const deadline = Date.now() + 1e4;
|
|
1227
|
+
for (; ; ) {
|
|
1228
|
+
try {
|
|
1229
|
+
return await this.http.request("POST", "/chat/bot-messages", request);
|
|
1230
|
+
} catch (error) {
|
|
1231
|
+
if (!(error instanceof ApiError) || error.status !== 409 || error.code !== "execution_not_ready") throw error;
|
|
1232
|
+
const delay2 = Math.max(250, error.retryAfterMs ?? 1e3);
|
|
1233
|
+
if (Date.now() + delay2 > deadline) throw error;
|
|
1234
|
+
await new Promise((resolve) => setTimeout(resolve, delay2));
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
// ── Live hints ────────────────────────────────────────────────────
|
|
1239
|
+
/**
|
|
1240
|
+
* Subscribes to live change hints through the host (installed apps only). Returns an unsubscribe function.
|
|
1241
|
+
* Hints carry ids only; duplicates and reordering are normal, and hints are lost while disconnected.
|
|
1242
|
+
*/
|
|
1243
|
+
subscribeChanges(handlers) {
|
|
1244
|
+
if (!this.bridge) throw new Error("Live chat hints are only available to apps running inside the workspace.");
|
|
1245
|
+
return this.bridge.subscribeChat(handlers);
|
|
1246
|
+
}
|
|
1247
|
+
};
|
|
1248
|
+
function id(value) {
|
|
1249
|
+
return encodeURIComponent(value);
|
|
1250
|
+
}
|
|
1251
|
+
function page(options) {
|
|
1252
|
+
return { cursor: options?.cursor, limit: options?.limit };
|
|
1253
|
+
}
|
|
1254
|
+
function headers(idempotencyKey) {
|
|
1255
|
+
return idempotencyKey ? { ...JSON_HEADERS, "Idempotency-Key": idempotencyKey } : JSON_HEADERS;
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
// src/transport/app-commands.ts
|
|
1259
|
+
var APP_COMMAND_BATCH_SIZE = 200;
|
|
1260
|
+
var APP_COMMANDS_CAPABILITY = "commands";
|
|
1261
|
+
var APP_COMMAND_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:/#@-]{0,255}$/;
|
|
1262
|
+
function isAppCommand(value) {
|
|
1263
|
+
if (!value || typeof value !== "object") return false;
|
|
1264
|
+
const c = value;
|
|
1265
|
+
const optionalText = (key, max) => c[key] === void 0 || typeof c[key] === "string" && c[key].length <= max;
|
|
1266
|
+
return typeof c.id === "string" && APP_COMMAND_ID_PATTERN.test(c.id) && typeof c.label === "string" && c.label.trim().length > 0 && c.label.length <= 200 && optionalText("description", 500) && optionalText("group", 100) && optionalText("disabledReason", 200) && (c.icon === void 0 || typeof c.icon === "string" && /^lucide:[a-z0-9-]{1,64}$/.test(c.icon)) && (c.keywords === void 0 || Array.isArray(c.keywords) && c.keywords.length <= 16 && c.keywords.every((k) => typeof k === "string" && k.length <= 64)) && (c.variant === void 0 || ["default", "outline", "destructive"].includes(String(c.variant))) && ["enabled", "busy"].every((key) => c[key] === void 0 || typeof c[key] === "boolean");
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1078
1269
|
// src/transport/header-actions.ts
|
|
1079
1270
|
function isHeaderAction(value) {
|
|
1080
1271
|
if (!value || typeof value !== "object") return false;
|
|
@@ -1107,7 +1298,7 @@ function element(value) {
|
|
|
1107
1298
|
return record(value) && identifier(value.id) && natural(value.version) && (value.versionNonce === void 0 || natural(value.versionNonce)) && (value.isDeleted === void 0 || typeof value.isDeleted === "boolean");
|
|
1108
1299
|
}
|
|
1109
1300
|
function files(value) {
|
|
1110
|
-
return record(value) && Object.keys(value).length <= 1e4 && Object.entries(value).every(([
|
|
1301
|
+
return record(value) && Object.keys(value).length <= 1e4 && Object.entries(value).every(([id2, file]) => record(file) && identifier(id2) && file.id === id2 && typeof file.dataURL === "string" && file.dataURL.length <= 10 * 1024 * 1024 && typeof file.mimeType === "string" && file.mimeType.length > 0 && file.mimeType.length <= 128 && natural(file.created) && (file.lastRetrieved === void 0 || natural(file.lastRetrieved)));
|
|
1111
1302
|
}
|
|
1112
1303
|
function isNativeSnapshot(value) {
|
|
1113
1304
|
if (!record(value) || !natural(value.sequence) || !natural(value.savedSequence) || value.savedSequence > value.sequence || typeof value.revision !== "string" || !value.revision || value.revision.length > 1024 || typeof value.readOnly !== "boolean" || !record(value.scene) || !Array.isArray(value.scene.elements) || value.scene.elements.length > 1e4 || !value.scene.elements.every(element) || !files(value.scene.files) || !record(value.scene.appState) || !Array.isArray(value.participants) || value.participants.length > 20)
|
|
@@ -1215,6 +1406,14 @@ var Bridge = class {
|
|
|
1215
1406
|
sessionId = null;
|
|
1216
1407
|
actions = /* @__PURE__ */ new Map();
|
|
1217
1408
|
requests = /* @__PURE__ */ new Set();
|
|
1409
|
+
commands = /* @__PURE__ */ new Map();
|
|
1410
|
+
commandUpserts = /* @__PURE__ */ new Set();
|
|
1411
|
+
commandRemovals = /* @__PURE__ */ new Set();
|
|
1412
|
+
commandReset = false;
|
|
1413
|
+
commandFlushScheduled = false;
|
|
1414
|
+
commandRequests = /* @__PURE__ */ new Set();
|
|
1415
|
+
_hostCapabilities = [];
|
|
1416
|
+
chatSubscribers = /* @__PURE__ */ new Set();
|
|
1218
1417
|
hostMessageHandlers = /* @__PURE__ */ new Map();
|
|
1219
1418
|
hostMessageRequests = /* @__PURE__ */ new Set();
|
|
1220
1419
|
wopiRequests = /* @__PURE__ */ new Map();
|
|
@@ -1243,6 +1442,17 @@ var Bridge = class {
|
|
|
1243
1442
|
get hostOrigin() {
|
|
1244
1443
|
return this._hostOrigin;
|
|
1245
1444
|
}
|
|
1445
|
+
/** Capabilities the host announced in `verentis:init`. */
|
|
1446
|
+
get hostCapabilities() {
|
|
1447
|
+
return this._hostCapabilities;
|
|
1448
|
+
}
|
|
1449
|
+
/**
|
|
1450
|
+
* Whether the host exports page commands to its command registry. Older hosts ignore registrations;
|
|
1451
|
+
* commands still run locally, they are just not discoverable in the workspace palette.
|
|
1452
|
+
*/
|
|
1453
|
+
get supportsCommands() {
|
|
1454
|
+
return this._hostCapabilities.includes(APP_COMMANDS_CAPABILITY);
|
|
1455
|
+
}
|
|
1246
1456
|
/** Send a message to the host */
|
|
1247
1457
|
postToHost(message) {
|
|
1248
1458
|
if (this._destroyed) throw new Error("Bridge has been destroyed.");
|
|
@@ -1381,6 +1591,113 @@ var Bridge = class {
|
|
|
1381
1591
|
}
|
|
1382
1592
|
};
|
|
1383
1593
|
}
|
|
1594
|
+
/**
|
|
1595
|
+
* Export a page command to the workspace command registry while it is active. There is no count limit;
|
|
1596
|
+
* dispose the registration when the control unmounts. May be called before the init handshake.
|
|
1597
|
+
*/
|
|
1598
|
+
registerCommand(descriptor, handler) {
|
|
1599
|
+
if (this._destroyed) throw new Error("Bridge has been destroyed.");
|
|
1600
|
+
if (!isAppCommand(descriptor)) throw new Error("Invalid command.");
|
|
1601
|
+
if (this.commands.has(descriptor.id)) throw new Error(`Command '${descriptor.id}' is already registered.`);
|
|
1602
|
+
const command = { descriptor: cloneCommand(descriptor), handler, busy: false };
|
|
1603
|
+
this.commands.set(descriptor.id, command);
|
|
1604
|
+
this.queueCommand(descriptor.id, "upsert");
|
|
1605
|
+
return {
|
|
1606
|
+
update: (next) => {
|
|
1607
|
+
if (this.commands.get(descriptor.id) !== command) throw new Error("Command has been disposed.");
|
|
1608
|
+
if (!isAppCommand(next) || next.id !== descriptor.id) throw new Error("Invalid command update.");
|
|
1609
|
+
if (sameCommand(command.descriptor, next)) return;
|
|
1610
|
+
command.descriptor = cloneCommand(next);
|
|
1611
|
+
this.queueCommand(descriptor.id, "upsert");
|
|
1612
|
+
},
|
|
1613
|
+
dispose: () => {
|
|
1614
|
+
if (this.commands.get(descriptor.id) !== command) return;
|
|
1615
|
+
this.commands.delete(descriptor.id);
|
|
1616
|
+
this.queueCommand(descriptor.id, "remove");
|
|
1617
|
+
}
|
|
1618
|
+
};
|
|
1619
|
+
}
|
|
1620
|
+
queueCommand(id2, change) {
|
|
1621
|
+
if (change === "upsert") {
|
|
1622
|
+
this.commandRemovals.delete(id2);
|
|
1623
|
+
this.commandUpserts.add(id2);
|
|
1624
|
+
} else {
|
|
1625
|
+
this.commandUpserts.delete(id2);
|
|
1626
|
+
this.commandRemovals.add(id2);
|
|
1627
|
+
}
|
|
1628
|
+
this.scheduleCommandFlush();
|
|
1629
|
+
}
|
|
1630
|
+
scheduleCommandFlush() {
|
|
1631
|
+
if (this.commandFlushScheduled) return;
|
|
1632
|
+
this.commandFlushScheduled = true;
|
|
1633
|
+
queueMicrotask(() => {
|
|
1634
|
+
this.commandFlushScheduled = false;
|
|
1635
|
+
this.flushCommands();
|
|
1636
|
+
});
|
|
1637
|
+
}
|
|
1638
|
+
commandSnapshot(id2) {
|
|
1639
|
+
const command = this.commands.get(id2);
|
|
1640
|
+
if (!command) return null;
|
|
1641
|
+
return command.busy ? { ...command.descriptor, busy: true } : command.descriptor;
|
|
1642
|
+
}
|
|
1643
|
+
flushCommands() {
|
|
1644
|
+
if (!this.sessionId || !this._hostOrigin || this._destroyed) return;
|
|
1645
|
+
const upsert = [...this.commandUpserts].map((id2) => this.commandSnapshot(id2)).filter((c) => !!c);
|
|
1646
|
+
const remove = this.commandReset ? [] : [...this.commandRemovals];
|
|
1647
|
+
let reset = this.commandReset;
|
|
1648
|
+
this.commandUpserts.clear();
|
|
1649
|
+
this.commandRemovals.clear();
|
|
1650
|
+
this.commandReset = false;
|
|
1651
|
+
if (!reset && !upsert.length && !remove.length) return;
|
|
1652
|
+
let offset = 0;
|
|
1653
|
+
let removeOffset = 0;
|
|
1654
|
+
do {
|
|
1655
|
+
const batchUpsert = upsert.slice(offset, offset + APP_COMMAND_BATCH_SIZE);
|
|
1656
|
+
offset += batchUpsert.length;
|
|
1657
|
+
const room = APP_COMMAND_BATCH_SIZE - batchUpsert.length;
|
|
1658
|
+
const batchRemove = remove.slice(removeOffset, removeOffset + room);
|
|
1659
|
+
removeOffset += batchRemove.length;
|
|
1660
|
+
this.postToHost({
|
|
1661
|
+
type: "verentis:commands:update",
|
|
1662
|
+
version: 1,
|
|
1663
|
+
sessionId: this.sessionId,
|
|
1664
|
+
...reset ? { reset: true } : {},
|
|
1665
|
+
upsert: batchUpsert,
|
|
1666
|
+
remove: batchRemove
|
|
1667
|
+
});
|
|
1668
|
+
reset = false;
|
|
1669
|
+
} while (offset < upsert.length || removeOffset < remove.length);
|
|
1670
|
+
}
|
|
1671
|
+
async invokeCommand(message) {
|
|
1672
|
+
if (message.sessionId !== this.sessionId || typeof message.requestId !== "string" || message.requestId.length > 128 || !message.requestId || this.commandRequests.has(message.requestId) || typeof message.commandId !== "string") return;
|
|
1673
|
+
this.commandRequests.add(message.requestId);
|
|
1674
|
+
if (this.commandRequests.size > 1e3) this.commandRequests.delete(this.commandRequests.values().next().value);
|
|
1675
|
+
const command = this.commands.get(message.commandId);
|
|
1676
|
+
const reply = {
|
|
1677
|
+
type: "verentis:command:result",
|
|
1678
|
+
version: 1,
|
|
1679
|
+
sessionId: message.sessionId,
|
|
1680
|
+
requestId: message.requestId,
|
|
1681
|
+
commandId: message.commandId
|
|
1682
|
+
};
|
|
1683
|
+
if (!command || command.busy || command.descriptor.busy || command.descriptor.enabled === false) {
|
|
1684
|
+
this.postToHost({ ...reply, error: "Command is unavailable." });
|
|
1685
|
+
return;
|
|
1686
|
+
}
|
|
1687
|
+
command.busy = true;
|
|
1688
|
+
this.queueCommand(message.commandId, "upsert");
|
|
1689
|
+
try {
|
|
1690
|
+
await command.handler();
|
|
1691
|
+
if (!this._destroyed && this.sessionId === message.sessionId) this.postToHost(reply);
|
|
1692
|
+
} catch (error) {
|
|
1693
|
+
if (!this._destroyed && this.sessionId === message.sessionId) {
|
|
1694
|
+
this.postToHost({ ...reply, error: (error instanceof Error ? error.message : "Command failed.").slice(0, 500) || "Command failed." });
|
|
1695
|
+
}
|
|
1696
|
+
} finally {
|
|
1697
|
+
command.busy = false;
|
|
1698
|
+
if (this.commands.get(message.commandId) === command) this.queueCommand(message.commandId, "upsert");
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1384
1701
|
publishActions() {
|
|
1385
1702
|
if (!this.sessionId || this._destroyed) return;
|
|
1386
1703
|
this.postToHost({
|
|
@@ -1465,6 +1782,41 @@ var Bridge = class {
|
|
|
1465
1782
|
this.postToHost({ ...reply, error: "The reply could not be sent to the workspace." });
|
|
1466
1783
|
}
|
|
1467
1784
|
}
|
|
1785
|
+
/**
|
|
1786
|
+
* Subscribes to the host's chat live hints (see `ChatModule.subscribeChanges`). The first subscriber asks the host
|
|
1787
|
+
* to relay; the last one to leave stops it. Messages from another session are ignored.
|
|
1788
|
+
*/
|
|
1789
|
+
subscribeChat(handlers) {
|
|
1790
|
+
if (this._destroyed) throw new Error("Bridge has been destroyed.");
|
|
1791
|
+
this.chatSubscribers.add(handlers);
|
|
1792
|
+
const subscribe = () => {
|
|
1793
|
+
if (this.sessionId && this._hostOrigin && this.chatSubscribers.size > 0)
|
|
1794
|
+
this.postToHost({ type: "verentis:chat:subscribe", version: 1, sessionId: this.sessionId });
|
|
1795
|
+
};
|
|
1796
|
+
if (this.chatSubscribers.size === 1) {
|
|
1797
|
+
if (this._hostOrigin) subscribe();
|
|
1798
|
+
else void this._initPromise.then(subscribe, () => void 0);
|
|
1799
|
+
}
|
|
1800
|
+
return () => {
|
|
1801
|
+
if (!this.chatSubscribers.delete(handlers) || this.chatSubscribers.size > 0) return;
|
|
1802
|
+
if (!this._destroyed && this.sessionId && this._hostOrigin)
|
|
1803
|
+
this.postToHost({ type: "verentis:chat:unsubscribe", version: 1, sessionId: this.sessionId });
|
|
1804
|
+
};
|
|
1805
|
+
}
|
|
1806
|
+
receiveChat(data) {
|
|
1807
|
+
if (data.type !== "verentis:chat:changed" && data.type !== "verentis:chat:connection" && data.type !== "verentis:chat:subscribed" && data.type !== "verentis:chat:error") return false;
|
|
1808
|
+
if (!this._hostOrigin || data.sessionId !== this.sessionId) return true;
|
|
1809
|
+
for (const subscriber of [...this.chatSubscribers]) {
|
|
1810
|
+
try {
|
|
1811
|
+
if (data.type === "verentis:chat:changed") subscriber.onChange(data.hint);
|
|
1812
|
+
else if (data.type === "verentis:chat:error") subscriber.onError?.(String(data.reason).slice(0, 500));
|
|
1813
|
+
else subscriber.onConnection?.(data.status);
|
|
1814
|
+
} catch (error) {
|
|
1815
|
+
console.error("[Verentis SDK] Chat subscriber failed", error);
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
return true;
|
|
1819
|
+
}
|
|
1468
1820
|
/** Subscribe to a specific message type from the host */
|
|
1469
1821
|
on(type, listener) {
|
|
1470
1822
|
if (!this.listeners.has(type)) {
|
|
@@ -1483,8 +1835,13 @@ var Bridge = class {
|
|
|
1483
1835
|
if (!this._hostOrigin) this._initReject(new Error("Bridge has been destroyed."));
|
|
1484
1836
|
this.actions.clear();
|
|
1485
1837
|
this.requests.clear();
|
|
1838
|
+
this.commands.clear();
|
|
1839
|
+
this.commandUpserts.clear();
|
|
1840
|
+
this.commandRemovals.clear();
|
|
1841
|
+
this.commandRequests.clear();
|
|
1486
1842
|
this.hostMessageHandlers.clear();
|
|
1487
1843
|
this.hostMessageRequests.clear();
|
|
1844
|
+
this.chatSubscribers.clear();
|
|
1488
1845
|
this.listeners.clear();
|
|
1489
1846
|
for (const pending of this.wopiRequests.values()) {
|
|
1490
1847
|
clearTimeout(pending.timer);
|
|
@@ -1513,6 +1870,13 @@ var Bridge = class {
|
|
|
1513
1870
|
this._initTimer = void 0;
|
|
1514
1871
|
this._hostOrigin = event.origin;
|
|
1515
1872
|
this.sessionId = typeof data.sessionId === "string" ? data.sessionId : null;
|
|
1873
|
+
this._hostCapabilities = Array.isArray(data.capabilities) ? data.capabilities.filter((c) => typeof c === "string").slice(0, 64) : [];
|
|
1874
|
+
if (this.sessionId && this.commands.size > 0) {
|
|
1875
|
+
this.commandReset = true;
|
|
1876
|
+
this.commandRemovals.clear();
|
|
1877
|
+
for (const id2 of this.commands.keys()) this.commandUpserts.add(id2);
|
|
1878
|
+
this.scheduleCommandFlush();
|
|
1879
|
+
}
|
|
1516
1880
|
console.info("[Verentis SDK] Received verentis:init from host", {
|
|
1517
1881
|
origin: event.origin,
|
|
1518
1882
|
workspaceId: data.context.workspace.id,
|
|
@@ -1550,10 +1914,15 @@ var Bridge = class {
|
|
|
1550
1914
|
void this.invokeAction(data);
|
|
1551
1915
|
return;
|
|
1552
1916
|
}
|
|
1917
|
+
if (data.type === "verentis:command:invoke") {
|
|
1918
|
+
void this.invokeCommand(data);
|
|
1919
|
+
return;
|
|
1920
|
+
}
|
|
1553
1921
|
if (data.type === "verentis:host:message") {
|
|
1554
1922
|
void this.receiveHostMessage(data);
|
|
1555
1923
|
return;
|
|
1556
1924
|
}
|
|
1925
|
+
if (this.receiveChat(data)) return;
|
|
1557
1926
|
const typeListeners = this.listeners.get(data.type);
|
|
1558
1927
|
if (typeListeners) {
|
|
1559
1928
|
for (const listener of typeListeners) {
|
|
@@ -1562,22 +1931,18 @@ var Bridge = class {
|
|
|
1562
1931
|
}
|
|
1563
1932
|
}
|
|
1564
1933
|
};
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
detail;
|
|
1578
|
-
title;
|
|
1579
|
-
code;
|
|
1580
|
-
};
|
|
1934
|
+
function cloneCommand(command) {
|
|
1935
|
+
return { ...command, ...command.keywords ? { keywords: [...command.keywords] } : {} };
|
|
1936
|
+
}
|
|
1937
|
+
function sameCommand(a, b) {
|
|
1938
|
+
const keys = /* @__PURE__ */ new Set([...Object.keys(a), ...Object.keys(b)]);
|
|
1939
|
+
for (const key of keys) {
|
|
1940
|
+
if (key === "keywords") {
|
|
1941
|
+
if ((a.keywords ?? []).join("\0") !== (b.keywords ?? []).join("\0")) return false;
|
|
1942
|
+
} else if (a[key] !== b[key]) return false;
|
|
1943
|
+
}
|
|
1944
|
+
return true;
|
|
1945
|
+
}
|
|
1581
1946
|
|
|
1582
1947
|
// src/transport/http.transport.ts
|
|
1583
1948
|
var HttpTransport = class {
|
|
@@ -1592,17 +1957,17 @@ var HttpTransport = class {
|
|
|
1592
1957
|
async request(method, path, options) {
|
|
1593
1958
|
const url = this.buildUrl(path, options?.params);
|
|
1594
1959
|
console.info("[Verentis SDK] Request started", { method, path, url });
|
|
1595
|
-
const
|
|
1960
|
+
const headers2 = {};
|
|
1596
1961
|
const authHeader = await this.auth.getAuthHeader();
|
|
1597
1962
|
if (authHeader) {
|
|
1598
|
-
|
|
1963
|
+
headers2["Authorization"] = authHeader;
|
|
1599
1964
|
}
|
|
1600
1965
|
if (options?.headers) {
|
|
1601
|
-
Object.assign(
|
|
1966
|
+
Object.assign(headers2, options.headers);
|
|
1602
1967
|
}
|
|
1603
1968
|
const response = await fetch(url, {
|
|
1604
1969
|
method,
|
|
1605
|
-
headers,
|
|
1970
|
+
headers: headers2,
|
|
1606
1971
|
body: options?.body
|
|
1607
1972
|
});
|
|
1608
1973
|
await this.ensureSuccess(response);
|
|
@@ -1621,15 +1986,15 @@ var HttpTransport = class {
|
|
|
1621
1986
|
async requestRaw(method, path, options) {
|
|
1622
1987
|
const url = this.buildUrl(path, options?.params);
|
|
1623
1988
|
console.info("[Verentis SDK] Raw request started", { method, path, url });
|
|
1624
|
-
const
|
|
1989
|
+
const headers2 = {};
|
|
1625
1990
|
const authHeader = await this.auth.getAuthHeader();
|
|
1626
1991
|
if (authHeader) {
|
|
1627
|
-
|
|
1992
|
+
headers2["Authorization"] = authHeader;
|
|
1628
1993
|
}
|
|
1629
1994
|
if (options?.headers) {
|
|
1630
|
-
Object.assign(
|
|
1995
|
+
Object.assign(headers2, options.headers);
|
|
1631
1996
|
}
|
|
1632
|
-
const response = await fetch(url, { method, headers, body: options?.body });
|
|
1997
|
+
const response = await fetch(url, { method, headers: headers2, body: options?.body });
|
|
1633
1998
|
console.info("[Verentis SDK] Raw request completed", {
|
|
1634
1999
|
method,
|
|
1635
2000
|
path,
|
|
@@ -1657,7 +2022,15 @@ var HttpTransport = class {
|
|
|
1657
2022
|
if (!(error instanceof SyntaxError)) throw error;
|
|
1658
2023
|
}
|
|
1659
2024
|
console.error("[Verentis SDK] Request failed", { status: response.status, code });
|
|
1660
|
-
|
|
2025
|
+
const retryAfter = response.headers.get("Retry-After");
|
|
2026
|
+
const retryAfterMs = retryAfter === null ? void 0 : /^\d+$/.test(retryAfter) ? Number(retryAfter) * 1e3 : Date.parse(retryAfter) - Date.now();
|
|
2027
|
+
throw new ApiError(
|
|
2028
|
+
response.status,
|
|
2029
|
+
detail,
|
|
2030
|
+
title,
|
|
2031
|
+
code,
|
|
2032
|
+
retryAfterMs !== void 0 && Number.isFinite(retryAfterMs) ? Math.max(0, retryAfterMs) : void 0
|
|
2033
|
+
);
|
|
1661
2034
|
}
|
|
1662
2035
|
buildUrl(path, params) {
|
|
1663
2036
|
const base = `${this.baseUrl}/${this.apiVersion}${path}`;
|
|
@@ -1688,8 +2061,9 @@ var VerentisClient = class {
|
|
|
1688
2061
|
installations;
|
|
1689
2062
|
resources;
|
|
1690
2063
|
settings;
|
|
1691
|
-
|
|
2064
|
+
notifications;
|
|
1692
2065
|
business;
|
|
2066
|
+
chat;
|
|
1693
2067
|
context;
|
|
1694
2068
|
bridge;
|
|
1695
2069
|
collaboration;
|
|
@@ -1724,8 +2098,9 @@ var VerentisClient = class {
|
|
|
1724
2098
|
this.installations = new InstallationsModule(this._http, options?.workspaceId);
|
|
1725
2099
|
this.resources = new ResourcesModule(this._http, options?.workspaceId);
|
|
1726
2100
|
this.settings = new SettingsModule(this._http, options?.workspaceId);
|
|
1727
|
-
this.
|
|
2101
|
+
this.notifications = new NotificationsModule(this._http, options?.workspaceId);
|
|
1728
2102
|
this.business = new BusinessModule(this._http);
|
|
2103
|
+
this.chat = new ChatModule(this._http, null, this.executions);
|
|
1729
2104
|
this._ready = Promise.resolve();
|
|
1730
2105
|
return;
|
|
1731
2106
|
}
|
|
@@ -1774,8 +2149,9 @@ var VerentisClient = class {
|
|
|
1774
2149
|
this.installations = new InstallationsModule(http, context.workspace.id);
|
|
1775
2150
|
this.resources = new ResourcesModule(http, context.workspace.id);
|
|
1776
2151
|
this.settings = new SettingsModule(http, context.workspace.id);
|
|
1777
|
-
this.
|
|
2152
|
+
this.notifications = new NotificationsModule(http, context.workspace.id);
|
|
1778
2153
|
this.business = new BusinessModule(http);
|
|
2154
|
+
this.chat = new ChatModule(http, this.bridge, this.executions);
|
|
1779
2155
|
}
|
|
1780
2156
|
};
|
|
1781
2157
|
function detectEnvironment() {
|
|
@@ -1871,6 +2247,6 @@ function createVerentisClient(options) {
|
|
|
1871
2247
|
return new VerentisClient(options);
|
|
1872
2248
|
}
|
|
1873
2249
|
|
|
1874
|
-
export { ApiError, ApiKeyAuth, Bridge, BridgeAuth, BusinessModule,
|
|
2250
|
+
export { APP_COMMANDS_CAPABILITY, APP_COMMAND_BATCH_SIZE, APP_COMMAND_ID_PATTERN, ApiError, ApiKeyAuth, Bridge, BridgeAuth, BusinessModule, ChatModule, ContextModule, EnginesModule, ExecutionsModule, FilesModule, HOST_MESSAGE_CHANNEL_PATTERN, HttpTransport, InstallationsModule, NativeCollaborationClient, NativeCollaborationError, NotificationsModule, ResourcesModule, SCRIPT_ARGUMENTS_SCHEMA, SettingsModule, TokenAuth, VerentisClient, createVerentisClient, exactHttpsOrigin, findBestMatch, isAppCommand, isDurableSaveConfirmed, isHeaderAction, isNativeSaveResult, isNativeSnapshot, isTerminalStatus, isTrustedMessage, matchMimeType, validateCollaborationDocument, validateNativeCommand };
|
|
1875
2251
|
//# sourceMappingURL=index.js.map
|
|
1876
2252
|
//# sourceMappingURL=index.js.map
|